@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.cjs
CHANGED
|
@@ -2026,27 +2026,71 @@ function convertMessageListToSections(messageList) {
|
|
|
2026
2026
|
}
|
|
2027
2027
|
return sections.length > 0 ? sections : void 0;
|
|
2028
2028
|
}
|
|
2029
|
-
function
|
|
2029
|
+
function readTraceContinuation(value) {
|
|
2030
|
+
if (!value || typeof value !== "object") return void 0;
|
|
2031
|
+
const raw = value;
|
|
2032
|
+
if (raw.v !== 1 || typeof raw.sessionId !== "string" || raw.sessionId.length === 0) return void 0;
|
|
2033
|
+
const nextSequence = Number(raw.nextSequence);
|
|
2034
|
+
const startedAt = Number(raw.startedAt);
|
|
2035
|
+
const part = Number(raw.part);
|
|
2036
|
+
if (!Number.isInteger(nextSequence) || nextSequence < 1) return void 0;
|
|
2037
|
+
if (!Number.isFinite(startedAt) || !Number.isInteger(part) || part < 1) return void 0;
|
|
2038
|
+
const summary = raw.summary && typeof raw.summary === "object" ? { ...createEmptySummary(), ...raw.summary } : createEmptySummary();
|
|
2039
|
+
summary.eventCounts = { ...raw.summary?.eventCounts ?? {} };
|
|
2040
|
+
return {
|
|
2041
|
+
v: 1,
|
|
2042
|
+
sessionId: raw.sessionId,
|
|
2043
|
+
traceId: typeof raw.traceId === "string" ? raw.traceId : void 0,
|
|
2044
|
+
rootSpanId: typeof raw.rootSpanId === "string" ? raw.rootSpanId : void 0,
|
|
2045
|
+
threadId: typeof raw.threadId === "string" ? raw.threadId : void 0,
|
|
2046
|
+
startedAt,
|
|
2047
|
+
nextSequence,
|
|
2048
|
+
part,
|
|
2049
|
+
summary,
|
|
2050
|
+
errors: Array.isArray(raw.errors) ? raw.errors : []
|
|
2051
|
+
};
|
|
2052
|
+
}
|
|
2053
|
+
function traceContinuationOf(session) {
|
|
2054
|
+
return {
|
|
2055
|
+
v: 1,
|
|
2056
|
+
sessionId: session.sessionId,
|
|
2057
|
+
traceId: session.traceId,
|
|
2058
|
+
rootSpanId: session.rootSpanId,
|
|
2059
|
+
threadId: session.threadId,
|
|
2060
|
+
startedAt: session.startedAt,
|
|
2061
|
+
nextSequence: (session.sequenceOffset ?? 0) + session.events.length + 1,
|
|
2062
|
+
part: session.part ?? 1,
|
|
2063
|
+
summary: JSON.parse(JSON.stringify(session.summary)),
|
|
2064
|
+
// Sink failures belong to the part that hit them; carrying them on would
|
|
2065
|
+
// mark every later part `partial`.
|
|
2066
|
+
errors: session.errors.filter((error) => error.type !== "sink")
|
|
2067
|
+
};
|
|
2068
|
+
}
|
|
2069
|
+
function createTraceSession(opts, continuation) {
|
|
2030
2070
|
const cfg = withDefaults(opts.tracing);
|
|
2031
2071
|
if (!cfg.enabled) return void 0;
|
|
2032
2072
|
const providedSessionId = opts.tracing?.sessionId?.trim();
|
|
2033
|
-
const sessionId = providedSessionId || generateSessionId();
|
|
2034
|
-
const traceId = generateTraceId();
|
|
2035
|
-
const rootSpanId = generateSpanId();
|
|
2073
|
+
const sessionId = continuation?.sessionId || providedSessionId || generateSessionId();
|
|
2074
|
+
const traceId = continuation?.traceId || generateTraceId();
|
|
2075
|
+
const rootSpanId = continuation?.rootSpanId || generateSpanId();
|
|
2036
2076
|
const runtime = {
|
|
2037
2077
|
sessionId,
|
|
2038
2078
|
traceId,
|
|
2039
2079
|
rootSpanId,
|
|
2040
|
-
threadId: opts.tracing?.threadId,
|
|
2080
|
+
threadId: continuation?.threadId ?? opts.tracing?.threadId,
|
|
2041
2081
|
configAgentName: opts.tracing?.agentName?.trim() || void 0,
|
|
2042
2082
|
configMetadata: opts.tracing?.metadata && Object.keys(opts.tracing.metadata).length > 0 ? opts.tracing.metadata : void 0,
|
|
2043
|
-
startedAt: Date.now(),
|
|
2083
|
+
startedAt: continuation?.startedAt ?? Date.now(),
|
|
2044
2084
|
resolvedConfig: cfg,
|
|
2045
2085
|
events: [],
|
|
2046
|
-
summary: createEmptySummary(),
|
|
2086
|
+
summary: continuation ? continuation.summary : createEmptySummary(),
|
|
2047
2087
|
status: "in_progress",
|
|
2048
|
-
errors: [],
|
|
2049
|
-
|
|
2088
|
+
errors: continuation ? [...continuation.errors] : [],
|
|
2089
|
+
// A continued session was announced by its first part; announcing it
|
|
2090
|
+
// again would reset a streaming receiver's copy.
|
|
2091
|
+
sessionStarted: Boolean(continuation),
|
|
2092
|
+
sequenceOffset: continuation ? continuation.nextSequence - 1 : 0,
|
|
2093
|
+
part: continuation ? continuation.part + 1 : 1
|
|
2050
2094
|
};
|
|
2051
2095
|
if (cfg.sink.type === "file") {
|
|
2052
2096
|
const baseDir = cfg.sink.baseDir;
|
|
@@ -2106,7 +2150,7 @@ async function startStreamingSession(session, agentRuntime) {
|
|
|
2106
2150
|
}
|
|
2107
2151
|
function recordTraceEvent(session, event) {
|
|
2108
2152
|
if (!session) return void 0;
|
|
2109
|
-
const sequence = session.events.length + 1;
|
|
2153
|
+
const sequence = (session.sequenceOffset ?? 0) + session.events.length + 1;
|
|
2110
2154
|
const id = generateEventId(sequence);
|
|
2111
2155
|
const timestampIso = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
2112
2156
|
const status = event.status ?? "success";
|
|
@@ -2296,7 +2340,8 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
2296
2340
|
summary: session.summary,
|
|
2297
2341
|
events: session.events,
|
|
2298
2342
|
status: status2,
|
|
2299
|
-
errors: session.errors
|
|
2343
|
+
errors: session.errors,
|
|
2344
|
+
...(session.part ?? 1) > 1 ? { continuation: { part: session.part, firstSequence: (session.sequenceOffset ?? 0) + 1 } } : {}
|
|
2300
2345
|
});
|
|
2301
2346
|
const payloadForSink = buildPayload(initialStatus);
|
|
2302
2347
|
let sinkFailed = false;
|
|
@@ -2353,7 +2398,17 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
2353
2398
|
if (sink.type === "file" && session.fileSessionDir) {
|
|
2354
2399
|
try {
|
|
2355
2400
|
const filePath = path__default.default.join(session.fileSessionDir, "trace.session.json");
|
|
2356
|
-
|
|
2401
|
+
let filePayload = finalPayload;
|
|
2402
|
+
if (finalPayload.continuation) {
|
|
2403
|
+
try {
|
|
2404
|
+
const previous = JSON.parse(await fs__default.default.promises.readFile(filePath, "utf8"));
|
|
2405
|
+
const earlier = (previous.events ?? []).filter((event) => event.sequence < finalPayload.continuation.firstSequence);
|
|
2406
|
+
filePayload = { ...finalPayload, events: [...earlier, ...finalPayload.events] };
|
|
2407
|
+
delete filePayload.continuation;
|
|
2408
|
+
} catch {
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
await fs__default.default.promises.writeFile(filePath, JSON.stringify(filePayload, null, 2), "utf8");
|
|
2357
2412
|
} catch (err) {
|
|
2358
2413
|
sinkFailed = true;
|
|
2359
2414
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -4792,6 +4847,207 @@ ${append}`;
|
|
|
4792
4847
|
};
|
|
4793
4848
|
}
|
|
4794
4849
|
|
|
4850
|
+
// src/utils/traceDecisions.ts
|
|
4851
|
+
var TRACED_KEY = "__outcomeTraced";
|
|
4852
|
+
function waitedMs(from, to) {
|
|
4853
|
+
if (!from || !to) return void 0;
|
|
4854
|
+
const ms = Date.parse(to) - Date.parse(from);
|
|
4855
|
+
return Number.isFinite(ms) && ms >= 0 ? ms : void 0;
|
|
4856
|
+
}
|
|
4857
|
+
function sameJson(a, b) {
|
|
4858
|
+
try {
|
|
4859
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
4860
|
+
} catch {
|
|
4861
|
+
return false;
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4864
|
+
function recordApprovalRequested(session, entry) {
|
|
4865
|
+
if (!session) return;
|
|
4866
|
+
const logData = session.resolvedConfig.logData;
|
|
4867
|
+
const sections = [
|
|
4868
|
+
{
|
|
4869
|
+
kind: "metadata",
|
|
4870
|
+
label: "Approval",
|
|
4871
|
+
data: {
|
|
4872
|
+
approvalId: entry.id,
|
|
4873
|
+
toolCallId: entry.toolCallId,
|
|
4874
|
+
status: "pending",
|
|
4875
|
+
requestedAt: entry.requestedAt,
|
|
4876
|
+
...entry.metadata?.prompt !== void 0 ? { prompt: entry.metadata.prompt } : {}
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4879
|
+
];
|
|
4880
|
+
if (logData) {
|
|
4881
|
+
sections.push({ kind: "tool_call", label: "Arguments to approve", tool: entry.toolName, arguments: sanitizeTracePayload(entry.args) });
|
|
4882
|
+
}
|
|
4883
|
+
recordTraceEvent(session, {
|
|
4884
|
+
type: "tool_approval",
|
|
4885
|
+
label: `Approval requested \xB7 ${entry.toolName}`,
|
|
4886
|
+
timestamp: entry.requestedAt,
|
|
4887
|
+
status: "pending",
|
|
4888
|
+
actor: { scope: "agent", name: entry.toolName, role: "approval_request" },
|
|
4889
|
+
sections
|
|
4890
|
+
});
|
|
4891
|
+
}
|
|
4892
|
+
function recordHumanDecisions(session, state) {
|
|
4893
|
+
if (!session) return;
|
|
4894
|
+
const logData = session.resolvedConfig.logData;
|
|
4895
|
+
for (const entry of state.pendingApprovals ?? []) {
|
|
4896
|
+
if (!entry.decidedAt || entry.metadata?.[TRACED_KEY]) continue;
|
|
4897
|
+
if (entry.status !== "approved" && entry.status !== "rejected") continue;
|
|
4898
|
+
const approved = entry.status === "approved";
|
|
4899
|
+
const edited = approved && entry.approvedArgs !== void 0 && !sameJson(entry.approvedArgs, entry.args);
|
|
4900
|
+
const sections = [
|
|
4901
|
+
{
|
|
4902
|
+
kind: "metadata",
|
|
4903
|
+
label: "Decision",
|
|
4904
|
+
data: {
|
|
4905
|
+
approvalId: entry.id,
|
|
4906
|
+
toolCallId: entry.toolCallId,
|
|
4907
|
+
decision: entry.status,
|
|
4908
|
+
...entry.decidedBy ? { decidedBy: entry.decidedBy } : {},
|
|
4909
|
+
...entry.comment ? { comment: entry.comment } : {},
|
|
4910
|
+
requestedAt: entry.requestedAt,
|
|
4911
|
+
decidedAt: entry.decidedAt,
|
|
4912
|
+
...waitedMs(entry.requestedAt, entry.decidedAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.decidedAt) } : {},
|
|
4913
|
+
...edited ? { argumentsEdited: true } : {}
|
|
4914
|
+
}
|
|
4915
|
+
}
|
|
4916
|
+
];
|
|
4917
|
+
if (logData) {
|
|
4918
|
+
sections.push({ kind: "tool_call", label: "Requested arguments", tool: entry.toolName, arguments: sanitizeTracePayload(entry.args) });
|
|
4919
|
+
if (edited) {
|
|
4920
|
+
sections.push({ kind: "tool_call", label: "Approved arguments", tool: entry.toolName, arguments: sanitizeTracePayload(entry.approvedArgs) });
|
|
4921
|
+
}
|
|
4922
|
+
}
|
|
4923
|
+
recordTraceEvent(session, {
|
|
4924
|
+
type: "tool_approval",
|
|
4925
|
+
label: `${approved ? "Approved" : "Rejected"} \xB7 ${entry.toolName}`,
|
|
4926
|
+
timestamp: entry.decidedAt,
|
|
4927
|
+
durationMs: waitedMs(entry.requestedAt, entry.decidedAt),
|
|
4928
|
+
status: "success",
|
|
4929
|
+
actor: { scope: "human", name: entry.decidedBy || "reviewer", role: "approver" },
|
|
4930
|
+
sections
|
|
4931
|
+
});
|
|
4932
|
+
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
4933
|
+
}
|
|
4934
|
+
for (const entry of state.pendingUserQuestions ?? []) {
|
|
4935
|
+
if (!entry.answeredAt || entry.metadata?.[TRACED_KEY]) continue;
|
|
4936
|
+
if (entry.status !== "answered" && entry.status !== "cancelled") continue;
|
|
4937
|
+
const clientTool = readClientTool(entry);
|
|
4938
|
+
if (clientTool) {
|
|
4939
|
+
recordClientToolResult(session, entry, clientTool, state.toolHistory);
|
|
4940
|
+
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
4941
|
+
continue;
|
|
4942
|
+
}
|
|
4943
|
+
const cancelled = entry.status === "cancelled";
|
|
4944
|
+
const data = {
|
|
4945
|
+
questionId: entry.id,
|
|
4946
|
+
toolCallId: entry.toolCallId,
|
|
4947
|
+
status: entry.status,
|
|
4948
|
+
...entry.answeredBy ? { answeredBy: entry.answeredBy } : {},
|
|
4949
|
+
...entry.notes ? { notes: entry.notes } : {},
|
|
4950
|
+
requestedAt: entry.requestedAt,
|
|
4951
|
+
answeredAt: entry.answeredAt,
|
|
4952
|
+
...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
|
|
4953
|
+
};
|
|
4954
|
+
const sections = [{ kind: "metadata", label: "Answer", data }];
|
|
4955
|
+
if (logData) {
|
|
4956
|
+
sections.push({
|
|
4957
|
+
kind: "metadata",
|
|
4958
|
+
label: "Questions and answers",
|
|
4959
|
+
data: {
|
|
4960
|
+
items: (entry.questions ?? []).map((item) => ({
|
|
4961
|
+
question: item.question,
|
|
4962
|
+
...item.header ? { header: item.header } : {},
|
|
4963
|
+
answer: sanitizeTracePayload(entry.answers?.[item.question] ?? (item.header ? entry.answers?.[item.header] : void 0) ?? null)
|
|
4964
|
+
}))
|
|
4965
|
+
}
|
|
4966
|
+
});
|
|
4967
|
+
}
|
|
4968
|
+
recordTraceEvent(session, {
|
|
4969
|
+
type: "user_question",
|
|
4970
|
+
label: cancelled ? "Question cancelled" : "Answer from user",
|
|
4971
|
+
timestamp: entry.answeredAt,
|
|
4972
|
+
durationMs: waitedMs(entry.requestedAt, entry.answeredAt),
|
|
4973
|
+
status: cancelled ? "skipped" : "success",
|
|
4974
|
+
actor: { scope: "human", name: entry.answeredBy || "user", role: "user" },
|
|
4975
|
+
sections
|
|
4976
|
+
});
|
|
4977
|
+
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
4978
|
+
}
|
|
4979
|
+
}
|
|
4980
|
+
function recordClientToolRequested(session, entry) {
|
|
4981
|
+
if (!session) return;
|
|
4982
|
+
const clientTool = readClientTool(entry);
|
|
4983
|
+
if (!clientTool) return;
|
|
4984
|
+
const sections = [
|
|
4985
|
+
{
|
|
4986
|
+
kind: "metadata",
|
|
4987
|
+
label: "Client tool",
|
|
4988
|
+
data: { questionId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt }
|
|
4989
|
+
}
|
|
4990
|
+
];
|
|
4991
|
+
if (session.resolvedConfig.logData) {
|
|
4992
|
+
sections.push({ kind: "tool_call", label: "Arguments", tool: clientTool.name, arguments: sanitizeTracePayload(clientTool.args) });
|
|
4993
|
+
}
|
|
4994
|
+
recordTraceEvent(session, {
|
|
4995
|
+
type: "tool_call",
|
|
4996
|
+
label: `Tool Execution - ${clientTool.name} (client)`,
|
|
4997
|
+
timestamp: entry.requestedAt,
|
|
4998
|
+
status: "pending",
|
|
4999
|
+
actor: { scope: "client", name: clientTool.name, role: "tool" },
|
|
5000
|
+
sections
|
|
5001
|
+
});
|
|
5002
|
+
}
|
|
5003
|
+
function readClientTool(entry) {
|
|
5004
|
+
const meta = entry.metadata?.clientTool;
|
|
5005
|
+
if (!meta || typeof meta !== "object" || typeof meta.name !== "string") return void 0;
|
|
5006
|
+
return { name: meta.name, args: meta.args };
|
|
5007
|
+
}
|
|
5008
|
+
function recordClientToolResult(session, entry, clientTool, toolHistory) {
|
|
5009
|
+
const step = [...toolHistory ?? []].reverse().find((item) => item?.tool_call_id === entry.toolCallId);
|
|
5010
|
+
const failed = step?.status === "error" || entry.status === "cancelled";
|
|
5011
|
+
const sections = [
|
|
5012
|
+
{
|
|
5013
|
+
kind: "metadata",
|
|
5014
|
+
label: "Client tool",
|
|
5015
|
+
data: {
|
|
5016
|
+
questionId: entry.id,
|
|
5017
|
+
toolCallId: entry.toolCallId,
|
|
5018
|
+
status: failed ? "error" : "answered",
|
|
5019
|
+
...entry.answeredBy ? { answeredBy: entry.answeredBy } : {},
|
|
5020
|
+
requestedAt: entry.requestedAt,
|
|
5021
|
+
answeredAt: entry.answeredAt,
|
|
5022
|
+
...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
];
|
|
5026
|
+
if (session.resolvedConfig.logData) {
|
|
5027
|
+
sections.push({ kind: "tool_call", label: "Arguments", tool: clientTool.name, arguments: sanitizeTracePayload(clientTool.args) });
|
|
5028
|
+
if (step) {
|
|
5029
|
+
const output = step.rawOutput ?? step.output;
|
|
5030
|
+
sections.push({
|
|
5031
|
+
kind: "tool_result",
|
|
5032
|
+
label: "Result from client",
|
|
5033
|
+
tool: clientTool.name,
|
|
5034
|
+
output: sanitizeTracePayload(output),
|
|
5035
|
+
summary: typeof step.output === "string" ? step.output.slice(0, 2e3) : void 0
|
|
5036
|
+
});
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
const ranMs = typeof step?.durationMs === "number" ? step.durationMs : void 0;
|
|
5040
|
+
recordTraceEvent(session, {
|
|
5041
|
+
type: "tool_call",
|
|
5042
|
+
label: `Tool Execution - ${clientTool.name} (client)`,
|
|
5043
|
+
timestamp: entry.answeredAt,
|
|
5044
|
+
durationMs: waitedMs(entry.requestedAt, entry.answeredAt) ?? ranMs,
|
|
5045
|
+
status: failed ? "error" : "success",
|
|
5046
|
+
actor: { scope: "client", name: clientTool.name, role: "tool" },
|
|
5047
|
+
sections
|
|
5048
|
+
});
|
|
5049
|
+
}
|
|
5050
|
+
|
|
4795
5051
|
// src/utils/traceSections.ts
|
|
4796
5052
|
init_content();
|
|
4797
5053
|
function truncate(text, max = 500) {
|
|
@@ -5105,10 +5361,10 @@ function createToolsNode(initialTools, opts) {
|
|
|
5105
5361
|
const toolCallId = tc.id || `${tc.name}_${toolCount + 1}`;
|
|
5106
5362
|
const validatedArgs = validateToolArgs(tool, args);
|
|
5107
5363
|
if (!validatedArgs.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
5108
|
-
const
|
|
5109
|
-
push({ role: "tool", content:
|
|
5110
|
-
markToolFailure(
|
|
5111
|
-
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message:
|
|
5364
|
+
const errorMessage2 = `Tool argument validation failed for ${tc.name}: ${validatedArgs.message}`;
|
|
5365
|
+
push({ role: "tool", content: errorMessage2, tool_call_id: toolCallId, name: tc.name });
|
|
5366
|
+
markToolFailure(errorMessage2, tc.name, toolCallId);
|
|
5367
|
+
onEvent?.({ type: "tool_call", phase: "error", name: tc.name, id: tc.id, args, error: { message: errorMessage2 } });
|
|
5112
5368
|
toolCount += 1;
|
|
5113
5369
|
return { status: "error" };
|
|
5114
5370
|
}
|
|
@@ -5260,6 +5516,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5260
5516
|
};
|
|
5261
5517
|
pendingApprovals.push(approvalEntry);
|
|
5262
5518
|
pendingByCallId.set(toolCallId, approvalEntry);
|
|
5519
|
+
recordApprovalRequested(traceSession, approvalEntry);
|
|
5263
5520
|
onEvent?.({ type: "tool_approval", status: "pending", id: approvalEntry.id, toolName: approvalEntry.toolName, toolCallId: approvalEntry.toolCallId, args });
|
|
5264
5521
|
if (host?.has("notification")) {
|
|
5265
5522
|
await host.runObservers("notification", {
|
|
@@ -5523,6 +5780,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5523
5780
|
if (!pendingApproval) {
|
|
5524
5781
|
throw new Error(`Tool ${toolName} requested approval but no pending approval entry was recorded.`);
|
|
5525
5782
|
}
|
|
5783
|
+
recordApprovalRequested(traceSession, pendingApproval);
|
|
5526
5784
|
awaitingApproval = true;
|
|
5527
5785
|
return {
|
|
5528
5786
|
status: "awaiting_approval",
|
|
@@ -5539,6 +5797,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5539
5797
|
if (!pendingQuestion) {
|
|
5540
5798
|
throw new Error(`Tool ${toolName} requested a user question but no pending question entry was recorded.`);
|
|
5541
5799
|
}
|
|
5800
|
+
recordClientToolRequested(traceSession, pendingQuestion);
|
|
5542
5801
|
awaitingUserQuestion = true;
|
|
5543
5802
|
if (host?.has("notification")) {
|
|
5544
5803
|
await host.runObservers("notification", {
|
|
@@ -6119,7 +6378,7 @@ var LEVEL_DEFAULTS = {
|
|
|
6119
6378
|
};
|
|
6120
6379
|
var VALID_LEVELS = ["minimal", "low", "medium", "high"];
|
|
6121
6380
|
var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
|
|
6122
|
-
var VALID_EFFORTS = ["none", "minimal", "low", "medium", "high"];
|
|
6381
|
+
var VALID_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
6123
6382
|
function validateReasoningConfig(input) {
|
|
6124
6383
|
if (!input) return;
|
|
6125
6384
|
if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
|
|
@@ -6635,16 +6894,20 @@ function createAskUserQuestionTool(stateRef, config) {
|
|
|
6635
6894
|
});
|
|
6636
6895
|
recordTraceEvent(ctx.__traceSession, {
|
|
6637
6896
|
type: "user_question",
|
|
6638
|
-
label: "
|
|
6897
|
+
label: "Question to user",
|
|
6898
|
+
timestamp: entry.requestedAt,
|
|
6639
6899
|
actor: { scope: "agent", name: "ask_user_question", role: "user_interaction" },
|
|
6640
|
-
status: "
|
|
6900
|
+
status: "pending",
|
|
6641
6901
|
sections: [
|
|
6642
6902
|
{
|
|
6643
6903
|
kind: "metadata",
|
|
6644
6904
|
label: "Pending Question",
|
|
6645
6905
|
data: {
|
|
6646
6906
|
id: entry.id,
|
|
6907
|
+
questionId: entry.id,
|
|
6647
6908
|
toolCallId: entry.toolCallId,
|
|
6909
|
+
status: "pending",
|
|
6910
|
+
requestedAt: entry.requestedAt,
|
|
6648
6911
|
questions: entry.questions,
|
|
6649
6912
|
allowFreeText
|
|
6650
6913
|
}
|
|
@@ -7863,15 +8126,17 @@ function createAgent(opts) {
|
|
|
7863
8126
|
}
|
|
7864
8127
|
const traceSession = state.ctx?.__traceSession;
|
|
7865
8128
|
if (traceSession) {
|
|
8129
|
+
const iterationNumber = (traceSession.summary.eventCounts.agent_iteration ?? 0) + 1;
|
|
7866
8130
|
const iterEvent = recordTraceEvent(traceSession, {
|
|
7867
8131
|
type: "agent_iteration",
|
|
7868
|
-
label: `Iteration ${
|
|
8132
|
+
label: `Iteration ${iterationNumber}`,
|
|
7869
8133
|
actor: { scope: "agent", name: opts.name || "agent", role: "orchestrator" },
|
|
7870
8134
|
parentSpanId: traceSession.rootSpanId
|
|
7871
8135
|
});
|
|
7872
8136
|
if (iterEvent) {
|
|
7873
8137
|
traceSession.currentIterationSpanId = iterEvent.spanId;
|
|
7874
8138
|
}
|
|
8139
|
+
recordHumanDecisions(traceSession, state);
|
|
7875
8140
|
}
|
|
7876
8141
|
if (cancelIfRequested("loop")) break;
|
|
7877
8142
|
const skippingAgent = resumeStage === "tools";
|
|
@@ -8152,7 +8417,7 @@ function createAgent(opts) {
|
|
|
8152
8417
|
}
|
|
8153
8418
|
emit({ type: "progress", ...progress });
|
|
8154
8419
|
};
|
|
8155
|
-
const traceSession = createTraceSession(opts);
|
|
8420
|
+
const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation));
|
|
8156
8421
|
const ctx = {
|
|
8157
8422
|
...input.ctx || {},
|
|
8158
8423
|
__onEvent: onEvent,
|
|
@@ -8160,6 +8425,7 @@ function createAgent(opts) {
|
|
|
8160
8425
|
__onStream: onStream,
|
|
8161
8426
|
__streaming: streamEnabled
|
|
8162
8427
|
};
|
|
8428
|
+
delete ctx.__traceContinuation;
|
|
8163
8429
|
if (traceSession) ctx.__traceSession = traceSession;
|
|
8164
8430
|
delete ctx.__plugins;
|
|
8165
8431
|
delete ctx.__applySystemPromptContribution;
|
|
@@ -8308,10 +8574,17 @@ function createAgent(opts) {
|
|
|
8308
8574
|
}
|
|
8309
8575
|
}
|
|
8310
8576
|
}
|
|
8577
|
+
const pausedForHuman = statusFor(res) === "paused";
|
|
8578
|
+
const midTurn = pausedForHuman || Boolean(res.ctx?.__needsSummarization);
|
|
8311
8579
|
await finalizeTraceSession(traceSession, {
|
|
8312
8580
|
agentRuntime: res.agent || runtime,
|
|
8313
|
-
status: "success"
|
|
8581
|
+
status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success"
|
|
8314
8582
|
});
|
|
8583
|
+
if (traceSession && midTurn) {
|
|
8584
|
+
res.ctx = { ...res.ctx || {}, __traceContinuation: traceContinuationOf(traceSession) };
|
|
8585
|
+
} else if (res.ctx && "__traceContinuation" in res.ctx) {
|
|
8586
|
+
delete res.ctx.__traceContinuation;
|
|
8587
|
+
}
|
|
8315
8588
|
const isTransientSummarizationExit = !!res.ctx?.__needsSummarization;
|
|
8316
8589
|
const finalAssistantMsg = isTransientSummarizationExit ? void 0 : getLastAssistantMessage(res.messages);
|
|
8317
8590
|
const finalIsSyntheticSummary = !isTransientSummarizationExit && finalAssistantMsg && isSyntheticSummaryMessage(finalAssistantMsg);
|
|
@@ -11215,6 +11488,14 @@ ${pluginAppend}`;
|
|
|
11215
11488
|
} else if (lastResult.state) {
|
|
11216
11489
|
lastResult = { ...lastResult, state: { ...lastResult.state, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, messages: rawMessages } };
|
|
11217
11490
|
}
|
|
11491
|
+
if (lastResult.state) {
|
|
11492
|
+
const endCtx = lastResult.state.ctx;
|
|
11493
|
+
if (endCtx?.__traceContinuation && !(endCtx.__awaitingApproval || endCtx.__awaitingUserQuestion || endCtx.__paused)) {
|
|
11494
|
+
const strippedCtx = { ...endCtx };
|
|
11495
|
+
delete strippedCtx.__traceContinuation;
|
|
11496
|
+
lastResult = { ...lastResult, state: { ...lastResult.state, ctx: strippedCtx } };
|
|
11497
|
+
}
|
|
11498
|
+
}
|
|
11218
11499
|
if (skillsEnabled && lastResult.state) {
|
|
11219
11500
|
const persisted = skillStateFromRegistry(toolSet.skillRegistryRef);
|
|
11220
11501
|
if (persisted) {
|
|
@@ -11589,6 +11870,7 @@ var BaseProvider = class {
|
|
|
11589
11870
|
/** Applies the transport options shared by every provider config. */
|
|
11590
11871
|
configureTransport(config) {
|
|
11591
11872
|
this.fetchImpl = config.fetch;
|
|
11873
|
+
this.onModelRuleLearned = config.onModelRuleLearned;
|
|
11592
11874
|
this.timeoutMs = typeof config.timeoutMs === "number" && config.timeoutMs > 0 ? config.timeoutMs : void 0;
|
|
11593
11875
|
}
|
|
11594
11876
|
/**
|
|
@@ -15256,32 +15538,805 @@ function languageGuard(config) {
|
|
|
15256
15538
|
// src/index.ts
|
|
15257
15539
|
init_content();
|
|
15258
15540
|
|
|
15541
|
+
// src/models/model-rules.json
|
|
15542
|
+
var model_rules_default = {
|
|
15543
|
+
version: 1,
|
|
15544
|
+
effortLadder: [
|
|
15545
|
+
"none",
|
|
15546
|
+
"minimal",
|
|
15547
|
+
"low",
|
|
15548
|
+
"medium",
|
|
15549
|
+
"high",
|
|
15550
|
+
"xhigh",
|
|
15551
|
+
"max"
|
|
15552
|
+
],
|
|
15553
|
+
budgets: {
|
|
15554
|
+
minimal: 1024,
|
|
15555
|
+
low: 2048,
|
|
15556
|
+
medium: 8192,
|
|
15557
|
+
high: 16384,
|
|
15558
|
+
xhigh: 24576,
|
|
15559
|
+
max: 32768
|
|
15560
|
+
},
|
|
15561
|
+
geminiBudgets: {
|
|
15562
|
+
minimal: 512,
|
|
15563
|
+
low: 1024,
|
|
15564
|
+
medium: 4096,
|
|
15565
|
+
high: 12e3,
|
|
15566
|
+
xhigh: 24576,
|
|
15567
|
+
max: 24576
|
|
15568
|
+
},
|
|
15569
|
+
rules: [
|
|
15570
|
+
{
|
|
15571
|
+
id: "openai-chat-models",
|
|
15572
|
+
family: "openai",
|
|
15573
|
+
match: "^(?:chatgpt|gpt-[\\d.]+[a-z0-9.-]*?-chat)",
|
|
15574
|
+
reasoning: {
|
|
15575
|
+
style: "none",
|
|
15576
|
+
efforts: [],
|
|
15577
|
+
off: null
|
|
15578
|
+
},
|
|
15579
|
+
sampling: {
|
|
15580
|
+
temperature: "any",
|
|
15581
|
+
topP: true,
|
|
15582
|
+
topK: true,
|
|
15583
|
+
penalties: true,
|
|
15584
|
+
logprobs: true
|
|
15585
|
+
},
|
|
15586
|
+
maxTokensParam: "max_completion_tokens",
|
|
15587
|
+
chatTools: {
|
|
15588
|
+
reasoning: "any"
|
|
15589
|
+
},
|
|
15590
|
+
source: "docs",
|
|
15591
|
+
note: "Chat-tuned *-chat variants are not reasoning models: ordinary sampling, no reasoning field."
|
|
15592
|
+
},
|
|
15593
|
+
{
|
|
15594
|
+
id: "openai-gpt-6-plus",
|
|
15595
|
+
family: "openai",
|
|
15596
|
+
match: "^gpt-?(?:[6-9]|(?!35(?!\\d))[1-9]\\d+)(?:[.-]|$)",
|
|
15597
|
+
reasoning: {
|
|
15598
|
+
style: "effort",
|
|
15599
|
+
efforts: [
|
|
15600
|
+
"none",
|
|
15601
|
+
"low",
|
|
15602
|
+
"medium",
|
|
15603
|
+
"high",
|
|
15604
|
+
"xhigh"
|
|
15605
|
+
],
|
|
15606
|
+
off: "none",
|
|
15607
|
+
responsesEfforts: [
|
|
15608
|
+
"none",
|
|
15609
|
+
"low",
|
|
15610
|
+
"medium",
|
|
15611
|
+
"high",
|
|
15612
|
+
"xhigh",
|
|
15613
|
+
"max"
|
|
15614
|
+
]
|
|
15615
|
+
},
|
|
15616
|
+
sampling: {
|
|
15617
|
+
temperature: "default-only",
|
|
15618
|
+
topP: false,
|
|
15619
|
+
topK: false,
|
|
15620
|
+
penalties: false,
|
|
15621
|
+
logprobs: false
|
|
15622
|
+
},
|
|
15623
|
+
maxTokensParam: "max_completion_tokens",
|
|
15624
|
+
chatTools: {
|
|
15625
|
+
reasoning: "force-none"
|
|
15626
|
+
},
|
|
15627
|
+
source: "verified-2026-10-14",
|
|
15628
|
+
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."
|
|
15629
|
+
},
|
|
15630
|
+
{
|
|
15631
|
+
id: "openai-gpt-5x",
|
|
15632
|
+
family: "openai",
|
|
15633
|
+
match: "^gpt-?5\\.[1-9]",
|
|
15634
|
+
reasoning: {
|
|
15635
|
+
style: "effort",
|
|
15636
|
+
efforts: [
|
|
15637
|
+
"none",
|
|
15638
|
+
"low",
|
|
15639
|
+
"medium",
|
|
15640
|
+
"high",
|
|
15641
|
+
"xhigh"
|
|
15642
|
+
],
|
|
15643
|
+
off: "none",
|
|
15644
|
+
responsesEfforts: [
|
|
15645
|
+
"none",
|
|
15646
|
+
"low",
|
|
15647
|
+
"medium",
|
|
15648
|
+
"high",
|
|
15649
|
+
"xhigh",
|
|
15650
|
+
"max"
|
|
15651
|
+
]
|
|
15652
|
+
},
|
|
15653
|
+
sampling: {
|
|
15654
|
+
temperature: "default-only",
|
|
15655
|
+
topP: false,
|
|
15656
|
+
topK: false,
|
|
15657
|
+
penalties: false,
|
|
15658
|
+
logprobs: false
|
|
15659
|
+
},
|
|
15660
|
+
maxTokensParam: "max_completion_tokens",
|
|
15661
|
+
chatTools: {
|
|
15662
|
+
reasoning: "force-none"
|
|
15663
|
+
},
|
|
15664
|
+
source: "verified-2026-10-14",
|
|
15665
|
+
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."
|
|
15666
|
+
},
|
|
15667
|
+
{
|
|
15668
|
+
id: "openai-gpt-5-base",
|
|
15669
|
+
family: "openai",
|
|
15670
|
+
match: "^gpt-?5(?![.\\d])",
|
|
15671
|
+
reasoning: {
|
|
15672
|
+
style: "effort",
|
|
15673
|
+
efforts: [
|
|
15674
|
+
"minimal",
|
|
15675
|
+
"low",
|
|
15676
|
+
"medium",
|
|
15677
|
+
"high"
|
|
15678
|
+
],
|
|
15679
|
+
off: null
|
|
15680
|
+
},
|
|
15681
|
+
sampling: {
|
|
15682
|
+
temperature: "default-only",
|
|
15683
|
+
topP: false,
|
|
15684
|
+
topK: false,
|
|
15685
|
+
penalties: false,
|
|
15686
|
+
logprobs: false
|
|
15687
|
+
},
|
|
15688
|
+
maxTokensParam: "max_completion_tokens",
|
|
15689
|
+
chatTools: {
|
|
15690
|
+
reasoning: "any"
|
|
15691
|
+
},
|
|
15692
|
+
source: "docs",
|
|
15693
|
+
note: "gpt-5, -mini, -nano, -codex: minimal/low/medium/high, reasoning cannot be turned off (none maps to minimal)."
|
|
15694
|
+
},
|
|
15695
|
+
{
|
|
15696
|
+
id: "openai-o-series",
|
|
15697
|
+
family: "openai",
|
|
15698
|
+
match: "^o[1-9]\\d?(?![a-z0-9])",
|
|
15699
|
+
reasoning: {
|
|
15700
|
+
style: "effort",
|
|
15701
|
+
efforts: [
|
|
15702
|
+
"low",
|
|
15703
|
+
"medium",
|
|
15704
|
+
"high"
|
|
15705
|
+
],
|
|
15706
|
+
off: null
|
|
15707
|
+
},
|
|
15708
|
+
sampling: {
|
|
15709
|
+
temperature: "default-only",
|
|
15710
|
+
topP: false,
|
|
15711
|
+
topK: false,
|
|
15712
|
+
penalties: false,
|
|
15713
|
+
logprobs: false
|
|
15714
|
+
},
|
|
15715
|
+
maxTokensParam: "max_completion_tokens",
|
|
15716
|
+
chatTools: {
|
|
15717
|
+
reasoning: "any"
|
|
15718
|
+
},
|
|
15719
|
+
source: "docs",
|
|
15720
|
+
note: "o1/o3/o4 family: low/medium/high, no sampling overrides."
|
|
15721
|
+
},
|
|
15722
|
+
{
|
|
15723
|
+
id: "openai-gpt-oss",
|
|
15724
|
+
family: "openai",
|
|
15725
|
+
match: "^gpt-?oss",
|
|
15726
|
+
reasoning: {
|
|
15727
|
+
style: "effort",
|
|
15728
|
+
efforts: [
|
|
15729
|
+
"low",
|
|
15730
|
+
"medium",
|
|
15731
|
+
"high"
|
|
15732
|
+
],
|
|
15733
|
+
off: null
|
|
15734
|
+
},
|
|
15735
|
+
sampling: {
|
|
15736
|
+
temperature: "any",
|
|
15737
|
+
topP: true,
|
|
15738
|
+
topK: true,
|
|
15739
|
+
penalties: true,
|
|
15740
|
+
logprobs: true
|
|
15741
|
+
},
|
|
15742
|
+
maxTokensParam: "max_tokens",
|
|
15743
|
+
chatTools: {
|
|
15744
|
+
reasoning: "any"
|
|
15745
|
+
},
|
|
15746
|
+
source: "docs",
|
|
15747
|
+
note: "Open-weight gpt-oss: low/medium/high; sampling and max_tokens behave like an ordinary chat model."
|
|
15748
|
+
},
|
|
15749
|
+
{
|
|
15750
|
+
id: "openai-legacy-gpt",
|
|
15751
|
+
family: "openai",
|
|
15752
|
+
match: "^(?:gpt-?(?:[0-4]|35)(?![0-9])|text-|davinci|babbage)",
|
|
15753
|
+
reasoning: {
|
|
15754
|
+
style: "none",
|
|
15755
|
+
efforts: [],
|
|
15756
|
+
off: null
|
|
15757
|
+
},
|
|
15758
|
+
sampling: {
|
|
15759
|
+
temperature: "any",
|
|
15760
|
+
topP: true,
|
|
15761
|
+
topK: true,
|
|
15762
|
+
penalties: true,
|
|
15763
|
+
logprobs: true
|
|
15764
|
+
},
|
|
15765
|
+
maxTokensParam: "max_tokens",
|
|
15766
|
+
chatTools: {
|
|
15767
|
+
reasoning: "any"
|
|
15768
|
+
},
|
|
15769
|
+
source: "docs",
|
|
15770
|
+
note: "gpt-4o, gpt-4.1, gpt-3.5 and older: no reasoning, ordinary sampling."
|
|
15771
|
+
},
|
|
15772
|
+
{
|
|
15773
|
+
id: "openai-compatible-toggle",
|
|
15774
|
+
family: "openai",
|
|
15775
|
+
match: "^(?:deepseek-(?:r\\d|reasoner)|qwq|qwen-?3)",
|
|
15776
|
+
reasoning: {
|
|
15777
|
+
style: "toggle",
|
|
15778
|
+
efforts: [
|
|
15779
|
+
"none",
|
|
15780
|
+
"minimal",
|
|
15781
|
+
"low",
|
|
15782
|
+
"medium",
|
|
15783
|
+
"high",
|
|
15784
|
+
"xhigh",
|
|
15785
|
+
"max"
|
|
15786
|
+
],
|
|
15787
|
+
off: "none"
|
|
15788
|
+
},
|
|
15789
|
+
sampling: {
|
|
15790
|
+
temperature: "any",
|
|
15791
|
+
topP: true,
|
|
15792
|
+
topK: true,
|
|
15793
|
+
penalties: true,
|
|
15794
|
+
logprobs: true
|
|
15795
|
+
},
|
|
15796
|
+
maxTokensParam: "max_tokens",
|
|
15797
|
+
chatTools: {
|
|
15798
|
+
reasoning: "any"
|
|
15799
|
+
},
|
|
15800
|
+
source: "docs",
|
|
15801
|
+
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)."
|
|
15802
|
+
},
|
|
15803
|
+
{
|
|
15804
|
+
id: "openai-default",
|
|
15805
|
+
family: "openai",
|
|
15806
|
+
match: ".*",
|
|
15807
|
+
reasoning: {
|
|
15808
|
+
style: "effort",
|
|
15809
|
+
efforts: [
|
|
15810
|
+
"none",
|
|
15811
|
+
"minimal",
|
|
15812
|
+
"low",
|
|
15813
|
+
"medium",
|
|
15814
|
+
"high",
|
|
15815
|
+
"xhigh",
|
|
15816
|
+
"max"
|
|
15817
|
+
],
|
|
15818
|
+
off: "none"
|
|
15819
|
+
},
|
|
15820
|
+
sampling: {
|
|
15821
|
+
temperature: "any",
|
|
15822
|
+
topP: true,
|
|
15823
|
+
topK: true,
|
|
15824
|
+
penalties: true,
|
|
15825
|
+
logprobs: true
|
|
15826
|
+
},
|
|
15827
|
+
maxTokensParam: "max_tokens",
|
|
15828
|
+
chatTools: {
|
|
15829
|
+
reasoning: "any"
|
|
15830
|
+
},
|
|
15831
|
+
source: "docs",
|
|
15832
|
+
note: "Permissive default for unknown OpenAI-wire models: pass what the caller asked; the provider learns from 400s."
|
|
15833
|
+
},
|
|
15834
|
+
{
|
|
15835
|
+
id: "claude-haiku-5",
|
|
15836
|
+
family: "anthropic",
|
|
15837
|
+
match: "^claude-(?:haiku-5|5(?:-\\d+)?-haiku)(?!\\d)",
|
|
15838
|
+
reasoning: {
|
|
15839
|
+
style: "adaptive",
|
|
15840
|
+
efforts: [
|
|
15841
|
+
"low",
|
|
15842
|
+
"medium",
|
|
15843
|
+
"high",
|
|
15844
|
+
"xhigh",
|
|
15845
|
+
"max"
|
|
15846
|
+
],
|
|
15847
|
+
off: "disabled"
|
|
15848
|
+
},
|
|
15849
|
+
sampling: {
|
|
15850
|
+
temperature: "unsupported",
|
|
15851
|
+
topP: false,
|
|
15852
|
+
topK: false,
|
|
15853
|
+
penalties: false,
|
|
15854
|
+
logprobs: false
|
|
15855
|
+
},
|
|
15856
|
+
maxTokensParam: "max_tokens",
|
|
15857
|
+
chatTools: {
|
|
15858
|
+
reasoning: "any"
|
|
15859
|
+
},
|
|
15860
|
+
source: "verified-2026-10-14",
|
|
15861
|
+
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."
|
|
15862
|
+
},
|
|
15863
|
+
{
|
|
15864
|
+
id: "claude-sonnet-5",
|
|
15865
|
+
family: "anthropic",
|
|
15866
|
+
match: "^claude-(?:sonnet-5|5(?:-\\d+)?-sonnet)(?!\\d)",
|
|
15867
|
+
reasoning: {
|
|
15868
|
+
style: "adaptive",
|
|
15869
|
+
efforts: [
|
|
15870
|
+
"low",
|
|
15871
|
+
"medium",
|
|
15872
|
+
"high",
|
|
15873
|
+
"xhigh",
|
|
15874
|
+
"max"
|
|
15875
|
+
],
|
|
15876
|
+
off: "between_tools"
|
|
15877
|
+
},
|
|
15878
|
+
sampling: {
|
|
15879
|
+
temperature: "unsupported",
|
|
15880
|
+
topP: false,
|
|
15881
|
+
topK: false,
|
|
15882
|
+
penalties: false,
|
|
15883
|
+
logprobs: false
|
|
15884
|
+
},
|
|
15885
|
+
maxTokensParam: "max_tokens",
|
|
15886
|
+
chatTools: {
|
|
15887
|
+
reasoning: "any"
|
|
15888
|
+
},
|
|
15889
|
+
source: "verified-2026-10-14",
|
|
15890
|
+
note: "Claude Sonnet 5.x: adaptive + output_config.effort. thinking:{type:disabled} is rejected; off = thinking:{type:between_tools}. Sampling params are rejected."
|
|
15891
|
+
},
|
|
15892
|
+
{
|
|
15893
|
+
id: "claude-opus-5",
|
|
15894
|
+
family: "anthropic",
|
|
15895
|
+
match: "^claude-(?:opus-5|5(?:-\\d+)?-opus)(?!\\d)",
|
|
15896
|
+
reasoning: {
|
|
15897
|
+
style: "adaptive",
|
|
15898
|
+
efforts: [
|
|
15899
|
+
"low",
|
|
15900
|
+
"medium",
|
|
15901
|
+
"high",
|
|
15902
|
+
"xhigh",
|
|
15903
|
+
"max"
|
|
15904
|
+
],
|
|
15905
|
+
off: null
|
|
15906
|
+
},
|
|
15907
|
+
sampling: {
|
|
15908
|
+
temperature: "unsupported",
|
|
15909
|
+
topP: false,
|
|
15910
|
+
topK: false,
|
|
15911
|
+
penalties: false,
|
|
15912
|
+
logprobs: false
|
|
15913
|
+
},
|
|
15914
|
+
maxTokensParam: "max_tokens",
|
|
15915
|
+
chatTools: {
|
|
15916
|
+
reasoning: "any"
|
|
15917
|
+
},
|
|
15918
|
+
source: "verified-2026-10-14",
|
|
15919
|
+
note: "Claude Opus 5.x: adaptive + output_config.effort; thinking cannot be turned off (none maps to the lowest effort). Sampling params are rejected."
|
|
15920
|
+
},
|
|
15921
|
+
{
|
|
15922
|
+
id: "claude-fable",
|
|
15923
|
+
family: "anthropic",
|
|
15924
|
+
match: "^claude-fable",
|
|
15925
|
+
reasoning: {
|
|
15926
|
+
style: "adaptive",
|
|
15927
|
+
efforts: [
|
|
15928
|
+
"low",
|
|
15929
|
+
"medium",
|
|
15930
|
+
"high",
|
|
15931
|
+
"xhigh",
|
|
15932
|
+
"max"
|
|
15933
|
+
],
|
|
15934
|
+
off: null
|
|
15935
|
+
},
|
|
15936
|
+
sampling: {
|
|
15937
|
+
temperature: "unsupported",
|
|
15938
|
+
topP: false,
|
|
15939
|
+
topK: false,
|
|
15940
|
+
penalties: false,
|
|
15941
|
+
logprobs: false
|
|
15942
|
+
},
|
|
15943
|
+
maxTokensParam: "max_tokens",
|
|
15944
|
+
chatTools: {
|
|
15945
|
+
reasoning: "any"
|
|
15946
|
+
},
|
|
15947
|
+
source: "docs",
|
|
15948
|
+
note: "Claude Fable line: treated like the 5.x adaptive models."
|
|
15949
|
+
},
|
|
15950
|
+
{
|
|
15951
|
+
id: "claude-4-7",
|
|
15952
|
+
family: "anthropic",
|
|
15953
|
+
match: "^claude-(?:(?:opus|sonnet|haiku)-4[-.]7|4[-.]7-(?:opus|sonnet|haiku))(?!\\d)",
|
|
15954
|
+
reasoning: {
|
|
15955
|
+
style: "adaptive",
|
|
15956
|
+
efforts: [
|
|
15957
|
+
"low",
|
|
15958
|
+
"medium",
|
|
15959
|
+
"high",
|
|
15960
|
+
"xhigh",
|
|
15961
|
+
"max"
|
|
15962
|
+
],
|
|
15963
|
+
off: "disabled"
|
|
15964
|
+
},
|
|
15965
|
+
sampling: {
|
|
15966
|
+
temperature: "thinking-requires-1",
|
|
15967
|
+
topP: true,
|
|
15968
|
+
topK: true,
|
|
15969
|
+
penalties: true,
|
|
15970
|
+
logprobs: true
|
|
15971
|
+
},
|
|
15972
|
+
maxTokensParam: "max_tokens",
|
|
15973
|
+
chatTools: {
|
|
15974
|
+
reasoning: "any"
|
|
15975
|
+
},
|
|
15976
|
+
source: "docs",
|
|
15977
|
+
note: "Claude 4.7: adaptive thinking, low/medium/high/xhigh/max."
|
|
15978
|
+
},
|
|
15979
|
+
{
|
|
15980
|
+
id: "claude-4-6",
|
|
15981
|
+
family: "anthropic",
|
|
15982
|
+
match: "^claude-(?:(?:opus|sonnet|haiku)-4[-.]6|4[-.]6-(?:opus|sonnet|haiku))(?!\\d)",
|
|
15983
|
+
reasoning: {
|
|
15984
|
+
style: "adaptive",
|
|
15985
|
+
efforts: [
|
|
15986
|
+
"low",
|
|
15987
|
+
"medium",
|
|
15988
|
+
"high",
|
|
15989
|
+
"max"
|
|
15990
|
+
],
|
|
15991
|
+
off: "disabled"
|
|
15992
|
+
},
|
|
15993
|
+
sampling: {
|
|
15994
|
+
temperature: "thinking-requires-1",
|
|
15995
|
+
topP: true,
|
|
15996
|
+
topK: true,
|
|
15997
|
+
penalties: true,
|
|
15998
|
+
logprobs: true
|
|
15999
|
+
},
|
|
16000
|
+
maxTokensParam: "max_tokens",
|
|
16001
|
+
chatTools: {
|
|
16002
|
+
reasoning: "any"
|
|
16003
|
+
},
|
|
16004
|
+
source: "docs",
|
|
16005
|
+
note: "Claude 4.6: adaptive thinking, low/medium/high/max (no xhigh)."
|
|
16006
|
+
},
|
|
16007
|
+
{
|
|
16008
|
+
id: "claude-legacy-budget",
|
|
16009
|
+
family: "anthropic",
|
|
16010
|
+
match: "^claude-(?:3|4-|(?:opus|sonnet|haiku)-4)",
|
|
16011
|
+
reasoning: {
|
|
16012
|
+
style: "budget",
|
|
16013
|
+
efforts: [
|
|
16014
|
+
"none",
|
|
16015
|
+
"minimal",
|
|
16016
|
+
"low",
|
|
16017
|
+
"medium",
|
|
16018
|
+
"high",
|
|
16019
|
+
"xhigh",
|
|
16020
|
+
"max"
|
|
16021
|
+
],
|
|
16022
|
+
off: null
|
|
16023
|
+
},
|
|
16024
|
+
sampling: {
|
|
16025
|
+
temperature: "thinking-requires-1",
|
|
16026
|
+
topP: true,
|
|
16027
|
+
topK: true,
|
|
16028
|
+
penalties: true,
|
|
16029
|
+
logprobs: true
|
|
16030
|
+
},
|
|
16031
|
+
maxTokensParam: "max_tokens",
|
|
16032
|
+
chatTools: {
|
|
16033
|
+
reasoning: "any"
|
|
16034
|
+
},
|
|
16035
|
+
source: "docs",
|
|
16036
|
+
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."
|
|
16037
|
+
},
|
|
16038
|
+
{
|
|
16039
|
+
id: "anthropic-default",
|
|
16040
|
+
family: "anthropic",
|
|
16041
|
+
match: ".*",
|
|
16042
|
+
reasoning: {
|
|
16043
|
+
style: "budget",
|
|
16044
|
+
efforts: [
|
|
16045
|
+
"none",
|
|
16046
|
+
"minimal",
|
|
16047
|
+
"low",
|
|
16048
|
+
"medium",
|
|
16049
|
+
"high",
|
|
16050
|
+
"xhigh",
|
|
16051
|
+
"max"
|
|
16052
|
+
],
|
|
16053
|
+
off: null
|
|
16054
|
+
},
|
|
16055
|
+
sampling: {
|
|
16056
|
+
temperature: "thinking-requires-1",
|
|
16057
|
+
topP: true,
|
|
16058
|
+
topK: true,
|
|
16059
|
+
penalties: true,
|
|
16060
|
+
logprobs: true
|
|
16061
|
+
},
|
|
16062
|
+
maxTokensParam: "max_tokens",
|
|
16063
|
+
chatTools: {
|
|
16064
|
+
reasoning: "any"
|
|
16065
|
+
},
|
|
16066
|
+
source: "docs",
|
|
16067
|
+
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."
|
|
16068
|
+
},
|
|
16069
|
+
{
|
|
16070
|
+
id: "gemini-budget",
|
|
16071
|
+
family: "gemini",
|
|
16072
|
+
match: "^gemini",
|
|
16073
|
+
reasoning: {
|
|
16074
|
+
style: "budget",
|
|
16075
|
+
efforts: [
|
|
16076
|
+
"none",
|
|
16077
|
+
"minimal",
|
|
16078
|
+
"low",
|
|
16079
|
+
"medium",
|
|
16080
|
+
"high",
|
|
16081
|
+
"xhigh",
|
|
16082
|
+
"max"
|
|
16083
|
+
],
|
|
16084
|
+
off: "none"
|
|
16085
|
+
},
|
|
16086
|
+
sampling: {
|
|
16087
|
+
temperature: "any",
|
|
16088
|
+
topP: true,
|
|
16089
|
+
topK: true,
|
|
16090
|
+
penalties: true,
|
|
16091
|
+
logprobs: true
|
|
16092
|
+
},
|
|
16093
|
+
maxTokensParam: "max_tokens",
|
|
16094
|
+
chatTools: {
|
|
16095
|
+
reasoning: "any"
|
|
16096
|
+
},
|
|
16097
|
+
source: "docs",
|
|
16098
|
+
note: "Gemini 2.5-style thinkingBudget; effort maps to a token budget, none = budget 0."
|
|
16099
|
+
},
|
|
16100
|
+
{
|
|
16101
|
+
id: "gemini-default",
|
|
16102
|
+
family: "gemini",
|
|
16103
|
+
match: ".*",
|
|
16104
|
+
reasoning: {
|
|
16105
|
+
style: "budget",
|
|
16106
|
+
efforts: [
|
|
16107
|
+
"none",
|
|
16108
|
+
"minimal",
|
|
16109
|
+
"low",
|
|
16110
|
+
"medium",
|
|
16111
|
+
"high",
|
|
16112
|
+
"xhigh",
|
|
16113
|
+
"max"
|
|
16114
|
+
],
|
|
16115
|
+
off: "none"
|
|
16116
|
+
},
|
|
16117
|
+
sampling: {
|
|
16118
|
+
temperature: "any",
|
|
16119
|
+
topP: true,
|
|
16120
|
+
topK: true,
|
|
16121
|
+
penalties: true,
|
|
16122
|
+
logprobs: true
|
|
16123
|
+
},
|
|
16124
|
+
maxTokensParam: "max_tokens",
|
|
16125
|
+
chatTools: {
|
|
16126
|
+
reasoning: "any"
|
|
16127
|
+
},
|
|
16128
|
+
source: "docs",
|
|
16129
|
+
note: "Permissive default for unknown Gemini-wire models."
|
|
16130
|
+
},
|
|
16131
|
+
{
|
|
16132
|
+
id: "other-default",
|
|
16133
|
+
family: "other",
|
|
16134
|
+
match: ".*",
|
|
16135
|
+
reasoning: {
|
|
16136
|
+
style: "effort",
|
|
16137
|
+
efforts: [
|
|
16138
|
+
"none",
|
|
16139
|
+
"minimal",
|
|
16140
|
+
"low",
|
|
16141
|
+
"medium",
|
|
16142
|
+
"high",
|
|
16143
|
+
"xhigh",
|
|
16144
|
+
"max"
|
|
16145
|
+
],
|
|
16146
|
+
off: "none"
|
|
16147
|
+
},
|
|
16148
|
+
sampling: {
|
|
16149
|
+
temperature: "any",
|
|
16150
|
+
topP: true,
|
|
16151
|
+
topK: true,
|
|
16152
|
+
penalties: true,
|
|
16153
|
+
logprobs: true
|
|
16154
|
+
},
|
|
16155
|
+
maxTokensParam: "max_tokens",
|
|
16156
|
+
chatTools: {
|
|
16157
|
+
reasoning: "any"
|
|
16158
|
+
},
|
|
16159
|
+
source: "docs",
|
|
16160
|
+
note: "Permissive default for model families the SDK has no rules for."
|
|
16161
|
+
}
|
|
16162
|
+
]
|
|
16163
|
+
};
|
|
16164
|
+
|
|
16165
|
+
// src/models/rules.ts
|
|
16166
|
+
var MODEL_RULES = model_rules_default;
|
|
16167
|
+
var LADDER = MODEL_RULES.effortLadder;
|
|
16168
|
+
var compiled = /* @__PURE__ */ new Map();
|
|
16169
|
+
function regexFor(rule) {
|
|
16170
|
+
let re = compiled.get(rule.id);
|
|
16171
|
+
if (!re) {
|
|
16172
|
+
re = new RegExp(rule.match, "i");
|
|
16173
|
+
compiled.set(rule.id, re);
|
|
16174
|
+
}
|
|
16175
|
+
return re;
|
|
16176
|
+
}
|
|
16177
|
+
var GATEWAY_PREFIX = /^(?:(?:global|us|eu|apac|jp|au|ca|us-gov)\.)?(?:(?:openai|anthropic|google|meta|amazon|deepseek|qwen|mistral|cohere|ai21)\.)?/;
|
|
16178
|
+
function modelIdCandidates(model) {
|
|
16179
|
+
if (!model) return [];
|
|
16180
|
+
const lower = String(model).trim().toLowerCase();
|
|
16181
|
+
const last = lower.split("/").pop() ?? lower;
|
|
16182
|
+
const out = [];
|
|
16183
|
+
for (const id of [lower, last]) {
|
|
16184
|
+
for (const c of [id, id.replace(GATEWAY_PREFIX, "")]) {
|
|
16185
|
+
if (c && !out.includes(c)) out.push(c);
|
|
16186
|
+
}
|
|
16187
|
+
}
|
|
16188
|
+
return out;
|
|
16189
|
+
}
|
|
16190
|
+
var OPENAI_WIRE = /* @__PURE__ */ new Set(["openai", "azure", "openai-compatible", "together", "openrouter", "groq", "fireworks", "ollama", "vllm", "litellm", "mistral", "deepseek", "xai", "jev"]);
|
|
16191
|
+
function familiesFor(provider) {
|
|
16192
|
+
const p = (provider ?? "").toLowerCase();
|
|
16193
|
+
if (OPENAI_WIRE.has(p)) return ["openai"];
|
|
16194
|
+
if (p === "anthropic") return ["anthropic"];
|
|
16195
|
+
if (p === "bedrock") return ["anthropic", "openai", "other"];
|
|
16196
|
+
if (p === "vertex" || p === "gemini" || p === "google") return ["gemini", "anthropic"];
|
|
16197
|
+
return ["openai", "anthropic", "gemini", "other"];
|
|
16198
|
+
}
|
|
16199
|
+
function matchRule(family, ids, allowDefault) {
|
|
16200
|
+
for (const rule of MODEL_RULES.rules) {
|
|
16201
|
+
if (rule.family !== family) continue;
|
|
16202
|
+
if (rule.match === ".*") {
|
|
16203
|
+
if (allowDefault) return rule;
|
|
16204
|
+
continue;
|
|
16205
|
+
}
|
|
16206
|
+
const re = regexFor(rule);
|
|
16207
|
+
if (ids.some((id) => re.test(id))) return rule;
|
|
16208
|
+
}
|
|
16209
|
+
return void 0;
|
|
16210
|
+
}
|
|
16211
|
+
function mergeRulePatch(base, patch) {
|
|
16212
|
+
if (!patch) return base;
|
|
16213
|
+
const out = { ...base };
|
|
16214
|
+
if (patch.reasoning) out.reasoning = { ...base.reasoning ?? {}, ...patch.reasoning };
|
|
16215
|
+
if (patch.sampling) out.sampling = { ...base.sampling ?? {}, ...patch.sampling };
|
|
16216
|
+
if (patch.chatTools) out.chatTools = { ...base.chatTools ?? {}, ...patch.chatTools };
|
|
16217
|
+
if (patch.maxTokensParam) out.maxTokensParam = patch.maxTokensParam;
|
|
16218
|
+
if (patch.dropParams) out.dropParams = [.../* @__PURE__ */ new Set([...base.dropParams ?? [], ...patch.dropParams])];
|
|
16219
|
+
return out;
|
|
16220
|
+
}
|
|
16221
|
+
var LEARNED_MAX = 500;
|
|
16222
|
+
var learned = /* @__PURE__ */ new Map();
|
|
16223
|
+
function learnedKey(provider, model, scope) {
|
|
16224
|
+
return `${(provider ?? "").toLowerCase()}@${scope ?? ""}::${(model ?? "").trim().toLowerCase()}`;
|
|
16225
|
+
}
|
|
16226
|
+
function rememberModelRulePatch(provider, model, patch, scope) {
|
|
16227
|
+
const key = learnedKey(provider, model, scope);
|
|
16228
|
+
const merged = mergeRulePatch(learned.get(key)?.patch ?? {}, patch);
|
|
16229
|
+
learned.delete(key);
|
|
16230
|
+
learned.set(key, { provider: provider.toLowerCase(), model: model.trim().toLowerCase(), scope, patch: merged });
|
|
16231
|
+
if (learned.size > LEARNED_MAX) learned.delete(learned.keys().next().value);
|
|
16232
|
+
}
|
|
16233
|
+
function getLearnedModelRulePatch(provider, model, scope) {
|
|
16234
|
+
return learned.get(learnedKey(provider, model, scope))?.patch;
|
|
16235
|
+
}
|
|
16236
|
+
function listLearnedModelRules() {
|
|
16237
|
+
return [...learned.values()].map((e) => ({ ...e }));
|
|
16238
|
+
}
|
|
16239
|
+
function clearLearnedModelRules() {
|
|
16240
|
+
learned.clear();
|
|
16241
|
+
}
|
|
16242
|
+
function resolveModelRule(opts) {
|
|
16243
|
+
const families = familiesFor(opts.provider);
|
|
16244
|
+
const ids = modelIdCandidates(opts.model);
|
|
16245
|
+
let rule;
|
|
16246
|
+
for (const family of families) {
|
|
16247
|
+
rule = matchRule(family, ids, false);
|
|
16248
|
+
if (rule) break;
|
|
16249
|
+
}
|
|
16250
|
+
let isDefault = false;
|
|
16251
|
+
if (!rule) {
|
|
16252
|
+
isDefault = true;
|
|
16253
|
+
rule = matchRule(families[0], ids, true) ?? MODEL_RULES.rules[MODEL_RULES.rules.length - 1];
|
|
16254
|
+
}
|
|
16255
|
+
let effective = rule;
|
|
16256
|
+
const known = opts.model ? learned.get(learnedKey(opts.provider, opts.model, opts.scope))?.patch : void 0;
|
|
16257
|
+
if (known) effective = mergeRulePatch(effective, known);
|
|
16258
|
+
if (opts.patch) effective = mergeRulePatch(effective, opts.patch);
|
|
16259
|
+
return { ...effective, matchedRuleId: rule.id, isDefault, learned: !!known };
|
|
16260
|
+
}
|
|
16261
|
+
function mapReasoningEffort(rule, effort, endpoint = "chat") {
|
|
16262
|
+
const efforts = endpoint === "responses" && rule.reasoning.responsesEfforts || rule.reasoning.efforts;
|
|
16263
|
+
if (rule.reasoning.style === "none" || efforts.length === 0) return { mapped: true };
|
|
16264
|
+
const supported = LADDER.filter((e) => efforts.includes(e));
|
|
16265
|
+
if (supported.includes(effort)) return { effort, mapped: false };
|
|
16266
|
+
if (effort === "none") {
|
|
16267
|
+
const off = rule.reasoning.off;
|
|
16268
|
+
if (off && off !== "none") return { off, mapped: true };
|
|
16269
|
+
const lowest = supported.find((e) => e !== "none");
|
|
16270
|
+
return lowest ? { effort: lowest, mapped: true } : { mapped: true };
|
|
16271
|
+
}
|
|
16272
|
+
const at = LADDER.indexOf(effort);
|
|
16273
|
+
if (at < 0) return { mapped: true };
|
|
16274
|
+
for (let i = at - 1; i >= 1; i--) if (supported.includes(LADDER[i])) return { effort: LADDER[i], mapped: true };
|
|
16275
|
+
for (let i = at + 1; i < LADDER.length; i++) if (supported.includes(LADDER[i])) return { effort: LADDER[i], mapped: true };
|
|
16276
|
+
return supported.includes("none") ? { effort: "none", mapped: true } : { mapped: true };
|
|
16277
|
+
}
|
|
16278
|
+
function allowsSampling(rule, field, value, thinkingOn = false) {
|
|
16279
|
+
const s = rule.sampling;
|
|
16280
|
+
switch (field) {
|
|
16281
|
+
case "temperature":
|
|
16282
|
+
switch (s.temperature) {
|
|
16283
|
+
case "any":
|
|
16284
|
+
return true;
|
|
16285
|
+
case "unsupported":
|
|
16286
|
+
return false;
|
|
16287
|
+
// The default is what the server applies anyway, so it is never sent.
|
|
16288
|
+
case "default-only":
|
|
16289
|
+
return false;
|
|
16290
|
+
case "thinking-requires-1":
|
|
16291
|
+
return !thinkingOn || value === 1;
|
|
16292
|
+
}
|
|
16293
|
+
return true;
|
|
16294
|
+
// Anthropic's thinking restriction covers top_p / top_k as well as temperature.
|
|
16295
|
+
case "topP":
|
|
16296
|
+
return s.topP && !(thinkingOn && s.temperature === "thinking-requires-1");
|
|
16297
|
+
case "topK":
|
|
16298
|
+
return s.topK && !(thinkingOn && s.temperature === "thinking-requires-1");
|
|
16299
|
+
case "presencePenalty":
|
|
16300
|
+
case "frequencyPenalty":
|
|
16301
|
+
return s.penalties;
|
|
16302
|
+
case "logprobs":
|
|
16303
|
+
return s.logprobs;
|
|
16304
|
+
}
|
|
16305
|
+
}
|
|
16306
|
+
function applyDropParams(body, rule) {
|
|
16307
|
+
for (const p of rule.dropParams ?? []) {
|
|
16308
|
+
const dot = p.indexOf(".");
|
|
16309
|
+
if (dot < 0) delete body[p];
|
|
16310
|
+
else if (body[p.slice(0, dot)] && typeof body[p.slice(0, dot)] === "object") delete body[p.slice(0, dot)][p.slice(dot + 1)];
|
|
16311
|
+
}
|
|
16312
|
+
}
|
|
16313
|
+
function effortBudget(effort, table = "anthropic") {
|
|
16314
|
+
if (effort === "none") return 0;
|
|
16315
|
+
return (table === "gemini" ? MODEL_RULES.geminiBudgets : MODEL_RULES.budgets)[effort] ?? 0;
|
|
16316
|
+
}
|
|
16317
|
+
|
|
15259
16318
|
// src/providers/utils/reasoning.ts
|
|
15260
16319
|
var ANTHROPIC_EFFORT_BUDGET = {
|
|
15261
16320
|
// 0 = off. `applyAnthropicReasoning` bails on a falsy budget and emits no
|
|
15262
16321
|
// thinking block, which on Anthropic IS off — thinking there is opt-in.
|
|
15263
16322
|
none: 0,
|
|
15264
|
-
|
|
15265
|
-
low: 2048,
|
|
15266
|
-
medium: 8192,
|
|
15267
|
-
high: 16384
|
|
16323
|
+
...MODEL_RULES.budgets
|
|
15268
16324
|
};
|
|
15269
16325
|
var GEMINI_EFFORT_BUDGET = {
|
|
15270
16326
|
// 0 is Gemini's own documented spelling for "do not think", and unlike
|
|
15271
16327
|
// Anthropic it has to be SENT — hence `applyGeminiReasoning` testing for null
|
|
15272
16328
|
// rather than falsiness.
|
|
15273
16329
|
none: 0,
|
|
15274
|
-
|
|
15275
|
-
low: 1024,
|
|
15276
|
-
medium: 4096,
|
|
15277
|
-
high: 12e3
|
|
16330
|
+
...MODEL_RULES.geminiBudgets
|
|
15278
16331
|
};
|
|
15279
16332
|
var THINKING_OUTPUT_RESERVE = 1024;
|
|
15280
16333
|
var MIN_THINKING_BUDGET = 1024;
|
|
15281
16334
|
var THINKING_MIN_MAX_TOKENS = 4096;
|
|
15282
|
-
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
16335
|
+
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort", model, rule) {
|
|
15283
16336
|
if (!reasoning) return;
|
|
15284
|
-
const
|
|
16337
|
+
const requested = normalizeEffort(reasoning.effort);
|
|
16338
|
+
const r = rule ?? resolveModelRule({ provider: "openai", model: model ?? body.model });
|
|
16339
|
+
const effort = requested && mapReasoningEffort(r, requested, mode === "responses" ? "responses" : "chat").effort;
|
|
15285
16340
|
if (mode === "responses") {
|
|
15286
16341
|
const obj = {};
|
|
15287
16342
|
if (effort) obj.effort = effort;
|
|
@@ -15295,48 +16350,54 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
|
15295
16350
|
}
|
|
15296
16351
|
function supportsAdaptiveThinking(model) {
|
|
15297
16352
|
if (typeof model !== "string") return false;
|
|
15298
|
-
|
|
15299
|
-
const at = id.indexOf("claude-");
|
|
15300
|
-
if (at < 0) return false;
|
|
15301
|
-
for (const tok of id.slice(at + 7).split("-")) {
|
|
15302
|
-
if (tok === "fable") return true;
|
|
15303
|
-
const m = /^(\d+)(?:@|$)/.exec(tok);
|
|
15304
|
-
if (m) {
|
|
15305
|
-
if (m[1].length <= 2) return Number(m[1]) >= 5;
|
|
15306
|
-
return false;
|
|
15307
|
-
}
|
|
15308
|
-
}
|
|
15309
|
-
return false;
|
|
16353
|
+
return resolveModelRule({ provider: "anthropic", model }).reasoning.style === "adaptive";
|
|
15310
16354
|
}
|
|
15311
|
-
function resolveThinkingForm(model, mode) {
|
|
16355
|
+
function resolveThinkingForm(model, mode, rule) {
|
|
15312
16356
|
if (mode === "adaptive" || mode === "budget") return mode;
|
|
16357
|
+
if (rule) return rule.reasoning.style === "adaptive" ? "adaptive" : "budget";
|
|
15313
16358
|
return supportsAdaptiveThinking(model) ? "adaptive" : "budget";
|
|
15314
16359
|
}
|
|
15315
|
-
function
|
|
15316
|
-
const
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
if (requested) effort = requested === "minimal" ? "low" : requested;
|
|
15320
|
-
else if (typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
15321
|
-
effort = reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.low ? "low" : reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.medium ? "medium" : "high";
|
|
16360
|
+
function enforceAnthropicSampling(target, rule, thinkingOn, bedrock = false) {
|
|
16361
|
+
const fields = bedrock ? [["temperature", "temperature"], ["topP", "topP"]] : [["temperature", "temperature"], ["top_p", "topP"], ["top_k", "topK"]];
|
|
16362
|
+
for (const [key, field] of fields) {
|
|
16363
|
+
if (key in target && !allowsSampling(rule, field, target[key], thinkingOn)) delete target[key];
|
|
15322
16364
|
}
|
|
15323
|
-
|
|
16365
|
+
}
|
|
16366
|
+
function applyAdaptiveThinking(reasoning, rule, setThinking, setOutputConfig) {
|
|
16367
|
+
let requested = normalizeEffort(reasoning.effort);
|
|
16368
|
+
if (!requested && typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
16369
|
+
requested = reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.low ? "low" : reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.medium ? "medium" : "high";
|
|
16370
|
+
}
|
|
16371
|
+
if (!requested) return false;
|
|
16372
|
+
const mapped = mapReasoningEffort(rule, requested);
|
|
16373
|
+
if (mapped.off) {
|
|
16374
|
+
setThinking({ type: mapped.off });
|
|
16375
|
+
return false;
|
|
16376
|
+
}
|
|
16377
|
+
if (!mapped.effort || mapped.effort === "none") return false;
|
|
15324
16378
|
const thinking = { type: "adaptive" };
|
|
15325
16379
|
if (reasoning.includeThoughts !== false) thinking.display = "summarized";
|
|
15326
16380
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
15327
|
-
setThinking(
|
|
15328
|
-
setOutputConfig({ effort });
|
|
16381
|
+
setThinking(thinking);
|
|
16382
|
+
setOutputConfig({ effort: mapped.effort });
|
|
15329
16383
|
return true;
|
|
15330
16384
|
}
|
|
15331
16385
|
function applyAnthropicReasoning(body, reasoning, opts) {
|
|
15332
|
-
|
|
15333
|
-
if (
|
|
15334
|
-
|
|
15335
|
-
|
|
16386
|
+
const rule = opts?.rule ?? resolveModelRule({ provider: "anthropic", model: opts?.model ?? body.model });
|
|
16387
|
+
if (!reasoning) {
|
|
16388
|
+
enforceAnthropicSampling(body, rule, false);
|
|
16389
|
+
return;
|
|
16390
|
+
}
|
|
16391
|
+
if (resolveThinkingForm(opts?.model ?? body.model, opts?.mode, rule) === "adaptive") {
|
|
16392
|
+
const on = applyAdaptiveThinking(reasoning, rule, (t) => body.thinking = t, (o) => body.output_config = { ...body.output_config ?? {}, ...o });
|
|
16393
|
+
enforceAnthropicSampling(body, rule, on);
|
|
16394
|
+
return;
|
|
16395
|
+
}
|
|
16396
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET, rule);
|
|
16397
|
+
if (!budget) {
|
|
16398
|
+
enforceAnthropicSampling(body, rule, false);
|
|
15336
16399
|
return;
|
|
15337
16400
|
}
|
|
15338
|
-
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
15339
|
-
if (!budget) return;
|
|
15340
16401
|
const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
|
|
15341
16402
|
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
15342
16403
|
if (currentMax < requiredMax) {
|
|
@@ -15346,18 +16407,25 @@ function applyAnthropicReasoning(body, reasoning, opts) {
|
|
|
15346
16407
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
15347
16408
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
15348
16409
|
body.thinking = thinking;
|
|
15349
|
-
|
|
16410
|
+
enforceAnthropicSampling(body, rule, true);
|
|
15350
16411
|
}
|
|
15351
16412
|
function applyBedrockReasoning(body, reasoning, opts) {
|
|
15352
|
-
|
|
15353
|
-
if (
|
|
16413
|
+
const rule = opts?.rule ?? resolveModelRule({ provider: "bedrock", model: opts?.model ?? body.modelId });
|
|
16414
|
+
if (!reasoning) {
|
|
16415
|
+
if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, false, true);
|
|
16416
|
+
return;
|
|
16417
|
+
}
|
|
16418
|
+
if (resolveThinkingForm(opts?.model ?? body.modelId, opts?.mode, rule) === "adaptive") {
|
|
15354
16419
|
const fields = () => body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
|
|
15355
|
-
const on = applyAdaptiveThinking(
|
|
15356
|
-
if (
|
|
16420
|
+
const on = applyAdaptiveThinking(reasoning, rule, (t) => fields().thinking = t, (o) => fields().output_config = { ...fields().output_config ?? {}, ...o });
|
|
16421
|
+
if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, on, true);
|
|
16422
|
+
return;
|
|
16423
|
+
}
|
|
16424
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET, rule);
|
|
16425
|
+
if (!budget) {
|
|
16426
|
+
if (body.inferenceConfig) enforceAnthropicSampling(body.inferenceConfig, rule, false, true);
|
|
15357
16427
|
return;
|
|
15358
16428
|
}
|
|
15359
|
-
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
15360
|
-
if (!budget) return;
|
|
15361
16429
|
const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
|
|
15362
16430
|
const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
|
|
15363
16431
|
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
@@ -15369,7 +16437,7 @@ function applyBedrockReasoning(body, reasoning, opts) {
|
|
|
15369
16437
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
15370
16438
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
15371
16439
|
extra.thinking = thinking;
|
|
15372
|
-
|
|
16440
|
+
enforceAnthropicSampling(inference, rule, true, true);
|
|
15373
16441
|
}
|
|
15374
16442
|
function applyGeminiReasoning(generationConfig, reasoning) {
|
|
15375
16443
|
if (!reasoning) return;
|
|
@@ -15381,11 +16449,6 @@ function applyGeminiReasoning(generationConfig, reasoning) {
|
|
|
15381
16449
|
if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
|
|
15382
16450
|
generationConfig.thinkingConfig = thinkingConfig;
|
|
15383
16451
|
}
|
|
15384
|
-
function stripSamplingParams(target, keys) {
|
|
15385
|
-
for (const k of keys) {
|
|
15386
|
-
if (k in target) delete target[k];
|
|
15387
|
-
}
|
|
15388
|
-
}
|
|
15389
16452
|
function clampBudget(budget, maxTokens) {
|
|
15390
16453
|
if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
|
|
15391
16454
|
const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
|
|
@@ -15394,16 +16457,17 @@ function clampBudget(budget, maxTokens) {
|
|
|
15394
16457
|
}
|
|
15395
16458
|
function normalizeEffort(effort) {
|
|
15396
16459
|
if (!effort) return void 0;
|
|
15397
|
-
const allowed = ["none", "minimal", "low", "medium", "high"];
|
|
16460
|
+
const allowed = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
15398
16461
|
return allowed.includes(effort) ? effort : void 0;
|
|
15399
16462
|
}
|
|
15400
|
-
function resolveBudget(reasoning,
|
|
16463
|
+
function resolveBudget(reasoning, effortBudget2, rule) {
|
|
15401
16464
|
const effort = normalizeEffort(reasoning.effort);
|
|
15402
16465
|
if (effort === "none") return 0;
|
|
15403
16466
|
if (typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
15404
16467
|
return Math.floor(reasoning.budgetTokens);
|
|
15405
16468
|
}
|
|
15406
|
-
|
|
16469
|
+
const mapped = effort && rule ? mapReasoningEffort(rule, effort).effort : effort;
|
|
16470
|
+
if (mapped && effortBudget2[mapped]) return effortBudget2[mapped];
|
|
15407
16471
|
return void 0;
|
|
15408
16472
|
}
|
|
15409
16473
|
|
|
@@ -15474,6 +16538,211 @@ function parseSSEBlock(block) {
|
|
|
15474
16538
|
return { event, data: dataLines.join("\n"), id, retry };
|
|
15475
16539
|
}
|
|
15476
16540
|
|
|
16541
|
+
// src/models/errors.ts
|
|
16542
|
+
var ModelRequestError = class extends ProviderError {
|
|
16543
|
+
constructor(init) {
|
|
16544
|
+
super(init.message, init.provider, init.status ?? 400, init.responseBody);
|
|
16545
|
+
this.status = init.status ?? 400;
|
|
16546
|
+
this.code = init.code;
|
|
16547
|
+
this.param = init.param;
|
|
16548
|
+
this.value = init.value;
|
|
16549
|
+
this.supportedValues = init.supportedValues;
|
|
16550
|
+
this.model = init.model;
|
|
16551
|
+
}
|
|
16552
|
+
};
|
|
16553
|
+
|
|
16554
|
+
// src/models/adjust.ts
|
|
16555
|
+
var MAX_ADJUSTMENTS = 3;
|
|
16556
|
+
var Q = "['\"`]";
|
|
16557
|
+
function errorMessage(text) {
|
|
16558
|
+
try {
|
|
16559
|
+
const j = JSON.parse(text);
|
|
16560
|
+
const e = j?.error ?? j;
|
|
16561
|
+
const message = typeof e?.message === "string" ? e.message : typeof j?.message === "string" ? j.message : text;
|
|
16562
|
+
return { message, param: typeof e?.param === "string" ? e.param : void 0, code: typeof e?.code === "string" ? e.code : void 0 };
|
|
16563
|
+
} catch {
|
|
16564
|
+
return { message: text };
|
|
16565
|
+
}
|
|
16566
|
+
}
|
|
16567
|
+
function quotedList(s) {
|
|
16568
|
+
const quoted = [...s.matchAll(new RegExp(`${Q}([^'"\`]+)${Q}`, "g"))].map((m) => m[1]);
|
|
16569
|
+
if (quoted.length > 0) return quoted;
|
|
16570
|
+
return s.split(/[,\s]+/).map((x) => x.replace(/[.\s]+$/, "")).filter(Boolean);
|
|
16571
|
+
}
|
|
16572
|
+
function parseModelError(text) {
|
|
16573
|
+
const { message, param: errParam } = errorMessage(String(text ?? ""));
|
|
16574
|
+
const m = message.toLowerCase();
|
|
16575
|
+
if (m.includes("function tools with reasoning_effort") && m.includes("not supported")) {
|
|
16576
|
+
return { kind: "chat_tools_effort", message };
|
|
16577
|
+
}
|
|
16578
|
+
if (m.includes("between_tools") && m.includes("thinking")) return { kind: "thinking_off_between_tools", message };
|
|
16579
|
+
if (m.includes("thinking.type.enabled") && m.includes("not supported")) return { kind: "thinking_enabled_unsupported", message };
|
|
16580
|
+
if (m.includes("thinking.type.adaptive") && m.includes("not supported")) return { kind: "thinking_adaptive_unsupported", message };
|
|
16581
|
+
if (m.includes("thinking.type.disabled") && m.includes("not supported")) return { kind: "thinking_disabled_unsupported", message };
|
|
16582
|
+
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);
|
|
16583
|
+
if (tt) return { kind: "temperature_thinking", param: tt[1].toLowerCase(), message };
|
|
16584
|
+
const dep = new RegExp(`${Q}([\\w.]+)${Q}\\s+is deprecated for this model`, "i").exec(message);
|
|
16585
|
+
if (dep) return { kind: "unsupported_parameter", param: dep[1], message };
|
|
16586
|
+
const rename = new RegExp(`use ${Q}(max_completion_tokens|max_tokens)${Q} instead`, "i").exec(message);
|
|
16587
|
+
if (rename) return { kind: "max_tokens_rename", renameTo: rename[1].toLowerCase(), param: rename[1].toLowerCase() === "max_tokens" ? "max_completion_tokens" : "max_tokens", message };
|
|
16588
|
+
const val = new RegExp(`unsupported value:?\\s*${Q}?([\\w.]+)${Q}?\\s+does not support\\s+(${Q}[^'"\`]*${Q}|[^\\s]+)`, "i").exec(message);
|
|
16589
|
+
if (val) {
|
|
16590
|
+
const param = val[1];
|
|
16591
|
+
const value = val[2].replace(/^['"`]|['"`]$/g, "");
|
|
16592
|
+
if (m.includes("only the default") && m.includes("value is supported")) return { kind: "default_only", param, value, message };
|
|
16593
|
+
const sup = /supported values? (?:are|is):?\s*([^\n]*)/i.exec(message);
|
|
16594
|
+
return { kind: "unsupported_value", param, value, supportedValues: sup ? quotedList(sup[1]) : void 0, message };
|
|
16595
|
+
}
|
|
16596
|
+
if (m.includes("only the default") && m.includes("value is supported")) {
|
|
16597
|
+
return { kind: "default_only", param: errParam ?? "temperature", message };
|
|
16598
|
+
}
|
|
16599
|
+
const prm = new RegExp(`unsupported parameter:?\\s*${Q}?([\\w.]+)${Q}?`, "i").exec(message);
|
|
16600
|
+
if (prm) return { kind: "unsupported_parameter", param: prm[1], message };
|
|
16601
|
+
return void 0;
|
|
16602
|
+
}
|
|
16603
|
+
var normParam = (p) => p.toLowerCase().replace(/[-\s]/g, "_");
|
|
16604
|
+
var LADDER2 = new Set(MODEL_RULES.effortLadder);
|
|
16605
|
+
function patchFromParsedError(parsed, endpoint = "chat") {
|
|
16606
|
+
const param = parsed.param ? normParam(parsed.param) : "";
|
|
16607
|
+
switch (parsed.kind) {
|
|
16608
|
+
case "chat_tools_effort":
|
|
16609
|
+
return { patch: { chatTools: { reasoning: "force-none" } }, adjustment: "chat-tools:force-effort-none" };
|
|
16610
|
+
case "max_tokens_rename":
|
|
16611
|
+
return { patch: { maxTokensParam: parsed.renameTo }, adjustment: `${parsed.param}->${parsed.renameTo}` };
|
|
16612
|
+
case "thinking_enabled_unsupported":
|
|
16613
|
+
return { patch: { reasoning: { style: "adaptive" } }, adjustment: "thinking:adaptive" };
|
|
16614
|
+
case "thinking_adaptive_unsupported":
|
|
16615
|
+
return { patch: { reasoning: { style: "budget" } }, adjustment: "thinking:budget" };
|
|
16616
|
+
case "thinking_off_between_tools":
|
|
16617
|
+
return { patch: { reasoning: { off: "between_tools" } }, adjustment: "thinking-off:between_tools" };
|
|
16618
|
+
case "thinking_disabled_unsupported":
|
|
16619
|
+
return { patch: { reasoning: { off: null } }, adjustment: "thinking-off:none" };
|
|
16620
|
+
case "temperature_thinking":
|
|
16621
|
+
return { patch: { sampling: { temperature: "unsupported" } }, adjustment: "drop:temperature" };
|
|
16622
|
+
case "default_only":
|
|
16623
|
+
if (param === "temperature") return { patch: { sampling: { temperature: "default-only" } }, adjustment: "temperature:default-only" };
|
|
16624
|
+
return { patch: { dropParams: [parsed.param ?? param] }, adjustment: `drop:${parsed.param ?? param}` };
|
|
16625
|
+
case "unsupported_value": {
|
|
16626
|
+
if (/^(reasoning_effort|reasoning\.effort|effort|output_config\.effort)$/.test(param)) {
|
|
16627
|
+
const list = (parsed.supportedValues ?? []).map((v) => v.toLowerCase()).filter((v) => LADDER2.has(v));
|
|
16628
|
+
if (list.length === 0) return void 0;
|
|
16629
|
+
const reasoning = endpoint === "responses" ? { responsesEfforts: list } : { efforts: list };
|
|
16630
|
+
return { patch: { reasoning }, adjustment: `efforts:${list.join("|")}` };
|
|
16631
|
+
}
|
|
16632
|
+
return paramDropPatch(param, parsed);
|
|
16633
|
+
}
|
|
16634
|
+
case "unsupported_parameter":
|
|
16635
|
+
return paramDropPatch(param, parsed);
|
|
16636
|
+
}
|
|
16637
|
+
}
|
|
16638
|
+
function paramDropPatch(param, parsed) {
|
|
16639
|
+
if (!param) return void 0;
|
|
16640
|
+
const label = `drop:${parsed.param ?? param}`;
|
|
16641
|
+
switch (param) {
|
|
16642
|
+
case "temperature":
|
|
16643
|
+
return { patch: { sampling: { temperature: "unsupported" } }, adjustment: label };
|
|
16644
|
+
case "top_p":
|
|
16645
|
+
return { patch: { sampling: { topP: false } }, adjustment: label };
|
|
16646
|
+
case "top_k":
|
|
16647
|
+
return { patch: { sampling: { topK: false } }, adjustment: label };
|
|
16648
|
+
case "presence_penalty":
|
|
16649
|
+
case "frequency_penalty":
|
|
16650
|
+
return { patch: { sampling: { penalties: false } }, adjustment: label };
|
|
16651
|
+
case "logprobs":
|
|
16652
|
+
case "top_logprobs":
|
|
16653
|
+
return { patch: { sampling: { logprobs: false } }, adjustment: label };
|
|
16654
|
+
case "max_tokens":
|
|
16655
|
+
return { patch: { maxTokensParam: "max_completion_tokens" }, adjustment: "max_tokens->max_completion_tokens" };
|
|
16656
|
+
case "max_completion_tokens":
|
|
16657
|
+
return { patch: { maxTokensParam: "max_tokens" }, adjustment: "max_completion_tokens->max_tokens" };
|
|
16658
|
+
case "reasoning_effort":
|
|
16659
|
+
case "reasoning.effort":
|
|
16660
|
+
case "reasoning":
|
|
16661
|
+
return { patch: { reasoning: { style: "none", efforts: [], responsesEfforts: [] }, dropParams: [param] }, adjustment: label };
|
|
16662
|
+
default:
|
|
16663
|
+
return { patch: { dropParams: [parsed.param ?? param] }, adjustment: label };
|
|
16664
|
+
}
|
|
16665
|
+
}
|
|
16666
|
+
function codeFor(parsed) {
|
|
16667
|
+
if (!parsed) return "model_request_invalid";
|
|
16668
|
+
if (parsed.kind === "unsupported_value" || parsed.kind === "default_only") return "unsupported_value";
|
|
16669
|
+
if (parsed.kind === "unsupported_parameter" || parsed.kind === "max_tokens_rename" || parsed.kind === "temperature_thinking") return "unsupported_parameter";
|
|
16670
|
+
return "model_request_invalid";
|
|
16671
|
+
}
|
|
16672
|
+
function toModelRequestError(err, parsed, provider, model) {
|
|
16673
|
+
return new ModelRequestError({
|
|
16674
|
+
status: err.statusCode ?? 400,
|
|
16675
|
+
code: codeFor(parsed),
|
|
16676
|
+
param: parsed?.param,
|
|
16677
|
+
value: parsed?.value,
|
|
16678
|
+
supportedValues: parsed?.supportedValues,
|
|
16679
|
+
provider: err.provider || provider,
|
|
16680
|
+
model,
|
|
16681
|
+
message: err.message,
|
|
16682
|
+
responseBody: err.responseBody
|
|
16683
|
+
});
|
|
16684
|
+
}
|
|
16685
|
+
var SameRequest = class extends Error {
|
|
16686
|
+
};
|
|
16687
|
+
function withoutCallerParams(step, callerParams) {
|
|
16688
|
+
const drops = step.patch.dropParams;
|
|
16689
|
+
if (!callerParams?.length || !drops) return step;
|
|
16690
|
+
const mine = (p) => callerParams.includes(p.split(".")[0]);
|
|
16691
|
+
if (!drops.some(mine)) return step;
|
|
16692
|
+
const { dropParams: _ignored, ...rest } = step.patch;
|
|
16693
|
+
const kept = drops.filter((p) => !mine(p));
|
|
16694
|
+
const patch = kept.length ? { ...rest, dropParams: kept } : rest;
|
|
16695
|
+
return Object.keys(patch).length ? { ...step, patch } : void 0;
|
|
16696
|
+
}
|
|
16697
|
+
async function runWithModelAdjustments(opts) {
|
|
16698
|
+
let overlay = {};
|
|
16699
|
+
const steps = [];
|
|
16700
|
+
let previous;
|
|
16701
|
+
let lastError;
|
|
16702
|
+
let lastParsed;
|
|
16703
|
+
for (; ; ) {
|
|
16704
|
+
const guard = (body) => {
|
|
16705
|
+
let json;
|
|
16706
|
+
try {
|
|
16707
|
+
json = JSON.stringify(body);
|
|
16708
|
+
} catch {
|
|
16709
|
+
return;
|
|
16710
|
+
}
|
|
16711
|
+
if (previous !== void 0 && json === previous) throw new SameRequest();
|
|
16712
|
+
previous = json;
|
|
16713
|
+
};
|
|
16714
|
+
try {
|
|
16715
|
+
const result = await opts.run(overlay, guard);
|
|
16716
|
+
for (const step of steps) {
|
|
16717
|
+
const s = withoutCallerParams(step, opts.callerParams);
|
|
16718
|
+
if (!s) continue;
|
|
16719
|
+
rememberModelRulePatch(opts.provider, opts.model, s.patch, opts.scope);
|
|
16720
|
+
if (opts.onLearned) {
|
|
16721
|
+
try {
|
|
16722
|
+
opts.onLearned({ provider: opts.provider, model: opts.model, adjustment: s.adjustment, patch: s.patch, reason: s.reason });
|
|
16723
|
+
} catch {
|
|
16724
|
+
}
|
|
16725
|
+
}
|
|
16726
|
+
}
|
|
16727
|
+
return result;
|
|
16728
|
+
} catch (err) {
|
|
16729
|
+
if (err instanceof SameRequest) throw toModelRequestError(lastError, lastParsed, opts.provider, opts.model);
|
|
16730
|
+
if (!(err instanceof ProviderError) || err instanceof ModelRequestError || err.statusCode !== 400) throw err;
|
|
16731
|
+
const parsed = parseModelError(String(err.responseBody ?? err.message));
|
|
16732
|
+
const fix = parsed ? patchFromParsedError(parsed, opts.endpoint) : void 0;
|
|
16733
|
+
lastError = err;
|
|
16734
|
+
lastParsed = parsed;
|
|
16735
|
+
if (!fix || steps.length >= MAX_ADJUSTMENTS) throw toModelRequestError(err, parsed, opts.provider, opts.model);
|
|
16736
|
+
overlay = mergeRulePatch(overlay, fix.patch);
|
|
16737
|
+
steps.push({ ...fix, reason: parsed.message });
|
|
16738
|
+
}
|
|
16739
|
+
}
|
|
16740
|
+
}
|
|
16741
|
+
function asModelRequestError(err, provider, model) {
|
|
16742
|
+
if (!(err instanceof ProviderError) || err instanceof ModelRequestError || err.statusCode !== 400) return err;
|
|
16743
|
+
return toModelRequestError(err, parseModelError(String(err.responseBody ?? err.message)), provider, model);
|
|
16744
|
+
}
|
|
16745
|
+
|
|
15477
16746
|
// src/providers/utils/media.ts
|
|
15478
16747
|
var EXTENSION_MIME = {
|
|
15479
16748
|
jpg: "image/jpeg",
|
|
@@ -15774,8 +17043,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15774
17043
|
if (this.useResponsesApi(request)) {
|
|
15775
17044
|
return this.completeResponses(request);
|
|
15776
17045
|
}
|
|
15777
|
-
const
|
|
15778
|
-
const res = await this.doFetch(body, request.signal);
|
|
17046
|
+
const res = await this.fetchChat(request, false);
|
|
15779
17047
|
const json = await res.json();
|
|
15780
17048
|
return this.parseResponse(json);
|
|
15781
17049
|
}
|
|
@@ -15799,8 +17067,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15799
17067
|
};
|
|
15800
17068
|
return;
|
|
15801
17069
|
}
|
|
15802
|
-
const
|
|
15803
|
-
const res = await this.doFetch(body, request.signal);
|
|
17070
|
+
const res = await this.fetchChat(request, true);
|
|
15804
17071
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15805
17072
|
let id = "";
|
|
15806
17073
|
let model = "";
|
|
@@ -15904,7 +17171,43 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15904
17171
|
return res;
|
|
15905
17172
|
}
|
|
15906
17173
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
15907
|
-
|
|
17174
|
+
/** Chat Completions call that corrects itself from the provider's own 400s (see models/adjust.ts). */
|
|
17175
|
+
fetchChat(request, stream) {
|
|
17176
|
+
const model = request.model || this.defaultModel;
|
|
17177
|
+
return runWithModelAdjustments({
|
|
17178
|
+
provider: this.providerName,
|
|
17179
|
+
model,
|
|
17180
|
+
endpoint: "chat",
|
|
17181
|
+
scope: this.baseURL,
|
|
17182
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
17183
|
+
onLearned: this.onModelRuleLearned,
|
|
17184
|
+
run: (overlay, guard) => {
|
|
17185
|
+
const body = this.buildRequestBody(request, stream, overlay);
|
|
17186
|
+
guard(body);
|
|
17187
|
+
return this.doFetch(body, request.signal);
|
|
17188
|
+
}
|
|
17189
|
+
});
|
|
17190
|
+
}
|
|
17191
|
+
/** Same for the Responses API. */
|
|
17192
|
+
fetchResponses(request, adaptExtras, stream = false) {
|
|
17193
|
+
const model = request.model || this.defaultModel;
|
|
17194
|
+
return runWithModelAdjustments({
|
|
17195
|
+
provider: this.providerName,
|
|
17196
|
+
model,
|
|
17197
|
+
endpoint: "responses",
|
|
17198
|
+
scope: this.baseURL,
|
|
17199
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
17200
|
+
onLearned: this.onModelRuleLearned,
|
|
17201
|
+
run: (overlay, guard) => {
|
|
17202
|
+
const body = this.buildResponsesBody(request, overlay);
|
|
17203
|
+
if (adaptExtras) adaptChatExtrasForResponses(body, request.extra);
|
|
17204
|
+
if (stream) body.stream = true;
|
|
17205
|
+
guard(body);
|
|
17206
|
+
return this.responsesFetch(body, request.signal);
|
|
17207
|
+
}
|
|
17208
|
+
});
|
|
17209
|
+
}
|
|
17210
|
+
buildRequestBody(request, stream, overlay) {
|
|
15908
17211
|
const body = {
|
|
15909
17212
|
model: request.model || this.defaultModel,
|
|
15910
17213
|
messages: request.messages.map((m) => this.toOpenAIMessage(m)),
|
|
@@ -15914,20 +17217,20 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15914
17217
|
body.stream_options = { include_usage: true };
|
|
15915
17218
|
}
|
|
15916
17219
|
const modelId = String(body.model);
|
|
15917
|
-
const
|
|
15918
|
-
if (request.temperature != null &&
|
|
17220
|
+
const rule = resolveModelRule({ provider: this.providerName, model: modelId, patch: overlay, scope: this.baseURL });
|
|
17221
|
+
if (request.temperature != null && allowsSampling(rule, "temperature", request.temperature)) body.temperature = request.temperature;
|
|
15919
17222
|
if (request.maxTokens != null) {
|
|
15920
|
-
const
|
|
15921
|
-
body[
|
|
17223
|
+
const param = this.maxTokensParam === "auto" ? rule.maxTokensParam : this.maxTokensParam;
|
|
17224
|
+
body[param] = request.maxTokens;
|
|
15922
17225
|
}
|
|
15923
|
-
if (request.topP != null &&
|
|
17226
|
+
if (request.topP != null && allowsSampling(rule, "topP")) body.top_p = request.topP;
|
|
15924
17227
|
if (request.stop) body.stop = request.stop;
|
|
15925
|
-
if (request.presencePenalty != null) body.presence_penalty = request.presencePenalty;
|
|
15926
|
-
if (request.frequencyPenalty != null) body.frequency_penalty = request.frequencyPenalty;
|
|
17228
|
+
if (request.presencePenalty != null && allowsSampling(rule, "presencePenalty")) body.presence_penalty = request.presencePenalty;
|
|
17229
|
+
if (request.frequencyPenalty != null && allowsSampling(rule, "frequencyPenalty")) body.frequency_penalty = request.frequencyPenalty;
|
|
15927
17230
|
if (request.seed != null) body.seed = request.seed;
|
|
15928
17231
|
if (request.n != null) body.n = request.n;
|
|
15929
|
-
if (request.logprobs != null) body.logprobs = request.logprobs;
|
|
15930
|
-
if (request.topLogprobs != null) body.top_logprobs = request.topLogprobs;
|
|
17232
|
+
if (request.logprobs != null && allowsSampling(rule, "logprobs")) body.logprobs = request.logprobs;
|
|
17233
|
+
if (request.topLogprobs != null && allowsSampling(rule, "logprobs")) body.top_logprobs = request.topLogprobs;
|
|
15931
17234
|
if (request.tools?.length) {
|
|
15932
17235
|
body.tools = request.tools.map((t) => this.toOpenAITool(t));
|
|
15933
17236
|
if (request.parallelToolCalls != null) body.parallel_tool_calls = request.parallelToolCalls;
|
|
@@ -15956,14 +17259,17 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15956
17259
|
if (request.extra) {
|
|
15957
17260
|
Object.assign(body, request.extra);
|
|
15958
17261
|
}
|
|
15959
|
-
applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
|
|
17262
|
+
applyOpenAIReasoning(body, request.reasoning, "legacy_effort", modelId, rule);
|
|
17263
|
+
if (body.tools?.length && rule.chatTools.reasoning === "force-none" && rule.reasoning.style !== "none") {
|
|
17264
|
+
body.reasoning_effort = "none";
|
|
17265
|
+
}
|
|
17266
|
+
applyDropParams(body, rule);
|
|
15960
17267
|
return body;
|
|
15961
17268
|
}
|
|
15962
17269
|
// ─── Responses API (reasoning models) ──────────────────────────────────────
|
|
15963
17270
|
async completeResponses(request) {
|
|
15964
|
-
const
|
|
15965
|
-
|
|
15966
|
-
const res = await this.responsesFetch(body, request.signal);
|
|
17271
|
+
const adapt = this.apiResponsesNative || this.isResponsesApiModel(request);
|
|
17272
|
+
const res = await this.fetchResponses(request, adapt);
|
|
15967
17273
|
const json = await res.json();
|
|
15968
17274
|
return this.parseResponsesResponse(json, request.model || this.defaultModel);
|
|
15969
17275
|
}
|
|
@@ -15976,10 +17282,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15976
17282
|
* reads it). */
|
|
15977
17283
|
async *streamResponses(request) {
|
|
15978
17284
|
const modelId = request.model || this.defaultModel;
|
|
15979
|
-
const
|
|
15980
|
-
adaptChatExtrasForResponses(body, request.extra);
|
|
15981
|
-
body.stream = true;
|
|
15982
|
-
const res = await this.responsesFetch(body, request.signal);
|
|
17285
|
+
const res = await this.fetchResponses(request, true, true);
|
|
15983
17286
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15984
17287
|
let id = "";
|
|
15985
17288
|
let model = modelId;
|
|
@@ -16068,13 +17371,14 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
16068
17371
|
finishReason: final?.finishReason ?? (calls.size > 0 ? "tool_calls" : "stop")
|
|
16069
17372
|
};
|
|
16070
17373
|
}
|
|
16071
|
-
buildResponsesBody(request) {
|
|
17374
|
+
buildResponsesBody(request, overlay) {
|
|
16072
17375
|
const body = {
|
|
16073
17376
|
model: request.model || this.defaultModel,
|
|
16074
17377
|
input: request.messages.map((m) => this.toResponsesInput(m))
|
|
16075
17378
|
};
|
|
16076
17379
|
if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
|
|
16077
|
-
|
|
17380
|
+
const rule = resolveModelRule({ provider: this.providerName, model: String(body.model), patch: overlay, scope: this.baseURL });
|
|
17381
|
+
if (request.topP != null && allowsSampling(rule, "topP")) body.top_p = request.topP;
|
|
16078
17382
|
if (request.tools?.length) {
|
|
16079
17383
|
body.tools = request.tools.map((t) => ({
|
|
16080
17384
|
type: "function",
|
|
@@ -16106,7 +17410,8 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
16106
17410
|
}
|
|
16107
17411
|
}
|
|
16108
17412
|
if (request.extra) Object.assign(body, request.extra);
|
|
16109
|
-
applyOpenAIReasoning(body, request.reasoning, "responses");
|
|
17413
|
+
applyOpenAIReasoning(body, request.reasoning, "responses", String(body.model), rule);
|
|
17414
|
+
applyDropParams(body, rule);
|
|
16110
17415
|
return body;
|
|
16111
17416
|
}
|
|
16112
17417
|
/** Maps a unified message to a Responses API `input` item. */
|
|
@@ -16371,8 +17676,8 @@ function pickProviderFields(top, message, choice) {
|
|
|
16371
17676
|
}
|
|
16372
17677
|
function isReasoningModel(model) {
|
|
16373
17678
|
if (!model) return false;
|
|
16374
|
-
const
|
|
16375
|
-
return
|
|
17679
|
+
const rule = resolveModelRule({ provider: "openai", model });
|
|
17680
|
+
return !rule.isDefault && rule.reasoning.style === "effort" && rule.sampling.temperature !== "any";
|
|
16376
17681
|
}
|
|
16377
17682
|
function adaptChatExtrasForResponses(body, extra) {
|
|
16378
17683
|
const native = extra ?? {};
|
|
@@ -16488,12 +17793,6 @@ function normalizeExplicitThinking(body) {
|
|
|
16488
17793
|
}
|
|
16489
17794
|
for (const k of ["temperature", "top_p", "top_k"]) delete body[k];
|
|
16490
17795
|
}
|
|
16491
|
-
function thinkingFormRejected(text) {
|
|
16492
|
-
const t = text.toLowerCase();
|
|
16493
|
-
if (t.indexOf("thinking.type.enabled") >= 0 && t.indexOf("not supported") >= 0) return "enabled";
|
|
16494
|
-
if (t.indexOf("thinking.type.adaptive") >= 0 && t.indexOf("not supported") >= 0 && t.indexOf("thinking.type.enabled") < 0) return "adaptive";
|
|
16495
|
-
return void 0;
|
|
16496
|
-
}
|
|
16497
17796
|
var AnthropicProvider = class extends BaseProvider {
|
|
16498
17797
|
constructor(config) {
|
|
16499
17798
|
super();
|
|
@@ -16644,7 +17943,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16644
17943
|
}
|
|
16645
17944
|
}
|
|
16646
17945
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
16647
|
-
buildRequestBody(request, stream,
|
|
17946
|
+
buildRequestBody(request, stream, overlay, downgradeToolChoice = false) {
|
|
16648
17947
|
const { system, messages } = this.splitSystemMessages(request.messages);
|
|
16649
17948
|
const body = {
|
|
16650
17949
|
model: request.model || this.defaultModel,
|
|
@@ -16659,6 +17958,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16659
17958
|
body.system = system;
|
|
16660
17959
|
}
|
|
16661
17960
|
}
|
|
17961
|
+
const rule = resolveModelRule({ provider: this.providerName, model: String(body.model), patch: overlay });
|
|
16662
17962
|
if (request.temperature != null) body.temperature = request.temperature;
|
|
16663
17963
|
if (request.topP != null) body.top_p = request.topP;
|
|
16664
17964
|
if (request.stop) body.stop_sequences = request.stop;
|
|
@@ -16685,9 +17985,11 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16685
17985
|
const explicitThinking = request.extra && typeof request.extra === "object" && "thinking" in request.extra;
|
|
16686
17986
|
if (explicitThinking) {
|
|
16687
17987
|
normalizeExplicitThinking(body);
|
|
17988
|
+
enforceAnthropicSampling(body, rule, body.thinking?.type === "enabled" || body.thinking?.type === "adaptive");
|
|
16688
17989
|
} else {
|
|
16689
|
-
applyAnthropicReasoning(body, request.reasoning, { model: body.model, mode:
|
|
17990
|
+
applyAnthropicReasoning(body, request.reasoning, { model: body.model, mode: this.thinkingMode, rule });
|
|
16690
17991
|
}
|
|
17992
|
+
applyDropParams(body, rule);
|
|
16691
17993
|
if (typeof body.max_tokens !== "number" || !(body.max_tokens > 0)) {
|
|
16692
17994
|
body.max_tokens = DEFAULT_MAX_TOKENS;
|
|
16693
17995
|
}
|
|
@@ -16823,31 +18125,28 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16823
18125
|
}
|
|
16824
18126
|
/** Builds and sends the request; retries once with the other thinking form
|
|
16825
18127
|
* when the upstream rejects the one we picked. */
|
|
16826
|
-
|
|
16827
|
-
let mode;
|
|
18128
|
+
send(request, stream) {
|
|
16828
18129
|
let downgrade = false;
|
|
16829
|
-
|
|
16830
|
-
|
|
16831
|
-
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
|
|
16835
|
-
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
|
|
16839
|
-
|
|
18130
|
+
return runWithModelAdjustments({
|
|
18131
|
+
provider: this.providerName,
|
|
18132
|
+
model: request.model || this.defaultModel,
|
|
18133
|
+
endpoint: "messages",
|
|
18134
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
18135
|
+
onLearned: this.onModelRuleLearned,
|
|
18136
|
+
run: async (overlay, guard) => {
|
|
18137
|
+
for (; ; ) {
|
|
18138
|
+
const body = this.buildRequestBody(request, stream, overlay, downgrade);
|
|
18139
|
+
guard(body);
|
|
18140
|
+
try {
|
|
18141
|
+
return await this.doFetch(body, request.signal);
|
|
18142
|
+
} catch (err) {
|
|
18143
|
+
const rejected = err instanceof ProviderError && err.statusCode === 400 && !downgrade && body.tool_choice && body.tool_choice.type !== "auto" && forcedToolChoiceRejected(String(err.responseBody ?? err.message));
|
|
18144
|
+
if (!rejected) throw err;
|
|
18145
|
+
downgrade = true;
|
|
18146
|
+
}
|
|
16840
18147
|
}
|
|
16841
|
-
const explicit = request.extra && typeof request.extra === "object" && "thinking" in request.extra;
|
|
16842
|
-
if (flippedThinking || explicit || !request.reasoning) throw err;
|
|
16843
|
-
const wrong = thinkingFormRejected(text);
|
|
16844
|
-
if (!wrong) throw err;
|
|
16845
|
-
const used = resolveThinkingForm(request.model ?? this.defaultModel, this.thinkingMode);
|
|
16846
|
-
if (wrong === "enabled" && used !== "budget" || wrong === "adaptive" && used !== "adaptive") throw err;
|
|
16847
|
-
mode = wrong === "enabled" ? "adaptive" : "budget";
|
|
16848
|
-
flippedThinking = true;
|
|
16849
18148
|
}
|
|
16850
|
-
}
|
|
18149
|
+
});
|
|
16851
18150
|
}
|
|
16852
18151
|
async doFetch(body, signal) {
|
|
16853
18152
|
const url = `${this.baseURL}/v1/messages`;
|
|
@@ -16964,6 +18263,7 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
16964
18263
|
retry: config.retry,
|
|
16965
18264
|
fetch: config.fetch,
|
|
16966
18265
|
timeoutMs: config.timeoutMs,
|
|
18266
|
+
onModelRuleLearned: config.onModelRuleLearned,
|
|
16967
18267
|
maxTokensParam: config.maxTokensParam,
|
|
16968
18268
|
api: config.api,
|
|
16969
18269
|
responsesApi: config.responsesApi,
|
|
@@ -17092,6 +18392,7 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
|
17092
18392
|
retry: config.retry,
|
|
17093
18393
|
fetch: config.fetch,
|
|
17094
18394
|
timeoutMs: config.timeoutMs,
|
|
18395
|
+
onModelRuleLearned: config.onModelRuleLearned,
|
|
17095
18396
|
maxTokensParam: config.maxTokensParam,
|
|
17096
18397
|
api: config.api,
|
|
17097
18398
|
// Unlike OpenAI / Azure, "auto" on a compatible server means Chat
|
|
@@ -17447,7 +18748,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
17447
18748
|
return res;
|
|
17448
18749
|
}
|
|
17449
18750
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
17450
|
-
buildConverseBody(request, downgradeToolChoice = false) {
|
|
18751
|
+
buildConverseBody(request, downgradeToolChoice = false, overlay) {
|
|
17451
18752
|
const { system, messages } = this.splitSystemMessages(request.messages);
|
|
17452
18753
|
const body = {
|
|
17453
18754
|
messages: this.toBedrockMessages(messages)
|
|
@@ -17493,7 +18794,12 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
17493
18794
|
Object.assign(body, topLevel);
|
|
17494
18795
|
if (Object.keys(fields).length > 0) body.additionalModelRequestFields = fields;
|
|
17495
18796
|
}
|
|
17496
|
-
|
|
18797
|
+
const rule = resolveModelRule({ provider: this.providerName, model: request.model || this.defaultModel, patch: overlay });
|
|
18798
|
+
applyBedrockReasoning(body, request.reasoning, { model: request.model || this.defaultModel, mode: this.thinkingMode, rule });
|
|
18799
|
+
if (body.inferenceConfig && rule.dropParams?.length) {
|
|
18800
|
+
for (const p of rule.dropParams) delete body.inferenceConfig[p === "top_p" ? "topP" : p === "max_tokens" ? "maxTokens" : p];
|
|
18801
|
+
}
|
|
18802
|
+
applyDropParams(body, rule);
|
|
17497
18803
|
return body;
|
|
17498
18804
|
}
|
|
17499
18805
|
splitSystemMessages(messages) {
|
|
@@ -17618,16 +18924,29 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
17618
18924
|
}
|
|
17619
18925
|
/** Sends the Converse call; retries once with toolChoice auto when the
|
|
17620
18926
|
* model rejects forced tool use. */
|
|
17621
|
-
|
|
17622
|
-
|
|
17623
|
-
|
|
17624
|
-
|
|
17625
|
-
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
18927
|
+
converseFetch(modelId, request, stream) {
|
|
18928
|
+
let downgrade = false;
|
|
18929
|
+
return runWithModelAdjustments({
|
|
18930
|
+
provider: this.providerName,
|
|
18931
|
+
model: modelId,
|
|
18932
|
+
endpoint: "converse",
|
|
18933
|
+
callerParams: request.extra ? Object.keys(request.extra) : void 0,
|
|
18934
|
+
onLearned: this.onModelRuleLearned,
|
|
18935
|
+
run: async (overlay, guard) => {
|
|
18936
|
+
for (; ; ) {
|
|
18937
|
+
const body = this.buildConverseBody(request, downgrade, overlay);
|
|
18938
|
+
guard(body);
|
|
18939
|
+
try {
|
|
18940
|
+
return await this.doFetch(modelId, body, request.signal, stream);
|
|
18941
|
+
} catch (err) {
|
|
18942
|
+
const tc = body.toolConfig?.toolChoice;
|
|
18943
|
+
const rejected = err instanceof ProviderError && err.statusCode === 400 && !downgrade && !!tc && !tc.auto && forcedToolChoiceRejected(String(err.responseBody ?? err.message));
|
|
18944
|
+
if (!rejected) throw err;
|
|
18945
|
+
downgrade = true;
|
|
18946
|
+
}
|
|
18947
|
+
}
|
|
18948
|
+
}
|
|
18949
|
+
});
|
|
17631
18950
|
}
|
|
17632
18951
|
async doFetch(modelId, body, signal, stream) {
|
|
17633
18952
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
@@ -17817,7 +19136,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
17817
19136
|
const modelId = request.model || this.defaultModel;
|
|
17818
19137
|
const body = this.buildGeminiBody(request);
|
|
17819
19138
|
const url = this.buildUrl(modelId, false);
|
|
17820
|
-
const res = await this.doFetch(url, body, request.signal);
|
|
19139
|
+
const res = await this.doFetch(url, body, request.signal, modelId);
|
|
17821
19140
|
const json = await res.json();
|
|
17822
19141
|
return this.parseResponse(json, modelId);
|
|
17823
19142
|
}
|
|
@@ -17825,7 +19144,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
17825
19144
|
const modelId = request.model || this.defaultModel;
|
|
17826
19145
|
const body = this.buildGeminiBody(request);
|
|
17827
19146
|
const url = this.buildUrl(modelId, true);
|
|
17828
|
-
const res = await this.doFetch(url, body, request.signal);
|
|
19147
|
+
const res = await this.doFetch(url, body, request.signal, modelId);
|
|
17829
19148
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
17830
19149
|
const counter = { next: 0 };
|
|
17831
19150
|
const contentType = res.headers.get("content-type") ?? "";
|
|
@@ -17905,7 +19224,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
17905
19224
|
};
|
|
17906
19225
|
if (Object.keys(parameters).length > 0) body.parameters = parameters;
|
|
17907
19226
|
Object.assign(body, extraRest);
|
|
17908
|
-
const res = await this.doFetch(url, body, request.signal);
|
|
19227
|
+
const res = await this.doFetch(url, body, request.signal, model);
|
|
17909
19228
|
const json = await res.json();
|
|
17910
19229
|
raw.push(json);
|
|
17911
19230
|
for (const p of json.predictions ?? []) {
|
|
@@ -18128,7 +19447,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
18128
19447
|
const tokenJson = await tokenRes.json();
|
|
18129
19448
|
return tokenJson.access_token;
|
|
18130
19449
|
}
|
|
18131
|
-
async doFetch(url, body, signal) {
|
|
19450
|
+
async doFetch(url, body, signal, model = "") {
|
|
18132
19451
|
const token = await this.getAccessToken();
|
|
18133
19452
|
const bodyStr = JSON.stringify(body);
|
|
18134
19453
|
const res = await this.doFetchWithRetry(
|
|
@@ -18146,6 +19465,20 @@ var VertexProvider = class extends BaseProvider {
|
|
|
18146
19465
|
);
|
|
18147
19466
|
if (!res.ok) {
|
|
18148
19467
|
const text = await res.text().catch(() => "");
|
|
19468
|
+
if (res.status === 400) {
|
|
19469
|
+
const parsed = parseModelError(text);
|
|
19470
|
+
throw new ModelRequestError({
|
|
19471
|
+
status: 400,
|
|
19472
|
+
code: parsed?.kind === "unsupported_value" ? "unsupported_value" : parsed?.kind === "unsupported_parameter" ? "unsupported_parameter" : "model_request_invalid",
|
|
19473
|
+
param: parsed?.param,
|
|
19474
|
+
value: parsed?.value,
|
|
19475
|
+
supportedValues: parsed?.supportedValues,
|
|
19476
|
+
provider: this.providerName,
|
|
19477
|
+
model,
|
|
19478
|
+
message: `Vertex AI API error ${res.status}: ${text}`,
|
|
19479
|
+
responseBody: text
|
|
19480
|
+
});
|
|
19481
|
+
}
|
|
18149
19482
|
throw new ProviderError(
|
|
18150
19483
|
`Vertex AI API error ${res.status}: ${text}`,
|
|
18151
19484
|
this.providerName,
|
|
@@ -18327,6 +19660,9 @@ exports.HOOK_NAMES = HOOK_NAMES;
|
|
|
18327
19660
|
exports.HookTimeoutError = HookTimeoutError;
|
|
18328
19661
|
exports.InMemoryMemoryStore = InMemoryMemoryStore;
|
|
18329
19662
|
exports.JevProvider = JevProvider;
|
|
19663
|
+
exports.MAX_ADJUSTMENTS = MAX_ADJUSTMENTS;
|
|
19664
|
+
exports.MODEL_RULES = MODEL_RULES;
|
|
19665
|
+
exports.ModelRequestError = ModelRequestError;
|
|
18330
19666
|
exports.NativeJsonSchemaStrategy = NativeJsonSchemaStrategy;
|
|
18331
19667
|
exports.OpenAICompatibleProvider = OpenAICompatibleProvider;
|
|
18332
19668
|
exports.OpenAIProvider = OpenAIProvider;
|
|
@@ -18338,7 +19674,10 @@ exports.TOOL_INPUT_DIGEST_KEY = TOOL_INPUT_DIGEST_KEY;
|
|
|
18338
19674
|
exports.ToolBasedStrategy = ToolBasedStrategy;
|
|
18339
19675
|
exports.VertexProvider = VertexProvider;
|
|
18340
19676
|
exports.agentVerdictRule = agentVerdictRule;
|
|
19677
|
+
exports.allowsSampling = allowsSampling;
|
|
18341
19678
|
exports.appendBoundTools = appendBoundTools;
|
|
19679
|
+
exports.applyDropParams = applyDropParams;
|
|
19680
|
+
exports.asModelRequestError = asModelRequestError;
|
|
18342
19681
|
exports.auditLog = auditLog;
|
|
18343
19682
|
exports.azureContentSafety = azureContentSafety;
|
|
18344
19683
|
exports.bedrockGuardrail = bedrockGuardrail;
|
|
@@ -18353,6 +19692,7 @@ exports.canOpenSkill = canOpenSkill;
|
|
|
18353
19692
|
exports.canSpawn = canSpawn;
|
|
18354
19693
|
exports.captureSnapshot = captureSnapshot;
|
|
18355
19694
|
exports.checkpointing = checkpointing;
|
|
19695
|
+
exports.clearLearnedModelRules = clearLearnedModelRules;
|
|
18356
19696
|
exports.codePresenceRule = codePresenceRule;
|
|
18357
19697
|
exports.coerceToolArgs = coerceToolArgs;
|
|
18358
19698
|
exports.cognipeerGuardrail = cognipeerGuardrail;
|
|
@@ -18415,6 +19755,7 @@ exports.detectTextFormat = detectTextFormat;
|
|
|
18415
19755
|
exports.detectVolatileContent = detectVolatileContent;
|
|
18416
19756
|
exports.digestToolInputArguments = digestToolInputArguments;
|
|
18417
19757
|
exports.digestToolInputValue = digestToolInputValue;
|
|
19758
|
+
exports.effortBudget = effortBudget;
|
|
18418
19759
|
exports.emptyUsage = emptyUsage;
|
|
18419
19760
|
exports.evaluateGuardrails = evaluateGuardrails;
|
|
18420
19761
|
exports.extractLatestUserQuery = extractLatestUserQuery;
|
|
@@ -18428,6 +19769,7 @@ exports.fromLangchainTools = fromLangchainTools;
|
|
|
18428
19769
|
exports.fromNativeProvider = fromNativeProvider;
|
|
18429
19770
|
exports.generateSpanId = generateSpanId;
|
|
18430
19771
|
exports.generateTraceId = generateTraceId;
|
|
19772
|
+
exports.getLearnedModelRulePatch = getLearnedModelRulePatch;
|
|
18431
19773
|
exports.getModelCapabilities = getModelCapabilities;
|
|
18432
19774
|
exports.getNestedValue = getNestedValue;
|
|
18433
19775
|
exports.getResolvedSmartConfig = getResolvedSmartConfig;
|
|
@@ -18448,12 +19790,16 @@ exports.jsonSchemaRule = jsonSchemaRule;
|
|
|
18448
19790
|
exports.langfuseDefaultPayload = defaultBuildPayload;
|
|
18449
19791
|
exports.langfuseTracing = langfuseTracing;
|
|
18450
19792
|
exports.languageGuard = languageGuard;
|
|
19793
|
+
exports.listLearnedModelRules = listLearnedModelRules;
|
|
18451
19794
|
exports.loadSkillsFromDisk = loadSkillsFromDisk;
|
|
18452
19795
|
exports.mapConsoleHookVerdict = mapConsoleHookVerdict;
|
|
19796
|
+
exports.mapReasoningEffort = mapReasoningEffort;
|
|
18453
19797
|
exports.mapTextParts = mapTextParts;
|
|
18454
19798
|
exports.mcp = mcp;
|
|
18455
19799
|
exports.mediaKindOf = mediaKindOf;
|
|
18456
19800
|
exports.mediaPolicy = mediaPolicy;
|
|
19801
|
+
exports.mergeRulePatch = mergeRulePatch;
|
|
19802
|
+
exports.modelIdCandidates = modelIdCandidates;
|
|
18457
19803
|
exports.normalizeSmartAgentOptions = normalizeSmartAgentOptions;
|
|
18458
19804
|
exports.normalizeVerdicts = normalizeVerdicts;
|
|
18459
19805
|
exports.openAIModeration = openAIModeration;
|
|
@@ -18461,6 +19807,7 @@ exports.otelTracing = otelTracing;
|
|
|
18461
19807
|
exports.otlpSink = otlpSink;
|
|
18462
19808
|
exports.outputGuard = outputGuard;
|
|
18463
19809
|
exports.parseApprovalDecision = parseApprovalDecision;
|
|
19810
|
+
exports.parseModelError = parseModelError;
|
|
18464
19811
|
exports.parseSkillFrontmatter = parseSkillFrontmatter;
|
|
18465
19812
|
exports.pathSandbox = pathSandbox;
|
|
18466
19813
|
exports.piiRedaction = piiRedaction;
|
|
@@ -18473,14 +19820,17 @@ exports.prepareStrictToolMenu = prepareStrictToolMenu;
|
|
|
18473
19820
|
exports.promptInjectionGuard = promptInjectionGuard;
|
|
18474
19821
|
exports.rateLimit = rateLimit;
|
|
18475
19822
|
exports.readMemoryFacts = readMemoryFacts;
|
|
19823
|
+
exports.readTraceContinuation = readTraceContinuation;
|
|
18476
19824
|
exports.redactText = redactText;
|
|
18477
19825
|
exports.regexGuardrail = regexGuardrail;
|
|
18478
19826
|
exports.regexRule = regexRule;
|
|
19827
|
+
exports.rememberModelRulePatch = rememberModelRulePatch;
|
|
18479
19828
|
exports.replaceTextContent = replaceTextContent;
|
|
18480
19829
|
exports.resolveAvailableSkills = resolveAvailableSkills;
|
|
18481
19830
|
exports.resolveAvailableSubagents = resolveAvailableSubagents;
|
|
18482
19831
|
exports.resolveInputRetention = resolveInputRetention;
|
|
18483
19832
|
exports.resolveMemoryStore = resolveMemoryStore;
|
|
19833
|
+
exports.resolveModelRule = resolveModelRule;
|
|
18484
19834
|
exports.resolveReasoning = resolveReasoning;
|
|
18485
19835
|
exports.resolveStrategy = resolveStrategy;
|
|
18486
19836
|
exports.resolveSubagentTools = resolveSubagentTools;
|
|
@@ -18491,6 +19841,7 @@ exports.responseCache = responseCache;
|
|
|
18491
19841
|
exports.restoreSnapshot = restoreSnapshot;
|
|
18492
19842
|
exports.restoreToolCalls = restoreToolCalls;
|
|
18493
19843
|
exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
|
|
19844
|
+
exports.runWithModelAdjustments = runWithModelAdjustments;
|
|
18494
19845
|
exports.scoreItemsByRelevance = scoreItemsByRelevance;
|
|
18495
19846
|
exports.searchSkills = searchSkills;
|
|
18496
19847
|
exports.seedChildMessages = seedChildMessages;
|
|
@@ -18506,6 +19857,7 @@ exports.toStrictCompatible = toStrictCompatible;
|
|
|
18506
19857
|
exports.toStrictToolSchema = toStrictToolSchema;
|
|
18507
19858
|
exports.tokenize = tokenize;
|
|
18508
19859
|
exports.toolPolicy = toolPolicy;
|
|
19860
|
+
exports.traceContinuationOf = traceContinuationOf;
|
|
18509
19861
|
exports.traceSessionToOtlp = traceSessionToOtlp;
|
|
18510
19862
|
exports.validateReasoningConfig = validateReasoningConfig;
|
|
18511
19863
|
exports.validateToolArgs = validateToolArgs;
|