@cognipeer/agent-sdk 0.4.4 → 0.4.6
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 +104 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +104 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2181,7 +2181,7 @@ function resolveToolResponsePolicy(toolName, output, config) {
|
|
|
2181
2181
|
const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
|
|
2182
2182
|
let retentionPolicy = byTool || config.toolResponses.defaultPolicy;
|
|
2183
2183
|
if (classification === "critical") {
|
|
2184
|
-
retentionPolicy = byTool ||
|
|
2184
|
+
retentionPolicy = byTool || config.toolResponses.fallbackPolicy;
|
|
2185
2185
|
} else if (classification === "verbose") {
|
|
2186
2186
|
retentionPolicy = byTool || config.toolResponses.largeResponsePolicy;
|
|
2187
2187
|
} else if (classification === "redundant") {
|
|
@@ -2887,6 +2887,21 @@ function isSyntheticSummaryMessage(message) {
|
|
|
2887
2887
|
}
|
|
2888
2888
|
return false;
|
|
2889
2889
|
}
|
|
2890
|
+
function getMessageText(message) {
|
|
2891
|
+
if (typeof message?.content === "string") return message.content;
|
|
2892
|
+
if (Array.isArray(message?.content)) {
|
|
2893
|
+
return message.content.map((chunk) => typeof chunk === "string" ? chunk : chunk?.text ?? chunk?.content ?? "").join("");
|
|
2894
|
+
}
|
|
2895
|
+
return "";
|
|
2896
|
+
}
|
|
2897
|
+
function getLastAssistantMessage(messages) {
|
|
2898
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
2899
|
+
if (messages[index]?.role === "assistant") {
|
|
2900
|
+
return messages[index];
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
return void 0;
|
|
2904
|
+
}
|
|
2890
2905
|
function createAgent(opts) {
|
|
2891
2906
|
const resolver = createResolverNode();
|
|
2892
2907
|
const agentCore = createAgentCoreNode(opts);
|
|
@@ -3075,7 +3090,7 @@ function createAgent(opts) {
|
|
|
3075
3090
|
const tokenCount = countMessagesTokens(tokCountMessages);
|
|
3076
3091
|
if (tokenCount > maxTok) {
|
|
3077
3092
|
const hasFreshSummary = (state.messages || []).some(
|
|
3078
|
-
(m) => m.role === "tool" && m.content === "SUMMARIZED"
|
|
3093
|
+
(m) => m.role === "tool" && typeof m.content === "string" && (m.content === "SUMMARIZED" || m.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))
|
|
3079
3094
|
);
|
|
3080
3095
|
if (hasFreshSummary && tokenCount <= maxTok * 1.15) ; else {
|
|
3081
3096
|
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
@@ -3190,10 +3205,25 @@ function createAgent(opts) {
|
|
|
3190
3205
|
} catch (err) {
|
|
3191
3206
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
3192
3207
|
emit?.({ type: "metadata", error: `Structured output force-finalize failed: ${errMsg}` });
|
|
3208
|
+
throw err;
|
|
3193
3209
|
}
|
|
3194
3210
|
}
|
|
3195
3211
|
}
|
|
3196
3212
|
}
|
|
3213
|
+
if (state.ctx?.__needsSummarization && !opts?.summarization) {
|
|
3214
|
+
throw new Error(
|
|
3215
|
+
"Agent context exceeded the available budget before a final assistant response could be generated. Reduce tool response size or use createSmartAgent with summarization enabled."
|
|
3216
|
+
);
|
|
3217
|
+
}
|
|
3218
|
+
const lastAfterLoop = state.messages[state.messages.length - 1];
|
|
3219
|
+
if (lastAfterLoop?.role === "tool" && !pausedStage) {
|
|
3220
|
+
const isExpectedExit = state.ctx?.__awaitingApproval || state.ctx?.__cancelled || state.ctx?.__finalizedDueToStructuredOutput || state.ctx?.__finalizedDueToToolLimit || state.ctx?.__needsSummarization;
|
|
3221
|
+
if (!isExpectedExit) {
|
|
3222
|
+
throw new Error(
|
|
3223
|
+
"Agent loop terminated with a pending tool response but no subsequent model invocation. This usually indicates a model provider error or exhausted iteration budget."
|
|
3224
|
+
);
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3197
3227
|
if (!pausedStage && typeof onStateChange === "function" && onStateChange(state)) {
|
|
3198
3228
|
checkpointIfRequested("after_loop");
|
|
3199
3229
|
}
|
|
@@ -3263,10 +3293,8 @@ function createAgent(opts) {
|
|
|
3263
3293
|
agentRuntime: res.agent || runtime,
|
|
3264
3294
|
status: "success"
|
|
3265
3295
|
});
|
|
3266
|
-
const
|
|
3267
|
-
|
|
3268
|
-
if (typeof finalMsg?.content === "string") content = finalMsg.content;
|
|
3269
|
-
else if (Array.isArray(finalMsg?.content)) content = finalMsg.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? "").join("");
|
|
3296
|
+
const finalAssistantMsg = getLastAssistantMessage(res.messages);
|
|
3297
|
+
const content = getMessageText(finalAssistantMsg);
|
|
3270
3298
|
let parsed = void 0;
|
|
3271
3299
|
const schema = opts.outputSchema;
|
|
3272
3300
|
if (schema && res.ctx?.__structuredOutputParsed) {
|
|
@@ -3287,7 +3315,7 @@ function createAgent(opts) {
|
|
|
3287
3315
|
} catch {
|
|
3288
3316
|
}
|
|
3289
3317
|
}
|
|
3290
|
-
emit({ type: "finalAnswer", content
|
|
3318
|
+
emit({ type: "finalAnswer", content });
|
|
3291
3319
|
if (streamEnabled && content) {
|
|
3292
3320
|
onStream?.({ text: content, isFinal: true });
|
|
3293
3321
|
emit({ type: "stream", text: content, isFinal: true });
|
|
@@ -3557,7 +3585,7 @@ function estimateContextRotScore(state) {
|
|
|
3557
3585
|
const summaryCount = state.summaryRecords?.length || 0;
|
|
3558
3586
|
const archivedCount = state.toolHistoryArchived?.length || 0;
|
|
3559
3587
|
const messageCount = state.messages?.length || 0;
|
|
3560
|
-
const summarizedMessages = state.messages?.filter((message) => message.role === "tool" && message.content === "SUMMARIZED").length || 0;
|
|
3588
|
+
const summarizedMessages = state.messages?.filter((message) => message.role === "tool" && typeof message.content === "string" && (message.content === "SUMMARIZED" || message.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))).length || 0;
|
|
3561
3589
|
const numerator = summaryCount * 2 + archivedCount + summarizedMessages;
|
|
3562
3590
|
const denominator = Math.max(messageCount, 1);
|
|
3563
3591
|
return Number((numerator / denominator).toFixed(3));
|
|
@@ -3674,6 +3702,69 @@ function extractCanonicalFacts(messages) {
|
|
|
3674
3702
|
}
|
|
3675
3703
|
return [...facts.values()];
|
|
3676
3704
|
}
|
|
3705
|
+
function flattenToolMessageContent(message) {
|
|
3706
|
+
if (typeof message.content === "string") {
|
|
3707
|
+
return message.content;
|
|
3708
|
+
}
|
|
3709
|
+
if (Array.isArray(message.content)) {
|
|
3710
|
+
return message.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? String(part ?? "")).join(" ");
|
|
3711
|
+
}
|
|
3712
|
+
return "";
|
|
3713
|
+
}
|
|
3714
|
+
function isSummarizedToolPlaceholder(content) {
|
|
3715
|
+
return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE"));
|
|
3716
|
+
}
|
|
3717
|
+
function summarizeToolMessagePreview(message) {
|
|
3718
|
+
const preview = flattenToolMessageContent(message).trim();
|
|
3719
|
+
if (!preview) {
|
|
3720
|
+
return "No summary available.";
|
|
3721
|
+
}
|
|
3722
|
+
return preview.length > 240 ? `${preview.slice(0, 240)}...` : preview;
|
|
3723
|
+
}
|
|
3724
|
+
function findToolHistoryEntry(state, toolCallId, toolName) {
|
|
3725
|
+
const entries = [
|
|
3726
|
+
...state.toolHistory || [],
|
|
3727
|
+
...state.toolHistoryArchived || []
|
|
3728
|
+
];
|
|
3729
|
+
if (toolCallId) {
|
|
3730
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
3731
|
+
const entry = entries[index];
|
|
3732
|
+
if (entry?.tool_call_id === toolCallId) {
|
|
3733
|
+
return entry;
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
3738
|
+
const entry = entries[index];
|
|
3739
|
+
if (entry?.toolName === toolName) {
|
|
3740
|
+
return entry;
|
|
3741
|
+
}
|
|
3742
|
+
}
|
|
3743
|
+
return void 0;
|
|
3744
|
+
}
|
|
3745
|
+
function buildSummarizedToolMessage(message, state) {
|
|
3746
|
+
const toolName = message.name || "unknown_tool";
|
|
3747
|
+
const toolCallId = message.tool_call_id;
|
|
3748
|
+
const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
|
|
3749
|
+
const executionId = historyEntry?.executionId;
|
|
3750
|
+
const summary = historyEntry?.summary || summarizeToolMessagePreview(message);
|
|
3751
|
+
const references = [
|
|
3752
|
+
`toolName=${toolName}`,
|
|
3753
|
+
toolCallId ? `toolCallId=${toolCallId}` : null,
|
|
3754
|
+
executionId ? `executionId=${executionId}` : null
|
|
3755
|
+
].filter(Boolean).join("; ");
|
|
3756
|
+
let retrievalHint = "Use get_tool_response if exact details are still needed.";
|
|
3757
|
+
if (executionId && toolCallId) {
|
|
3758
|
+
retrievalHint = `Use get_tool_response with executionId "${executionId}" or tool call id "${toolCallId}" if exact details are still needed.`;
|
|
3759
|
+
} else if (executionId || toolCallId) {
|
|
3760
|
+
retrievalHint = `Use get_tool_response with executionId "${executionId || toolCallId}" if exact details are still needed.`;
|
|
3761
|
+
}
|
|
3762
|
+
return [
|
|
3763
|
+
`SUMMARIZED_TOOL_RESPONSE [${references}]`,
|
|
3764
|
+
`Summary: ${summary}`,
|
|
3765
|
+
retrievalHint
|
|
3766
|
+
].join("\n");
|
|
3767
|
+
}
|
|
3677
3768
|
function mergeStableFacts(summary, additionalFacts) {
|
|
3678
3769
|
if (additionalFacts.length === 0) return summary;
|
|
3679
3770
|
const merged = new Map(summary.stable_facts.map((fact) => [fact.key, fact]));
|
|
@@ -3732,7 +3823,7 @@ function createContextSummarizeNode(opts) {
|
|
|
3732
3823
|
const onEvent = state.ctx?.__onEvent;
|
|
3733
3824
|
const traceSession = state.ctx?.__traceSession;
|
|
3734
3825
|
const compressableMessages = messages.filter(
|
|
3735
|
-
(m) => m.role === "tool" && m.content
|
|
3826
|
+
(m) => m.role === "tool" && !isSummarizedToolPlaceholder(m.content) && !isSyntheticSummaryToolMessage(m)
|
|
3736
3827
|
);
|
|
3737
3828
|
if (compressableMessages.length === 0) {
|
|
3738
3829
|
return {};
|
|
@@ -3897,10 +3988,10 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
3897
3988
|
if (!toolCallId || !toolCallIdToAssistantIdx.has(toolCallId)) {
|
|
3898
3989
|
return null;
|
|
3899
3990
|
}
|
|
3900
|
-
if (m.content
|
|
3991
|
+
if (isSummarizedToolPlaceholder(m.content)) return m;
|
|
3901
3992
|
return {
|
|
3902
3993
|
...m,
|
|
3903
|
-
content:
|
|
3994
|
+
content: buildSummarizedToolMessage(m, state)
|
|
3904
3995
|
};
|
|
3905
3996
|
}
|
|
3906
3997
|
return m;
|
|
@@ -4210,8 +4301,8 @@ function createContextTools(stateRef, opts) {
|
|
|
4210
4301
|
}
|
|
4211
4302
|
const getTool = createTool({
|
|
4212
4303
|
name: "get_tool_response",
|
|
4213
|
-
description: "RETRIEVE the full output of a tool execution whose response was archived or
|
|
4214
|
-
schema: z.object({ executionId: z.string().describe("Tool execution id") }),
|
|
4304
|
+
description: "RETRIEVE the full output of a tool execution whose response was archived, dropped, or later compacted in conversation history. When a tool response appears as 'ARCHIVED_TOOL_RESPONSE [executionId=xxx]', 'DROPPED_TOOL_RESPONSE [executionId=xxx]', or 'SUMMARIZED_TOOL_RESPONSE [...]', pass the referenced executionId to this tool to get the complete data. You can also pass the original tool_call_id from the tool call.",
|
|
4305
|
+
schema: z.object({ executionId: z.string().describe("Tool execution id or original tool_call_id") }),
|
|
4215
4306
|
func: async ({ executionId }) => {
|
|
4216
4307
|
const matchesExecution = (t) => t?.executionId === executionId || t?.tool_call_id === executionId;
|
|
4217
4308
|
let execution = stateRef.toolHistory?.find((t) => matchesExecution(t));
|