@nodetool-ai/base-nodes 0.7.0-rc.12 → 0.7.0-rc.14
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/nodes/agent-tool-hydration.d.ts +10 -0
- package/dist/nodes/agent-tool-hydration.d.ts.map +1 -0
- package/dist/nodes/agent-tool-hydration.js +43 -0
- package/dist/nodes/agent-tool-hydration.js.map +1 -0
- package/dist/nodes/agents.d.ts +1 -0
- package/dist/nodes/agents.d.ts.map +1 -1
- package/dist/nodes/agents.js +130 -68
- package/dist/nodes/agents.js.map +1 -1
- package/dist/nodes/team.d.ts.map +1 -1
- package/dist/nodes/team.js +6 -1
- package/dist/nodes/team.js.map +1 -1
- package/dist/nodes/video.d.ts.map +1 -1
- package/dist/nodes/video.js +26 -4
- package/dist/nodes/video.js.map +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Tool } from "@nodetool-ai/agents";
|
|
2
|
+
type MaybeTool = {
|
|
3
|
+
name: string;
|
|
4
|
+
process?: unknown;
|
|
5
|
+
};
|
|
6
|
+
export declare function resolveBuiltinAgentTool(name: string): Tool | null;
|
|
7
|
+
export declare function hydrateBuiltinAgentTool<T extends MaybeTool>(tool: T): T | Tool;
|
|
8
|
+
export declare function hydrateBuiltinAgentTools<T extends MaybeTool>(tools: T[]): Array<T | Tool>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=agent-tool-hydration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-tool-hydration.d.ts","sourceRoot":"","sources":["../../src/nodes/agent-tool-hydration.ts"],"names":[],"mappings":"AAAA,OAAO,EAqBL,IAAI,EACL,MAAM,qBAAqB,CAAC;AAI7B,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA2BF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CASjE;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAG9E;AAED,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAEzF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BrowserTool, CalculatorTool, ConversionTool, DataForSEOImagesTool, DataForSEONewsTool, DataForSEOSearchTool, GeometryTool, GoogleGroundedSearchTool, GoogleImageGenerationTool, GoogleImagesTool, GoogleNewsTool, GoogleSearchTool, HttpRequestTool, OpenAIImageGenerationTool, OpenAITextToSpeechTool, OpenAIWebSearchTool, RunCodeTool, ScreenshotTool, SearchEmailTool, StatisticsTool } from "@nodetool-ai/agents";
|
|
2
|
+
const BUILTIN_AGENT_TOOL_CLASSES = [
|
|
3
|
+
GoogleSearchTool,
|
|
4
|
+
GoogleNewsTool,
|
|
5
|
+
GoogleImagesTool,
|
|
6
|
+
GoogleGroundedSearchTool,
|
|
7
|
+
GoogleImageGenerationTool,
|
|
8
|
+
OpenAIWebSearchTool,
|
|
9
|
+
OpenAIImageGenerationTool,
|
|
10
|
+
OpenAITextToSpeechTool,
|
|
11
|
+
BrowserTool,
|
|
12
|
+
ScreenshotTool,
|
|
13
|
+
HttpRequestTool,
|
|
14
|
+
CalculatorTool,
|
|
15
|
+
RunCodeTool,
|
|
16
|
+
StatisticsTool,
|
|
17
|
+
GeometryTool,
|
|
18
|
+
ConversionTool,
|
|
19
|
+
SearchEmailTool,
|
|
20
|
+
DataForSEOSearchTool,
|
|
21
|
+
DataForSEONewsTool,
|
|
22
|
+
DataForSEOImagesTool
|
|
23
|
+
];
|
|
24
|
+
let builtinAgentTools = null;
|
|
25
|
+
export function resolveBuiltinAgentTool(name) {
|
|
26
|
+
if (!builtinAgentTools) {
|
|
27
|
+
builtinAgentTools = new Map();
|
|
28
|
+
for (const ToolClass of BUILTIN_AGENT_TOOL_CLASSES) {
|
|
29
|
+
const tool = new ToolClass();
|
|
30
|
+
builtinAgentTools.set(tool.name, tool);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return builtinAgentTools.get(name) ?? null;
|
|
34
|
+
}
|
|
35
|
+
export function hydrateBuiltinAgentTool(tool) {
|
|
36
|
+
if (typeof tool.process === "function")
|
|
37
|
+
return tool;
|
|
38
|
+
return resolveBuiltinAgentTool(tool.name) ?? tool;
|
|
39
|
+
}
|
|
40
|
+
export function hydrateBuiltinAgentTools(tools) {
|
|
41
|
+
return tools.map(hydrateBuiltinAgentTool);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=agent-tool-hydration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-tool-hydration.js","sourceRoot":"","sources":["../../src/nodes/agent-tool-hydration.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EAEf,MAAM,qBAAqB,CAAC;AAS7B,MAAM,0BAA0B,GAAe;IAC7C,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,wBAAwB;IACxB,yBAAyB;IACzB,mBAAmB;IACnB,yBAAyB;IACzB,sBAAsB;IACtB,WAAW;IACX,cAAc;IACd,eAAe;IACf,cAAc;IACd,WAAW;IACX,cAAc;IACd,YAAY;IACZ,cAAc;IACd,eAAe;IACf,oBAAoB;IACpB,kBAAkB;IAClB,oBAAoB;CACrB,CAAC;AAEF,IAAI,iBAAiB,GAA6B,IAAI,CAAC;AAEvD,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,iBAAiB,GAAG,IAAI,GAAG,EAAgB,CAAC;QAC5C,KAAK,MAAM,SAAS,IAAI,0BAA0B,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;YAC7B,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAsB,IAAO;IAClE,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAsB,KAAU;IACtE,OAAO,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC5C,CAAC"}
|
package/dist/nodes/agents.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/nodes/agents.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAQ,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EAEP,cAAc,EAEd,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACT,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAqB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/nodes/agents.ts"],"names":[],"mappings":"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"}
|
package/dist/nodes/agents.js
CHANGED
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { createLogger } from "@nodetool-ai/config";
|
|
8
8
|
import { BaseNode, prop } from "@nodetool-ai/node-sdk";
|
|
9
9
|
import { MultiModeAgent, Tool as AgentTool } from "@nodetool-ai/agents";
|
|
10
|
+
import { hydrateBuiltinAgentTool } from "./agent-tool-hydration.js";
|
|
10
11
|
const THREAD_STORE = new Map();
|
|
11
12
|
const log = createLogger("nodetool.base-nodes.agents");
|
|
12
13
|
const DEFAULT_SYSTEM_PROMPT = "You are a friendly assistant";
|
|
@@ -157,6 +158,32 @@ function normalizeProviderStreamItem(item) {
|
|
|
157
158
|
content_type: "text"
|
|
158
159
|
};
|
|
159
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Render a tool-call streaming item as a Chunk so callers see tool dispatches
|
|
163
|
+
* inline with the assistant's text/thinking stream. The structured payload
|
|
164
|
+
* lives in `content_metadata`; `content` is a human-readable summary.
|
|
165
|
+
*/
|
|
166
|
+
function toolCallChunk(toolCall) {
|
|
167
|
+
const argsJson = (() => {
|
|
168
|
+
try {
|
|
169
|
+
return JSON.stringify(toolCall.args ?? {});
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return "{}";
|
|
173
|
+
}
|
|
174
|
+
})();
|
|
175
|
+
return {
|
|
176
|
+
type: "chunk",
|
|
177
|
+
content: `${toolCall.name}(${argsJson})`,
|
|
178
|
+
content_type: "tool_call",
|
|
179
|
+
content_metadata: {
|
|
180
|
+
tool_call_id: toolCall.id,
|
|
181
|
+
tool_name: toolCall.name,
|
|
182
|
+
args: toolCall.args ?? {}
|
|
183
|
+
},
|
|
184
|
+
done: false
|
|
185
|
+
};
|
|
186
|
+
}
|
|
160
187
|
export async function* streamProviderMessages(provider, args) {
|
|
161
188
|
const request = {
|
|
162
189
|
...args,
|
|
@@ -455,9 +482,20 @@ export function isToolCallItem(item) {
|
|
|
455
482
|
function normalizeTools(value) {
|
|
456
483
|
if (!Array.isArray(value))
|
|
457
484
|
return [];
|
|
458
|
-
return value
|
|
485
|
+
return value
|
|
486
|
+
.filter((tool) => !!tool &&
|
|
459
487
|
typeof tool === "object" &&
|
|
460
|
-
typeof tool.name === "string")
|
|
488
|
+
typeof tool.name === "string")
|
|
489
|
+
.map((tool) => hydrateBuiltinAgentTool(tool));
|
|
490
|
+
}
|
|
491
|
+
function uniqueToolName(baseName, existingNames) {
|
|
492
|
+
const used = new Set(existingNames);
|
|
493
|
+
if (!used.has(baseName))
|
|
494
|
+
return baseName;
|
|
495
|
+
let suffix = 2;
|
|
496
|
+
while (used.has(`${baseName}_${suffix}`))
|
|
497
|
+
suffix += 1;
|
|
498
|
+
return `${baseName}_${suffix}`;
|
|
461
499
|
}
|
|
462
500
|
export function toProviderTools(tools) {
|
|
463
501
|
return tools.map((tool) => typeof tool.toProviderTool === "function"
|
|
@@ -871,6 +909,8 @@ function getStructuredOutputSchema(node) {
|
|
|
871
909
|
type = "object";
|
|
872
910
|
properties[name] = { type };
|
|
873
911
|
}
|
|
912
|
+
if (required.length === 0)
|
|
913
|
+
return null;
|
|
874
914
|
return {
|
|
875
915
|
type: "object",
|
|
876
916
|
additionalProperties: false,
|
|
@@ -2066,7 +2106,7 @@ export class AgentNode extends BaseNode {
|
|
|
2066
2106
|
return;
|
|
2067
2107
|
}
|
|
2068
2108
|
const prompt = asText(this.prompt ?? this.prompt ?? "");
|
|
2069
|
-
|
|
2109
|
+
let system = asText(this.system ?? this.system ?? DEFAULT_SYSTEM_PROMPT);
|
|
2070
2110
|
const image = this.image ?? this.image;
|
|
2071
2111
|
const audio = this.audio ?? this.audio;
|
|
2072
2112
|
const historyInput = this.history ?? this.history;
|
|
@@ -2077,6 +2117,7 @@ export class AgentNode extends BaseNode {
|
|
|
2077
2117
|
: [];
|
|
2078
2118
|
const threadId = String(this.thread_id ?? this.thread_id ?? "").trim();
|
|
2079
2119
|
const maxTokens = Number(this.max_tokens ?? this.max_tokens ?? 8192);
|
|
2120
|
+
const maxTurns = Math.max(1, Number(this.max_turns ?? 100));
|
|
2080
2121
|
const tools = await this.buildTools(context);
|
|
2081
2122
|
// Build control tools from _control_context (injected by the kernel
|
|
2082
2123
|
// for nodes that have outgoing control edges). This lets the LLM
|
|
@@ -2092,6 +2133,22 @@ export class AgentNode extends BaseNode {
|
|
|
2092
2133
|
});
|
|
2093
2134
|
}
|
|
2094
2135
|
const structuredSchema = getStructuredOutputSchema(this);
|
|
2136
|
+
let structuredResult = null;
|
|
2137
|
+
const structuredToolName = structuredSchema
|
|
2138
|
+
? uniqueToolName("submit_result", tools.map((tool) => tool.name))
|
|
2139
|
+
: null;
|
|
2140
|
+
if (structuredSchema && structuredToolName) {
|
|
2141
|
+
tools.push({
|
|
2142
|
+
name: structuredToolName,
|
|
2143
|
+
description: "Submit the final structured result for this agent node's dynamic outputs. Call this exactly once when you have the final answer.",
|
|
2144
|
+
inputSchema: structuredSchema,
|
|
2145
|
+
process: async (_context, params) => {
|
|
2146
|
+
structuredResult = params ?? {};
|
|
2147
|
+
return { status: "completed" };
|
|
2148
|
+
}
|
|
2149
|
+
});
|
|
2150
|
+
system = `${system}\n\nWhen the final answer is ready, call the ${structuredToolName} tool with values for the dynamic outputs. Do not format the final result as JSON text.`;
|
|
2151
|
+
}
|
|
2095
2152
|
const messages = [
|
|
2096
2153
|
{ role: "system", content: system },
|
|
2097
2154
|
...(await loadThreadMessages(context, threadId)),
|
|
@@ -2114,8 +2171,6 @@ export class AgentNode extends BaseNode {
|
|
|
2114
2171
|
await saveThreadMessage(context, threadId, messages[messages.length - 1]);
|
|
2115
2172
|
}
|
|
2116
2173
|
let lastTextOutput = null;
|
|
2117
|
-
/** Latest extracted `<think>` body (for diagnostics / truncation errors). */
|
|
2118
|
-
let lastExtractedThinking = null;
|
|
2119
2174
|
const providerTools = tools.length > 0 ? toProviderTools(tools) : undefined;
|
|
2120
2175
|
const provider = await context.getProvider(providerId);
|
|
2121
2176
|
// --- Agentic provider fast-path (e.g. Claude Agent SDK with MCP) ---
|
|
@@ -2177,6 +2232,7 @@ export class AgentNode extends BaseNode {
|
|
|
2177
2232
|
model: modelId,
|
|
2178
2233
|
tools: providerTools,
|
|
2179
2234
|
maxTokens,
|
|
2235
|
+
maxTurns,
|
|
2180
2236
|
threadId: threadId || undefined,
|
|
2181
2237
|
onToolCall
|
|
2182
2238
|
})) {
|
|
@@ -2212,6 +2268,12 @@ export class AgentNode extends BaseNode {
|
|
|
2212
2268
|
nodeId: this.__node_id ?? null,
|
|
2213
2269
|
toolName: item.name
|
|
2214
2270
|
});
|
|
2271
|
+
yield {
|
|
2272
|
+
chunk: toolCallChunk(item),
|
|
2273
|
+
thinking: null,
|
|
2274
|
+
text: null,
|
|
2275
|
+
audio: null
|
|
2276
|
+
};
|
|
2215
2277
|
}
|
|
2216
2278
|
}
|
|
2217
2279
|
for (const part of thinkSplitter.flush()) {
|
|
@@ -2245,9 +2307,6 @@ export class AgentNode extends BaseNode {
|
|
|
2245
2307
|
if (trimmed) {
|
|
2246
2308
|
lastTextOutput = trimmed;
|
|
2247
2309
|
}
|
|
2248
|
-
if (thinkingText.trim()) {
|
|
2249
|
-
lastExtractedThinking = thinkingText;
|
|
2250
|
-
}
|
|
2251
2310
|
if (thinkingText && !streamedRedactedThinking) {
|
|
2252
2311
|
yield {
|
|
2253
2312
|
chunk: null,
|
|
@@ -2278,15 +2337,19 @@ export class AgentNode extends BaseNode {
|
|
|
2278
2337
|
// --- Standard multi-iteration loop (for non-agentic providers) ---
|
|
2279
2338
|
let shouldContinue = false;
|
|
2280
2339
|
let firstIteration = true;
|
|
2281
|
-
|
|
2340
|
+
let turn = 0;
|
|
2341
|
+
while ((firstIteration || shouldContinue) && turn < maxTurns) {
|
|
2282
2342
|
firstIteration = false;
|
|
2283
2343
|
shouldContinue = false;
|
|
2344
|
+
turn += 1;
|
|
2284
2345
|
log.info("AgentNode provider iteration starting", {
|
|
2285
2346
|
nodeId: this.__node_id ?? null,
|
|
2286
2347
|
providerId,
|
|
2287
2348
|
modelId,
|
|
2288
2349
|
threadId: threadId || null,
|
|
2289
|
-
messageCount: messages.length
|
|
2350
|
+
messageCount: messages.length,
|
|
2351
|
+
turn,
|
|
2352
|
+
maxTurns
|
|
2290
2353
|
});
|
|
2291
2354
|
const assistantToolCalls = [];
|
|
2292
2355
|
let assistantText = "";
|
|
@@ -2300,6 +2363,7 @@ export class AgentNode extends BaseNode {
|
|
|
2300
2363
|
model: modelId,
|
|
2301
2364
|
tools: providerTools,
|
|
2302
2365
|
maxTokens,
|
|
2366
|
+
maxTurns,
|
|
2303
2367
|
threadId: threadId || undefined
|
|
2304
2368
|
})) {
|
|
2305
2369
|
if (isChunkItem(item)) {
|
|
@@ -2343,6 +2407,12 @@ export class AgentNode extends BaseNode {
|
|
|
2343
2407
|
toolName: item.name,
|
|
2344
2408
|
argKeys: Object.keys(item.args ?? {})
|
|
2345
2409
|
});
|
|
2410
|
+
yield {
|
|
2411
|
+
chunk: toolCallChunk(item),
|
|
2412
|
+
thinking: null,
|
|
2413
|
+
text: null,
|
|
2414
|
+
audio: null
|
|
2415
|
+
};
|
|
2346
2416
|
}
|
|
2347
2417
|
}
|
|
2348
2418
|
log.info("AgentNode provider iteration completed", {
|
|
@@ -2385,9 +2455,6 @@ export class AgentNode extends BaseNode {
|
|
|
2385
2455
|
if (trimmed) {
|
|
2386
2456
|
lastTextOutput = trimmed;
|
|
2387
2457
|
}
|
|
2388
|
-
if (thinkingText.trim()) {
|
|
2389
|
-
lastExtractedThinking = thinkingText;
|
|
2390
|
-
}
|
|
2391
2458
|
if (thinkingText && !streamedRedactedThinking) {
|
|
2392
2459
|
yield {
|
|
2393
2460
|
chunk: null,
|
|
@@ -2409,18 +2476,31 @@ export class AgentNode extends BaseNode {
|
|
|
2409
2476
|
content: [{ type: "text", text: assistantText }],
|
|
2410
2477
|
toolCalls: assistantToolCalls.length > 0 ? assistantToolCalls : null
|
|
2411
2478
|
};
|
|
2479
|
+
const rawParts = assistantToolCalls.find((tc) => tc._rawGeminiParts)?._rawGeminiParts;
|
|
2480
|
+
if (rawParts) {
|
|
2481
|
+
assistantMessage._rawGeminiParts = rawParts;
|
|
2482
|
+
}
|
|
2412
2483
|
messages.push(assistantMessage);
|
|
2413
2484
|
await saveThreadMessage(context, threadId, assistantMessage);
|
|
2414
2485
|
}
|
|
2415
2486
|
for (const toolCall of assistantToolCalls) {
|
|
2416
2487
|
const tool = tools.find((candidate) => candidate.name === toolCall.name);
|
|
2417
2488
|
if (!tool || typeof tool.process !== "function") {
|
|
2489
|
+
const message = `Unknown or non-executable tool: ${toolCall.name}`;
|
|
2418
2490
|
log.warn("AgentNode tool call had no matching executable tool", {
|
|
2419
2491
|
nodeId: this.__node_id ?? null,
|
|
2420
2492
|
toolCallId: toolCall.id,
|
|
2421
2493
|
toolName: toolCall.name,
|
|
2422
2494
|
availableTools: tools.map((candidate) => candidate.name)
|
|
2423
2495
|
});
|
|
2496
|
+
const toolMessage = {
|
|
2497
|
+
role: "tool",
|
|
2498
|
+
toolCallId: toolCall.id,
|
|
2499
|
+
content: JSON.stringify({ status: "error", error: message })
|
|
2500
|
+
};
|
|
2501
|
+
messages.push(toolMessage);
|
|
2502
|
+
await saveThreadMessage(context, threadId, toolMessage);
|
|
2503
|
+
shouldContinue = true;
|
|
2424
2504
|
continue;
|
|
2425
2505
|
}
|
|
2426
2506
|
let result;
|
|
@@ -2464,7 +2544,19 @@ export class AgentNode extends BaseNode {
|
|
|
2464
2544
|
toolCallId: toolCall.id,
|
|
2465
2545
|
toolName: toolCall.name
|
|
2466
2546
|
});
|
|
2467
|
-
|
|
2547
|
+
try {
|
|
2548
|
+
result = await tool.process(context, toolCall.args);
|
|
2549
|
+
}
|
|
2550
|
+
catch (err) {
|
|
2551
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2552
|
+
log.warn("AgentNode tool execution failed", {
|
|
2553
|
+
nodeId: this.__node_id ?? null,
|
|
2554
|
+
toolCallId: toolCall.id,
|
|
2555
|
+
toolName: toolCall.name,
|
|
2556
|
+
error: message
|
|
2557
|
+
});
|
|
2558
|
+
result = { status: "error", error: message };
|
|
2559
|
+
}
|
|
2468
2560
|
}
|
|
2469
2561
|
const toolMessage = {
|
|
2470
2562
|
role: "tool",
|
|
@@ -2473,74 +2565,34 @@ export class AgentNode extends BaseNode {
|
|
|
2473
2565
|
};
|
|
2474
2566
|
messages.push(toolMessage);
|
|
2475
2567
|
await saveThreadMessage(context, threadId, toolMessage);
|
|
2568
|
+
if (structuredToolName && toolCall.name === structuredToolName) {
|
|
2569
|
+
shouldContinue = false;
|
|
2570
|
+
break;
|
|
2571
|
+
}
|
|
2476
2572
|
shouldContinue = true;
|
|
2477
2573
|
}
|
|
2478
2574
|
}
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
const structuredText = (lastTextOutput ?? "").trim();
|
|
2482
|
-
if (!structuredText) {
|
|
2483
|
-
const reasoningOnly = Boolean(lastExtractedThinking?.trim());
|
|
2484
|
-
log.error("AgentNode structured output missing text payload", {
|
|
2575
|
+
if (shouldContinue && turn >= maxTurns) {
|
|
2576
|
+
log.warn("AgentNode hit max_turns cap with pending tool calls", {
|
|
2485
2577
|
nodeId: this.__node_id ?? null,
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
reasoningOnly,
|
|
2489
|
-
maxTokens
|
|
2490
|
-
});
|
|
2491
|
-
throw new Error(reasoningOnly
|
|
2492
|
-
? "Agent did not return structured output text: the response was cut off during internal reasoning before any answer was produced. Increase max_tokens on this node (or reduce prompt / reasoning) so the model can finish with valid JSON."
|
|
2493
|
-
: "Agent did not return structured output text.");
|
|
2494
|
-
}
|
|
2495
|
-
lastTextOutput = structuredText;
|
|
2496
|
-
let parsed = extractJson(lastTextOutput);
|
|
2497
|
-
if (!parsed) {
|
|
2498
|
-
// The LLM returned plain text instead of JSON. Rather than failing
|
|
2499
|
-
// the workflow, build a best-effort result by assigning the raw text
|
|
2500
|
-
// to each required string field in the schema.
|
|
2501
|
-
log.warn("AgentNode structured output was not valid JSON, falling back to raw text", {
|
|
2502
|
-
nodeId: this.__node_id ?? null,
|
|
2503
|
-
providerId,
|
|
2504
|
-
modelId,
|
|
2505
|
-
textPreview: lastTextOutput.slice(0, 200)
|
|
2578
|
+
turn,
|
|
2579
|
+
maxTurns
|
|
2506
2580
|
});
|
|
2507
|
-
const props = structuredSchema.properties ?? {};
|
|
2508
|
-
const fallback = {};
|
|
2509
|
-
for (const [name, spec] of Object.entries(props)) {
|
|
2510
|
-
if (spec.type === "string") {
|
|
2511
|
-
fallback[name] = lastTextOutput.trim();
|
|
2512
|
-
}
|
|
2513
|
-
else {
|
|
2514
|
-
fallback[name] = null;
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
parsed = fallback;
|
|
2518
|
-
}
|
|
2519
|
-
const required = Array.isArray(structuredSchema.required)
|
|
2520
|
-
? (structuredSchema.required ?? [])
|
|
2521
|
-
: [];
|
|
2522
|
-
for (const name of required) {
|
|
2523
|
-
if (!(name in parsed)) {
|
|
2524
|
-
log.error("AgentNode structured output missing required field", {
|
|
2525
|
-
nodeId: this.__node_id ?? null,
|
|
2526
|
-
missingField: name,
|
|
2527
|
-
parsedKeys: Object.keys(parsed)
|
|
2528
|
-
});
|
|
2529
|
-
throw new Error(`Agent structured output is missing required field '${name}'`);
|
|
2530
|
-
}
|
|
2531
2581
|
}
|
|
2532
|
-
|
|
2582
|
+
}
|
|
2583
|
+
if (structuredSchema && structuredResult) {
|
|
2584
|
+
log.info("AgentNode yielding dynamic output tool result", {
|
|
2533
2585
|
nodeId: this.__node_id ?? null,
|
|
2534
|
-
keys: Object.keys(
|
|
2586
|
+
keys: Object.keys(structuredResult)
|
|
2535
2587
|
});
|
|
2536
|
-
yield
|
|
2588
|
+
yield structuredResult;
|
|
2537
2589
|
}
|
|
2538
2590
|
log.info("AgentNode completed", {
|
|
2539
2591
|
nodeId: this.__node_id ?? null,
|
|
2540
2592
|
providerId,
|
|
2541
2593
|
modelId,
|
|
2542
2594
|
finalTextLength: lastTextOutput?.length ?? 0,
|
|
2543
|
-
returnedStructured: Boolean(
|
|
2595
|
+
returnedStructured: Boolean(structuredResult)
|
|
2544
2596
|
});
|
|
2545
2597
|
}
|
|
2546
2598
|
async process(context) {
|
|
@@ -2765,6 +2817,16 @@ __decorate([
|
|
|
2765
2817
|
max: 100000
|
|
2766
2818
|
})
|
|
2767
2819
|
], AgentNode.prototype, "max_tokens", void 0);
|
|
2820
|
+
__decorate([
|
|
2821
|
+
prop({
|
|
2822
|
+
type: "int",
|
|
2823
|
+
default: 100,
|
|
2824
|
+
title: "Max Turns",
|
|
2825
|
+
description: "Upper bound on agentic turns — one turn is a model call plus any tool execution it triggers. Caps both the AgentNode tool-loop iteration count and the provider's internal multi-turn budget (e.g. Claude Agent SDK). Raise for long sandbox sessions; lower to fail fast on runaway loops.",
|
|
2826
|
+
min: 1,
|
|
2827
|
+
max: 1000
|
|
2828
|
+
})
|
|
2829
|
+
], AgentNode.prototype, "max_turns", void 0);
|
|
2768
2830
|
__decorate([
|
|
2769
2831
|
prop({
|
|
2770
2832
|
type: "int",
|