@nodetool-ai/base-nodes 0.7.0-rc.11 → 0.7.0-rc.13
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 +12 -3
- package/dist/nodes/agents.d.ts.map +1 -1
- package/dist/nodes/agents.js +142 -70
- package/dist/nodes/agents.js.map +1 -1
- package/dist/nodes/sandbox.d.ts +12 -16
- package/dist/nodes/sandbox.d.ts.map +1 -1
- package/dist/nodes/sandbox.js +38 -86
- package/dist/nodes/sandbox.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
|
@@ -177,9 +177,9 @@ export declare class ClassifierNode extends BaseNode {
|
|
|
177
177
|
process(context?: ProcessingContext): Promise<Record<string, unknown>>;
|
|
178
178
|
}
|
|
179
179
|
export declare class AgentNode extends BaseNode {
|
|
180
|
-
static readonly nodeType
|
|
181
|
-
static readonly title
|
|
182
|
-
static readonly description
|
|
180
|
+
static readonly nodeType: string;
|
|
181
|
+
static readonly title: string;
|
|
182
|
+
static readonly description: string;
|
|
183
183
|
static readonly metadataOutputTypes: {
|
|
184
184
|
text: string;
|
|
185
185
|
chunk: string;
|
|
@@ -239,8 +239,17 @@ export declare class AgentNode extends BaseNode {
|
|
|
239
239
|
history: any;
|
|
240
240
|
thread_id: any;
|
|
241
241
|
max_tokens: any;
|
|
242
|
+
max_turns: any;
|
|
242
243
|
num_agents: any;
|
|
243
244
|
team_strategy: any;
|
|
245
|
+
/**
|
|
246
|
+
* Build the tool list for this run. Override in subclasses to inject
|
|
247
|
+
* additional tools (e.g. sandbox shell/file/browser tools) alongside the
|
|
248
|
+
* user-selected ones. Control tools from kernel control edges are
|
|
249
|
+
* appended separately by the genProcess paths and don't need to be
|
|
250
|
+
* handled here.
|
|
251
|
+
*/
|
|
252
|
+
protected buildTools(_context?: ProcessingContext): Promise<ToolLike[]>;
|
|
244
253
|
genProcess(context?: ProcessingContext): AsyncGenerator<Record<string, unknown>>;
|
|
245
254
|
process(context?: ProcessingContext): Promise<Record<string, unknown>>;
|
|
246
255
|
/**
|
|
@@ -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,
|
|
@@ -2020,6 +2060,16 @@ export class AgentNode extends BaseNode {
|
|
|
2020
2060
|
}
|
|
2021
2061
|
];
|
|
2022
2062
|
static isStreamingOutput = true;
|
|
2063
|
+
/**
|
|
2064
|
+
* Build the tool list for this run. Override in subclasses to inject
|
|
2065
|
+
* additional tools (e.g. sandbox shell/file/browser tools) alongside the
|
|
2066
|
+
* user-selected ones. Control tools from kernel control edges are
|
|
2067
|
+
* appended separately by the genProcess paths and don't need to be
|
|
2068
|
+
* handled here.
|
|
2069
|
+
*/
|
|
2070
|
+
async buildTools(_context) {
|
|
2071
|
+
return normalizeTools(this.tools ?? []);
|
|
2072
|
+
}
|
|
2023
2073
|
async *genProcess(context) {
|
|
2024
2074
|
const { providerId, modelId } = getModelConfig(this.serialize());
|
|
2025
2075
|
log.info("AgentNode starting", {
|
|
@@ -2056,7 +2106,7 @@ export class AgentNode extends BaseNode {
|
|
|
2056
2106
|
return;
|
|
2057
2107
|
}
|
|
2058
2108
|
const prompt = asText(this.prompt ?? this.prompt ?? "");
|
|
2059
|
-
|
|
2109
|
+
let system = asText(this.system ?? this.system ?? DEFAULT_SYSTEM_PROMPT);
|
|
2060
2110
|
const image = this.image ?? this.image;
|
|
2061
2111
|
const audio = this.audio ?? this.audio;
|
|
2062
2112
|
const historyInput = this.history ?? this.history;
|
|
@@ -2067,7 +2117,8 @@ export class AgentNode extends BaseNode {
|
|
|
2067
2117
|
: [];
|
|
2068
2118
|
const threadId = String(this.thread_id ?? this.thread_id ?? "").trim();
|
|
2069
2119
|
const maxTokens = Number(this.max_tokens ?? this.max_tokens ?? 8192);
|
|
2070
|
-
const
|
|
2120
|
+
const maxTurns = Math.max(1, Number(this.max_turns ?? 100));
|
|
2121
|
+
const tools = await this.buildTools(context);
|
|
2071
2122
|
// Build control tools from _control_context (injected by the kernel
|
|
2072
2123
|
// for nodes that have outgoing control edges). This lets the LLM
|
|
2073
2124
|
// call controlled nodes as tools.
|
|
@@ -2082,6 +2133,22 @@ export class AgentNode extends BaseNode {
|
|
|
2082
2133
|
});
|
|
2083
2134
|
}
|
|
2084
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
|
+
}
|
|
2085
2152
|
const messages = [
|
|
2086
2153
|
{ role: "system", content: system },
|
|
2087
2154
|
...(await loadThreadMessages(context, threadId)),
|
|
@@ -2104,8 +2171,6 @@ export class AgentNode extends BaseNode {
|
|
|
2104
2171
|
await saveThreadMessage(context, threadId, messages[messages.length - 1]);
|
|
2105
2172
|
}
|
|
2106
2173
|
let lastTextOutput = null;
|
|
2107
|
-
/** Latest extracted `<think>` body (for diagnostics / truncation errors). */
|
|
2108
|
-
let lastExtractedThinking = null;
|
|
2109
2174
|
const providerTools = tools.length > 0 ? toProviderTools(tools) : undefined;
|
|
2110
2175
|
const provider = await context.getProvider(providerId);
|
|
2111
2176
|
// --- Agentic provider fast-path (e.g. Claude Agent SDK with MCP) ---
|
|
@@ -2167,6 +2232,7 @@ export class AgentNode extends BaseNode {
|
|
|
2167
2232
|
model: modelId,
|
|
2168
2233
|
tools: providerTools,
|
|
2169
2234
|
maxTokens,
|
|
2235
|
+
maxTurns,
|
|
2170
2236
|
threadId: threadId || undefined,
|
|
2171
2237
|
onToolCall
|
|
2172
2238
|
})) {
|
|
@@ -2202,6 +2268,12 @@ export class AgentNode extends BaseNode {
|
|
|
2202
2268
|
nodeId: this.__node_id ?? null,
|
|
2203
2269
|
toolName: item.name
|
|
2204
2270
|
});
|
|
2271
|
+
yield {
|
|
2272
|
+
chunk: toolCallChunk(item),
|
|
2273
|
+
thinking: null,
|
|
2274
|
+
text: null,
|
|
2275
|
+
audio: null
|
|
2276
|
+
};
|
|
2205
2277
|
}
|
|
2206
2278
|
}
|
|
2207
2279
|
for (const part of thinkSplitter.flush()) {
|
|
@@ -2235,9 +2307,6 @@ export class AgentNode extends BaseNode {
|
|
|
2235
2307
|
if (trimmed) {
|
|
2236
2308
|
lastTextOutput = trimmed;
|
|
2237
2309
|
}
|
|
2238
|
-
if (thinkingText.trim()) {
|
|
2239
|
-
lastExtractedThinking = thinkingText;
|
|
2240
|
-
}
|
|
2241
2310
|
if (thinkingText && !streamedRedactedThinking) {
|
|
2242
2311
|
yield {
|
|
2243
2312
|
chunk: null,
|
|
@@ -2268,15 +2337,19 @@ export class AgentNode extends BaseNode {
|
|
|
2268
2337
|
// --- Standard multi-iteration loop (for non-agentic providers) ---
|
|
2269
2338
|
let shouldContinue = false;
|
|
2270
2339
|
let firstIteration = true;
|
|
2271
|
-
|
|
2340
|
+
let turn = 0;
|
|
2341
|
+
while ((firstIteration || shouldContinue) && turn < maxTurns) {
|
|
2272
2342
|
firstIteration = false;
|
|
2273
2343
|
shouldContinue = false;
|
|
2344
|
+
turn += 1;
|
|
2274
2345
|
log.info("AgentNode provider iteration starting", {
|
|
2275
2346
|
nodeId: this.__node_id ?? null,
|
|
2276
2347
|
providerId,
|
|
2277
2348
|
modelId,
|
|
2278
2349
|
threadId: threadId || null,
|
|
2279
|
-
messageCount: messages.length
|
|
2350
|
+
messageCount: messages.length,
|
|
2351
|
+
turn,
|
|
2352
|
+
maxTurns
|
|
2280
2353
|
});
|
|
2281
2354
|
const assistantToolCalls = [];
|
|
2282
2355
|
let assistantText = "";
|
|
@@ -2290,6 +2363,7 @@ export class AgentNode extends BaseNode {
|
|
|
2290
2363
|
model: modelId,
|
|
2291
2364
|
tools: providerTools,
|
|
2292
2365
|
maxTokens,
|
|
2366
|
+
maxTurns,
|
|
2293
2367
|
threadId: threadId || undefined
|
|
2294
2368
|
})) {
|
|
2295
2369
|
if (isChunkItem(item)) {
|
|
@@ -2333,6 +2407,12 @@ export class AgentNode extends BaseNode {
|
|
|
2333
2407
|
toolName: item.name,
|
|
2334
2408
|
argKeys: Object.keys(item.args ?? {})
|
|
2335
2409
|
});
|
|
2410
|
+
yield {
|
|
2411
|
+
chunk: toolCallChunk(item),
|
|
2412
|
+
thinking: null,
|
|
2413
|
+
text: null,
|
|
2414
|
+
audio: null
|
|
2415
|
+
};
|
|
2336
2416
|
}
|
|
2337
2417
|
}
|
|
2338
2418
|
log.info("AgentNode provider iteration completed", {
|
|
@@ -2375,9 +2455,6 @@ export class AgentNode extends BaseNode {
|
|
|
2375
2455
|
if (trimmed) {
|
|
2376
2456
|
lastTextOutput = trimmed;
|
|
2377
2457
|
}
|
|
2378
|
-
if (thinkingText.trim()) {
|
|
2379
|
-
lastExtractedThinking = thinkingText;
|
|
2380
|
-
}
|
|
2381
2458
|
if (thinkingText && !streamedRedactedThinking) {
|
|
2382
2459
|
yield {
|
|
2383
2460
|
chunk: null,
|
|
@@ -2399,18 +2476,31 @@ export class AgentNode extends BaseNode {
|
|
|
2399
2476
|
content: [{ type: "text", text: assistantText }],
|
|
2400
2477
|
toolCalls: assistantToolCalls.length > 0 ? assistantToolCalls : null
|
|
2401
2478
|
};
|
|
2479
|
+
const rawParts = assistantToolCalls.find((tc) => tc._rawGeminiParts)?._rawGeminiParts;
|
|
2480
|
+
if (rawParts) {
|
|
2481
|
+
assistantMessage._rawGeminiParts = rawParts;
|
|
2482
|
+
}
|
|
2402
2483
|
messages.push(assistantMessage);
|
|
2403
2484
|
await saveThreadMessage(context, threadId, assistantMessage);
|
|
2404
2485
|
}
|
|
2405
2486
|
for (const toolCall of assistantToolCalls) {
|
|
2406
2487
|
const tool = tools.find((candidate) => candidate.name === toolCall.name);
|
|
2407
2488
|
if (!tool || typeof tool.process !== "function") {
|
|
2489
|
+
const message = `Unknown or non-executable tool: ${toolCall.name}`;
|
|
2408
2490
|
log.warn("AgentNode tool call had no matching executable tool", {
|
|
2409
2491
|
nodeId: this.__node_id ?? null,
|
|
2410
2492
|
toolCallId: toolCall.id,
|
|
2411
2493
|
toolName: toolCall.name,
|
|
2412
2494
|
availableTools: tools.map((candidate) => candidate.name)
|
|
2413
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;
|
|
2414
2504
|
continue;
|
|
2415
2505
|
}
|
|
2416
2506
|
let result;
|
|
@@ -2454,7 +2544,19 @@ export class AgentNode extends BaseNode {
|
|
|
2454
2544
|
toolCallId: toolCall.id,
|
|
2455
2545
|
toolName: toolCall.name
|
|
2456
2546
|
});
|
|
2457
|
-
|
|
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
|
+
}
|
|
2458
2560
|
}
|
|
2459
2561
|
const toolMessage = {
|
|
2460
2562
|
role: "tool",
|
|
@@ -2463,74 +2565,34 @@ export class AgentNode extends BaseNode {
|
|
|
2463
2565
|
};
|
|
2464
2566
|
messages.push(toolMessage);
|
|
2465
2567
|
await saveThreadMessage(context, threadId, toolMessage);
|
|
2568
|
+
if (structuredToolName && toolCall.name === structuredToolName) {
|
|
2569
|
+
shouldContinue = false;
|
|
2570
|
+
break;
|
|
2571
|
+
}
|
|
2466
2572
|
shouldContinue = true;
|
|
2467
2573
|
}
|
|
2468
2574
|
}
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
const structuredText = (lastTextOutput ?? "").trim();
|
|
2472
|
-
if (!structuredText) {
|
|
2473
|
-
const reasoningOnly = Boolean(lastExtractedThinking?.trim());
|
|
2474
|
-
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", {
|
|
2475
2577
|
nodeId: this.__node_id ?? null,
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
reasoningOnly,
|
|
2479
|
-
maxTokens
|
|
2578
|
+
turn,
|
|
2579
|
+
maxTurns
|
|
2480
2580
|
});
|
|
2481
|
-
throw new Error(reasoningOnly
|
|
2482
|
-
? "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."
|
|
2483
|
-
: "Agent did not return structured output text.");
|
|
2484
2581
|
}
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
// The LLM returned plain text instead of JSON. Rather than failing
|
|
2489
|
-
// the workflow, build a best-effort result by assigning the raw text
|
|
2490
|
-
// to each required string field in the schema.
|
|
2491
|
-
log.warn("AgentNode structured output was not valid JSON, falling back to raw text", {
|
|
2492
|
-
nodeId: this.__node_id ?? null,
|
|
2493
|
-
providerId,
|
|
2494
|
-
modelId,
|
|
2495
|
-
textPreview: lastTextOutput.slice(0, 200)
|
|
2496
|
-
});
|
|
2497
|
-
const props = structuredSchema.properties ?? {};
|
|
2498
|
-
const fallback = {};
|
|
2499
|
-
for (const [name, spec] of Object.entries(props)) {
|
|
2500
|
-
if (spec.type === "string") {
|
|
2501
|
-
fallback[name] = lastTextOutput.trim();
|
|
2502
|
-
}
|
|
2503
|
-
else {
|
|
2504
|
-
fallback[name] = null;
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
parsed = fallback;
|
|
2508
|
-
}
|
|
2509
|
-
const required = Array.isArray(structuredSchema.required)
|
|
2510
|
-
? (structuredSchema.required ?? [])
|
|
2511
|
-
: [];
|
|
2512
|
-
for (const name of required) {
|
|
2513
|
-
if (!(name in parsed)) {
|
|
2514
|
-
log.error("AgentNode structured output missing required field", {
|
|
2515
|
-
nodeId: this.__node_id ?? null,
|
|
2516
|
-
missingField: name,
|
|
2517
|
-
parsedKeys: Object.keys(parsed)
|
|
2518
|
-
});
|
|
2519
|
-
throw new Error(`Agent structured output is missing required field '${name}'`);
|
|
2520
|
-
}
|
|
2521
|
-
}
|
|
2522
|
-
log.info("AgentNode yielding structured output", {
|
|
2582
|
+
}
|
|
2583
|
+
if (structuredSchema && structuredResult) {
|
|
2584
|
+
log.info("AgentNode yielding dynamic output tool result", {
|
|
2523
2585
|
nodeId: this.__node_id ?? null,
|
|
2524
|
-
keys: Object.keys(
|
|
2586
|
+
keys: Object.keys(structuredResult)
|
|
2525
2587
|
});
|
|
2526
|
-
yield
|
|
2588
|
+
yield structuredResult;
|
|
2527
2589
|
}
|
|
2528
2590
|
log.info("AgentNode completed", {
|
|
2529
2591
|
nodeId: this.__node_id ?? null,
|
|
2530
2592
|
providerId,
|
|
2531
2593
|
modelId,
|
|
2532
2594
|
finalTextLength: lastTextOutput?.length ?? 0,
|
|
2533
|
-
returnedStructured: Boolean(
|
|
2595
|
+
returnedStructured: Boolean(structuredResult)
|
|
2534
2596
|
});
|
|
2535
2597
|
}
|
|
2536
2598
|
async process(context) {
|
|
@@ -2580,7 +2642,7 @@ export class AgentNode extends BaseNode {
|
|
|
2580
2642
|
async *genProcessMultiMode(context, providerId, modelId, mode) {
|
|
2581
2643
|
const prompt = asText(this.prompt ?? "");
|
|
2582
2644
|
const system = asText(this.system ?? DEFAULT_SYSTEM_PROMPT);
|
|
2583
|
-
const rawTools =
|
|
2645
|
+
const rawTools = await this.buildTools(context);
|
|
2584
2646
|
// Build control tools
|
|
2585
2647
|
const controlContext = this._control_context;
|
|
2586
2648
|
const controlTools = buildControlTools(controlContext);
|
|
@@ -2755,6 +2817,16 @@ __decorate([
|
|
|
2755
2817
|
max: 100000
|
|
2756
2818
|
})
|
|
2757
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);
|
|
2758
2830
|
__decorate([
|
|
2759
2831
|
prop({
|
|
2760
2832
|
type: "int",
|