@cognipeer/agent-sdk 0.5.4 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -14
- package/dist/index.cjs +415 -190
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +134 -22
- package/dist/index.d.ts +134 -22
- package/dist/index.mjs +416 -191
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1978,7 +1978,9 @@ function createAgentCoreNode(opts) {
|
|
|
1978
1978
|
const cancellationToken = state.ctx?.__cancellationToken;
|
|
1979
1979
|
const abortSignal = state.ctx?.__abortSignal;
|
|
1980
1980
|
const responseFormat = runtime.responseFormat;
|
|
1981
|
-
const
|
|
1981
|
+
const reasoningForCall = state.ctx?.__reasoning;
|
|
1982
|
+
const reasoningInvokeOpts = reasoningForCall ? { reasoning: reasoningForCall } : void 0;
|
|
1983
|
+
const extractText2 = (chunk) => {
|
|
1982
1984
|
if (chunk == null) return "";
|
|
1983
1985
|
if (typeof chunk === "string") return chunk;
|
|
1984
1986
|
if (typeof chunk?.content === "string") return chunk.content;
|
|
@@ -1996,7 +1998,7 @@ function createAgentCoreNode(opts) {
|
|
|
1996
1998
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
1997
1999
|
let streamedText = "";
|
|
1998
2000
|
let streamedMessage;
|
|
1999
|
-
const streamOptions = { signal: abortSignal, cancellationToken, ...responseFormat };
|
|
2001
|
+
const streamOptions = { signal: abortSignal, cancellationToken, ...responseFormat, ...reasoningInvokeOpts };
|
|
2000
2002
|
for await (const chunk of modelWithTools.stream(normalizedMessages, streamOptions)) {
|
|
2001
2003
|
if (cancellationToken && cancellationToken.isCancellationRequested || abortSignal?.aborted) {
|
|
2002
2004
|
break;
|
|
@@ -2004,7 +2006,7 @@ function createAgentCoreNode(opts) {
|
|
|
2004
2006
|
if (chunk && typeof chunk === "object" && chunk.role) {
|
|
2005
2007
|
streamedMessage = chunk;
|
|
2006
2008
|
}
|
|
2007
|
-
const text =
|
|
2009
|
+
const text = extractText2(chunk);
|
|
2008
2010
|
if (text) {
|
|
2009
2011
|
streamedText += text;
|
|
2010
2012
|
onStream?.({ text });
|
|
@@ -2020,7 +2022,7 @@ function createAgentCoreNode(opts) {
|
|
|
2020
2022
|
response = { role: "assistant", content: streamedText };
|
|
2021
2023
|
}
|
|
2022
2024
|
} else {
|
|
2023
|
-
response = await modelWithTools.invoke(normalizedMessages, { signal: abortSignal, cancellationToken, ...responseFormat });
|
|
2025
|
+
response = await modelWithTools.invoke(normalizedMessages, { signal: abortSignal, cancellationToken, ...responseFormat, ...reasoningInvokeOpts });
|
|
2024
2026
|
}
|
|
2025
2027
|
} catch (err) {
|
|
2026
2028
|
const durationMs2 = Date.now() - start;
|
|
@@ -2136,18 +2138,13 @@ var BASE_DEFAULTS = {
|
|
|
2136
2138
|
requireJsonOutputContract: true
|
|
2137
2139
|
},
|
|
2138
2140
|
toolResponses: {
|
|
2139
|
-
maxToolResponseChars:
|
|
2140
|
-
maxToolResponseTokens:
|
|
2141
|
-
|
|
2142
|
-
smallResponsePolicy: "keep_full",
|
|
2143
|
-
defaultPolicy: "keep_structured",
|
|
2144
|
-
largeResponsePolicy: "summarize_archive",
|
|
2141
|
+
maxToolResponseChars: 12e3,
|
|
2142
|
+
maxToolResponseTokens: 3e3,
|
|
2143
|
+
defaultPolicy: "summarize_archive",
|
|
2145
2144
|
toolResponseRetentionByTool: {},
|
|
2146
2145
|
criticalTools: [...DEFAULT_CRITICAL_TOOLS],
|
|
2147
2146
|
schemaValidation: "strict",
|
|
2148
|
-
retryOnSchemaError: true
|
|
2149
|
-
fallbackPolicy: "keep_full",
|
|
2150
|
-
keepRecentFullCount: 0
|
|
2147
|
+
retryOnSchemaError: true
|
|
2151
2148
|
}
|
|
2152
2149
|
};
|
|
2153
2150
|
function buildProfile(overrides) {
|
|
@@ -2186,7 +2183,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2186
2183
|
},
|
|
2187
2184
|
memory: { readPolicy: "recent_only" },
|
|
2188
2185
|
delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
|
|
2189
|
-
toolResponses: { maxToolResponseChars:
|
|
2186
|
+
toolResponses: { maxToolResponseChars: 8e3, maxToolResponseTokens: 2e3 }
|
|
2190
2187
|
}),
|
|
2191
2188
|
balanced: buildProfile({}),
|
|
2192
2189
|
deep: buildProfile({
|
|
@@ -2203,7 +2200,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2203
2200
|
},
|
|
2204
2201
|
memory: { scope: "workspace" },
|
|
2205
2202
|
delegation: { maxDelegationDepth: 3, maxChildCalls: 6 },
|
|
2206
|
-
toolResponses: { maxToolResponseChars:
|
|
2203
|
+
toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
|
|
2207
2204
|
}),
|
|
2208
2205
|
research: buildProfile({
|
|
2209
2206
|
limits: { maxToolCalls: 20, maxParallelTools: 4, maxContextTokens: 56e3 },
|
|
@@ -2219,7 +2216,7 @@ var DEFAULT_PROFILE_CONFIGS = {
|
|
|
2219
2216
|
},
|
|
2220
2217
|
memory: { scope: "workspace" },
|
|
2221
2218
|
delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 8, maxParallelChild: 3, childContextPolicy: "full" },
|
|
2222
|
-
toolResponses: { maxToolResponseChars:
|
|
2219
|
+
toolResponses: { maxToolResponseChars: 24e3, maxToolResponseTokens: 6e3 }
|
|
2223
2220
|
})
|
|
2224
2221
|
};
|
|
2225
2222
|
function mergeLimits(base, override) {
|
|
@@ -2426,63 +2423,65 @@ function summarizeObject(value) {
|
|
|
2426
2423
|
return safeStringify(value);
|
|
2427
2424
|
}
|
|
2428
2425
|
function classifyToolResponse(toolName, output, config) {
|
|
2429
|
-
const serialized = safeStringify(output);
|
|
2430
|
-
const tokenCount = countApproxTokens(serialized);
|
|
2431
2426
|
const criticalTools = new Set(config.toolResponses.criticalTools);
|
|
2432
2427
|
if (criticalTools.has(toolName)) return "critical";
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
}
|
|
2428
|
+
const serialized = safeStringify(output);
|
|
2429
|
+
const tokenCount = countApproxTokens(serialized);
|
|
2436
2430
|
if (tokenCount >= config.toolResponses.maxToolResponseTokens || serialized.length >= config.toolResponses.maxToolResponseChars) {
|
|
2437
2431
|
return "verbose";
|
|
2438
2432
|
}
|
|
2439
|
-
const smallChars = config.toolResponses.smallResponseChars;
|
|
2440
|
-
if (smallChars > 0 && serialized.length <= smallChars) {
|
|
2441
|
-
return "small";
|
|
2442
|
-
}
|
|
2443
2433
|
return "informative";
|
|
2444
2434
|
}
|
|
2445
|
-
function
|
|
2435
|
+
function applyToolResponseHardCap(toolName, output, executionId, config) {
|
|
2446
2436
|
const serialized = safeStringify(output);
|
|
2447
2437
|
const tokenCount = countApproxTokens(serialized);
|
|
2448
2438
|
const classification = classifyToolResponse(toolName, output, config);
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
if (byTool) ; else if (classification === "critical") {
|
|
2452
|
-
retentionPolicy = config.toolResponses.fallbackPolicy;
|
|
2453
|
-
} else if (classification === "verbose") {
|
|
2454
|
-
retentionPolicy = config.toolResponses.largeResponsePolicy;
|
|
2455
|
-
} else if (classification === "small") {
|
|
2456
|
-
retentionPolicy = config.toolResponses.smallResponsePolicy;
|
|
2457
|
-
} else if (classification === "redundant") {
|
|
2458
|
-
retentionPolicy = "drop";
|
|
2459
|
-
}
|
|
2460
|
-
const summary = summarizeObject(output);
|
|
2461
|
-
if (retentionPolicy === "keep_full") {
|
|
2462
|
-
return { classification, retentionPolicy, content: serialized, rawOutput: output, summary, tokenCount };
|
|
2463
|
-
}
|
|
2464
|
-
if (retentionPolicy === "keep_structured") {
|
|
2465
|
-
return { classification, retentionPolicy, content: summary, rawOutput: output, summary, tokenCount };
|
|
2466
|
-
}
|
|
2467
|
-
if (retentionPolicy === "summarize_archive") {
|
|
2468
|
-
return {
|
|
2469
|
-
classification,
|
|
2470
|
-
retentionPolicy,
|
|
2471
|
-
content: `ARCHIVED_TOOL_RESPONSE: ${summary}`,
|
|
2472
|
-
rawOutput: output,
|
|
2473
|
-
summary,
|
|
2474
|
-
tokenCount
|
|
2475
|
-
};
|
|
2439
|
+
if (classification !== "verbose") {
|
|
2440
|
+
return { classification, content: serialized, rawOutput: output, tokenCount, truncated: false };
|
|
2476
2441
|
}
|
|
2442
|
+
const cap = config.toolResponses.maxToolResponseChars;
|
|
2443
|
+
const head = serialized.slice(0, cap);
|
|
2444
|
+
const note = `
|
|
2445
|
+
... [TRUNCATED ${serialized.length - cap} chars by hard cap. Use get_tool_response with executionId="${executionId}" to fetch the full payload.]`;
|
|
2477
2446
|
return {
|
|
2478
2447
|
classification,
|
|
2479
|
-
|
|
2480
|
-
content: `DROPPED_TOOL_RESPONSE: ${summary}`,
|
|
2448
|
+
content: head + note,
|
|
2481
2449
|
rawOutput: output,
|
|
2482
|
-
|
|
2483
|
-
|
|
2450
|
+
tokenCount,
|
|
2451
|
+
truncated: true
|
|
2484
2452
|
};
|
|
2485
2453
|
}
|
|
2454
|
+
function resolveSummarizationRetention(toolName, config) {
|
|
2455
|
+
const criticalTools = new Set(config.toolResponses.criticalTools);
|
|
2456
|
+
if (criticalTools.has(toolName)) return "keep_full";
|
|
2457
|
+
const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
|
|
2458
|
+
return byTool || config.toolResponses.defaultPolicy;
|
|
2459
|
+
}
|
|
2460
|
+
function renderRetainedToolMessage(args) {
|
|
2461
|
+
const { policy, rawOutput, toolName, toolCallId, executionId, prebuiltSummary } = args;
|
|
2462
|
+
if (policy === "keep_full") {
|
|
2463
|
+
return typeof rawOutput === "string" ? rawOutput : safeStringify(rawOutput);
|
|
2464
|
+
}
|
|
2465
|
+
const summary = prebuiltSummary || summarizeObject(rawOutput);
|
|
2466
|
+
const refs = [
|
|
2467
|
+
`toolName=${toolName}`,
|
|
2468
|
+
toolCallId ? `toolCallId=${toolCallId}` : null,
|
|
2469
|
+
executionId ? `executionId=${executionId}` : null
|
|
2470
|
+
].filter(Boolean).join("; ");
|
|
2471
|
+
const refId = executionId || toolCallId || "";
|
|
2472
|
+
if (policy === "keep_structured") {
|
|
2473
|
+
return `STRUCTURED_TOOL_RESPONSE [${refs}]
|
|
2474
|
+
Preview: ${summary}
|
|
2475
|
+
Use get_tool_response with executionId "${refId}" to fetch the full payload when a specific field is needed.`;
|
|
2476
|
+
}
|
|
2477
|
+
if (policy === "summarize_archive") {
|
|
2478
|
+
return `ARCHIVED_TOOL_RESPONSE [${refs}]
|
|
2479
|
+
Summary: ${summary}
|
|
2480
|
+
Use get_tool_response with executionId "${refId}" to fetch the full payload.`;
|
|
2481
|
+
}
|
|
2482
|
+
return `DROPPED_TOOL_RESPONSE [${refs}]
|
|
2483
|
+
Use get_tool_response with executionId "${refId}" only if you must recover the original payload.`;
|
|
2484
|
+
}
|
|
2486
2485
|
function validateToolArgs(tool, args) {
|
|
2487
2486
|
const schema = tool.schema;
|
|
2488
2487
|
if (!schema || typeof schema.parse !== "function") {
|
|
@@ -2761,52 +2760,25 @@ function createToolsNode(initialTools, opts) {
|
|
|
2761
2760
|
state.ctx.__structuredOutputParsed = output.data;
|
|
2762
2761
|
state.ctx.__finalizedDueToStructuredOutput = true;
|
|
2763
2762
|
}
|
|
2764
|
-
const responsePolicy =
|
|
2763
|
+
const responsePolicy = applyToolResponseHardCap(toolName, output, executionId, resolved);
|
|
2765
2764
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2766
|
-
const storedOutput = responsePolicy.retentionPolicy === "keep_full" ? output : responsePolicy.summary;
|
|
2767
2765
|
toolHistory.push({
|
|
2768
2766
|
executionId,
|
|
2769
2767
|
toolName,
|
|
2770
2768
|
args,
|
|
2771
|
-
output
|
|
2769
|
+
output,
|
|
2772
2770
|
rawOutput: output,
|
|
2773
2771
|
timestamp,
|
|
2774
2772
|
tool_call_id: tc.id,
|
|
2775
|
-
summarized:
|
|
2773
|
+
summarized: false,
|
|
2776
2774
|
originalTokenCount: responsePolicy.tokenCount,
|
|
2777
2775
|
classification: responsePolicy.classification,
|
|
2778
|
-
retentionPolicy:
|
|
2779
|
-
summary:
|
|
2780
|
-
archiveId:
|
|
2776
|
+
retentionPolicy: "keep_full",
|
|
2777
|
+
summary: void 0,
|
|
2778
|
+
archiveId: void 0,
|
|
2781
2779
|
status: "success"
|
|
2782
2780
|
});
|
|
2783
|
-
|
|
2784
|
-
toolHistoryArchived.push({
|
|
2785
|
-
executionId,
|
|
2786
|
-
toolName,
|
|
2787
|
-
args,
|
|
2788
|
-
output,
|
|
2789
|
-
rawOutput: output,
|
|
2790
|
-
timestamp,
|
|
2791
|
-
tool_call_id: tc.id,
|
|
2792
|
-
summarized: true,
|
|
2793
|
-
originalTokenCount: responsePolicy.tokenCount,
|
|
2794
|
-
classification: responsePolicy.classification,
|
|
2795
|
-
retentionPolicy: responsePolicy.retentionPolicy,
|
|
2796
|
-
summary: responsePolicy.summary,
|
|
2797
|
-
archiveId: executionId,
|
|
2798
|
-
status: "success"
|
|
2799
|
-
});
|
|
2800
|
-
}
|
|
2801
|
-
let toolMessageContent = responsePolicy.content;
|
|
2802
|
-
if (responsePolicy.retentionPolicy === "summarize_archive") {
|
|
2803
|
-
toolMessageContent = `ARCHIVED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
|
|
2804
|
-
Only use get_tool_response with executionId "${executionId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
2805
|
-
} else if (responsePolicy.retentionPolicy === "drop") {
|
|
2806
|
-
toolMessageContent = `DROPPED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
|
|
2807
|
-
Only use get_tool_response with executionId "${executionId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
2808
|
-
}
|
|
2809
|
-
appended.push({ role: "tool", content: toolMessageContent, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
|
|
2781
|
+
appended.push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
|
|
2810
2782
|
onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
|
|
2811
2783
|
onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
|
|
2812
2784
|
if (needsApproval && approvalEntry) {
|
|
@@ -2850,8 +2822,9 @@ Only use get_tool_response with executionId "${executionId}" if this summary is
|
|
|
2850
2822
|
messageList,
|
|
2851
2823
|
debug: {
|
|
2852
2824
|
classification: responsePolicy.classification,
|
|
2853
|
-
retentionPolicy:
|
|
2854
|
-
originalTokenCount: responsePolicy.tokenCount
|
|
2825
|
+
retentionPolicy: "keep_full",
|
|
2826
|
+
originalTokenCount: responsePolicy.tokenCount,
|
|
2827
|
+
truncated: responsePolicy.truncated
|
|
2855
2828
|
}
|
|
2856
2829
|
});
|
|
2857
2830
|
toolCount += 1;
|
|
@@ -2968,6 +2941,246 @@ function createToolLimitFinalizeNode(_opts) {
|
|
|
2968
2941
|
return { messages: [...state.messages, notice], ctx };
|
|
2969
2942
|
};
|
|
2970
2943
|
}
|
|
2944
|
+
var REFLECTION_SYSTEM_NAME = "agent_reflection";
|
|
2945
|
+
var REFLECTION_ASK_NAME = "agent_reflection_ask";
|
|
2946
|
+
var DEFAULT_REFLECT_PROMPT = `Reflect briefly \u2014 plain text, no JSON, no tool calls.
|
|
2947
|
+
Structure your note (1\u20132 sentences each):
|
|
2948
|
+
1) What the latest tool results actually tell us (facts, surprises).
|
|
2949
|
+
2) What is still missing or uncertain before we can finish the user's task.
|
|
2950
|
+
3) The single next step you plan to take, and why that step over alternatives.
|
|
2951
|
+
Be concrete. Do not repeat the task description. Do not apologize. Max ${"${maxChars}"} characters total.`;
|
|
2952
|
+
function trimToChars(text, maxChars) {
|
|
2953
|
+
if (text.length <= maxChars) return text;
|
|
2954
|
+
return text.slice(0, maxChars - 1).trimEnd() + "\u2026";
|
|
2955
|
+
}
|
|
2956
|
+
function countToolCallsInLastTurn(state) {
|
|
2957
|
+
const ids = [];
|
|
2958
|
+
const names = [];
|
|
2959
|
+
for (let i = state.messages.length - 1; i >= 0; i--) {
|
|
2960
|
+
const m = state.messages[i];
|
|
2961
|
+
if (m?.role === "tool") {
|
|
2962
|
+
if (m.tool_call_id) ids.push(m.tool_call_id);
|
|
2963
|
+
if (m.name) names.push(m.name);
|
|
2964
|
+
} else if (m?.role === "assistant") {
|
|
2965
|
+
break;
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
return { ids, names };
|
|
2969
|
+
}
|
|
2970
|
+
function stripReflectionAskMessages(messages) {
|
|
2971
|
+
return messages.filter((m) => !(m?.role === "user" && m?.name === REFLECTION_ASK_NAME));
|
|
2972
|
+
}
|
|
2973
|
+
function shouldRunReflection(cadence, state, ranToolsThisTurn) {
|
|
2974
|
+
if (cadence === "off") return false;
|
|
2975
|
+
if (cadence === "every_turn") return true;
|
|
2976
|
+
if (cadence === "after_tool") return ranToolsThisTurn;
|
|
2977
|
+
if (cadence === "on_branch") {
|
|
2978
|
+
const reflections = state.reflections || [];
|
|
2979
|
+
const lastReflectionTurn = reflections[reflections.length - 1]?.turn ?? -1;
|
|
2980
|
+
const currentTurnId = state.toolCallCount ?? 0;
|
|
2981
|
+
return currentTurnId - lastReflectionTurn >= 2;
|
|
2982
|
+
}
|
|
2983
|
+
return false;
|
|
2984
|
+
}
|
|
2985
|
+
function createReflectionNode(opts, resolved) {
|
|
2986
|
+
return async function reflectNode(state, trigger) {
|
|
2987
|
+
if (!resolved.enabled) return {};
|
|
2988
|
+
const runtime = state.agent || {
|
|
2989
|
+
model: opts.model,
|
|
2990
|
+
name: opts.name,
|
|
2991
|
+
version: opts.version
|
|
2992
|
+
};
|
|
2993
|
+
const model = runtime.model;
|
|
2994
|
+
if (!model?.invoke && !model?.stream) return {};
|
|
2995
|
+
const onEvent = state.ctx?.__onEvent;
|
|
2996
|
+
const traceSession = state.ctx?.__traceSession;
|
|
2997
|
+
const maxChars = resolved.maxChars;
|
|
2998
|
+
const promptBody = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
|
|
2999
|
+
const baseMessages = stripReflectionAskMessages([...state.messages]);
|
|
3000
|
+
const askMessage = {
|
|
3001
|
+
role: "user",
|
|
3002
|
+
name: REFLECTION_ASK_NAME,
|
|
3003
|
+
content: promptBody
|
|
3004
|
+
};
|
|
3005
|
+
const messagesForCall = resolved.mode === "piggyback" ? [...baseMessages, askMessage] : buildSeparateCallMessages(baseMessages, promptBody);
|
|
3006
|
+
const start = Date.now();
|
|
3007
|
+
let response;
|
|
3008
|
+
try {
|
|
3009
|
+
response = await model.invoke(messagesForCall, {
|
|
3010
|
+
// tool_choice:"none" so the model won't try to call tools during reflection
|
|
3011
|
+
tool_choice: "none",
|
|
3012
|
+
toolChoice: "none",
|
|
3013
|
+
// Override max_tokens for the reflection call. BaseChatModel passes this through
|
|
3014
|
+
// to the adapter which forwards into the provider body.
|
|
3015
|
+
max_tokens: resolved.maxTokens,
|
|
3016
|
+
maxTokens: resolved.maxTokens
|
|
3017
|
+
});
|
|
3018
|
+
} catch (err) {
|
|
3019
|
+
recordTraceEvent(traceSession, {
|
|
3020
|
+
type: "reflection",
|
|
3021
|
+
label: "Reflection error",
|
|
3022
|
+
actor: { scope: "agent", name: opts.name || "agent", role: "reflection" },
|
|
3023
|
+
status: "error",
|
|
3024
|
+
error: { message: err?.message || String(err) }
|
|
3025
|
+
});
|
|
3026
|
+
return {};
|
|
3027
|
+
}
|
|
3028
|
+
const durationMs = Date.now() - start;
|
|
3029
|
+
const rawText = extractText(response);
|
|
3030
|
+
const text = trimToChars(String(rawText ?? "").trim(), maxChars);
|
|
3031
|
+
if (!text) return {};
|
|
3032
|
+
const rawUsage = response?.usage_metadata || response?.response_metadata?.usage || response?.usage || response?.additional_kwargs?.usage;
|
|
3033
|
+
const usage = normalizeUsage(rawUsage);
|
|
3034
|
+
const { ids, names } = countToolCallsInLastTurn(state);
|
|
3035
|
+
const turn = state.toolCallCount ?? 0;
|
|
3036
|
+
const record = {
|
|
3037
|
+
id: safeRandomId(),
|
|
3038
|
+
turn,
|
|
3039
|
+
text,
|
|
3040
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3041
|
+
durationMs,
|
|
3042
|
+
anchorMessageIndex: state.messages.length,
|
|
3043
|
+
trigger,
|
|
3044
|
+
usage: usage ? {
|
|
3045
|
+
inputTokens: usage.prompt_tokens,
|
|
3046
|
+
outputTokens: usage.completion_tokens,
|
|
3047
|
+
cachedInputTokens: usage.prompt_tokens_details?.cached_tokens,
|
|
3048
|
+
totalTokens: usage.total_tokens,
|
|
3049
|
+
reasoningTokens: usage.completion_tokens_details?.reasoning_tokens
|
|
3050
|
+
} : void 0,
|
|
3051
|
+
toolCallIds: ids.length > 0 ? ids : void 0
|
|
3052
|
+
};
|
|
3053
|
+
recordTraceEvent(traceSession, {
|
|
3054
|
+
type: "reflection",
|
|
3055
|
+
label: `Reflection turn ${turn}`,
|
|
3056
|
+
actor: { scope: "agent", name: opts.name || "agent", role: "reflection" },
|
|
3057
|
+
status: "success",
|
|
3058
|
+
durationMs,
|
|
3059
|
+
inputTokens: record.usage?.inputTokens,
|
|
3060
|
+
outputTokens: record.usage?.outputTokens,
|
|
3061
|
+
cachedInputTokens: record.usage?.cachedInputTokens,
|
|
3062
|
+
totalTokens: record.usage?.totalTokens,
|
|
3063
|
+
debug: { text, toolNames: names }
|
|
3064
|
+
});
|
|
3065
|
+
if (resolved.emitEvents) {
|
|
3066
|
+
try {
|
|
3067
|
+
onEvent?.({
|
|
3068
|
+
type: "reflection",
|
|
3069
|
+
id: record.id,
|
|
3070
|
+
turn,
|
|
3071
|
+
text,
|
|
3072
|
+
trigger,
|
|
3073
|
+
durationMs,
|
|
3074
|
+
usage: record.usage,
|
|
3075
|
+
toolCallIds: record.toolCallIds
|
|
3076
|
+
});
|
|
3077
|
+
} catch (e) {
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
const nextMessages = stripReflectionAskMessages([...state.messages]);
|
|
3081
|
+
const reflections = [...state.reflections || [], record];
|
|
3082
|
+
const kept = reflections.slice(-Math.max(1, resolved.keepLast));
|
|
3083
|
+
const prunedMessages = nextMessages.filter(
|
|
3084
|
+
(m) => !(m?.role === "system" && m?.name === REFLECTION_SYSTEM_NAME)
|
|
3085
|
+
);
|
|
3086
|
+
for (const r of kept) {
|
|
3087
|
+
prunedMessages.push({
|
|
3088
|
+
role: "system",
|
|
3089
|
+
name: REFLECTION_SYSTEM_NAME,
|
|
3090
|
+
content: `<agent_reflection turn=${r.turn} at=${r.createdAt}>
|
|
3091
|
+
${r.text}
|
|
3092
|
+
</agent_reflection>`,
|
|
3093
|
+
metadata: { reflectionId: r.id, reflectionTurn: r.turn, reflectionTrigger: r.trigger }
|
|
3094
|
+
});
|
|
3095
|
+
}
|
|
3096
|
+
return { messages: prunedMessages, reflections };
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
function extractText(chunk) {
|
|
3100
|
+
if (chunk == null) return "";
|
|
3101
|
+
if (typeof chunk === "string") return chunk;
|
|
3102
|
+
if (typeof chunk?.content === "string") return chunk.content;
|
|
3103
|
+
if (Array.isArray(chunk?.content)) {
|
|
3104
|
+
return chunk.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? "").join("");
|
|
3105
|
+
}
|
|
3106
|
+
if (typeof chunk?.text === "string") return chunk.text;
|
|
3107
|
+
return "";
|
|
3108
|
+
}
|
|
3109
|
+
function buildSeparateCallMessages(base, promptBody) {
|
|
3110
|
+
const systemMessages = base.filter((m) => m?.role === "system");
|
|
3111
|
+
const tail = base.slice(-8);
|
|
3112
|
+
return [
|
|
3113
|
+
...systemMessages,
|
|
3114
|
+
...tail,
|
|
3115
|
+
{ role: "user", name: REFLECTION_ASK_NAME, content: promptBody }
|
|
3116
|
+
];
|
|
3117
|
+
}
|
|
3118
|
+
function safeRandomId() {
|
|
3119
|
+
try {
|
|
3120
|
+
return crypto.randomUUID();
|
|
3121
|
+
} catch {
|
|
3122
|
+
return `r_${Math.random().toString(36).slice(2, 10)}_${Date.now().toString(36)}`;
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
// src/smart/reasoning.ts
|
|
3127
|
+
var LEVEL_DEFAULTS = {
|
|
3128
|
+
low: {
|
|
3129
|
+
native: { effort: "low" },
|
|
3130
|
+
reflection: { maxTokens: 200, maxChars: 600, cadence: "on_branch" }
|
|
3131
|
+
},
|
|
3132
|
+
medium: {
|
|
3133
|
+
native: { effort: "medium" },
|
|
3134
|
+
reflection: { maxTokens: 350, maxChars: 1200, cadence: "after_tool" }
|
|
3135
|
+
},
|
|
3136
|
+
high: {
|
|
3137
|
+
native: { effort: "high" },
|
|
3138
|
+
reflection: { maxTokens: 600, maxChars: 2e3, cadence: "after_tool" }
|
|
3139
|
+
}
|
|
3140
|
+
};
|
|
3141
|
+
function resolveReasoning(input) {
|
|
3142
|
+
if (!input || input.enabled === false) return void 0;
|
|
3143
|
+
const enabled = input.enabled ?? (input.native !== void 0 || input.reflection !== void 0 || input.level !== void 0);
|
|
3144
|
+
if (!enabled) return void 0;
|
|
3145
|
+
const level = input.level ?? "medium";
|
|
3146
|
+
const presets = LEVEL_DEFAULTS[level];
|
|
3147
|
+
let native;
|
|
3148
|
+
if (input.native === false) {
|
|
3149
|
+
native = void 0;
|
|
3150
|
+
} else {
|
|
3151
|
+
native = { ...presets.native, ...input.native ?? {} };
|
|
3152
|
+
}
|
|
3153
|
+
const reflection = resolveReflection(input.reflection, presets.reflection);
|
|
3154
|
+
return { enabled: true, level, native, reflection };
|
|
3155
|
+
}
|
|
3156
|
+
function resolveReflection(input, preset) {
|
|
3157
|
+
if (input === false) {
|
|
3158
|
+
return {
|
|
3159
|
+
enabled: false,
|
|
3160
|
+
cadence: "off",
|
|
3161
|
+
mode: "piggyback",
|
|
3162
|
+
maxTokens: preset.maxTokens,
|
|
3163
|
+
maxChars: preset.maxChars,
|
|
3164
|
+
keepLast: 3,
|
|
3165
|
+
summarize: false,
|
|
3166
|
+
emitEvents: true
|
|
3167
|
+
};
|
|
3168
|
+
}
|
|
3169
|
+
const cfg = input ?? {};
|
|
3170
|
+
const enabled = cfg.enabled ?? true;
|
|
3171
|
+
const cadence = cfg.cadence ?? preset.cadence;
|
|
3172
|
+
return {
|
|
3173
|
+
enabled: enabled && cadence !== "off",
|
|
3174
|
+
cadence: enabled ? cadence : "off",
|
|
3175
|
+
mode: cfg.mode ?? "piggyback",
|
|
3176
|
+
maxTokens: cfg.maxTokens ?? preset.maxTokens,
|
|
3177
|
+
maxChars: cfg.maxChars ?? preset.maxChars,
|
|
3178
|
+
keepLast: cfg.keepLast ?? 3,
|
|
3179
|
+
summarize: cfg.summarize ?? false,
|
|
3180
|
+
promptTemplate: cfg.promptTemplate,
|
|
3181
|
+
emitEvents: cfg.emitEvents ?? true
|
|
3182
|
+
};
|
|
3183
|
+
}
|
|
2971
3184
|
function ensureArray(value) {
|
|
2972
3185
|
return Array.isArray(value) ? value : [];
|
|
2973
3186
|
}
|
|
@@ -3381,6 +3594,8 @@ function createAgent(opts) {
|
|
|
3381
3594
|
}
|
|
3382
3595
|
const toolsNode = createToolsNode(toolsBase, opts);
|
|
3383
3596
|
const finalizeNode = createToolLimitFinalizeNode();
|
|
3597
|
+
const resolvedReasoning = resolveReasoning(opts.reasoning);
|
|
3598
|
+
const reflectNode = resolvedReasoning?.reflection.enabled ? createReflectionNode(opts, resolvedReasoning.reflection) : void 0;
|
|
3384
3599
|
const mergeGuardrailOutcomes = (prev, next) => {
|
|
3385
3600
|
if (!prev) return next;
|
|
3386
3601
|
return {
|
|
@@ -3435,6 +3650,13 @@ function createAgent(opts) {
|
|
|
3435
3650
|
if (summarizationThreshold === void 0) {
|
|
3436
3651
|
state = clearNeedsSummarization(state);
|
|
3437
3652
|
}
|
|
3653
|
+
if (resolvedReasoning?.native) {
|
|
3654
|
+
const ctx = { ...state.ctx || {} };
|
|
3655
|
+
if (!ctx.__reasoning) {
|
|
3656
|
+
ctx.__reasoning = resolvedReasoning.native;
|
|
3657
|
+
state = { ...state, ctx };
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3438
3660
|
const mergedLimits = {
|
|
3439
3661
|
...opts.limits || {},
|
|
3440
3662
|
...config?.limits || {}
|
|
@@ -3663,6 +3885,18 @@ function createAgent(opts) {
|
|
|
3663
3885
|
if (state.ctx?.__awaitingApproval) break;
|
|
3664
3886
|
if (checkpointIfRequested("after_tools")) break;
|
|
3665
3887
|
if (state.ctx?.__finalizedDueToStructuredOutput) break;
|
|
3888
|
+
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
3889
|
+
const cadence = resolvedReasoning.reflection.cadence;
|
|
3890
|
+
if (shouldRunReflection(cadence, state, true)) {
|
|
3891
|
+
try {
|
|
3892
|
+
const patch = await reflectNode(state, cadence);
|
|
3893
|
+
if (patch && Object.keys(patch).length > 0) {
|
|
3894
|
+
state = { ...state, ...patch };
|
|
3895
|
+
}
|
|
3896
|
+
} catch {
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3666
3900
|
}
|
|
3667
3901
|
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput) {
|
|
3668
3902
|
const lastForParse = state.messages[state.messages.length - 1];
|
|
@@ -3990,40 +4224,6 @@ function createAgentNode(opts) {
|
|
|
3990
4224
|
}
|
|
3991
4225
|
|
|
3992
4226
|
// src/smart/contextPolicy.ts
|
|
3993
|
-
function collectRecentFullToolCallIds(state, keepRecentFullCount) {
|
|
3994
|
-
if (!keepRecentFullCount || keepRecentFullCount <= 0) return /* @__PURE__ */ new Set();
|
|
3995
|
-
const history = state.toolHistory || [];
|
|
3996
|
-
const ids = [];
|
|
3997
|
-
for (let index = history.length - 1; index >= 0 && ids.length < keepRecentFullCount; index -= 1) {
|
|
3998
|
-
const entry = history[index];
|
|
3999
|
-
if (!entry || !entry.tool_call_id) continue;
|
|
4000
|
-
if (entry.status && entry.status !== "success") continue;
|
|
4001
|
-
ids.push(entry.tool_call_id);
|
|
4002
|
-
}
|
|
4003
|
-
return new Set(ids);
|
|
4004
|
-
}
|
|
4005
|
-
function applyRecentFullOverride(messages, state, config) {
|
|
4006
|
-
const keepN = config.toolResponses.keepRecentFullCount;
|
|
4007
|
-
if (!keepN || keepN <= 0) return messages;
|
|
4008
|
-
const recentIds = collectRecentFullToolCallIds(state, keepN);
|
|
4009
|
-
if (recentIds.size === 0) return messages;
|
|
4010
|
-
const history = state.toolHistory || [];
|
|
4011
|
-
const byCallId = /* @__PURE__ */ new Map();
|
|
4012
|
-
for (const entry of history) {
|
|
4013
|
-
if (entry?.tool_call_id) byCallId.set(entry.tool_call_id, entry);
|
|
4014
|
-
}
|
|
4015
|
-
return messages.map((message) => {
|
|
4016
|
-
if (message.role !== "tool" || !message.tool_call_id) return message;
|
|
4017
|
-
if (!recentIds.has(message.tool_call_id)) return message;
|
|
4018
|
-
const entry = byCallId.get(message.tool_call_id);
|
|
4019
|
-
if (!entry) return message;
|
|
4020
|
-
const raw = entry.rawOutput ?? entry.output;
|
|
4021
|
-
if (raw === void 0) return message;
|
|
4022
|
-
const fullContent = typeof raw === "string" ? raw : safeStringify(raw);
|
|
4023
|
-
if (!fullContent || fullContent === message.content) return message;
|
|
4024
|
-
return { ...message, content: fullContent };
|
|
4025
|
-
});
|
|
4026
|
-
}
|
|
4027
4227
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
4028
4228
|
if (lastTurnsToKeep <= 0) return [];
|
|
4029
4229
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -4124,7 +4324,7 @@ function clampToBudget(messages, maxContextTokens) {
|
|
|
4124
4324
|
function buildModelMessages(state, config) {
|
|
4125
4325
|
const rawMessages = state.messages || [];
|
|
4126
4326
|
if (config.context.policy === "raw") {
|
|
4127
|
-
return clampToBudget(
|
|
4327
|
+
return clampToBudget(rawMessages, config.limits.maxContextTokens);
|
|
4128
4328
|
}
|
|
4129
4329
|
const recentMessages = collectRecentTurns(rawMessages, config.context.lastTurnsToKeep);
|
|
4130
4330
|
const latestSummary = state.summaryRecords?.[state.summaryRecords.length - 1];
|
|
@@ -4144,7 +4344,7 @@ function buildModelMessages(state, config) {
|
|
|
4144
4344
|
...syntheticContextMessages,
|
|
4145
4345
|
...config.context.policy === "summary_only" ? body.filter((message) => message.role === "user" || message.role === "assistant").slice(-2) : body
|
|
4146
4346
|
];
|
|
4147
|
-
return clampToBudget(
|
|
4347
|
+
return clampToBudget(assembled, config.limits.maxContextTokens);
|
|
4148
4348
|
}
|
|
4149
4349
|
|
|
4150
4350
|
// src/nodes/contextSummarize.ts
|
|
@@ -4246,24 +4446,8 @@ function extractCanonicalFacts(messages) {
|
|
|
4246
4446
|
}
|
|
4247
4447
|
return [...facts.values()];
|
|
4248
4448
|
}
|
|
4249
|
-
function flattenToolMessageContent(message) {
|
|
4250
|
-
if (typeof message.content === "string") {
|
|
4251
|
-
return message.content;
|
|
4252
|
-
}
|
|
4253
|
-
if (Array.isArray(message.content)) {
|
|
4254
|
-
return message.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? String(part ?? "")).join(" ");
|
|
4255
|
-
}
|
|
4256
|
-
return "";
|
|
4257
|
-
}
|
|
4258
4449
|
function isSummarizedToolPlaceholder(content) {
|
|
4259
|
-
return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE"));
|
|
4260
|
-
}
|
|
4261
|
-
function summarizeToolMessagePreview(message) {
|
|
4262
|
-
const preview = flattenToolMessageContent(message).trim();
|
|
4263
|
-
if (!preview) {
|
|
4264
|
-
return "No summary available.";
|
|
4265
|
-
}
|
|
4266
|
-
return preview.length > 240 ? `${preview.slice(0, 240)}...` : preview;
|
|
4450
|
+
return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE") || content.startsWith("ARCHIVED_TOOL_RESPONSE") || content.startsWith("STRUCTURED_TOOL_RESPONSE") || content.startsWith("DROPPED_TOOL_RESPONSE"));
|
|
4267
4451
|
}
|
|
4268
4452
|
function findToolHistoryEntry(state, toolCallId, toolName) {
|
|
4269
4453
|
const entries = [
|
|
@@ -4289,29 +4473,6 @@ function findToolHistoryEntry(state, toolCallId, toolName) {
|
|
|
4289
4473
|
}
|
|
4290
4474
|
return void 0;
|
|
4291
4475
|
}
|
|
4292
|
-
function buildSummarizedToolMessage(message, state) {
|
|
4293
|
-
const toolName = message.name || "unknown_tool";
|
|
4294
|
-
const toolCallId = message.tool_call_id;
|
|
4295
|
-
const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
|
|
4296
|
-
const executionId = historyEntry?.executionId;
|
|
4297
|
-
const summary = historyEntry?.summary || summarizeToolMessagePreview(message);
|
|
4298
|
-
const references = [
|
|
4299
|
-
`toolName=${toolName}`,
|
|
4300
|
-
toolCallId ? `toolCallId=${toolCallId}` : null,
|
|
4301
|
-
executionId ? `executionId=${executionId}` : null
|
|
4302
|
-
].filter(Boolean).join("; ");
|
|
4303
|
-
let retrievalHint = "Only use get_tool_response if this summary is missing a specific field, id, snippet, or exact payload you still need.";
|
|
4304
|
-
if (executionId && toolCallId) {
|
|
4305
|
-
retrievalHint = `Only use get_tool_response with executionId "${executionId}" or tool call id "${toolCallId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
4306
|
-
} else if (executionId || toolCallId) {
|
|
4307
|
-
retrievalHint = `Only use get_tool_response with executionId "${executionId || toolCallId}" if this summary is missing a specific field, id, snippet, or exact payload you still need.`;
|
|
4308
|
-
}
|
|
4309
|
-
return [
|
|
4310
|
-
`SUMMARIZED_TOOL_RESPONSE [${references}]`,
|
|
4311
|
-
`Summary: ${summary}`,
|
|
4312
|
-
retrievalHint
|
|
4313
|
-
].join("\n");
|
|
4314
|
-
}
|
|
4315
4476
|
function mergeStableFacts(summary, additionalFacts) {
|
|
4316
4477
|
if (additionalFacts.length === 0) return summary;
|
|
4317
4478
|
const merged = new Map(summary.stable_facts.map((fact) => [fact.key, fact]));
|
|
@@ -4369,20 +4530,13 @@ function createContextSummarizeNode(opts) {
|
|
|
4369
4530
|
const messages = state.messages || [];
|
|
4370
4531
|
const onEvent = state.ctx?.__onEvent;
|
|
4371
4532
|
const traceSession = state.ctx?.__traceSession;
|
|
4372
|
-
const toolResponsesConfigEarly = resolved.toolResponses;
|
|
4373
|
-
const recentFullToolCallIdsEarly = collectRecentFullToolCallIds(state, toolResponsesConfigEarly.keepRecentFullCount);
|
|
4374
4533
|
const compressableMessages = messages.filter(
|
|
4375
4534
|
(m) => {
|
|
4376
4535
|
if (m.role !== "tool") return false;
|
|
4377
4536
|
if (isSummarizedToolPlaceholder(m.content)) return false;
|
|
4378
4537
|
if (isSyntheticSummaryMessage(m)) return false;
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
if (histEntry?.retentionPolicy === "keep_full") return false;
|
|
4382
|
-
if (!histEntry?.retentionPolicy) {
|
|
4383
|
-
const byTool = toolResponsesConfigEarly.toolResponseRetentionByTool?.[m.name || ""];
|
|
4384
|
-
if ((byTool || toolResponsesConfigEarly.defaultPolicy) === "keep_full") return false;
|
|
4385
|
-
}
|
|
4538
|
+
const policy = resolveSummarizationRetention(m.name || "", resolved);
|
|
4539
|
+
if (policy === "keep_full") return false;
|
|
4386
4540
|
return true;
|
|
4387
4541
|
}
|
|
4388
4542
|
);
|
|
@@ -4562,8 +4716,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4562
4716
|
break;
|
|
4563
4717
|
}
|
|
4564
4718
|
}
|
|
4565
|
-
const
|
|
4566
|
-
const
|
|
4719
|
+
const archivedExecutions = [...state.toolHistoryArchived || []];
|
|
4720
|
+
const archivedIds = new Set(archivedExecutions.map((entry) => entry?.executionId).filter(Boolean));
|
|
4567
4721
|
const newMessages = messages.map((m) => {
|
|
4568
4722
|
if (m.role === "tool") {
|
|
4569
4723
|
if (isSyntheticSummaryMessage(m)) {
|
|
@@ -4575,25 +4729,39 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4575
4729
|
}
|
|
4576
4730
|
if (isSummarizedToolPlaceholder(m.content)) return m;
|
|
4577
4731
|
if (toolCallId && protectedToolCallIds.has(toolCallId)) return m;
|
|
4578
|
-
if (toolCallId && recentFullToolCallIds.has(toolCallId)) return m;
|
|
4579
4732
|
const toolName = m.name || "";
|
|
4733
|
+
const policy = resolveSummarizationRetention(toolName, resolved);
|
|
4734
|
+
if (policy === "keep_full") return m;
|
|
4580
4735
|
const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
|
|
4581
|
-
const
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4736
|
+
const rawOutput = historyEntry?.rawOutput ?? historyEntry?.output ?? m.content;
|
|
4737
|
+
const executionId = historyEntry?.executionId;
|
|
4738
|
+
const prebuiltSummary = historyEntry?.summary || summarizeObject(rawOutput);
|
|
4739
|
+
if ((policy === "summarize_archive" || policy === "drop") && historyEntry && executionId && !archivedIds.has(executionId)) {
|
|
4740
|
+
archivedExecutions.push({
|
|
4741
|
+
...historyEntry,
|
|
4742
|
+
summarized: true,
|
|
4743
|
+
retentionPolicy: policy,
|
|
4744
|
+
archiveId: executionId,
|
|
4745
|
+
summary: prebuiltSummary
|
|
4746
|
+
});
|
|
4747
|
+
archivedIds.add(executionId);
|
|
4587
4748
|
}
|
|
4588
4749
|
return {
|
|
4589
4750
|
...m,
|
|
4590
|
-
content:
|
|
4751
|
+
content: renderRetainedToolMessage({
|
|
4752
|
+
policy,
|
|
4753
|
+
rawOutput,
|
|
4754
|
+
toolName,
|
|
4755
|
+
toolCallId,
|
|
4756
|
+
executionId,
|
|
4757
|
+
prebuiltSummary
|
|
4758
|
+
})
|
|
4591
4759
|
};
|
|
4592
4760
|
}
|
|
4593
4761
|
return m;
|
|
4594
4762
|
}).filter((m) => m !== null);
|
|
4595
4763
|
const actuallyCompressed = newMessages.filter(
|
|
4596
|
-
(m) => m.role === "tool" &&
|
|
4764
|
+
(m) => m.role === "tool" && isSummarizedToolPlaceholder(m.content) && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
|
|
4597
4765
|
);
|
|
4598
4766
|
if (actuallyCompressed.length === 0) {
|
|
4599
4767
|
return {};
|
|
@@ -4672,7 +4840,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
4672
4840
|
return {
|
|
4673
4841
|
messages: finalMessages,
|
|
4674
4842
|
summaries,
|
|
4675
|
-
summaryRecords
|
|
4843
|
+
summaryRecords,
|
|
4844
|
+
toolHistoryArchived: archivedExecutions
|
|
4676
4845
|
};
|
|
4677
4846
|
};
|
|
4678
4847
|
}
|
|
@@ -5737,6 +5906,52 @@ function parseSSEBlock(block) {
|
|
|
5737
5906
|
return { event, data: dataLines.join("\n"), id, retry };
|
|
5738
5907
|
}
|
|
5739
5908
|
|
|
5909
|
+
// src/providers/utils/reasoning.ts
|
|
5910
|
+
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
5911
|
+
if (!reasoning) return;
|
|
5912
|
+
const effort = normalizeEffort(reasoning.effort);
|
|
5913
|
+
if (mode === "responses") {
|
|
5914
|
+
const obj = {};
|
|
5915
|
+
if (effort) obj.effort = effort;
|
|
5916
|
+
if (reasoning.includeThoughts) obj.summary = "auto";
|
|
5917
|
+
if (reasoning.providerExtras) Object.assign(obj, reasoning.providerExtras);
|
|
5918
|
+
if (Object.keys(obj).length > 0) body.reasoning = obj;
|
|
5919
|
+
} else {
|
|
5920
|
+
if (effort) body.reasoning_effort = effort;
|
|
5921
|
+
if (reasoning.providerExtras) Object.assign(body, reasoning.providerExtras);
|
|
5922
|
+
}
|
|
5923
|
+
}
|
|
5924
|
+
function applyAnthropicReasoning(body, reasoning) {
|
|
5925
|
+
if (!reasoning) return;
|
|
5926
|
+
const budget = resolveBudget(reasoning, { low: 2048, medium: 8192, high: 16384, minimal: 1024 });
|
|
5927
|
+
if (!budget) return;
|
|
5928
|
+
const thinking = { type: "enabled", budget_tokens: budget };
|
|
5929
|
+
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
5930
|
+
body.thinking = thinking;
|
|
5931
|
+
}
|
|
5932
|
+
function applyGeminiReasoning(generationConfig, reasoning) {
|
|
5933
|
+
if (!reasoning) return;
|
|
5934
|
+
const budget = resolveBudget(reasoning, { low: 1024, medium: 4096, high: 12e3, minimal: 512 });
|
|
5935
|
+
if (budget == null) return;
|
|
5936
|
+
const thinkingConfig = { thinkingBudget: budget };
|
|
5937
|
+
if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
|
|
5938
|
+
if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
|
|
5939
|
+
generationConfig.thinkingConfig = thinkingConfig;
|
|
5940
|
+
}
|
|
5941
|
+
function normalizeEffort(effort) {
|
|
5942
|
+
if (!effort) return void 0;
|
|
5943
|
+
const allowed = ["minimal", "low", "medium", "high"];
|
|
5944
|
+
return allowed.includes(effort) ? effort : void 0;
|
|
5945
|
+
}
|
|
5946
|
+
function resolveBudget(reasoning, effortBudget) {
|
|
5947
|
+
if (typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
5948
|
+
return Math.floor(reasoning.budgetTokens);
|
|
5949
|
+
}
|
|
5950
|
+
const effort = normalizeEffort(reasoning.effort);
|
|
5951
|
+
if (effort && effortBudget[effort]) return effortBudget[effort];
|
|
5952
|
+
return void 0;
|
|
5953
|
+
}
|
|
5954
|
+
|
|
5740
5955
|
// src/providers/openai.ts
|
|
5741
5956
|
var OpenAIProvider = class extends BaseProvider {
|
|
5742
5957
|
constructor(config) {
|
|
@@ -5852,6 +6067,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
5852
6067
|
if (request.extra) {
|
|
5853
6068
|
Object.assign(body, request.extra);
|
|
5854
6069
|
}
|
|
6070
|
+
applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
|
|
5855
6071
|
return body;
|
|
5856
6072
|
}
|
|
5857
6073
|
toOpenAIMessage(m) {
|
|
@@ -6110,6 +6326,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
6110
6326
|
if (request.extra) {
|
|
6111
6327
|
Object.assign(body, request.extra);
|
|
6112
6328
|
}
|
|
6329
|
+
applyAnthropicReasoning(body, request.reasoning);
|
|
6113
6330
|
return body;
|
|
6114
6331
|
}
|
|
6115
6332
|
splitSystemMessages(messages) {
|
|
@@ -6764,6 +6981,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
6764
6981
|
}
|
|
6765
6982
|
}
|
|
6766
6983
|
}
|
|
6984
|
+
applyGeminiReasoning(generationConfig, request.reasoning);
|
|
6767
6985
|
if (Object.keys(generationConfig).length > 0) body.generationConfig = generationConfig;
|
|
6768
6986
|
if (request.tools?.length) {
|
|
6769
6987
|
body.tools = [
|
|
@@ -7102,6 +7320,13 @@ function fromNativeProvider(provider, options) {
|
|
|
7102
7320
|
if (opts?.maxTokens != null) req.maxTokens = opts.maxTokens;
|
|
7103
7321
|
if (tools?.length) req.tools = tools;
|
|
7104
7322
|
if (opts?.extra) req.extra = opts.extra;
|
|
7323
|
+
const reasoningOverride = invokeOptions?.reasoning;
|
|
7324
|
+
const reasoningCfg = reasoningOverride ?? opts?.reasoning;
|
|
7325
|
+
if (reasoningCfg) req.reasoning = reasoningCfg;
|
|
7326
|
+
const tc = invokeOptions?.tool_choice ?? invokeOptions?.toolChoice;
|
|
7327
|
+
if (tc) {
|
|
7328
|
+
req.toolChoice = tc;
|
|
7329
|
+
}
|
|
7105
7330
|
const rf = invokeOptions?.response_format;
|
|
7106
7331
|
if (rf && typeof rf === "object" && rf.type) {
|
|
7107
7332
|
if (rf.type === "json_schema" && rf.json_schema) {
|