@cognipeer/agent-sdk 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1502 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -506
- package/dist/index.d.ts +103 -506
- package/dist/index.mjs +1484 -151
- package/dist/index.mjs.map +1 -1
- package/dist/model-rules-Bg9nSqyN.d.cts +658 -0
- package/dist/model-rules-Bg9nSqyN.d.ts +658 -0
- package/dist/model-rules.cjs +763 -0
- package/dist/model-rules.cjs.map +1 -0
- package/dist/model-rules.d.cts +1 -0
- package/dist/model-rules.d.ts +1 -0
- package/dist/model-rules.json +622 -0
- package/dist/model-rules.mjs +756 -0
- package/dist/model-rules.mjs.map +1 -0
- package/package.json +8 -2
package/dist/index.mjs
CHANGED
|
@@ -2016,27 +2016,71 @@ function convertMessageListToSections(messageList) {
|
|
|
2016
2016
|
}
|
|
2017
2017
|
return sections.length > 0 ? sections : void 0;
|
|
2018
2018
|
}
|
|
2019
|
-
function
|
|
2019
|
+
function readTraceContinuation(value) {
|
|
2020
|
+
if (!value || typeof value !== "object") return void 0;
|
|
2021
|
+
const raw = value;
|
|
2022
|
+
if (raw.v !== 1 || typeof raw.sessionId !== "string" || raw.sessionId.length === 0) return void 0;
|
|
2023
|
+
const nextSequence = Number(raw.nextSequence);
|
|
2024
|
+
const startedAt = Number(raw.startedAt);
|
|
2025
|
+
const part = Number(raw.part);
|
|
2026
|
+
if (!Number.isInteger(nextSequence) || nextSequence < 1) return void 0;
|
|
2027
|
+
if (!Number.isFinite(startedAt) || !Number.isInteger(part) || part < 1) return void 0;
|
|
2028
|
+
const summary = raw.summary && typeof raw.summary === "object" ? { ...createEmptySummary(), ...raw.summary } : createEmptySummary();
|
|
2029
|
+
summary.eventCounts = { ...raw.summary?.eventCounts ?? {} };
|
|
2030
|
+
return {
|
|
2031
|
+
v: 1,
|
|
2032
|
+
sessionId: raw.sessionId,
|
|
2033
|
+
traceId: typeof raw.traceId === "string" ? raw.traceId : void 0,
|
|
2034
|
+
rootSpanId: typeof raw.rootSpanId === "string" ? raw.rootSpanId : void 0,
|
|
2035
|
+
threadId: typeof raw.threadId === "string" ? raw.threadId : void 0,
|
|
2036
|
+
startedAt,
|
|
2037
|
+
nextSequence,
|
|
2038
|
+
part,
|
|
2039
|
+
summary,
|
|
2040
|
+
errors: Array.isArray(raw.errors) ? raw.errors : []
|
|
2041
|
+
};
|
|
2042
|
+
}
|
|
2043
|
+
function traceContinuationOf(session) {
|
|
2044
|
+
return {
|
|
2045
|
+
v: 1,
|
|
2046
|
+
sessionId: session.sessionId,
|
|
2047
|
+
traceId: session.traceId,
|
|
2048
|
+
rootSpanId: session.rootSpanId,
|
|
2049
|
+
threadId: session.threadId,
|
|
2050
|
+
startedAt: session.startedAt,
|
|
2051
|
+
nextSequence: (session.sequenceOffset ?? 0) + session.events.length + 1,
|
|
2052
|
+
part: session.part ?? 1,
|
|
2053
|
+
summary: JSON.parse(JSON.stringify(session.summary)),
|
|
2054
|
+
// Sink failures belong to the part that hit them; carrying them on would
|
|
2055
|
+
// mark every later part `partial`.
|
|
2056
|
+
errors: session.errors.filter((error) => error.type !== "sink")
|
|
2057
|
+
};
|
|
2058
|
+
}
|
|
2059
|
+
function createTraceSession(opts, continuation) {
|
|
2020
2060
|
const cfg = withDefaults(opts.tracing);
|
|
2021
2061
|
if (!cfg.enabled) return void 0;
|
|
2022
2062
|
const providedSessionId = opts.tracing?.sessionId?.trim();
|
|
2023
|
-
const sessionId = providedSessionId || generateSessionId();
|
|
2024
|
-
const traceId = generateTraceId();
|
|
2025
|
-
const rootSpanId = generateSpanId();
|
|
2063
|
+
const sessionId = continuation?.sessionId || providedSessionId || generateSessionId();
|
|
2064
|
+
const traceId = continuation?.traceId || generateTraceId();
|
|
2065
|
+
const rootSpanId = continuation?.rootSpanId || generateSpanId();
|
|
2026
2066
|
const runtime = {
|
|
2027
2067
|
sessionId,
|
|
2028
2068
|
traceId,
|
|
2029
2069
|
rootSpanId,
|
|
2030
|
-
threadId: opts.tracing?.threadId,
|
|
2070
|
+
threadId: continuation?.threadId ?? opts.tracing?.threadId,
|
|
2031
2071
|
configAgentName: opts.tracing?.agentName?.trim() || void 0,
|
|
2032
2072
|
configMetadata: opts.tracing?.metadata && Object.keys(opts.tracing.metadata).length > 0 ? opts.tracing.metadata : void 0,
|
|
2033
|
-
startedAt: Date.now(),
|
|
2073
|
+
startedAt: continuation?.startedAt ?? Date.now(),
|
|
2034
2074
|
resolvedConfig: cfg,
|
|
2035
2075
|
events: [],
|
|
2036
|
-
summary: createEmptySummary(),
|
|
2076
|
+
summary: continuation ? continuation.summary : createEmptySummary(),
|
|
2037
2077
|
status: "in_progress",
|
|
2038
|
-
errors: [],
|
|
2039
|
-
|
|
2078
|
+
errors: continuation ? [...continuation.errors] : [],
|
|
2079
|
+
// A continued session was announced by its first part; announcing it
|
|
2080
|
+
// again would reset a streaming receiver's copy.
|
|
2081
|
+
sessionStarted: Boolean(continuation),
|
|
2082
|
+
sequenceOffset: continuation ? continuation.nextSequence - 1 : 0,
|
|
2083
|
+
part: continuation ? continuation.part + 1 : 1
|
|
2040
2084
|
};
|
|
2041
2085
|
if (cfg.sink.type === "file") {
|
|
2042
2086
|
const baseDir = cfg.sink.baseDir;
|
|
@@ -2096,7 +2140,7 @@ async function startStreamingSession(session, agentRuntime) {
|
|
|
2096
2140
|
}
|
|
2097
2141
|
function recordTraceEvent(session, event) {
|
|
2098
2142
|
if (!session) return void 0;
|
|
2099
|
-
const sequence = session.events.length + 1;
|
|
2143
|
+
const sequence = (session.sequenceOffset ?? 0) + session.events.length + 1;
|
|
2100
2144
|
const id = generateEventId(sequence);
|
|
2101
2145
|
const timestampIso = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
2102
2146
|
const status = event.status ?? "success";
|
|
@@ -2286,7 +2330,8 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
2286
2330
|
summary: session.summary,
|
|
2287
2331
|
events: session.events,
|
|
2288
2332
|
status: status2,
|
|
2289
|
-
errors: session.errors
|
|
2333
|
+
errors: session.errors,
|
|
2334
|
+
...(session.part ?? 1) > 1 ? { continuation: { part: session.part, firstSequence: (session.sequenceOffset ?? 0) + 1 } } : {}
|
|
2290
2335
|
});
|
|
2291
2336
|
const payloadForSink = buildPayload(initialStatus);
|
|
2292
2337
|
let sinkFailed = false;
|
|
@@ -2343,7 +2388,17 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
2343
2388
|
if (sink.type === "file" && session.fileSessionDir) {
|
|
2344
2389
|
try {
|
|
2345
2390
|
const filePath = path.join(session.fileSessionDir, "trace.session.json");
|
|
2346
|
-
|
|
2391
|
+
let filePayload = finalPayload;
|
|
2392
|
+
if (finalPayload.continuation) {
|
|
2393
|
+
try {
|
|
2394
|
+
const previous = JSON.parse(await fs.promises.readFile(filePath, "utf8"));
|
|
2395
|
+
const earlier = (previous.events ?? []).filter((event) => event.sequence < finalPayload.continuation.firstSequence);
|
|
2396
|
+
filePayload = { ...finalPayload, events: [...earlier, ...finalPayload.events] };
|
|
2397
|
+
delete filePayload.continuation;
|
|
2398
|
+
} catch {
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
await fs.promises.writeFile(filePath, JSON.stringify(filePayload, null, 2), "utf8");
|
|
2347
2402
|
} catch (err) {
|
|
2348
2403
|
sinkFailed = true;
|
|
2349
2404
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -4782,6 +4837,207 @@ ${append}`;
|
|
|
4782
4837
|
};
|
|
4783
4838
|
}
|
|
4784
4839
|
|
|
4840
|
+
// src/utils/traceDecisions.ts
|
|
4841
|
+
var TRACED_KEY = "__outcomeTraced";
|
|
4842
|
+
function waitedMs(from, to) {
|
|
4843
|
+
if (!from || !to) return void 0;
|
|
4844
|
+
const ms = Date.parse(to) - Date.parse(from);
|
|
4845
|
+
return Number.isFinite(ms) && ms >= 0 ? ms : void 0;
|
|
4846
|
+
}
|
|
4847
|
+
function sameJson(a, b) {
|
|
4848
|
+
try {
|
|
4849
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
4850
|
+
} catch {
|
|
4851
|
+
return false;
|
|
4852
|
+
}
|
|
4853
|
+
}
|
|
4854
|
+
function recordApprovalRequested(session, entry) {
|
|
4855
|
+
if (!session) return;
|
|
4856
|
+
const logData = session.resolvedConfig.logData;
|
|
4857
|
+
const sections = [
|
|
4858
|
+
{
|
|
4859
|
+
kind: "metadata",
|
|
4860
|
+
label: "Approval",
|
|
4861
|
+
data: {
|
|
4862
|
+
approvalId: entry.id,
|
|
4863
|
+
toolCallId: entry.toolCallId,
|
|
4864
|
+
status: "pending",
|
|
4865
|
+
requestedAt: entry.requestedAt,
|
|
4866
|
+
...entry.metadata?.prompt !== void 0 ? { prompt: entry.metadata.prompt } : {}
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4869
|
+
];
|
|
4870
|
+
if (logData) {
|
|
4871
|
+
sections.push({ kind: "tool_call", label: "Arguments to approve", tool: entry.toolName, arguments: sanitizeTracePayload(entry.args) });
|
|
4872
|
+
}
|
|
4873
|
+
recordTraceEvent(session, {
|
|
4874
|
+
type: "tool_approval",
|
|
4875
|
+
label: `Approval requested \xB7 ${entry.toolName}`,
|
|
4876
|
+
timestamp: entry.requestedAt,
|
|
4877
|
+
status: "pending",
|
|
4878
|
+
actor: { scope: "agent", name: entry.toolName, role: "approval_request" },
|
|
4879
|
+
sections
|
|
4880
|
+
});
|
|
4881
|
+
}
|
|
4882
|
+
function recordHumanDecisions(session, state) {
|
|
4883
|
+
if (!session) return;
|
|
4884
|
+
const logData = session.resolvedConfig.logData;
|
|
4885
|
+
for (const entry of state.pendingApprovals ?? []) {
|
|
4886
|
+
if (!entry.decidedAt || entry.metadata?.[TRACED_KEY]) continue;
|
|
4887
|
+
if (entry.status !== "approved" && entry.status !== "rejected") continue;
|
|
4888
|
+
const approved = entry.status === "approved";
|
|
4889
|
+
const edited = approved && entry.approvedArgs !== void 0 && !sameJson(entry.approvedArgs, entry.args);
|
|
4890
|
+
const sections = [
|
|
4891
|
+
{
|
|
4892
|
+
kind: "metadata",
|
|
4893
|
+
label: "Decision",
|
|
4894
|
+
data: {
|
|
4895
|
+
approvalId: entry.id,
|
|
4896
|
+
toolCallId: entry.toolCallId,
|
|
4897
|
+
decision: entry.status,
|
|
4898
|
+
...entry.decidedBy ? { decidedBy: entry.decidedBy } : {},
|
|
4899
|
+
...entry.comment ? { comment: entry.comment } : {},
|
|
4900
|
+
requestedAt: entry.requestedAt,
|
|
4901
|
+
decidedAt: entry.decidedAt,
|
|
4902
|
+
...waitedMs(entry.requestedAt, entry.decidedAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.decidedAt) } : {},
|
|
4903
|
+
...edited ? { argumentsEdited: true } : {}
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
];
|
|
4907
|
+
if (logData) {
|
|
4908
|
+
sections.push({ kind: "tool_call", label: "Requested arguments", tool: entry.toolName, arguments: sanitizeTracePayload(entry.args) });
|
|
4909
|
+
if (edited) {
|
|
4910
|
+
sections.push({ kind: "tool_call", label: "Approved arguments", tool: entry.toolName, arguments: sanitizeTracePayload(entry.approvedArgs) });
|
|
4911
|
+
}
|
|
4912
|
+
}
|
|
4913
|
+
recordTraceEvent(session, {
|
|
4914
|
+
type: "tool_approval",
|
|
4915
|
+
label: `${approved ? "Approved" : "Rejected"} \xB7 ${entry.toolName}`,
|
|
4916
|
+
timestamp: entry.decidedAt,
|
|
4917
|
+
durationMs: waitedMs(entry.requestedAt, entry.decidedAt),
|
|
4918
|
+
status: "success",
|
|
4919
|
+
actor: { scope: "human", name: entry.decidedBy || "reviewer", role: "approver" },
|
|
4920
|
+
sections
|
|
4921
|
+
});
|
|
4922
|
+
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
4923
|
+
}
|
|
4924
|
+
for (const entry of state.pendingUserQuestions ?? []) {
|
|
4925
|
+
if (!entry.answeredAt || entry.metadata?.[TRACED_KEY]) continue;
|
|
4926
|
+
if (entry.status !== "answered" && entry.status !== "cancelled") continue;
|
|
4927
|
+
const clientTool = readClientTool(entry);
|
|
4928
|
+
if (clientTool) {
|
|
4929
|
+
recordClientToolResult(session, entry, clientTool, state.toolHistory);
|
|
4930
|
+
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
4931
|
+
continue;
|
|
4932
|
+
}
|
|
4933
|
+
const cancelled = entry.status === "cancelled";
|
|
4934
|
+
const data = {
|
|
4935
|
+
questionId: entry.id,
|
|
4936
|
+
toolCallId: entry.toolCallId,
|
|
4937
|
+
status: entry.status,
|
|
4938
|
+
...entry.answeredBy ? { answeredBy: entry.answeredBy } : {},
|
|
4939
|
+
...entry.notes ? { notes: entry.notes } : {},
|
|
4940
|
+
requestedAt: entry.requestedAt,
|
|
4941
|
+
answeredAt: entry.answeredAt,
|
|
4942
|
+
...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
|
|
4943
|
+
};
|
|
4944
|
+
const sections = [{ kind: "metadata", label: "Answer", data }];
|
|
4945
|
+
if (logData) {
|
|
4946
|
+
sections.push({
|
|
4947
|
+
kind: "metadata",
|
|
4948
|
+
label: "Questions and answers",
|
|
4949
|
+
data: {
|
|
4950
|
+
items: (entry.questions ?? []).map((item) => ({
|
|
4951
|
+
question: item.question,
|
|
4952
|
+
...item.header ? { header: item.header } : {},
|
|
4953
|
+
answer: sanitizeTracePayload(entry.answers?.[item.question] ?? (item.header ? entry.answers?.[item.header] : void 0) ?? null)
|
|
4954
|
+
}))
|
|
4955
|
+
}
|
|
4956
|
+
});
|
|
4957
|
+
}
|
|
4958
|
+
recordTraceEvent(session, {
|
|
4959
|
+
type: "user_question",
|
|
4960
|
+
label: cancelled ? "Question cancelled" : "Answer from user",
|
|
4961
|
+
timestamp: entry.answeredAt,
|
|
4962
|
+
durationMs: waitedMs(entry.requestedAt, entry.answeredAt),
|
|
4963
|
+
status: cancelled ? "skipped" : "success",
|
|
4964
|
+
actor: { scope: "human", name: entry.answeredBy || "user", role: "user" },
|
|
4965
|
+
sections
|
|
4966
|
+
});
|
|
4967
|
+
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
4968
|
+
}
|
|
4969
|
+
}
|
|
4970
|
+
function recordClientToolRequested(session, entry) {
|
|
4971
|
+
if (!session) return;
|
|
4972
|
+
const clientTool = readClientTool(entry);
|
|
4973
|
+
if (!clientTool) return;
|
|
4974
|
+
const sections = [
|
|
4975
|
+
{
|
|
4976
|
+
kind: "metadata",
|
|
4977
|
+
label: "Client tool",
|
|
4978
|
+
data: { questionId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt }
|
|
4979
|
+
}
|
|
4980
|
+
];
|
|
4981
|
+
if (session.resolvedConfig.logData) {
|
|
4982
|
+
sections.push({ kind: "tool_call", label: "Arguments", tool: clientTool.name, arguments: sanitizeTracePayload(clientTool.args) });
|
|
4983
|
+
}
|
|
4984
|
+
recordTraceEvent(session, {
|
|
4985
|
+
type: "tool_call",
|
|
4986
|
+
label: `Tool Execution - ${clientTool.name} (client)`,
|
|
4987
|
+
timestamp: entry.requestedAt,
|
|
4988
|
+
status: "pending",
|
|
4989
|
+
actor: { scope: "client", name: clientTool.name, role: "tool" },
|
|
4990
|
+
sections
|
|
4991
|
+
});
|
|
4992
|
+
}
|
|
4993
|
+
function readClientTool(entry) {
|
|
4994
|
+
const meta = entry.metadata?.clientTool;
|
|
4995
|
+
if (!meta || typeof meta !== "object" || typeof meta.name !== "string") return void 0;
|
|
4996
|
+
return { name: meta.name, args: meta.args };
|
|
4997
|
+
}
|
|
4998
|
+
function recordClientToolResult(session, entry, clientTool, toolHistory) {
|
|
4999
|
+
const step = [...toolHistory ?? []].reverse().find((item) => item?.tool_call_id === entry.toolCallId);
|
|
5000
|
+
const failed = step?.status === "error" || entry.status === "cancelled";
|
|
5001
|
+
const sections = [
|
|
5002
|
+
{
|
|
5003
|
+
kind: "metadata",
|
|
5004
|
+
label: "Client tool",
|
|
5005
|
+
data: {
|
|
5006
|
+
questionId: entry.id,
|
|
5007
|
+
toolCallId: entry.toolCallId,
|
|
5008
|
+
status: failed ? "error" : "answered",
|
|
5009
|
+
...entry.answeredBy ? { answeredBy: entry.answeredBy } : {},
|
|
5010
|
+
requestedAt: entry.requestedAt,
|
|
5011
|
+
answeredAt: entry.answeredAt,
|
|
5012
|
+
...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
|
|
5013
|
+
}
|
|
5014
|
+
}
|
|
5015
|
+
];
|
|
5016
|
+
if (session.resolvedConfig.logData) {
|
|
5017
|
+
sections.push({ kind: "tool_call", label: "Arguments", tool: clientTool.name, arguments: sanitizeTracePayload(clientTool.args) });
|
|
5018
|
+
if (step) {
|
|
5019
|
+
const output = step.rawOutput ?? step.output;
|
|
5020
|
+
sections.push({
|
|
5021
|
+
kind: "tool_result",
|
|
5022
|
+
label: "Result from client",
|
|
5023
|
+
tool: clientTool.name,
|
|
5024
|
+
output: sanitizeTracePayload(output),
|
|
5025
|
+
summary: typeof step.output === "string" ? step.output.slice(0, 2e3) : void 0
|
|
5026
|
+
});
|
|
5027
|
+
}
|
|
5028
|
+
}
|
|
5029
|
+
const ranMs = typeof step?.durationMs === "number" ? step.durationMs : void 0;
|
|
5030
|
+
recordTraceEvent(session, {
|
|
5031
|
+
type: "tool_call",
|
|
5032
|
+
label: `Tool Execution - ${clientTool.name} (client)`,
|
|
5033
|
+
timestamp: entry.answeredAt,
|
|
5034
|
+
durationMs: waitedMs(entry.requestedAt, entry.answeredAt) ?? ranMs,
|
|
5035
|
+
status: failed ? "error" : "success",
|
|
5036
|
+
actor: { scope: "client", name: clientTool.name, role: "tool" },
|
|
5037
|
+
sections
|
|
5038
|
+
});
|
|
5039
|
+
}
|
|
5040
|
+
|
|
4785
5041
|
// src/utils/traceSections.ts
|
|
4786
5042
|
init_content();
|
|
4787
5043
|
function truncate(text, max = 500) {
|
|
@@ -5095,10 +5351,10 @@ function createToolsNode(initialTools, opts) {
|
|
|
5095
5351
|
const toolCallId = tc.id || `${tc.name}_${toolCount + 1}`;
|
|
5096
5352
|
const validatedArgs = validateToolArgs(tool, args);
|
|
5097
5353
|
if (!validatedArgs.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
5098
|
-
const
|
|
5099
|
-
push({ role: "tool", content:
|
|
5100
|
-
markToolFailure(
|
|
5101
|
-
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message:
|
|
5354
|
+
const errorMessage2 = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
|
|
5355
|
+
push({ role: "tool", content: errorMessage2, tool_call_id: toolCallId, name: tc.name });
|
|
5356
|
+
markToolFailure(errorMessage2, tc.name, toolCallId);
|
|
5357
|
+
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage2 } });
|
|
5102
5358
|
toolCount += 1;
|
|
5103
5359
|
return { status: "error" };
|
|
5104
5360
|
}
|
|
@@ -5250,6 +5506,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5250
5506
|
};
|
|
5251
5507
|
pendingApprovals.push(approvalEntry);
|
|
5252
5508
|
pendingByCallId.set(toolCallId, approvalEntry);
|
|
5509
|
+
recordApprovalRequested(traceSession, approvalEntry);
|
|
5253
5510
|
onEvent?.({ type: "tool_approval", status: "pending", id: approvalEntry.id, toolName: approvalEntry.toolName, toolCallId: approvalEntry.toolCallId, args });
|
|
5254
5511
|
if (host?.has("notification")) {
|
|
5255
5512
|
await host.runObservers("notification", {
|
|
@@ -5513,6 +5770,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5513
5770
|
if (!pendingApproval) {
|
|
5514
5771
|
throw new Error(`Tool ${toolName} requested approval but no pending approval entry was recorded.`);
|
|
5515
5772
|
}
|
|
5773
|
+
recordApprovalRequested(traceSession, pendingApproval);
|
|
5516
5774
|
awaitingApproval = true;
|
|
5517
5775
|
return {
|
|
5518
5776
|
status: "awaiting_approval",
|
|
@@ -5529,6 +5787,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5529
5787
|
if (!pendingQuestion) {
|
|
5530
5788
|
throw new Error(`Tool ${toolName} requested a user question but no pending question entry was recorded.`);
|
|
5531
5789
|
}
|
|
5790
|
+
recordClientToolRequested(traceSession, pendingQuestion);
|
|
5532
5791
|
awaitingUserQuestion = true;
|
|
5533
5792
|
if (host?.has("notification")) {
|
|
5534
5793
|
await host.runObservers("notification", {
|
|
@@ -6109,7 +6368,7 @@ var LEVEL_DEFAULTS = {
|
|
|
6109
6368
|
};
|
|
6110
6369
|
var VALID_LEVELS = ["minimal", "low", "medium", "high"];
|
|
6111
6370
|
var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
|
|
6112
|
-
var VALID_EFFORTS = ["none", "minimal", "low", "medium", "high"];
|
|
6371
|
+
var VALID_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
6113
6372
|
function validateReasoningConfig(input) {
|
|
6114
6373
|
if (!input) return;
|
|
6115
6374
|
if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
|
|
@@ -6625,16 +6884,20 @@ function createAskUserQuestionTool(stateRef, config) {
|
|
|
6625
6884
|
});
|
|
6626
6885
|
recordTraceEvent(ctx.__traceSession, {
|
|
6627
6886
|
type: "user_question",
|
|
6628
|
-
label: "
|
|
6887
|
+
label: "Question to user",
|
|
6888
|
+
timestamp: entry.requestedAt,
|
|
6629
6889
|
actor: { scope: "agent", name: "ask_user_question", role: "user_interaction" },
|
|
6630
|
-
status: "
|
|
6890
|
+
status: "pending",
|
|
6631
6891
|
sections: [
|
|
6632
6892
|
{
|
|
6633
6893
|
kind: "metadata",
|
|
6634
6894
|
label: "Pending Question",
|
|
6635
6895
|
data: {
|
|
6636
6896
|
id: entry.id,
|
|
6897
|
+
questionId: entry.id,
|
|
6637
6898
|
toolCallId: entry.toolCallId,
|
|
6899
|
+
status: "pending",
|
|
6900
|
+
requestedAt: entry.requestedAt,
|
|
6638
6901
|
questions: entry.questions,
|
|
6639
6902
|
allowFreeText
|
|
6640
6903
|
}
|
|
@@ -7853,15 +8116,17 @@ function createAgent(opts) {
|
|
|
7853
8116
|
}
|
|
7854
8117
|
const traceSession = state.ctx?.__traceSession;
|
|
7855
8118
|
if (traceSession) {
|
|
8119
|
+
const iterationNumber = (traceSession.summary.eventCounts.agent_iteration ?? 0) + 1;
|
|
7856
8120
|
const iterEvent = recordTraceEvent(traceSession, {
|
|
7857
8121
|
type: "agent_iteration",
|
|
7858
|
-
label: `Iteration ${
|
|
8122
|
+
label: `Iteration ${iterationNumber}`,
|
|
7859
8123
|
actor: { scope: "agent", name: opts.name || "agent", role: "orchestrator" },
|
|
7860
8124
|
parentSpanId: traceSession.rootSpanId
|
|
7861
8125
|
});
|
|
7862
8126
|
if (iterEvent) {
|
|
7863
8127
|
traceSession.currentIterationSpanId = iterEvent.spanId;
|
|
7864
8128
|
}
|
|
8129
|
+
recordHumanDecisions(traceSession, state);
|
|
7865
8130
|
}
|
|
7866
8131
|
if (cancelIfRequested("loop")) break;
|
|
7867
8132
|
const skippingAgent = resumeStage === "tools";
|
|
@@ -8142,7 +8407,7 @@ function createAgent(opts) {
|
|
|
8142
8407
|
}
|
|
8143
8408
|
emit({ type: "progress", ...progress });
|
|
8144
8409
|
};
|
|
8145
|
-
const traceSession = createTraceSession(opts);
|
|
8410
|
+
const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation));
|
|
8146
8411
|
const ctx = {
|
|
8147
8412
|
...input.ctx || {},
|
|
8148
8413
|
__onEvent: onEvent,
|
|
@@ -8150,6 +8415,7 @@ function createAgent(opts) {
|
|
|
8150
8415
|
__onStream: onStream,
|
|
8151
8416
|
__streaming: streamEnabled
|
|
8152
8417
|
};
|
|
8418
|
+
delete ctx.__traceContinuation;
|
|
8153
8419
|
if (traceSession) ctx.__traceSession = traceSession;
|
|
8154
8420
|
delete ctx.__plugins;
|
|
8155
8421
|
delete ctx.__applySystemPromptContribution;
|
|
@@ -8298,10 +8564,17 @@ function createAgent(opts) {
|
|
|
8298
8564
|
}
|
|
8299
8565
|
}
|
|
8300
8566
|
}
|
|
8567
|
+
const pausedForHuman = statusFor(res) === "paused";
|
|
8568
|
+
const midTurn = pausedForHuman || Boolean(res.ctx?.__needsSummarization);
|
|
8301
8569
|
await finalizeTraceSession(traceSession, {
|
|
8302
8570
|
agentRuntime: res.agent || runtime,
|
|
8303
|
-
status: "success"
|
|
8571
|
+
status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success"
|
|
8304
8572
|
});
|
|
8573
|
+
if (traceSession && midTurn) {
|
|
8574
|
+
res.ctx = { ...res.ctx || {}, __traceContinuation: traceContinuationOf(traceSession) };
|
|
8575
|
+
} else if (res.ctx && "__traceContinuation" in res.ctx) {
|
|
8576
|
+
delete res.ctx.__traceContinuation;
|
|
8577
|
+
}
|
|
8305
8578
|
const isTransientSummarizationExit = !!res.ctx?.__needsSummarization;
|
|
8306
8579
|
const finalAssistantMsg = isTransientSummarizationExit ? void 0 : getLastAssistantMessage(res.messages);
|
|
8307
8580
|
const finalIsSyntheticSummary = !isTransientSummarizationExit && finalAssistantMsg && isSyntheticSummaryMessage(finalAssistantMsg);
|
|
@@ -11205,6 +11478,14 @@ ${pluginAppend}`;
|
|
|
11205
11478
|
} else if (lastResult.state) {
|
|
11206
11479
|
lastResult = { ...lastResult, state: { ...lastResult.state, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, messages: rawMessages } };
|
|
11207
11480
|
}
|
|
11481
|
+
if (lastResult.state) {
|
|
11482
|
+
const endCtx = lastResult.state.ctx;
|
|
11483
|
+
if (endCtx?.__traceContinuation && !(endCtx.__awaitingApproval || endCtx.__awaitingUserQuestion || endCtx.__paused)) {
|
|
11484
|
+
const strippedCtx = { ...endCtx };
|
|
11485
|
+
delete strippedCtx.__traceContinuation;
|
|
11486
|
+
lastResult = { ...lastResult, state: { ...lastResult.state, ctx: strippedCtx } };
|
|
11487
|
+
}
|
|
11488
|
+
}
|
|
11208
11489
|
if (skillsEnabled && lastResult.state) {
|
|
11209
11490
|
const persisted = skillStateFromRegistry(toolSet.skillRegistryRef);
|
|
11210
11491
|
if (persisted) {
|
|
@@ -11579,6 +11860,7 @@ var BaseProvider = class {
|
|
|
11579
11860
|
/** Applies the transport options shared by every provider config. */
|
|
11580
11861
|
configureTransport(config) {
|
|
11581
11862
|
this.fetchImpl = config.fetch;
|
|
11863
|
+
this.onModelRuleLearned = config.onModelRuleLearned;
|
|
11582
11864
|
this.timeoutMs = typeof config.timeoutMs === "number" && config.timeoutMs > 0 ? config.timeoutMs : void 0;
|
|
11583
11865
|
}
|
|
11584
11866
|
/**
|
|
@@ -15246,32 +15528,805 @@ function languageGuard(config) {
|
|
|
15246
15528
|
// src/index.ts
|
|
15247
15529
|
init_content();
|
|
15248
15530
|
|
|
15531
|
+
// src/models/model-rules.json
|
|
15532
|
+
var model_rules_default = {
|
|
15533
|
+
version: 1,
|
|
15534
|
+
effortLadder: [
|
|
15535
|
+
"none",
|
|
15536
|
+
"minimal",
|
|
15537
|
+
"low",
|
|
15538
|
+
"medium",
|
|
15539
|
+
"high",
|
|
15540
|
+
"xhigh",
|
|
15541
|
+
"max"
|
|
15542
|
+
],
|
|
15543
|
+
budgets: {
|
|
15544
|
+
minimal: 1024,
|
|
15545
|
+
low: 2048,
|
|
15546
|
+
medium: 8192,
|
|
15547
|
+
high: 16384,
|
|
15548
|
+
xhigh: 24576,
|
|
15549
|
+
max: 32768
|
|
15550
|
+
},
|
|
15551
|
+
geminiBudgets: {
|
|
15552
|
+
minimal: 512,
|
|
15553
|
+
low: 1024,
|
|
15554
|
+
medium: 4096,
|
|
15555
|
+
high: 12e3,
|
|
15556
|
+
xhigh: 24576,
|
|
15557
|
+
max: 24576
|
|
15558
|
+
},
|
|
15559
|
+
rules: [
|
|
15560
|
+
{
|
|
15561
|
+
id: "openai-chat-models",
|
|
15562
|
+
family: "openai",
|
|
15563
|
+
match: "^(?:chatgpt|gpt-[\\d.]+[a-z0-9.-]*?-chat)",
|
|
15564
|
+
reasoning: {
|
|
15565
|
+
style: "none",
|
|
15566
|
+
efforts: [],
|
|
15567
|
+
off: null
|
|
15568
|
+
},
|
|
15569
|
+
sampling: {
|
|
15570
|
+
temperature: "any",
|
|
15571
|
+
topP: true,
|
|
15572
|
+
topK: true,
|
|
15573
|
+
penalties: true,
|
|
15574
|
+
logprobs: true
|
|
15575
|
+
},
|
|
15576
|
+
maxTokensParam: "max_completion_tokens",
|
|
15577
|
+
chatTools: {
|
|
15578
|
+
reasoning: "any"
|
|
15579
|
+
},
|
|
15580
|
+
source: "docs",
|
|
15581
|
+
note: "Chat-tuned *-chat variants are not reasoning models: ordinary sampling, no reasoning field."
|
|
15582
|
+
},
|
|
15583
|
+
{
|
|
15584
|
+
id: "openai-gpt-6-plus",
|
|
15585
|
+
family: "openai",
|
|
15586
|
+
match: "^gpt-?(?:[6-9]|(?!35(?!\\d))[1-9]\\d+)(?:[.-]|$)",
|
|
15587
|
+
reasoning: {
|
|
15588
|
+
style: "effort",
|
|
15589
|
+
efforts: [
|
|
15590
|
+
"none",
|
|
15591
|
+
"low",
|
|
15592
|
+
"medium",
|
|
15593
|
+
"high",
|
|
15594
|
+
"xhigh"
|
|
15595
|
+
],
|
|
15596
|
+
off: "none",
|
|
15597
|
+
responsesEfforts: [
|
|
15598
|
+
"none",
|
|
15599
|
+
"low",
|
|
15600
|
+
"medium",
|
|
15601
|
+
"high",
|
|
15602
|
+
"xhigh",
|
|
15603
|
+
"max"
|
|
15604
|
+
]
|
|
15605
|
+
},
|
|
15606
|
+
sampling: {
|
|
15607
|
+
temperature: "default-only",
|
|
15608
|
+
topP: false,
|
|
15609
|
+
topK: false,
|
|
15610
|
+
penalties: false,
|
|
15611
|
+
logprobs: false
|
|
15612
|
+
},
|
|
15613
|
+
maxTokensParam: "max_completion_tokens",
|
|
15614
|
+
chatTools: {
|
|
15615
|
+
reasoning: "force-none"
|
|
15616
|
+
},
|
|
15617
|
+
source: "verified-2026-10-14",
|
|
15618
|
+
note: "gpt-N, N>=6. Chat Completions takes none/low/medium/high/xhigh (minimal and max are 400s); Responses also takes max. Function tools with an effort other than none are a 400 on Chat Completions and the default effort is not none, so none is sent explicitly. Rejects max_tokens, temperature != 1, top_p, penalties, logprobs."
|
|
15619
|
+
},
|
|
15620
|
+
{
|
|
15621
|
+
id: "openai-gpt-5x",
|
|
15622
|
+
family: "openai",
|
|
15623
|
+
match: "^gpt-?5\\.[1-9]",
|
|
15624
|
+
reasoning: {
|
|
15625
|
+
style: "effort",
|
|
15626
|
+
efforts: [
|
|
15627
|
+
"none",
|
|
15628
|
+
"low",
|
|
15629
|
+
"medium",
|
|
15630
|
+
"high",
|
|
15631
|
+
"xhigh"
|
|
15632
|
+
],
|
|
15633
|
+
off: "none",
|
|
15634
|
+
responsesEfforts: [
|
|
15635
|
+
"none",
|
|
15636
|
+
"low",
|
|
15637
|
+
"medium",
|
|
15638
|
+
"high",
|
|
15639
|
+
"xhigh",
|
|
15640
|
+
"max"
|
|
15641
|
+
]
|
|
15642
|
+
},
|
|
15643
|
+
sampling: {
|
|
15644
|
+
temperature: "default-only",
|
|
15645
|
+
topP: false,
|
|
15646
|
+
topK: false,
|
|
15647
|
+
penalties: false,
|
|
15648
|
+
logprobs: false
|
|
15649
|
+
},
|
|
15650
|
+
maxTokensParam: "max_completion_tokens",
|
|
15651
|
+
chatTools: {
|
|
15652
|
+
reasoning: "force-none"
|
|
15653
|
+
},
|
|
15654
|
+
source: "verified-2026-10-14",
|
|
15655
|
+
note: "gpt-5.1 and newer 5.x. Same wire rules as gpt-6: no minimal/max on Chat Completions (Responses takes max), function tools need reasoning_effort none on Chat Completions."
|
|
15656
|
+
},
|
|
15657
|
+
{
|
|
15658
|
+
id: "openai-gpt-5-base",
|
|
15659
|
+
family: "openai",
|
|
15660
|
+
match: "^gpt-?5(?![.\\d])",
|
|
15661
|
+
reasoning: {
|
|
15662
|
+
style: "effort",
|
|
15663
|
+
efforts: [
|
|
15664
|
+
"minimal",
|
|
15665
|
+
"low",
|
|
15666
|
+
"medium",
|
|
15667
|
+
"high"
|
|
15668
|
+
],
|
|
15669
|
+
off: null
|
|
15670
|
+
},
|
|
15671
|
+
sampling: {
|
|
15672
|
+
temperature: "default-only",
|
|
15673
|
+
topP: false,
|
|
15674
|
+
topK: false,
|
|
15675
|
+
penalties: false,
|
|
15676
|
+
logprobs: false
|
|
15677
|
+
},
|
|
15678
|
+
maxTokensParam: "max_completion_tokens",
|
|
15679
|
+
chatTools: {
|
|
15680
|
+
reasoning: "any"
|
|
15681
|
+
},
|
|
15682
|
+
source: "docs",
|
|
15683
|
+
note: "gpt-5, -mini, -nano, -codex: minimal/low/medium/high, reasoning cannot be turned off (none maps to minimal)."
|
|
15684
|
+
},
|
|
15685
|
+
{
|
|
15686
|
+
id: "openai-o-series",
|
|
15687
|
+
family: "openai",
|
|
15688
|
+
match: "^o[1-9]\\d?(?![a-z0-9])",
|
|
15689
|
+
reasoning: {
|
|
15690
|
+
style: "effort",
|
|
15691
|
+
efforts: [
|
|
15692
|
+
"low",
|
|
15693
|
+
"medium",
|
|
15694
|
+
"high"
|
|
15695
|
+
],
|
|
15696
|
+
off: null
|
|
15697
|
+
},
|
|
15698
|
+
sampling: {
|
|
15699
|
+
temperature: "default-only",
|
|
15700
|
+
topP: false,
|
|
15701
|
+
topK: false,
|
|
15702
|
+
penalties: false,
|
|
15703
|
+
logprobs: false
|
|
15704
|
+
},
|
|
15705
|
+
maxTokensParam: "max_completion_tokens",
|
|
15706
|
+
chatTools: {
|
|
15707
|
+
reasoning: "any"
|
|
15708
|
+
},
|
|
15709
|
+
source: "docs",
|
|
15710
|
+
note: "o1/o3/o4 family: low/medium/high, no sampling overrides."
|
|
15711
|
+
},
|
|
15712
|
+
{
|
|
15713
|
+
id: "openai-gpt-oss",
|
|
15714
|
+
family: "openai",
|
|
15715
|
+
match: "^gpt-?oss",
|
|
15716
|
+
reasoning: {
|
|
15717
|
+
style: "effort",
|
|
15718
|
+
efforts: [
|
|
15719
|
+
"low",
|
|
15720
|
+
"medium",
|
|
15721
|
+
"high"
|
|
15722
|
+
],
|
|
15723
|
+
off: null
|
|
15724
|
+
},
|
|
15725
|
+
sampling: {
|
|
15726
|
+
temperature: "any",
|
|
15727
|
+
topP: true,
|
|
15728
|
+
topK: true,
|
|
15729
|
+
penalties: true,
|
|
15730
|
+
logprobs: true
|
|
15731
|
+
},
|
|
15732
|
+
maxTokensParam: "max_tokens",
|
|
15733
|
+
chatTools: {
|
|
15734
|
+
reasoning: "any"
|
|
15735
|
+
},
|
|
15736
|
+
source: "docs",
|
|
15737
|
+
note: "Open-weight gpt-oss: low/medium/high; sampling and max_tokens behave like an ordinary chat model."
|
|
15738
|
+
},
|
|
15739
|
+
{
|
|
15740
|
+
id: "openai-legacy-gpt",
|
|
15741
|
+
family: "openai",
|
|
15742
|
+
match: "^(?:gpt-?(?:[0-4]|35)(?![0-9])|text-|davinci|babbage)",
|
|
15743
|
+
reasoning: {
|
|
15744
|
+
style: "none",
|
|
15745
|
+
efforts: [],
|
|
15746
|
+
off: null
|
|
15747
|
+
},
|
|
15748
|
+
sampling: {
|
|
15749
|
+
temperature: "any",
|
|
15750
|
+
topP: true,
|
|
15751
|
+
topK: true,
|
|
15752
|
+
penalties: true,
|
|
15753
|
+
logprobs: true
|
|
15754
|
+
},
|
|
15755
|
+
maxTokensParam: "max_tokens",
|
|
15756
|
+
chatTools: {
|
|
15757
|
+
reasoning: "any"
|
|
15758
|
+
},
|
|
15759
|
+
source: "docs",
|
|
15760
|
+
note: "gpt-4o, gpt-4.1, gpt-3.5 and older: no reasoning, ordinary sampling."
|
|
15761
|
+
},
|
|
15762
|
+
{
|
|
15763
|
+
id: "openai-compatible-toggle",
|
|
15764
|
+
family: "openai",
|
|
15765
|
+
match: "^(?:deepseek-(?:r\\d|reasoner)|qwq|qwen-?3)",
|
|
15766
|
+
reasoning: {
|
|
15767
|
+
style: "toggle",
|
|
15768
|
+
efforts: [
|
|
15769
|
+
"none",
|
|
15770
|
+
"minimal",
|
|
15771
|
+
"low",
|
|
15772
|
+
"medium",
|
|
15773
|
+
"high",
|
|
15774
|
+
"xhigh",
|
|
15775
|
+
"max"
|
|
15776
|
+
],
|
|
15777
|
+
off: "none"
|
|
15778
|
+
},
|
|
15779
|
+
sampling: {
|
|
15780
|
+
temperature: "any",
|
|
15781
|
+
topP: true,
|
|
15782
|
+
topK: true,
|
|
15783
|
+
penalties: true,
|
|
15784
|
+
logprobs: true
|
|
15785
|
+
},
|
|
15786
|
+
maxTokensParam: "max_tokens",
|
|
15787
|
+
chatTools: {
|
|
15788
|
+
reasoning: "any"
|
|
15789
|
+
},
|
|
15790
|
+
source: "docs",
|
|
15791
|
+
note: "DeepSeek R/reasoner, QwQ, Qwen3: on/off style hosts. The effort is forwarded as-is (including none, which switches thinking off on thinking-by-default models)."
|
|
15792
|
+
},
|
|
15793
|
+
{
|
|
15794
|
+
id: "openai-default",
|
|
15795
|
+
family: "openai",
|
|
15796
|
+
match: ".*",
|
|
15797
|
+
reasoning: {
|
|
15798
|
+
style: "effort",
|
|
15799
|
+
efforts: [
|
|
15800
|
+
"none",
|
|
15801
|
+
"minimal",
|
|
15802
|
+
"low",
|
|
15803
|
+
"medium",
|
|
15804
|
+
"high",
|
|
15805
|
+
"xhigh",
|
|
15806
|
+
"max"
|
|
15807
|
+
],
|
|
15808
|
+
off: "none"
|
|
15809
|
+
},
|
|
15810
|
+
sampling: {
|
|
15811
|
+
temperature: "any",
|
|
15812
|
+
topP: true,
|
|
15813
|
+
topK: true,
|
|
15814
|
+
penalties: true,
|
|
15815
|
+
logprobs: true
|
|
15816
|
+
},
|
|
15817
|
+
maxTokensParam: "max_tokens",
|
|
15818
|
+
chatTools: {
|
|
15819
|
+
reasoning: "any"
|
|
15820
|
+
},
|
|
15821
|
+
source: "docs",
|
|
15822
|
+
note: "Permissive default for unknown OpenAI-wire models: pass what the caller asked; the provider learns from 400s."
|
|
15823
|
+
},
|
|
15824
|
+
{
|
|
15825
|
+
id: "claude-haiku-5",
|
|
15826
|
+
family: "anthropic",
|
|
15827
|
+
match: "^claude-(?:haiku-5|5(?:-\\d+)?-haiku)(?!\\d)",
|
|
15828
|
+
reasoning: {
|
|
15829
|
+
style: "adaptive",
|
|
15830
|
+
efforts: [
|
|
15831
|
+
"low",
|
|
15832
|
+
"medium",
|
|
15833
|
+
"high",
|
|
15834
|
+
"xhigh",
|
|
15835
|
+
"max"
|
|
15836
|
+
],
|
|
15837
|
+
off: "disabled"
|
|
15838
|
+
},
|
|
15839
|
+
sampling: {
|
|
15840
|
+
temperature: "unsupported",
|
|
15841
|
+
topP: false,
|
|
15842
|
+
topK: false,
|
|
15843
|
+
penalties: false,
|
|
15844
|
+
logprobs: false
|
|
15845
|
+
},
|
|
15846
|
+
maxTokensParam: "max_tokens",
|
|
15847
|
+
chatTools: {
|
|
15848
|
+
reasoning: "any"
|
|
15849
|
+
},
|
|
15850
|
+
source: "verified-2026-10-14",
|
|
15851
|
+
note: "Claude Haiku 5.x: thinking:{type:adaptive} + output_config.effort; thinking:{type:enabled,budget_tokens} is rejected. Off = thinking:{type:disabled}. Sampling params are rejected."
|
|
15852
|
+
},
|
|
15853
|
+
{
|
|
15854
|
+
id: "claude-sonnet-5",
|
|
15855
|
+
family: "anthropic",
|
|
15856
|
+
match: "^claude-(?:sonnet-5|5(?:-\\d+)?-sonnet)(?!\\d)",
|
|
15857
|
+
reasoning: {
|
|
15858
|
+
style: "adaptive",
|
|
15859
|
+
efforts: [
|
|
15860
|
+
"low",
|
|
15861
|
+
"medium",
|
|
15862
|
+
"high",
|
|
15863
|
+
"xhigh",
|
|
15864
|
+
"max"
|
|
15865
|
+
],
|
|
15866
|
+
off: "between_tools"
|
|
15867
|
+
},
|
|
15868
|
+
sampling: {
|
|
15869
|
+
temperature: "unsupported",
|
|
15870
|
+
topP: false,
|
|
15871
|
+
topK: false,
|
|
15872
|
+
penalties: false,
|
|
15873
|
+
logprobs: false
|
|
15874
|
+
},
|
|
15875
|
+
maxTokensParam: "max_tokens",
|
|
15876
|
+
chatTools: {
|
|
15877
|
+
reasoning: "any"
|
|
15878
|
+
},
|
|
15879
|
+
source: "verified-2026-10-14",
|
|
15880
|
+
note: "Claude Sonnet 5.x: adaptive + output_config.effort. thinking:{type:disabled} is rejected; off = thinking:{type:between_tools}. Sampling params are rejected."
|
|
15881
|
+
},
|
|
15882
|
+
{
|
|
15883
|
+
id: "claude-opus-5",
|
|
15884
|
+
family: "anthropic",
|
|
15885
|
+
match: "^claude-(?:opus-5|5(?:-\\d+)?-opus)(?!\\d)",
|
|
15886
|
+
reasoning: {
|
|
15887
|
+
style: "adaptive",
|
|
15888
|
+
efforts: [
|
|
15889
|
+
"low",
|
|
15890
|
+
"medium",
|
|
15891
|
+
"high",
|
|
15892
|
+
"xhigh",
|
|
15893
|
+
"max"
|
|
15894
|
+
],
|
|
15895
|
+
off: null
|
|
15896
|
+
},
|
|
15897
|
+
sampling: {
|
|
15898
|
+
temperature: "unsupported",
|
|
15899
|
+
topP: false,
|
|
15900
|
+
topK: false,
|
|
15901
|
+
penalties: false,
|
|
15902
|
+
logprobs: false
|
|
15903
|
+
},
|
|
15904
|
+
maxTokensParam: "max_tokens",
|
|
15905
|
+
chatTools: {
|
|
15906
|
+
reasoning: "any"
|
|
15907
|
+
},
|
|
15908
|
+
source: "verified-2026-10-14",
|
|
15909
|
+
note: "Claude Opus 5.x: adaptive + output_config.effort; thinking cannot be turned off (none maps to the lowest effort). Sampling params are rejected."
|
|
15910
|
+
},
|
|
15911
|
+
{
|
|
15912
|
+
id: "claude-fable",
|
|
15913
|
+
family: "anthropic",
|
|
15914
|
+
match: "^claude-fable",
|
|
15915
|
+
reasoning: {
|
|
15916
|
+
style: "adaptive",
|
|
15917
|
+
efforts: [
|
|
15918
|
+
"low",
|
|
15919
|
+
"medium",
|
|
15920
|
+
"high",
|
|
15921
|
+
"xhigh",
|
|
15922
|
+
"max"
|
|
15923
|
+
],
|
|
15924
|
+
off: null
|
|
15925
|
+
},
|
|
15926
|
+
sampling: {
|
|
15927
|
+
temperature: "unsupported",
|
|
15928
|
+
topP: false,
|
|
15929
|
+
topK: false,
|
|
15930
|
+
penalties: false,
|
|
15931
|
+
logprobs: false
|
|
15932
|
+
},
|
|
15933
|
+
maxTokensParam: "max_tokens",
|
|
15934
|
+
chatTools: {
|
|
15935
|
+
reasoning: "any"
|
|
15936
|
+
},
|
|
15937
|
+
source: "docs",
|
|
15938
|
+
note: "Claude Fable line: treated like the 5.x adaptive models."
|
|
15939
|
+
},
|
|
15940
|
+
{
|
|
15941
|
+
id: "claude-4-7",
|
|
15942
|
+
family: "anthropic",
|
|
15943
|
+
match: "^claude-(?:(?:opus|sonnet|haiku)-4[-.]7|4[-.]7-(?:opus|sonnet|haiku))(?!\\d)",
|
|
15944
|
+
reasoning: {
|
|
15945
|
+
style: "adaptive",
|
|
15946
|
+
efforts: [
|
|
15947
|
+
"low",
|
|
15948
|
+
"medium",
|
|
15949
|
+
"high",
|
|
15950
|
+
"xhigh",
|
|
15951
|
+
"max"
|
|
15952
|
+
],
|
|
15953
|
+
off: "disabled"
|
|
15954
|
+
},
|
|
15955
|
+
sampling: {
|
|
15956
|
+
temperature: "thinking-requires-1",
|
|
15957
|
+
topP: true,
|
|
15958
|
+
topK: true,
|
|
15959
|
+
penalties: true,
|
|
15960
|
+
logprobs: true
|
|
15961
|
+
},
|
|
15962
|
+
maxTokensParam: "max_tokens",
|
|
15963
|
+
chatTools: {
|
|
15964
|
+
reasoning: "any"
|
|
15965
|
+
},
|
|
15966
|
+
source: "docs",
|
|
15967
|
+
note: "Claude 4.7: adaptive thinking, low/medium/high/xhigh/max."
|
|
15968
|
+
},
|
|
15969
|
+
{
|
|
15970
|
+
id: "claude-4-6",
|
|
15971
|
+
family: "anthropic",
|
|
15972
|
+
match: "^claude-(?:(?:opus|sonnet|haiku)-4[-.]6|4[-.]6-(?:opus|sonnet|haiku))(?!\\d)",
|
|
15973
|
+
reasoning: {
|
|
15974
|
+
style: "adaptive",
|
|
15975
|
+
efforts: [
|
|
15976
|
+
"low",
|
|
15977
|
+
"medium",
|
|
15978
|
+
"high",
|
|
15979
|
+
"max"
|
|
15980
|
+
],
|
|
15981
|
+
off: "disabled"
|
|
15982
|
+
},
|
|
15983
|
+
sampling: {
|
|
15984
|
+
temperature: "thinking-requires-1",
|
|
15985
|
+
topP: true,
|
|
15986
|
+
topK: true,
|
|
15987
|
+
penalties: true,
|
|
15988
|
+
logprobs: true
|
|
15989
|
+
},
|
|
15990
|
+
maxTokensParam: "max_tokens",
|
|
15991
|
+
chatTools: {
|
|
15992
|
+
reasoning: "any"
|
|
15993
|
+
},
|
|
15994
|
+
source: "docs",
|
|
15995
|
+
note: "Claude 4.6: adaptive thinking, low/medium/high/max (no xhigh)."
|
|
15996
|
+
},
|
|
15997
|
+
{
|
|
15998
|
+
id: "claude-legacy-budget",
|
|
15999
|
+
family: "anthropic",
|
|
16000
|
+
match: "^claude-(?:3|4-|(?:opus|sonnet|haiku)-4)",
|
|
16001
|
+
reasoning: {
|
|
16002
|
+
style: "budget",
|
|
16003
|
+
efforts: [
|
|
16004
|
+
"none",
|
|
16005
|
+
"minimal",
|
|
16006
|
+
"low",
|
|
16007
|
+
"medium",
|
|
16008
|
+
"high",
|
|
16009
|
+
"xhigh",
|
|
16010
|
+
"max"
|
|
16011
|
+
],
|
|
16012
|
+
off: null
|
|
16013
|
+
},
|
|
16014
|
+
sampling: {
|
|
16015
|
+
temperature: "thinking-requires-1",
|
|
16016
|
+
topP: true,
|
|
16017
|
+
topK: true,
|
|
16018
|
+
penalties: true,
|
|
16019
|
+
logprobs: true
|
|
16020
|
+
},
|
|
16021
|
+
maxTokensParam: "max_tokens",
|
|
16022
|
+
chatTools: {
|
|
16023
|
+
reasoning: "any"
|
|
16024
|
+
},
|
|
16025
|
+
source: "docs",
|
|
16026
|
+
note: "Claude 3.7 and 4.0-4.5: thinking:{type:enabled,budget_tokens}; every effort maps to a budget; sampling overrides are not allowed while thinking."
|
|
16027
|
+
},
|
|
16028
|
+
{
|
|
16029
|
+
id: "anthropic-default",
|
|
16030
|
+
family: "anthropic",
|
|
16031
|
+
match: ".*",
|
|
16032
|
+
reasoning: {
|
|
16033
|
+
style: "budget",
|
|
16034
|
+
efforts: [
|
|
16035
|
+
"none",
|
|
16036
|
+
"minimal",
|
|
16037
|
+
"low",
|
|
16038
|
+
"medium",
|
|
16039
|
+
"high",
|
|
16040
|
+
"xhigh",
|
|
16041
|
+
"max"
|
|
16042
|
+
],
|
|
16043
|
+
off: null
|
|
16044
|
+
},
|
|
16045
|
+
sampling: {
|
|
16046
|
+
temperature: "thinking-requires-1",
|
|
16047
|
+
topP: true,
|
|
16048
|
+
topK: true,
|
|
16049
|
+
penalties: true,
|
|
16050
|
+
logprobs: true
|
|
16051
|
+
},
|
|
16052
|
+
maxTokensParam: "max_tokens",
|
|
16053
|
+
chatTools: {
|
|
16054
|
+
reasoning: "any"
|
|
16055
|
+
},
|
|
16056
|
+
source: "docs",
|
|
16057
|
+
note: "Permissive default for unknown Anthropic-wire models: budget style (the long-standing form); the provider flips the thinking form when the API says so."
|
|
16058
|
+
},
|
|
16059
|
+
{
|
|
16060
|
+
id: "gemini-budget",
|
|
16061
|
+
family: "gemini",
|
|
16062
|
+
match: "^gemini",
|
|
16063
|
+
reasoning: {
|
|
16064
|
+
style: "budget",
|
|
16065
|
+
efforts: [
|
|
16066
|
+
"none",
|
|
16067
|
+
"minimal",
|
|
16068
|
+
"low",
|
|
16069
|
+
"medium",
|
|
16070
|
+
"high",
|
|
16071
|
+
"xhigh",
|
|
16072
|
+
"max"
|
|
16073
|
+
],
|
|
16074
|
+
off: "none"
|
|
16075
|
+
},
|
|
16076
|
+
sampling: {
|
|
16077
|
+
temperature: "any",
|
|
16078
|
+
topP: true,
|
|
16079
|
+
topK: true,
|
|
16080
|
+
penalties: true,
|
|
16081
|
+
logprobs: true
|
|
16082
|
+
},
|
|
16083
|
+
maxTokensParam: "max_tokens",
|
|
16084
|
+
chatTools: {
|
|
16085
|
+
reasoning: "any"
|
|
16086
|
+
},
|
|
16087
|
+
source: "docs",
|
|
16088
|
+
note: "Gemini 2.5-style thinkingBudget; effort maps to a token budget, none = budget 0."
|
|
16089
|
+
},
|
|
16090
|
+
{
|
|
16091
|
+
id: "gemini-default",
|
|
16092
|
+
family: "gemini",
|
|
16093
|
+
match: ".*",
|
|
16094
|
+
reasoning: {
|
|
16095
|
+
style: "budget",
|
|
16096
|
+
efforts: [
|
|
16097
|
+
"none",
|
|
16098
|
+
"minimal",
|
|
16099
|
+
"low",
|
|
16100
|
+
"medium",
|
|
16101
|
+
"high",
|
|
16102
|
+
"xhigh",
|
|
16103
|
+
"max"
|
|
16104
|
+
],
|
|
16105
|
+
off: "none"
|
|
16106
|
+
},
|
|
16107
|
+
sampling: {
|
|
16108
|
+
temperature: "any",
|
|
16109
|
+
topP: true,
|
|
16110
|
+
topK: true,
|
|
16111
|
+
penalties: true,
|
|
16112
|
+
logprobs: true
|
|
16113
|
+
},
|
|
16114
|
+
maxTokensParam: "max_tokens",
|
|
16115
|
+
chatTools: {
|
|
16116
|
+
reasoning: "any"
|
|
16117
|
+
},
|
|
16118
|
+
source: "docs",
|
|
16119
|
+
note: "Permissive default for unknown Gemini-wire models."
|
|
16120
|
+
},
|
|
16121
|
+
{
|
|
16122
|
+
id: "other-default",
|
|
16123
|
+
family: "other",
|
|
16124
|
+
match: ".*",
|
|
16125
|
+
reasoning: {
|
|
16126
|
+
style: "effort",
|
|
16127
|
+
efforts: [
|
|
16128
|
+
"none",
|
|
16129
|
+
"minimal",
|
|
16130
|
+
"low",
|
|
16131
|
+
"medium",
|
|
16132
|
+
"high",
|
|
16133
|
+
"xhigh",
|
|
16134
|
+
"max"
|
|
16135
|
+
],
|
|
16136
|
+
off: "none"
|
|
16137
|
+
},
|
|
16138
|
+
sampling: {
|
|
16139
|
+
temperature: "any",
|
|
16140
|
+
topP: true,
|
|
16141
|
+
topK: true,
|
|
16142
|
+
penalties: true,
|
|
16143
|
+
logprobs: true
|
|
16144
|
+
},
|
|
16145
|
+
maxTokensParam: "max_tokens",
|
|
16146
|
+
chatTools: {
|
|
16147
|
+
reasoning: "any"
|
|
16148
|
+
},
|
|
16149
|
+
source: "docs",
|
|
16150
|
+
note: "Permissive default for model families the SDK has no rules for."
|
|
16151
|
+
}
|
|
16152
|
+
]
|
|
16153
|
+
};
|
|
16154
|
+
|
|
16155
|
+
// src/models/rules.ts
|
|
16156
|
+
var MODEL_RULES = model_rules_default;
|
|
16157
|
+
var LADDER = MODEL_RULES.effortLadder;
|
|
16158
|
+
var compiled = /* @__PURE__ */ new Map();
|
|
16159
|
+
function regexFor(rule) {
|
|
16160
|
+
let re = compiled.get(rule.id);
|
|
16161
|
+
if (!re) {
|
|
16162
|
+
re = new RegExp(rule.match, "i");
|
|
16163
|
+
compiled.set(rule.id, re);
|
|
16164
|
+
}
|
|
16165
|
+
return re;
|
|
16166
|
+
}
|
|
16167
|
+
var GATEWAY_PREFIX = /^(?:(?:global|us|eu|apac|jp|au|ca|us-gov)\.)?(?:(?:openai|anthropic|google|meta|amazon|deepseek|qwen|mistral|cohere|ai21)\.)?/;
|
|
16168
|
+
function modelIdCandidates(model) {
|
|
16169
|
+
if (!model) return [];
|
|
16170
|
+
const lower = String(model).trim().toLowerCase();
|
|
16171
|
+
const last = lower.split("/").pop() ?? lower;
|
|
16172
|
+
const out = [];
|
|
16173
|
+
for (const id of [lower, last]) {
|
|
16174
|
+
for (const c of [id, id.replace(GATEWAY_PREFIX, "")]) {
|
|
16175
|
+
if (c && !out.includes(c)) out.push(c);
|
|
16176
|
+
}
|
|
16177
|
+
}
|
|
16178
|
+
return out;
|
|
16179
|
+
}
|
|
16180
|
+
var OPENAI_WIRE = /* @__PURE__ */ new Set(["openai", "azure", "openai-compatible", "together", "openrouter", "groq", "fireworks", "ollama", "vllm", "litellm", "mistral", "deepseek", "xai", "jev"]);
|
|
16181
|
+
function familiesFor(provider) {
|
|
16182
|
+
const p = (provider ?? "").toLowerCase();
|
|
16183
|
+
if (OPENAI_WIRE.has(p)) return ["openai"];
|
|
16184
|
+
if (p === "anthropic") return ["anthropic"];
|
|
16185
|
+
if (p === "bedrock") return ["anthropic", "openai", "other"];
|
|
16186
|
+
if (p === "vertex" || p === "gemini" || p === "google") return ["gemini", "anthropic"];
|
|
16187
|
+
return ["openai", "anthropic", "gemini", "other"];
|
|
16188
|
+
}
|
|
16189
|
+
function matchRule(family, ids, allowDefault) {
|
|
16190
|
+
for (const rule of MODEL_RULES.rules) {
|
|
16191
|
+
if (rule.family !== family) continue;
|
|
16192
|
+
if (rule.match === ".*") {
|
|
16193
|
+
if (allowDefault) return rule;
|
|
16194
|
+
continue;
|
|
16195
|
+
}
|
|
16196
|
+
const re = regexFor(rule);
|
|
16197
|
+
if (ids.some((id) => re.test(id))) return rule;
|
|
16198
|
+
}
|
|
16199
|
+
return void 0;
|
|
16200
|
+
}
|
|
16201
|
+
function mergeRulePatch(base, patch) {
|
|
16202
|
+
if (!patch) return base;
|
|
16203
|
+
const out = { ...base };
|
|
16204
|
+
if (patch.reasoning) out.reasoning = { ...base.reasoning ?? {}, ...patch.reasoning };
|
|
16205
|
+
if (patch.sampling) out.sampling = { ...base.sampling ?? {}, ...patch.sampling };
|
|
16206
|
+
if (patch.chatTools) out.chatTools = { ...base.chatTools ?? {}, ...patch.chatTools };
|
|
16207
|
+
if (patch.maxTokensParam) out.maxTokensParam = patch.maxTokensParam;
|
|
16208
|
+
if (patch.dropParams) out.dropParams = [.../* @__PURE__ */ new Set([...base.dropParams ?? [], ...patch.dropParams])];
|
|
16209
|
+
return out;
|
|
16210
|
+
}
|
|
16211
|
+
var LEARNED_MAX = 500;
|
|
16212
|
+
var learned = /* @__PURE__ */ new Map();
|
|
16213
|
+
function learnedKey(provider, model, scope) {
|
|
16214
|
+
return `${(provider ?? "").toLowerCase()}@${scope ?? ""}::${(model ?? "").trim().toLowerCase()}`;
|
|
16215
|
+
}
|
|
16216
|
+
function rememberModelRulePatch(provider, model, patch, scope) {
|
|
16217
|
+
const key = learnedKey(provider, model, scope);
|
|
16218
|
+
const merged = mergeRulePatch(learned.get(key)?.patch ?? {}, patch);
|
|
16219
|
+
learned.delete(key);
|
|
16220
|
+
learned.set(key, { provider: provider.toLowerCase(), model: model.trim().toLowerCase(), scope, patch: merged });
|
|
16221
|
+
if (learned.size > LEARNED_MAX) learned.delete(learned.keys().next().value);
|
|
16222
|
+
}
|
|
16223
|
+
function getLearnedModelRulePatch(provider, model, scope) {
|
|
16224
|
+
return learned.get(learnedKey(provider, model, scope))?.patch;
|
|
16225
|
+
}
|
|
16226
|
+
function listLearnedModelRules() {
|
|
16227
|
+
return [...learned.values()].map((e) => ({ ...e }));
|
|
16228
|
+
}
|
|
16229
|
+
function clearLearnedModelRules() {
|
|
16230
|
+
learned.clear();
|
|
16231
|
+
}
|
|
16232
|
+
function resolveModelRule(opts) {
|
|
16233
|
+
const families = familiesFor(opts.provider);
|
|
16234
|
+
const ids = modelIdCandidates(opts.model);
|
|
16235
|
+
let rule;
|
|
16236
|
+
for (const family of families) {
|
|
16237
|
+
rule = matchRule(family, ids, false);
|
|
16238
|
+
if (rule) break;
|
|
16239
|
+
}
|
|
16240
|
+
let isDefault = false;
|
|
16241
|
+
if (!rule) {
|
|
16242
|
+
isDefault = true;
|
|
16243
|
+
rule = matchRule(families[0], ids, true) ?? MODEL_RULES.rules[MODEL_RULES.rules.length - 1];
|
|
16244
|
+
}
|
|
16245
|
+
let effective = rule;
|
|
16246
|
+
const known = opts.model ? learned.get(learnedKey(opts.provider, opts.model, opts.scope))?.patch : void 0;
|
|
16247
|
+
if (known) effective = mergeRulePatch(effective, known);
|
|
16248
|
+
if (opts.patch) effective = mergeRulePatch(effective, opts.patch);
|
|
16249
|
+
return { ...effective, matchedRuleId: rule.id, isDefault, learned: !!known };
|
|
16250
|
+
}
|
|
16251
|
+
function mapReasoningEffort(rule, effort, endpoint = "chat") {
|
|
16252
|
+
const efforts = endpoint === "responses" && rule.reasoning.responsesEfforts || rule.reasoning.efforts;
|
|
16253
|
+
if (rule.reasoning.style === "none" || efforts.length === 0) return { mapped: true };
|
|
16254
|
+
const supported = LADDER.filter((e) => efforts.includes(e));
|
|
16255
|
+
if (supported.includes(effort)) return { effort, mapped: false };
|
|
16256
|
+
if (effort === "none") {
|
|
16257
|
+
const off = rule.reasoning.off;
|
|
16258
|
+
if (off && off !== "none") return { off, mapped: true };
|
|
16259
|
+
const lowest = supported.find((e) => e !== "none");
|
|
16260
|
+
return lowest ? { effort: lowest, mapped: true } : { mapped: true };
|
|
16261
|
+
}
|
|
16262
|
+
const at = LADDER.indexOf(effort);
|
|
16263
|
+
if (at < 0) return { mapped: true };
|
|
16264
|
+
for (let i = at - 1; i >= 1; i--) if (supported.includes(LADDER[i])) return { effort: LADDER[i], mapped: true };
|
|
16265
|
+
for (let i = at + 1; i < LADDER.length; i++) if (supported.includes(LADDER[i])) return { effort: LADDER[i], mapped: true };
|
|
16266
|
+
return supported.includes("none") ? { effort: "none", mapped: true } : { mapped: true };
|
|
16267
|
+
}
|
|
16268
|
+
function allowsSampling(rule, field, value, thinkingOn = false) {
|
|
16269
|
+
const s = rule.sampling;
|
|
16270
|
+
switch (field) {
|
|
16271
|
+
case "temperature":
|
|
16272
|
+
switch (s.temperature) {
|
|
16273
|
+
case "any":
|
|
16274
|
+
return true;
|
|
16275
|
+
case "unsupported":
|
|
16276
|
+
return false;
|
|
16277
|
+
// The default is what the server applies anyway, so it is never sent.
|
|
16278
|
+
case "default-only":
|
|
16279
|
+
return false;
|
|
16280
|
+
case "thinking-requires-1":
|
|
16281
|
+
return !thinkingOn || value === 1;
|
|
16282
|
+
}
|
|
16283
|
+
return true;
|
|
16284
|
+
// Anthropic's thinking restriction covers top_p / top_k as well as temperature.
|
|
16285
|
+
case "topP":
|
|
16286
|
+
return s.topP && !(thinkingOn && s.temperature === "thinking-requires-1");
|
|
16287
|
+
case "topK":
|
|
16288
|
+
return s.topK && !(thinkingOn && s.temperature === "thinking-requires-1");
|
|
16289
|
+
case "presencePenalty":
|
|
16290
|
+
case "frequencyPenalty":
|
|
16291
|
+
return s.penalties;
|
|
16292
|
+
case "logprobs":
|
|
16293
|
+
return s.logprobs;
|
|
16294
|
+
}
|
|
16295
|
+
}
|
|
16296
|
+
function applyDropParams(body, rule) {
|
|
16297
|
+
for (const p of rule.dropParams ?? []) {
|
|
16298
|
+
const dot = p.indexOf(".");
|
|
16299
|
+
if (dot < 0) delete body[p];
|
|
16300
|
+
else if (body[p.slice(0, dot)] && typeof body[p.slice(0, dot)] === "object") delete body[p.slice(0, dot)][p.slice(dot + 1)];
|
|
16301
|
+
}
|
|
16302
|
+
}
|
|
16303
|
+
function effortBudget(effort, table = "anthropic") {
|
|
16304
|
+
if (effort === "none") return 0;
|
|
16305
|
+
return (table === "gemini" ? MODEL_RULES.geminiBudgets : MODEL_RULES.budgets)[effort] ?? 0;
|
|
16306
|
+
}
|
|
16307
|
+
|
|
15249
16308
|
// src/providers/utils/reasoning.ts
|
|
15250
16309
|
var ANTHROPIC_EFFORT_BUDGET = {
|
|
15251
16310
|
// 0 = off. `applyAnthropicReasoning` bails on a falsy budget and emits no
|
|
15252
16311
|
// thinking block, which on Anthropic IS off — thinking there is opt-in.
|
|
15253
16312
|
none: 0,
|
|
15254
|
-
|
|
15255
|
-
low: 2048,
|
|
15256
|
-
medium: 8192,
|
|
15257
|
-
high: 16384
|
|
16313
|
+
...MODEL_RULES.budgets
|
|
15258
16314
|
};
|
|
15259
16315
|
var GEMINI_EFFORT_BUDGET = {
|
|
15260
16316
|
// 0 is Gemini's own documented spelling for "do not think", and unlike
|
|
15261
16317
|
// Anthropic it has to be SENT — hence `applyGeminiReasoning` testing for null
|
|
15262
16318
|
// rather than falsiness.
|
|
15263
16319
|
none: 0,
|
|
15264
|
-
|
|
15265
|
-
low: 1024,
|
|
15266
|
-
medium: 4096,
|
|
15267
|
-
high: 12e3
|
|
16320
|
+
...MODEL_RULES.geminiBudgets
|
|
15268
16321
|
};
|
|
15269
16322
|
var THINKING_OUTPUT_RESERVE = 1024;
|
|
15270
16323
|
var MIN_THINKING_BUDGET = 1024;
|
|
15271
16324
|
var THINKING_MIN_MAX_TOKENS = 4096;
|
|
15272
|
-
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
16325
|
+
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort", model, rule) {
|
|
15273
16326
|
if (!reasoning) return;
|
|
15274
|
-
const
|
|
16327
|
+
const requested = normalizeEffort(reasoning.effort);
|
|
16328
|
+
const r = rule ?? resolveModelRule({ provider: "openai", model: model ?? body.model });
|
|
16329
|
+
const effort = requested && mapReasoningEffort(r, requested, mode === "responses" ? "responses" : "chat").effort;
|
|
15275
16330
|
if (mode === "responses") {
|
|
15276
16331
|
const obj = {};
|
|
15277
16332
|
if (effort) obj.effort = effort;
|
|
@@ -15285,48 +16340,54 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
|
15285
16340
|
}
|
|
15286
16341
|
function supportsAdaptiveThinking(model) {
|
|
15287
16342
|
if (typeof model !== "string") return false;
|
|
15288
|
-
|
|
15289
|
-
const at = id.indexOf("claude-");
|
|
15290
|
-
if (at < 0) return false;
|
|
15291
|
-
for (const tok of id.slice(at + 7).split("-")) {
|
|
15292
|
-
if (tok === "fable") return true;
|
|
15293
|
-
const m = /^(\d+)(?:@|$)/.exec(tok);
|
|
15294
|
-
if (m) {
|
|
15295
|
-
if (m[1].length <= 2) return Number(m[1]) >= 5;
|
|
15296
|
-
return false;
|
|
15297
|
-
}
|
|
15298
|
-
}
|
|
15299
|
-
return false;
|
|
16343
|
+
return resolveModelRule({ provider: "anthropic", model }).reasoning.style === "adaptive";
|
|
15300
16344
|
}
|
|
15301
|
-
function resolveThinkingForm(model, mode) {
|
|
16345
|
+
function resolveThinkingForm(model, mode, rule) {
|
|
15302
16346
|
if (mode === "adaptive" || mode === "budget") return mode;
|
|
16347
|
+
if (rule) return rule.reasoning.style === "adaptive" ? "adaptive" : "budget";
|
|
15303
16348
|
return supportsAdaptiveThinking(model) ? "adaptive" : "budget";
|
|
15304
16349
|
}
|
|
15305
|
-
function
|
|
15306
|
-
const
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
if (requested) effort = requested === "minimal" ? "low" : requested;
|
|
15310
|
-
else if (typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
15311
|
-
effort = reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.low ? "low" : reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.medium ? "medium" : "high";
|
|
16350
|
+
function enforceAnthropicSampling(target, rule, thinkingOn, bedrock = false) {
|
|
16351
|
+
const fields = bedrock ? [["temperature", "temperature"], ["topP", "topP"]] : [["temperature", "temperature"], ["top_p", "topP"], ["top_k", "topK"]];
|
|
16352
|
+
for (const [key, field] of fields) {
|
|
16353
|
+
if (key in target && !allowsSampling(rule, field, target[key], thinkingOn)) delete target[key];
|
|
15312
16354
|
}
|
|
15313
|
-
|
|
16355
|
+
}
|
|
16356
|
+
function applyAdaptiveThinking(reasoning, rule, setThinking, setOutputConfig) {
|
|
16357
|
+
let requested = normalizeEffort(reasoning.effort);
|
|
16358
|
+
if (!requested && typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
16359
|
+
requested = reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.low ? "low" : reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.medium ? "medium" : "high";
|
|
16360
|
+
}
|
|
16361
|
+
if (!requested) return false;
|
|
16362
|
+
const mapped = mapReasoningEffort(rule, requested);
|
|
16363
|
+
if (mapped.off) {
|
|
16364
|
+
setThinking({ type: mapped.off });
|
|
16365
|
+
return false;
|
|
16366
|
+
}
|
|
16367
|
+
if (!mapped.effort || mapped.effort === "none") return false;
|
|
15314
16368
|
const thinking = { type: "adaptive" };
|
|
15315
16369
|
if (reasoning.includeThoughts !== false) thinking.display = "summarized";
|
|
15316
16370
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
15317
|
-
setThinking(
|
|
15318
|
-
setOutputConfig({ effort });
|
|
16371
|
+
setThinking(thinking);
|
|
16372
|
+
setOutputConfig({ effort: mapped.effort });
|
|
15319
16373
|
return true;
|
|
15320
16374
|
}
|
|
15321
16375
|
function applyAnthropicReasoning(body, reasoning, opts) {
|
|
15322
|
-
|
|
15323
|
-
if (
|
|
15324
|
-
|
|
15325
|
-
|
|
16376
|
+
const rule = opts?.rule ?? resolveModelRule({ provider: "anthropic", model: opts?.model ?? body.model });
|
|
16377
|
+
if (!reasoning) {
|
|
16378
|
+
enforceAnthropicSampling(body, rule, false);
|
|
16379
|
+
return;
|
|
16380
|
+
}
|
|
16381
|
+
if (resolveThinkingForm(opts?.model ?? body.model, opts?.mode, rule) === "adaptive") {
|
|
16382
|
+
const on = applyAdaptiveThinking(reasoning, rule, (t) => body.thinking = t, (o) => body.output_config = { ...body.output_config ?? {}, ...o });
|
|
16383
|
+
enforceAnthropicSampling(body, rule, on);
|
|
16384
|
+
return;
|
|
16385
|
+
}
|
|
16386
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET, rule);
|
|
16387
|
+
if (!budget) {
|
|
16388
|
+
enforceAnthropicSampling(body, rule, false);
|
|
15326
16389
|
return;
|
|
15327
16390
|
}
|
|
15328
|
-
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
15329
|
-
if (!budget) return;
|
|
15330
16391
|
const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
|
|
15331
16392
|
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
15332
16393
|
if (currentMax < requiredMax) {
|
|
@@ -15336,18 +16397,25 @@ function applyAnthropicReasoning(body, reasoning, opts) {
|
|
|
15336
16397
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
15337
16398
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
15338
16399
|
body.thinking = thinking;
|
|
15339
|
-
|
|
16400
|
+
enforceAnthropicSampling(body, rule, true);
|
|
15340
16401
|
}
|
|
15341
16402
|
function applyBedrockReasoning(body, reasoning, opts) {
|
|
15342
|
-
|
|
15343
|
-
if (
|
|
16403
|
+
const rule = opts?.rule ?? resolveModelRule({ provider: "bedrock", model: opts?.model ?? body.modelId });
|
|
16404
|
+
if (!reasoning) {
|
|
16405
|
+
if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, false, true);
|
|
16406
|
+
return;
|
|
16407
|
+
}
|
|
16408
|
+
if (resolveThinkingForm(opts?.model ?? body.modelId, opts?.mode, rule) === "adaptive") {
|
|
15344
16409
|
const fields = () => body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
|
|
15345
|
-
const on = applyAdaptiveThinking(
|
|
15346
|
-
if (
|
|
16410
|
+
const on = applyAdaptiveThinking(reasoning, rule, (t) => fields().thinking = t, (o) => fields().output_config = { ...fields().output_config ?? {}, ...o });
|
|
16411
|
+
if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, on, true);
|
|
16412
|
+
return;
|
|
16413
|
+
}
|
|
16414
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET, rule);
|
|
16415
|
+
if (!budget) {
|
|
16416
|
+
if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, false, true);
|
|
15347
16417
|
return;
|
|
15348
16418
|
}
|
|
15349
|
-
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
15350
|
-
if (!budget) return;
|
|
15351
16419
|
const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
|
|
15352
16420
|
const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
|
|
15353
16421
|
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
@@ -15359,7 +16427,7 @@ function applyBedrockReasoning(body, reasoning, opts) {
|
|
|
15359
16427
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
15360
16428
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
15361
16429
|
extra.thinking = thinking;
|
|
15362
|
-
|
|
16430
|
+
enforceAnthropicSampling(inference, rule, true, true);
|
|
15363
16431
|
}
|
|
15364
16432
|
function applyGeminiReasoning(generationConfig, reasoning) {
|
|
15365
16433
|
if (!reasoning) return;
|
|
@@ -15371,11 +16439,6 @@ function applyGeminiReasoning(generationConfig, reasoning) {
|
|
|
15371
16439
|
if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
|
|
15372
16440
|
generationConfig.thinkingConfig = thinkingConfig;
|
|
15373
16441
|
}
|
|
15374
|
-
function stripSamplingParams(target, keys) {
|
|
15375
|
-
for (const k of keys) {
|
|
15376
|
-
if (k in target) delete target[k];
|
|
15377
|
-
}
|
|
15378
|
-
}
|
|
15379
16442
|
function clampBudget(budget, maxTokens) {
|
|
15380
16443
|
if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
|
|
15381
16444
|
const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
|
|
@@ -15384,16 +16447,17 @@ function clampBudget(budget, maxTokens) {
|
|
|
15384
16447
|
}
|
|
15385
16448
|
function normalizeEffort(effort) {
|
|
15386
16449
|
if (!effort) return void 0;
|
|
15387
|
-
const allowed = ["none", "minimal", "low", "medium", "high"];
|
|
16450
|
+
const allowed = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
15388
16451
|
return allowed.includes(effort) ? effort : void 0;
|
|
15389
16452
|
}
|
|
15390
|
-
function resolveBudget(reasoning,
|
|
16453
|
+
function resolveBudget(reasoning, effortBudget2, rule) {
|
|
15391
16454
|
const effort = normalizeEffort(reasoning.effort);
|
|
15392
16455
|
if (effort === "none") return 0;
|
|
15393
16456
|
if (typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
15394
16457
|
return Math.floor(reasoning.budgetTokens);
|
|
15395
16458
|
}
|
|
15396
|
-
|
|
16459
|
+
const mapped = effort && rule ? mapReasoningEffort(rule, effort).effort : effort;
|
|
16460
|
+
if (mapped && effortBudget2[mapped]) return effortBudget2[mapped];
|
|
15397
16461
|
return void 0;
|
|
15398
16462
|
}
|
|
15399
16463
|
|
|
@@ -15464,6 +16528,211 @@ function parseSSEBlock(block) {
|
|
|
15464
16528
|
return { event, data: dataLines.join("\n"), id, retry };
|
|
15465
16529
|
}
|
|
15466
16530
|
|
|
16531
|
+
// src/models/errors.ts
|
|
16532
|
+
var ModelRequestError = class extends ProviderError {
|
|
16533
|
+
constructor(init) {
|
|
16534
|
+
super(init.message, init.provider, init.status ?? 400, init.responseBody);
|
|
16535
|
+
this.status = init.status ?? 400;
|
|
16536
|
+
this.code = init.code;
|
|
16537
|
+
this.param = init.param;
|
|
16538
|
+
this.value = init.value;
|
|
16539
|
+
this.supportedValues = init.supportedValues;
|
|
16540
|
+
this.model = init.model;
|
|
16541
|
+
}
|
|
16542
|
+
};
|
|
16543
|
+
|
|
16544
|
+
// src/models/adjust.ts
|
|
16545
|
+
var MAX_ADJUSTMENTS = 3;
|
|
16546
|
+
var Q = "['\"`]";
|
|
16547
|
+
function errorMessage(text) {
|
|
16548
|
+
try {
|
|
16549
|
+
const j = JSON.parse(text);
|
|
16550
|
+
const e = j?.error ?? j;
|
|
16551
|
+
const message = typeof e?.message === "string" ? e.message : typeof j?.message === "string" ? j.message : text;
|
|
16552
|
+
return { message, param: typeof e?.param === "string" ? e.param : void 0, code: typeof e?.code === "string" ? e.code : void 0 };
|
|
16553
|
+
} catch {
|
|
16554
|
+
return { message: text };
|
|
16555
|
+
}
|
|
16556
|
+
}
|
|
16557
|
+
function quotedList(s) {
|
|
16558
|
+
const quoted = [...s.matchAll(new RegExp(`${Q}([^'"\`]+)${Q}`, "g"))].map((m) => m[1]);
|
|
16559
|
+
if (quoted.length > 0) return quoted;
|
|
16560
|
+
return s.split(/[,\s]+/).map((x) => x.replace(/[.\s]+$/, "")).filter(Boolean);
|
|
16561
|
+
}
|
|
16562
|
+
function parseModelError(text) {
|
|
16563
|
+
const { message, param: errParam } = errorMessage(String(text ?? ""));
|
|
16564
|
+
const m = message.toLowerCase();
|
|
16565
|
+
if (m.includes("function tools with reasoning_effort") && m.includes("not supported")) {
|
|
16566
|
+
return { kind: "chat_tools_effort", message };
|
|
16567
|
+
}
|
|
16568
|
+
if (m.includes("between_tools") && m.includes("thinking")) return { kind: "thinking_off_between_tools", message };
|
|
16569
|
+
if (m.includes("thinking.type.enabled") && m.includes("not supported")) return { kind: "thinking_enabled_unsupported", message };
|
|
16570
|
+
if (m.includes("thinking.type.adaptive") && m.includes("not supported")) return { kind: "thinking_adaptive_unsupported", message };
|
|
16571
|
+
if (m.includes("thinking.type.disabled") && m.includes("not supported")) return { kind: "thinking_disabled_unsupported", message };
|
|
16572
|
+
const tt = new RegExp(`${Q}?(temperature|top_p|top_k)${Q}?\\s+may only be set to 1 when thinking is enabled`, "i").exec(message);
|
|
16573
|
+
if (tt) return { kind: "temperature_thinking", param: tt[1].toLowerCase(), message };
|
|
16574
|
+
const dep = new RegExp(`${Q}([\\w.]+)${Q}\\s+is deprecated for this model`, "i").exec(message);
|
|
16575
|
+
if (dep) return { kind: "unsupported_parameter", param: dep[1], message };
|
|
16576
|
+
const rename = new RegExp(`use ${Q}(max_completion_tokens|max_tokens)${Q} instead`, "i").exec(message);
|
|
16577
|
+
if (rename) return { kind: "max_tokens_rename", renameTo: rename[1].toLowerCase(), param: rename[1].toLowerCase() === "max_tokens" ? "max_completion_tokens" : "max_tokens", message };
|
|
16578
|
+
const val = new RegExp(`unsupported value:?\\s*${Q}?([\\w.]+)${Q}?\\s+does not support\\s+(${Q}[^'"\`]*${Q}|[^\\s]+)`, "i").exec(message);
|
|
16579
|
+
if (val) {
|
|
16580
|
+
const param = val[1];
|
|
16581
|
+
const value = val[2].replace(/^['"`]|['"`]$/g, "");
|
|
16582
|
+
if (m.includes("only the default") && m.includes("value is supported")) return { kind: "default_only", param, value, message };
|
|
16583
|
+
const sup = /supported values? (?:are|is):?\s*([^\n]*)/i.exec(message);
|
|
16584
|
+
return { kind: "unsupported_value", param, value, supportedValues: sup ? quotedList(sup[1]) : void 0, message };
|
|
16585
|
+
}
|
|
16586
|
+
if (m.includes("only the default") && m.includes("value is supported")) {
|
|
16587
|
+
return { kind: "default_only", param: errParam ?? "temperature", message };
|
|
16588
|
+
}
|
|
16589
|
+
const prm = new RegExp(`unsupported parameter:?\\s*${Q}?([\\w.]+)${Q}?`, "i").exec(message);
|
|
16590
|
+
if (prm) return { kind: "unsupported_parameter", param: prm[1], message };
|
|
16591
|
+
return void 0;
|
|
16592
|
+
}
|
|
16593
|
+
var normParam = (p) => p.toLowerCase().replace(/[-\s]/g, "_");
|
|
16594
|
+
var LADDER2 = new Set(MODEL_RULES.effortLadder);
|
|
16595
|
+
function patchFromParsedError(parsed, endpoint = "chat") {
|
|
16596
|
+
const param = parsed.param ? normParam(parsed.param) : "";
|
|
16597
|
+
switch (parsed.kind) {
|
|
16598
|
+
case "chat_tools_effort":
|
|
16599
|
+
return { patch: { chatTools: { reasoning: "force-none" } }, adjustment: "chat-tools:force-effort-none" };
|
|
16600
|
+
case "max_tokens_rename":
|
|
16601
|
+
return { patch: { maxTokensParam: parsed.renameTo }, adjustment: `${parsed.param}->${parsed.renameTo}` };
|
|
16602
|
+
case "thinking_enabled_unsupported":
|
|
16603
|
+
return { patch: { reasoning: { style: "adaptive" } }, adjustment: "thinking:adaptive" };
|
|
16604
|
+
case "thinking_adaptive_unsupported":
|
|
16605
|
+
return { patch: { reasoning: { style: "budget" } }, adjustment: "thinking:budget" };
|
|
16606
|
+
case "thinking_off_between_tools":
|
|
16607
|
+
return { patch: { reasoning: { off: "between_tools" } }, adjustment: "thinking-off:between_tools" };
|
|
16608
|
+
case "thinking_disabled_unsupported":
|
|
16609
|
+
return { patch: { reasoning: { off: null } }, adjustment: "thinking-off:none" };
|
|
16610
|
+
case "temperature_thinking":
|
|
16611
|
+
return { patch: { sampling: { temperature: "unsupported" } }, adjustment: "drop:temperature" };
|
|
16612
|
+
case "default_only":
|
|
16613
|
+
if (param === "temperature") return { patch: { sampling: { temperature: "default-only" } }, adjustment: "temperature:default-only" };
|
|
16614
|
+
return { patch: { dropParams: [parsed.param ?? param] }, adjustment: `drop:${parsed.param ?? param}` };
|
|
16615
|
+
case "unsupported_value": {
|
|
16616
|
+
if (/^(reasoning_effort|reasoning\.effort|effort|output_config\.effort)$/.test(param)) {
|
|
16617
|
+
const list = (parsed.supportedValues ?? []).map((v) => v.toLowerCase()).filter((v) => LADDER2.has(v));
|
|
16618
|
+
if (list.length === 0) return void 0;
|
|
16619
|
+
const reasoning = endpoint === "responses" ? { responsesEfforts: list } : { efforts: list };
|
|
16620
|
+
return { patch: { reasoning }, adjustment: `efforts:${list.join("|")}` };
|
|
16621
|
+
}
|
|
16622
|
+
return paramDropPatch(param, parsed);
|
|
16623
|
+
}
|
|
16624
|
+
case "unsupported_parameter":
|
|
16625
|
+
return paramDropPatch(param, parsed);
|
|
16626
|
+
}
|
|
16627
|
+
}
|
|
16628
|
+
function paramDropPatch(param, parsed) {
|
|
16629
|
+
if (!param) return void 0;
|
|
16630
|
+
const label = `drop:${parsed.param ?? param}`;
|
|
16631
|
+
switch (param) {
|
|
16632
|
+
case "temperature":
|
|
16633
|
+
return { patch: { sampling: { temperature: "unsupported" } }, adjustment: label };
|
|
16634
|
+
case "top_p":
|
|
16635
|
+
return { patch: { sampling: { topP: false } }, adjustment: label };
|
|
16636
|
+
case "top_k":
|
|
16637
|
+
return { patch: { sampling: { topK: false } }, adjustment: label };
|
|
16638
|
+
case "presence_penalty":
|
|
16639
|
+
case "frequency_penalty":
|
|
16640
|
+
return { patch: { sampling: { penalties: false } }, adjustment: label };
|
|
16641
|
+
case "logprobs":
|
|
16642
|
+
case "top_logprobs":
|
|
16643
|
+
return { patch: { sampling: { logprobs: false } }, adjustment: label };
|
|
16644
|
+
case "max_tokens":
|
|
16645
|
+
return { patch: { maxTokensParam: "max_completion_tokens" }, adjustment: "max_tokens->max_completion_tokens" };
|
|
16646
|
+
case "max_completion_tokens":
|
|
16647
|
+
return { patch: { maxTokensParam: "max_tokens" }, adjustment: "max_completion_tokens->max_tokens" };
|
|
16648
|
+
case "reasoning_effort":
|
|
16649
|
+
case "reasoning.effort":
|
|
16650
|
+
case "reasoning":
|
|
16651
|
+
return { patch: { reasoning: { style: "none", efforts: [], responsesEfforts: [] }, dropParams: [param] }, adjustment: label };
|
|
16652
|
+
default:
|
|
16653
|
+
return { patch: { dropParams: [parsed.param ?? param] }, adjustment: label };
|
|
16654
|
+
}
|
|
16655
|
+
}
|
|
16656
|
+
function codeFor(parsed) {
|
|
16657
|
+
if (!parsed) return "model_request_invalid";
|
|
16658
|
+
if (parsed.kind === "unsupported_value" || parsed.kind === "default_only") return "unsupported_value";
|
|
16659
|
+
if (parsed.kind === "unsupported_parameter" || parsed.kind === "max_tokens_rename" || parsed.kind === "temperature_thinking") return "unsupported_parameter";
|
|
16660
|
+
return "model_request_invalid";
|
|
16661
|
+
}
|
|
16662
|
+
function toModelRequestError(err, parsed, provider, model) {
|
|
16663
|
+
return new ModelRequestError({
|
|
16664
|
+
status: err.statusCode ?? 400,
|
|
16665
|
+
code: codeFor(parsed),
|
|
16666
|
+
param: parsed?.param,
|
|
16667
|
+
value: parsed?.value,
|
|
16668
|
+
supportedValues: parsed?.supportedValues,
|
|
16669
|
+
provider: err.provider || provider,
|
|
16670
|
+
model,
|
|
16671
|
+
message: err.message,
|
|
16672
|
+
responseBody: err.responseBody
|
|
16673
|
+
});
|
|
16674
|
+
}
|
|
16675
|
+
var SameRequest = class extends Error {
|
|
16676
|
+
};
|
|
16677
|
+
function withoutCallerParams(step, callerParams) {
|
|
16678
|
+
const drops = step.patch.dropParams;
|
|
16679
|
+
if (!callerParams?.length || !drops) return step;
|
|
16680
|
+
const mine = (p) => callerParams.includes(p.split(".")[0]);
|
|
16681
|
+
if (!drops.some(mine)) return step;
|
|
16682
|
+
const { dropParams: _ignored, ...rest } = step.patch;
|
|
16683
|
+
const kept = drops.filter((p) => !mine(p));
|
|
16684
|
+
const patch = kept.length ? { ...rest, dropParams: kept } : rest;
|
|
16685
|
+
return Object.keys(patch).length ? { ...step, patch } : void 0;
|
|
16686
|
+
}
|
|
16687
|
+
async function runWithModelAdjustments(opts) {
|
|
16688
|
+
let overlay = {};
|
|
16689
|
+
const steps = [];
|
|
16690
|
+
let previous;
|
|
16691
|
+
let lastError;
|
|
16692
|
+
let lastParsed;
|
|
16693
|
+
for (; ; ) {
|
|
16694
|
+
const guard = (body) => {
|
|
16695
|
+
let json;
|
|
16696
|
+
try {
|
|
16697
|
+
json = JSON.stringify(body);
|
|
16698
|
+
} catch {
|
|
16699
|
+
return;
|
|
16700
|
+
}
|
|
16701
|
+
if (previous !== void 0 && json === previous) throw new SameRequest();
|
|
16702
|
+
previous = json;
|
|
16703
|
+
};
|
|
16704
|
+
try {
|
|
16705
|
+
const result = await opts.run(overlay, guard);
|
|
16706
|
+
for (const step of steps) {
|
|
16707
|
+
const s = withoutCallerParams(step, opts.callerParams);
|
|
16708
|
+
if (!s) continue;
|
|
16709
|
+
rememberModelRulePatch(opts.provider, opts.model, s.patch, opts.scope);
|
|
16710
|
+
if (opts.onLearned) {
|
|
16711
|
+
try {
|
|
16712
|
+
opts.onLearned({ provider: opts.provider, model: opts.model, adjustment: s.adjustment, patch: s.patch, reason: s.reason });
|
|
16713
|
+
} catch {
|
|
16714
|
+
}
|
|
16715
|
+
}
|
|
16716
|
+
}
|
|
16717
|
+
return result;
|
|
16718
|
+
} catch (err) {
|
|
16719
|
+
if (err instanceof SameRequest) throw toModelRequestError(lastError, lastParsed, opts.provider, opts.model);
|
|
16720
|
+
if (!(err instanceof ProviderError) || err instanceof ModelRequestError || err.statusCode !== 400) throw err;
|
|
16721
|
+
const parsed = parseModelError(String(err.responseBody ?? err.message));
|
|
16722
|
+
const fix = parsed ? patchFromParsedError(parsed, opts.endpoint) : void 0;
|
|
16723
|
+
lastError = err;
|
|
16724
|
+
lastParsed = parsed;
|
|
16725
|
+
if (!fix || steps.length >= MAX_ADJUSTMENTS) throw toModelRequestError(err, parsed, opts.provider, opts.model);
|
|
16726
|
+
overlay = mergeRulePatch(overlay, fix.patch);
|
|
16727
|
+
steps.push({ ...fix, reason: parsed.message });
|
|
16728
|
+
}
|
|
16729
|
+
}
|
|
16730
|
+
}
|
|
16731
|
+
function asModelRequestError(err, provider, model) {
|
|
16732
|
+
if (!(err instanceof ProviderError) || err instanceof ModelRequestError || err.statusCode !== 400) return err;
|
|
16733
|
+
return toModelRequestError(err, parseModelError(String(err.responseBody ?? err.message)), provider, model);
|
|
16734
|
+
}
|
|
16735
|
+
|
|
15467
16736
|
// src/providers/utils/media.ts
|
|
15468
16737
|
var EXTENSION_MIME = {
|
|
15469
16738
|
jpg: "image/jpeg",
|
|
@@ -15764,8 +17033,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15764
17033
|
if (this.useResponsesApi(request)) {
|
|
15765
17034
|
return this.completeResponses(request);
|
|
15766
17035
|
}
|
|
15767
|
-
const
|
|
15768
|
-
const res = await this.doFetch(body, request.signal);
|
|
17036
|
+
const res = await this.fetchChat(request, false);
|
|
15769
17037
|
const json = await res.json();
|
|
15770
17038
|
return this.parseResponse(json);
|
|
15771
17039
|
}
|
|
@@ -15789,8 +17057,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15789
17057
|
};
|
|
15790
17058
|
return;
|
|
15791
17059
|
}
|
|
15792
|
-
const
|
|
15793
|
-
const res = await this.doFetch(body, request.signal);
|
|
17060
|
+
const res = await this.fetchChat(request, true);
|
|
15794
17061
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15795
17062
|
let id = "";
|
|
15796
17063
|
let model = "";
|
|
@@ -15894,7 +17161,43 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15894
17161
|
return res;
|
|
15895
17162
|
}
|
|
15896
17163
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
15897
|
-
|
|
17164
|
+
/** Chat Completions call that corrects itself from the provider's own 400s (see models/adjust.ts). */
|
|
17165
|
+
fetchChat(request, stream) {
|
|
17166
|
+
const model = request.model || this.defaultModel;
|
|
17167
|
+
return runWithModelAdjustments({
|
|
17168
|
+
provider: this.providerName,
|
|
17169
|
+
model,
|
|
17170
|
+
endpoint: "chat",
|
|
17171
|
+
scope: this.baseURL,
|
|
17172
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
17173
|
+
onLearned: this.onModelRuleLearned,
|
|
17174
|
+
run: (overlay, guard) => {
|
|
17175
|
+
const body = this.buildRequestBody(request, stream, overlay);
|
|
17176
|
+
guard(body);
|
|
17177
|
+
return this.doFetch(body, request.signal);
|
|
17178
|
+
}
|
|
17179
|
+
});
|
|
17180
|
+
}
|
|
17181
|
+
/** Same for the Responses API. */
|
|
17182
|
+
fetchResponses(request, adaptExtras, stream = false) {
|
|
17183
|
+
const model = request.model || this.defaultModel;
|
|
17184
|
+
return runWithModelAdjustments({
|
|
17185
|
+
provider: this.providerName,
|
|
17186
|
+
model,
|
|
17187
|
+
endpoint: "responses",
|
|
17188
|
+
scope: this.baseURL,
|
|
17189
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
17190
|
+
onLearned: this.onModelRuleLearned,
|
|
17191
|
+
run: (overlay, guard) => {
|
|
17192
|
+
const body = this.buildResponsesBody(request, overlay);
|
|
17193
|
+
if (adaptExtras) adaptChatExtrasForResponses(body, request.extra);
|
|
17194
|
+
if (stream) body.stream = true;
|
|
17195
|
+
guard(body);
|
|
17196
|
+
return this.responsesFetch(body, request.signal);
|
|
17197
|
+
}
|
|
17198
|
+
});
|
|
17199
|
+
}
|
|
17200
|
+
buildRequestBody(request, stream, overlay) {
|
|
15898
17201
|
const body = {
|
|
15899
17202
|
model: request.model || this.defaultModel,
|
|
15900
17203
|
messages: request.messages.map((m) => this.toOpenAIMessage(m)),
|
|
@@ -15904,20 +17207,20 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15904
17207
|
body.stream_options = { include_usage: true };
|
|
15905
17208
|
}
|
|
15906
17209
|
const modelId = String(body.model);
|
|
15907
|
-
const
|
|
15908
|
-
if (request.temperature != null &&
|
|
17210
|
+
const rule = resolveModelRule({ provider: this.providerName, model: modelId, patch: overlay, scope: this.baseURL });
|
|
17211
|
+
if (request.temperature != null && allowsSampling(rule, "temperature", request.temperature)) body.temperature = request.temperature;
|
|
15909
17212
|
if (request.maxTokens != null) {
|
|
15910
|
-
const
|
|
15911
|
-
body[
|
|
17213
|
+
const param = this.maxTokensParam === "auto" ? rule.maxTokensParam : this.maxTokensParam;
|
|
17214
|
+
body[param] = request.maxTokens;
|
|
15912
17215
|
}
|
|
15913
|
-
if (request.topP != null &&
|
|
17216
|
+
if (request.topP != null && allowsSampling(rule, "topP")) body.top_p = request.topP;
|
|
15914
17217
|
if (request.stop) body.stop = request.stop;
|
|
15915
|
-
if (request.presencePenalty != null) body.presence_penalty = request.presencePenalty;
|
|
15916
|
-
if (request.frequencyPenalty != null) body.frequency_penalty = request.frequencyPenalty;
|
|
17218
|
+
if (request.presencePenalty != null && allowsSampling(rule, "presencePenalty")) body.presence_penalty = request.presencePenalty;
|
|
17219
|
+
if (request.frequencyPenalty != null && allowsSampling(rule, "frequencyPenalty")) body.frequency_penalty = request.frequencyPenalty;
|
|
15917
17220
|
if (request.seed != null) body.seed = request.seed;
|
|
15918
17221
|
if (request.n != null) body.n = request.n;
|
|
15919
|
-
if (request.logprobs != null) body.logprobs = request.logprobs;
|
|
15920
|
-
if (request.topLogprobs != null) body.top_logprobs = request.topLogprobs;
|
|
17222
|
+
if (request.logprobs != null && allowsSampling(rule, "logprobs")) body.logprobs = request.logprobs;
|
|
17223
|
+
if (request.topLogprobs != null && allowsSampling(rule, "logprobs")) body.top_logprobs = request.topLogprobs;
|
|
15921
17224
|
if (request.tools?.length) {
|
|
15922
17225
|
body.tools = request.tools.map((t) => this.toOpenAITool(t));
|
|
15923
17226
|
if (request.parallelToolCalls != null) body.parallel_tool_calls = request.parallelToolCalls;
|
|
@@ -15946,14 +17249,17 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15946
17249
|
if (request.extra) {
|
|
15947
17250
|
Object.assign(body, request.extra);
|
|
15948
17251
|
}
|
|
15949
|
-
applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
|
|
17252
|
+
applyOpenAIReasoning(body, request.reasoning, "legacy_effort", modelId, rule);
|
|
17253
|
+
if (body.tools?.length && rule.chatTools.reasoning === "force-none" && rule.reasoning.style !== "none") {
|
|
17254
|
+
body.reasoning_effort = "none";
|
|
17255
|
+
}
|
|
17256
|
+
applyDropParams(body, rule);
|
|
15950
17257
|
return body;
|
|
15951
17258
|
}
|
|
15952
17259
|
// ─── Responses API (reasoning models) ──────────────────────────────────────
|
|
15953
17260
|
async completeResponses(request) {
|
|
15954
|
-
const
|
|
15955
|
-
|
|
15956
|
-
const res = await this.responsesFetch(body, request.signal);
|
|
17261
|
+
const adapt = this.apiResponsesNative || this.isResponsesApiModel(request);
|
|
17262
|
+
const res = await this.fetchResponses(request, adapt);
|
|
15957
17263
|
const json = await res.json();
|
|
15958
17264
|
return this.parseResponsesResponse(json, request.model || this.defaultModel);
|
|
15959
17265
|
}
|
|
@@ -15966,10 +17272,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15966
17272
|
* reads it). */
|
|
15967
17273
|
async *streamResponses(request) {
|
|
15968
17274
|
const modelId = request.model || this.defaultModel;
|
|
15969
|
-
const
|
|
15970
|
-
adaptChatExtrasForResponses(body, request.extra);
|
|
15971
|
-
body.stream = true;
|
|
15972
|
-
const res = await this.responsesFetch(body, request.signal);
|
|
17275
|
+
const res = await this.fetchResponses(request, true, true);
|
|
15973
17276
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15974
17277
|
let id = "";
|
|
15975
17278
|
let model = modelId;
|
|
@@ -16058,13 +17361,14 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
16058
17361
|
finishReason: final?.finishReason ?? (calls.size > 0 ? "tool_calls" : "stop")
|
|
16059
17362
|
};
|
|
16060
17363
|
}
|
|
16061
|
-
buildResponsesBody(request) {
|
|
17364
|
+
buildResponsesBody(request, overlay) {
|
|
16062
17365
|
const body = {
|
|
16063
17366
|
model: request.model || this.defaultModel,
|
|
16064
17367
|
input: request.messages.map((m) => this.toResponsesInput(m))
|
|
16065
17368
|
};
|
|
16066
17369
|
if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
|
|
16067
|
-
|
|
17370
|
+
const rule = resolveModelRule({ provider: this.providerName, model: String(body.model), patch: overlay, scope: this.baseURL });
|
|
17371
|
+
if (request.topP != null && allowsSampling(rule, "topP")) body.top_p = request.topP;
|
|
16068
17372
|
if (request.tools?.length) {
|
|
16069
17373
|
body.tools = request.tools.map((t) => ({
|
|
16070
17374
|
type: "function",
|
|
@@ -16096,7 +17400,8 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
16096
17400
|
}
|
|
16097
17401
|
}
|
|
16098
17402
|
if (request.extra) Object.assign(body, request.extra);
|
|
16099
|
-
applyOpenAIReasoning(body, request.reasoning, "responses");
|
|
17403
|
+
applyOpenAIReasoning(body, request.reasoning, "responses", String(body.model), rule);
|
|
17404
|
+
applyDropParams(body, rule);
|
|
16100
17405
|
return body;
|
|
16101
17406
|
}
|
|
16102
17407
|
/** Maps a unified message to a Responses API `input` item. */
|
|
@@ -16361,8 +17666,8 @@ function pickProviderFields(top, message, choice) {
|
|
|
16361
17666
|
}
|
|
16362
17667
|
function isReasoningModel(model) {
|
|
16363
17668
|
if (!model) return false;
|
|
16364
|
-
const
|
|
16365
|
-
return
|
|
17669
|
+
const rule = resolveModelRule({ provider: "openai", model });
|
|
17670
|
+
return !rule.isDefault && rule.reasoning.style === "effort" && rule.sampling.temperature !== "any";
|
|
16366
17671
|
}
|
|
16367
17672
|
function adaptChatExtrasForResponses(body, extra) {
|
|
16368
17673
|
const native = extra ?? {};
|
|
@@ -16478,12 +17783,6 @@ function normalizeExplicitThinking(body) {
|
|
|
16478
17783
|
}
|
|
16479
17784
|
for (const k of ["temperature", "top_p", "top_k"]) delete body[k];
|
|
16480
17785
|
}
|
|
16481
|
-
function thinkingFormRejected(text) {
|
|
16482
|
-
const t = text.toLowerCase();
|
|
16483
|
-
if (t.indexOf("thinking.type.enabled") >= 0 && t.indexOf("not supported") >= 0) return "enabled";
|
|
16484
|
-
if (t.indexOf("thinking.type.adaptive") >= 0 && t.indexOf("not supported") >= 0 && t.indexOf("thinking.type.enabled") < 0) return "adaptive";
|
|
16485
|
-
return void 0;
|
|
16486
|
-
}
|
|
16487
17786
|
var AnthropicProvider = class extends BaseProvider {
|
|
16488
17787
|
constructor(config) {
|
|
16489
17788
|
super();
|
|
@@ -16634,7 +17933,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16634
17933
|
}
|
|
16635
17934
|
}
|
|
16636
17935
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
16637
|
-
buildRequestBody(request, stream,
|
|
17936
|
+
buildRequestBody(request, stream, overlay, downgradeToolChoice = false) {
|
|
16638
17937
|
const { system, messages } = this.splitSystemMessages(request.messages);
|
|
16639
17938
|
const body = {
|
|
16640
17939
|
model: request.model || this.defaultModel,
|
|
@@ -16649,6 +17948,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16649
17948
|
body.system = system;
|
|
16650
17949
|
}
|
|
16651
17950
|
}
|
|
17951
|
+
const rule = resolveModelRule({ provider: this.providerName, model: String(body.model), patch: overlay });
|
|
16652
17952
|
if (request.temperature != null) body.temperature = request.temperature;
|
|
16653
17953
|
if (request.topP != null) body.top_p = request.topP;
|
|
16654
17954
|
if (request.stop) body.stop_sequences = request.stop;
|
|
@@ -16675,9 +17975,11 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16675
17975
|
const explicitThinking = request.extra && typeof request.extra === "object" && "thinking" in request.extra;
|
|
16676
17976
|
if (explicitThinking) {
|
|
16677
17977
|
normalizeExplicitThinking(body);
|
|
17978
|
+
enforceAnthropicSampling(body, rule, body.thinking?.type === "enabled" || body.thinking?.type === "adaptive");
|
|
16678
17979
|
} else {
|
|
16679
|
-
applyAnthropicReasoning(body, request.reasoning, { model: body.model, mode:
|
|
17980
|
+
applyAnthropicReasoning(body, request.reasoning, { model: body.model, mode: this.thinkingMode, rule });
|
|
16680
17981
|
}
|
|
17982
|
+
applyDropParams(body, rule);
|
|
16681
17983
|
if (typeof body.max_tokens !== "number" || !(body.max_tokens > 0)) {
|
|
16682
17984
|
body.max_tokens = DEFAULT_MAX_TOKENS;
|
|
16683
17985
|
}
|
|
@@ -16813,31 +18115,28 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16813
18115
|
}
|
|
16814
18116
|
/** Builds and sends the request; retries once with the other thinking form
|
|
16815
18117
|
* when the upstream rejects the one we picked. */
|
|
16816
|
-
|
|
16817
|
-
let mode;
|
|
18118
|
+
send(request, stream) {
|
|
16818
18119
|
let downgrade = false;
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
18120
|
+
return runWithModelAdjustments({
|
|
18121
|
+
provider: this.providerName,
|
|
18122
|
+
model: request.model || this.defaultModel,
|
|
18123
|
+
endpoint: "messages",
|
|
18124
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
18125
|
+
onLearned: this.onModelRuleLearned,
|
|
18126
|
+
run: async (overlay, guard) => {
|
|
18127
|
+
for (; ; ) {
|
|
18128
|
+
const body = this.buildRequestBody(request, stream, overlay, downgrade);
|
|
18129
|
+
guard(body);
|
|
18130
|
+
try {
|
|
18131
|
+
return await this.doFetch(body, request.signal);
|
|
18132
|
+
} catch (err) {
|
|
18133
|
+
const rejected = err instanceof ProviderError && err.statusCode === 400 && !downgrade && body.tool_choice && body.tool_choice.type !== "auto" && forcedToolChoiceRejected(String(err.responseBody ?? err.message));
|
|
18134
|
+
if (!rejected) throw err;
|
|
18135
|
+
downgrade = true;
|
|
18136
|
+
}
|
|
16830
18137
|
}
|
|
16831
|
-
const explicit = request.extra && typeof request.extra === "object" && "thinking" in request.extra;
|
|
16832
|
-
if (flippedThinking || explicit || !request.reasoning) throw err;
|
|
16833
|
-
const wrong = thinkingFormRejected(text);
|
|
16834
|
-
if (!wrong) throw err;
|
|
16835
|
-
const used = resolveThinkingForm(request.model ?? this.defaultModel, this.thinkingMode);
|
|
16836
|
-
if (wrong === "enabled" && used !== "budget" || wrong === "adaptive" && used !== "adaptive") throw err;
|
|
16837
|
-
mode = wrong === "enabled" ? "adaptive" : "budget";
|
|
16838
|
-
flippedThinking = true;
|
|
16839
18138
|
}
|
|
16840
|
-
}
|
|
18139
|
+
});
|
|
16841
18140
|
}
|
|
16842
18141
|
async doFetch(body, signal) {
|
|
16843
18142
|
const url = `${this.baseURL}/v1/messages`;
|
|
@@ -16954,6 +18253,7 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
16954
18253
|
retry: config.retry,
|
|
16955
18254
|
fetch: config.fetch,
|
|
16956
18255
|
timeoutMs: config.timeoutMs,
|
|
18256
|
+
onModelRuleLearned: config.onModelRuleLearned,
|
|
16957
18257
|
maxTokensParam: config.maxTokensParam,
|
|
16958
18258
|
api: config.api,
|
|
16959
18259
|
responsesApi: config.responsesApi,
|
|
@@ -17082,6 +18382,7 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
|
17082
18382
|
retry: config.retry,
|
|
17083
18383
|
fetch: config.fetch,
|
|
17084
18384
|
timeoutMs: config.timeoutMs,
|
|
18385
|
+
onModelRuleLearned: config.onModelRuleLearned,
|
|
17085
18386
|
maxTokensParam: config.maxTokensParam,
|
|
17086
18387
|
api: config.api,
|
|
17087
18388
|
// Unlike OpenAI / Azure, "auto" on a compatible server means Chat
|
|
@@ -17437,7 +18738,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
17437
18738
|
return res;
|
|
17438
18739
|
}
|
|
17439
18740
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
17440
|
-
buildConverseBody(request, downgradeToolChoice = false) {
|
|
18741
|
+
buildConverseBody(request, downgradeToolChoice = false, overlay) {
|
|
17441
18742
|
const { system, messages } = this.splitSystemMessages(request.messages);
|
|
17442
18743
|
const body = {
|
|
17443
18744
|
messages: this.toBedrockMessages(messages)
|
|
@@ -17483,7 +18784,12 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
17483
18784
|
Object.assign(body, topLevel);
|
|
17484
18785
|
if (Object.keys(fields).length > 0) body.additionalModelRequestFields = fields;
|
|
17485
18786
|
}
|
|
17486
|
-
|
|
18787
|
+
const rule = resolveModelRule({ provider: this.providerName, model: request.model || this.defaultModel, patch: overlay });
|
|
18788
|
+
applyBedrockReasoning(body, request.reasoning, { model: request.model || this.defaultModel, mode: this.thinkingMode, rule });
|
|
18789
|
+
if (body.inferenceConfig && rule.dropParams?.length) {
|
|
18790
|
+
for (const p of rule.dropParams) delete body.inferenceConfig[p === "top_p" ? "topP" : p === "max_tokens" ? "maxTokens" : p];
|
|
18791
|
+
}
|
|
18792
|
+
applyDropParams(body, rule);
|
|
17487
18793
|
return body;
|
|
17488
18794
|
}
|
|
17489
18795
|
splitSystemMessages(messages) {
|
|
@@ -17608,16 +18914,29 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
17608
18914
|
}
|
|
17609
18915
|
/** Sends the Converse call; retries once with toolChoice auto when the
|
|
17610
18916
|
* model rejects forced tool use. */
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
|
|
17614
|
-
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
|
|
17619
|
-
|
|
17620
|
-
|
|
18917
|
+
converseFetch(modelId, request, stream) {
|
|
18918
|
+
let downgrade = false;
|
|
18919
|
+
return runWithModelAdjustments({
|
|
18920
|
+
provider: this.providerName,
|
|
18921
|
+
model: modelId,
|
|
18922
|
+
endpoint: "converse",
|
|
18923
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
18924
|
+
onLearned: this.onModelRuleLearned,
|
|
18925
|
+
run: async (overlay, guard) => {
|
|
18926
|
+
for (; ; ) {
|
|
18927
|
+
const body = this.buildConverseBody(request, downgrade, overlay);
|
|
18928
|
+
guard(body);
|
|
18929
|
+
try {
|
|
18930
|
+
return await this.doFetch(modelId, body, request.signal, stream);
|
|
18931
|
+
} catch (err) {
|
|
18932
|
+
const tc = body.toolConfig?.toolChoice;
|
|
18933
|
+
const rejected = err instanceof ProviderError && err.statusCode === 400 && !downgrade && !!tc && !tc.auto && forcedToolChoiceRejected(String(err.responseBody ?? err.message));
|
|
18934
|
+
if (!rejected) throw err;
|
|
18935
|
+
downgrade = true;
|
|
18936
|
+
}
|
|
18937
|
+
}
|
|
18938
|
+
}
|
|
18939
|
+
});
|
|
17621
18940
|
}
|
|
17622
18941
|
async doFetch(modelId, body, signal, stream) {
|
|
17623
18942
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
@@ -17807,7 +19126,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
17807
19126
|
const modelId = request.model || this.defaultModel;
|
|
17808
19127
|
const body = this.buildGeminiBody(request);
|
|
17809
19128
|
const url = this.buildUrl(modelId, false);
|
|
17810
|
-
const res = await this.doFetch(url, body, request.signal);
|
|
19129
|
+
const res = await this.doFetch(url, body, request.signal, modelId);
|
|
17811
19130
|
const json = await res.json();
|
|
17812
19131
|
return this.parseResponse(json, modelId);
|
|
17813
19132
|
}
|
|
@@ -17815,7 +19134,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
17815
19134
|
const modelId = request.model || this.defaultModel;
|
|
17816
19135
|
const body = this.buildGeminiBody(request);
|
|
17817
19136
|
const url = this.buildUrl(modelId, true);
|
|
17818
|
-
const res = await this.doFetch(url, body, request.signal);
|
|
19137
|
+
const res = await this.doFetch(url, body, request.signal, modelId);
|
|
17819
19138
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
17820
19139
|
const counter = { next: 0 };
|
|
17821
19140
|
const contentType = res.headers.get("content-type") ?? "";
|
|
@@ -17895,7 +19214,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
17895
19214
|
};
|
|
17896
19215
|
if (Object.keys(parameters).length > 0) body.parameters = parameters;
|
|
17897
19216
|
Object.assign(body, extraRest);
|
|
17898
|
-
const res = await this.doFetch(url, body, request.signal);
|
|
19217
|
+
const res = await this.doFetch(url, body, request.signal, model);
|
|
17899
19218
|
const json = await res.json();
|
|
17900
19219
|
raw.push(json);
|
|
17901
19220
|
for (const p of json.predictions ?? []) {
|
|
@@ -18118,7 +19437,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
18118
19437
|
const tokenJson = await tokenRes.json();
|
|
18119
19438
|
return tokenJson.access_token;
|
|
18120
19439
|
}
|
|
18121
|
-
async doFetch(url, body, signal) {
|
|
19440
|
+
async doFetch(url, body, signal, model = "") {
|
|
18122
19441
|
const token = await this.getAccessToken();
|
|
18123
19442
|
const bodyStr = JSON.stringify(body);
|
|
18124
19443
|
const res = await this.doFetchWithRetry(
|
|
@@ -18136,6 +19455,20 @@ var VertexProvider = class extends BaseProvider {
|
|
|
18136
19455
|
);
|
|
18137
19456
|
if (!res.ok) {
|
|
18138
19457
|
const text = await res.text().catch(() => "");
|
|
19458
|
+
if (res.status === 400) {
|
|
19459
|
+
const parsed = parseModelError(text);
|
|
19460
|
+
throw new ModelRequestError({
|
|
19461
|
+
status: 400,
|
|
19462
|
+
code: parsed?.kind === "unsupported_value" ? "unsupported_value" : parsed?.kind === "unsupported_parameter" ? "unsupported_parameter" : "model_request_invalid",
|
|
19463
|
+
param: parsed?.param,
|
|
19464
|
+
value: parsed?.value,
|
|
19465
|
+
supportedValues: parsed?.supportedValues,
|
|
19466
|
+
provider: this.providerName,
|
|
19467
|
+
model,
|
|
19468
|
+
message: `Vertex AI API error ${res.status}: ${text}`,
|
|
19469
|
+
responseBody: text
|
|
19470
|
+
});
|
|
19471
|
+
}
|
|
18139
19472
|
throw new ProviderError(
|
|
18140
19473
|
`Vertex AI API error ${res.status}: ${text}`,
|
|
18141
19474
|
this.providerName,
|
|
@@ -18294,6 +19627,6 @@ function createProvider(config) {
|
|
|
18294
19627
|
}
|
|
18295
19628
|
}
|
|
18296
19629
|
|
|
18297
|
-
export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, JevProvider, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, appendBoundTools, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentPartToText, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, describeContentPart, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, emptyUsage, evaluateGuardrails, extractLatestUserQuery, extractMessageText, fileCheckpointStore, fileSink, findSubagent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasMediaPart, hasToolResponseRecoveryReference, httpGuardrail, httpSink, inMemoryCheckpointStore, inMemoryConversationStore, isHookImplemented, isOpenAIHostedEndpoint, isSmartModel, isValidIban, isValidLuhn, isValidTckn, jsonSchemaRule, defaultBuildPayload as langfuseDefaultPayload, langfuseTracing, languageGuard, loadSkillsFromDisk, mapConsoleHookVerdict, mapTextParts, mcp, mediaKindOf, mediaPolicy, normalizeSmartAgentOptions, normalizeVerdicts, openAIModeration, otelTracing, otlpSink, outputGuard, parseApprovalDecision, parseSkillFrontmatter, pathSandbox, piiRedaction, pluginCapabilities, portkeyGateway, portkeyGuardrail, preopenSkills, preopenToolCallId, prepareStrictToolMenu, promptInjectionGuard, rateLimit, readMemoryFacts, redactText, regexGuardrail, regexRule, replaceTextContent, resolveAvailableSkills, resolveAvailableSubagents, resolveInputRetention, resolveMemoryStore, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveSummarizationRetention, resolveToolApprovalState, resolveUserQuestionState, responseCache, restoreSnapshot, restoreToolCalls, runSmartAgentEvalHarness, scoreItemsByRelevance, searchSkills, seedChildMessages, selectTopIndicesInOrder, sessionMetrics, setTokenCounter, startStreamingSession, summarizeObject, supportsAdaptiveThinking, textFromContent, toMessageUsage, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceSessionToOtlp, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
|
|
19630
|
+
export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, JevProvider, MAX_ADJUSTMENTS, MODEL_RULES, ModelRequestError, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, allowsSampling, appendBoundTools, applyDropParams, asModelRequestError, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, clearLearnedModelRules, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentPartToText, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, describeContentPart, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, effortBudget, emptyUsage, evaluateGuardrails, extractLatestUserQuery, extractMessageText, fileCheckpointStore, fileSink, findSubagent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getLearnedModelRulePatch, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasMediaPart, hasToolResponseRecoveryReference, httpGuardrail, httpSink, inMemoryCheckpointStore, inMemoryConversationStore, isHookImplemented, isOpenAIHostedEndpoint, isSmartModel, isValidIban, isValidLuhn, isValidTckn, jsonSchemaRule, defaultBuildPayload as langfuseDefaultPayload, langfuseTracing, languageGuard, listLearnedModelRules, loadSkillsFromDisk, mapConsoleHookVerdict, mapReasoningEffort, mapTextParts, mcp, mediaKindOf, mediaPolicy, mergeRulePatch, modelIdCandidates, normalizeSmartAgentOptions, normalizeVerdicts, openAIModeration, otelTracing, otlpSink, outputGuard, parseApprovalDecision, parseModelError, parseSkillFrontmatter, pathSandbox, piiRedaction, pluginCapabilities, portkeyGateway, portkeyGuardrail, preopenSkills, preopenToolCallId, prepareStrictToolMenu, promptInjectionGuard, rateLimit, readMemoryFacts, readTraceContinuation, redactText, regexGuardrail, regexRule, rememberModelRulePatch, replaceTextContent, resolveAvailableSkills, resolveAvailableSubagents, resolveInputRetention, resolveMemoryStore, resolveModelRule, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveSummarizationRetention, resolveToolApprovalState, resolveUserQuestionState, responseCache, restoreSnapshot, restoreToolCalls, runSmartAgentEvalHarness, runWithModelAdjustments, scoreItemsByRelevance, searchSkills, seedChildMessages, selectTopIndicesInOrder, sessionMetrics, setTokenCounter, startStreamingSession, summarizeObject, supportsAdaptiveThinking, textFromContent, toMessageUsage, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceContinuationOf, traceSessionToOtlp, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
|
|
18298
19631
|
//# sourceMappingURL=index.mjs.map
|
|
18299
19632
|
//# sourceMappingURL=index.mjs.map
|