@nodetool-ai/llm-nodes 0.8.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 +52 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/nodes/agent-control-tools.d.ts +22 -0
- package/dist/nodes/agent-control-tools.d.ts.map +1 -0
- package/dist/nodes/agent-control-tools.js +123 -0
- package/dist/nodes/agent-control-tools.js.map +1 -0
- package/dist/nodes/agent-loop.d.ts +73 -0
- package/dist/nodes/agent-loop.d.ts.map +1 -0
- package/dist/nodes/agent-loop.js +168 -0
- package/dist/nodes/agent-loop.js.map +1 -0
- package/dist/nodes/agent-recommended-models.d.ts +152 -0
- package/dist/nodes/agent-recommended-models.d.ts.map +1 -0
- package/dist/nodes/agent-recommended-models.js +656 -0
- package/dist/nodes/agent-recommended-models.js.map +1 -0
- package/dist/nodes/agent-thinking.d.ts +29 -0
- package/dist/nodes/agent-thinking.d.ts.map +1 -0
- package/dist/nodes/agent-thinking.js +139 -0
- package/dist/nodes/agent-thinking.js.map +1 -0
- package/dist/nodes/agent-threads.d.ts +17 -0
- package/dist/nodes/agent-threads.d.ts.map +1 -0
- package/dist/nodes/agent-threads.js +93 -0
- package/dist/nodes/agent-threads.js.map +1 -0
- package/dist/nodes/agent-tool-hydration.d.ts +50 -0
- package/dist/nodes/agent-tool-hydration.d.ts.map +1 -0
- package/dist/nodes/agent-tool-hydration.js +106 -0
- package/dist/nodes/agent-tool-hydration.js.map +1 -0
- package/dist/nodes/agent-utils.d.ts +174 -0
- package/dist/nodes/agent-utils.d.ts.map +1 -0
- package/dist/nodes/agent-utils.js +553 -0
- package/dist/nodes/agent-utils.js.map +1 -0
- package/dist/nodes/agents.d.ts +402 -0
- package/dist/nodes/agents.d.ts.map +1 -0
- package/dist/nodes/agents.js +1491 -0
- package/dist/nodes/agents.js.map +1 -0
- package/dist/nodes/director.d.ts +126 -0
- package/dist/nodes/director.d.ts.map +1 -0
- package/dist/nodes/director.js +337 -0
- package/dist/nodes/director.js.map +1 -0
- package/dist/nodes/gemini.d.ts +171 -0
- package/dist/nodes/gemini.d.ts.map +1 -0
- package/dist/nodes/gemini.js +985 -0
- package/dist/nodes/gemini.js.map +1 -0
- package/dist/nodes/generators.d.ts +162 -0
- package/dist/nodes/generators.d.ts.map +1 -0
- package/dist/nodes/generators.js +966 -0
- package/dist/nodes/generators.js.map +1 -0
- package/dist/nodes/mistral.d.ts +109 -0
- package/dist/nodes/mistral.d.ts.map +1 -0
- package/dist/nodes/mistral.js +447 -0
- package/dist/nodes/mistral.js.map +1 -0
- package/dist/nodes/openai.d.ts +292 -0
- package/dist/nodes/openai.d.ts.map +1 -0
- package/dist/nodes/openai.js +1806 -0
- package/dist/nodes/openai.js.map +1 -0
- package/dist/nodes/provider-spend.d.ts +45 -0
- package/dist/nodes/provider-spend.d.ts.map +1 -0
- package/dist/nodes/provider-spend.js +69 -0
- package/dist/nodes/provider-spend.js.map +1 -0
- package/dist/nodes/shots.d.ts +108 -0
- package/dist/nodes/shots.d.ts.map +1 -0
- package/dist/nodes/shots.js +378 -0
- package/dist/nodes/shots.js.map +1 -0
- package/dist/nodes/xai.d.ts +99 -0
- package/dist/nodes/xai.d.ts.map +1 -0
- package/dist/nodes/xai.js +360 -0
- package/dist/nodes/xai.js.map +1 -0
- package/package.json +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @nodetool-ai/llm-nodes
|
|
2
|
+
|
|
3
|
+
LLM provider and agent nodes for [NodeTool](https://nodetool.ai).
|
|
4
|
+
|
|
5
|
+
Call OpenAI, Google Gemini, Mistral, and xAI directly from visual AI workflows —
|
|
6
|
+
chat, embeddings, image generation, speech, transcription, web search — plus
|
|
7
|
+
NodeTool agent nodes for summarizing, extracting, classifying, and generating
|
|
8
|
+
structured output.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @nodetool-ai/llm-nodes
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Nodes
|
|
17
|
+
|
|
18
|
+
**OpenAI** (`openai.*`) — `text.Embedding`, `text.WebSearch`, `text.Moderation`,
|
|
19
|
+
`image.CreateImage`, `image.EditImage`, `image.ImageVariation`,
|
|
20
|
+
`audio.TextToSpeech`, `audio.Transcribe`, `audio.Translate`,
|
|
21
|
+
`agents.RealtimeAgent`, `agents.RealtimeTranscription`, `agents.LiveAgent`.
|
|
22
|
+
|
|
23
|
+
**Gemini** (`gemini.*`) — `text.GroundedSearch`, `text.Embedding`,
|
|
24
|
+
`image.ImageGeneration`, `video.TextToVideo`, `video.ImageToVideo`,
|
|
25
|
+
`audio.TextToSpeech`, `audio.Transcribe`.
|
|
26
|
+
|
|
27
|
+
**Mistral** (`mistral.*`) — `text.ChatComplete`, `text.CodeComplete`,
|
|
28
|
+
`embeddings.Embedding`, `vision.ImageToText`, `vision.OCR`.
|
|
29
|
+
|
|
30
|
+
**xAI** (`xai.*`) — `text.ChatComplete`, `text.WebSearch`, `vision.ImageToText`,
|
|
31
|
+
`image.GenerateImage`.
|
|
32
|
+
|
|
33
|
+
**Agents** (`nodetool.agents.*`) — `Summarizer`, `Extractor`, `Classifier`,
|
|
34
|
+
`EnhancePrompt`, `CreateThread`.
|
|
35
|
+
|
|
36
|
+
**Generators** (`nodetool.generators.*`) — `StructuredOutputGenerator`,
|
|
37
|
+
`DataGenerator`, `ListGenerator`, `ChartGenerator`, `SVGGenerator`.
|
|
38
|
+
|
|
39
|
+
## Configuration
|
|
40
|
+
|
|
41
|
+
Set the provider keys you use in NodeTool's secret store (Settings → API Keys)
|
|
42
|
+
or as environment variables:
|
|
43
|
+
|
|
44
|
+
- `OPENAI_API_KEY`
|
|
45
|
+
- `GEMINI_API_KEY`
|
|
46
|
+
- `MISTRAL_API_KEY`
|
|
47
|
+
- `XAI_API_KEY`
|
|
48
|
+
|
|
49
|
+
## Links
|
|
50
|
+
|
|
51
|
+
- [NodeTool](https://nodetool.ai)
|
|
52
|
+
- [GitHub](https://github.com/nodetool-ai/nodetool)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2026-09-28T09:19:15.219Z
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nodetool-ai/llm-nodes — LLM provider + agent node bundle.
|
|
3
|
+
*
|
|
4
|
+
* Classes from `openai.ts`, `gemini.ts` and `xai.ts` share names with
|
|
5
|
+
* each other and with `mistral.ts` (e.g. `EmbeddingNode`,
|
|
6
|
+
* `ChatComplete`, `ImageToText`), so we re-export those provider modules
|
|
7
|
+
* via subpath exports (`@nodetool-ai/llm-nodes/openai`, `/gemini`,
|
|
8
|
+
* `/mistral`, `/xai`, `/agents`) rather than the barrel. The barrel fully
|
|
9
|
+
* re-exports everything else.
|
|
10
|
+
*/
|
|
11
|
+
export * from "./nodes/agents.js";
|
|
12
|
+
export * from "./nodes/agent-tool-hydration.js";
|
|
13
|
+
export * from "./nodes/generators.js";
|
|
14
|
+
export * from "./nodes/mistral.js";
|
|
15
|
+
export { OPENAI_NODES } from "./nodes/openai.js";
|
|
16
|
+
export { GEMINI_NODES } from "./nodes/gemini.js";
|
|
17
|
+
export { XAI_NODES } from "./nodes/xai.js";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AAMnC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nodetool-ai/llm-nodes — LLM provider + agent node bundle.
|
|
3
|
+
*
|
|
4
|
+
* Classes from `openai.ts`, `gemini.ts` and `xai.ts` share names with
|
|
5
|
+
* each other and with `mistral.ts` (e.g. `EmbeddingNode`,
|
|
6
|
+
* `ChatComplete`, `ImageToText`), so we re-export those provider modules
|
|
7
|
+
* via subpath exports (`@nodetool-ai/llm-nodes/openai`, `/gemini`,
|
|
8
|
+
* `/mistral`, `/xai`, `/agents`) rather than the barrel. The barrel fully
|
|
9
|
+
* re-exports everything else.
|
|
10
|
+
*/
|
|
11
|
+
export * from "./nodes/agents.js";
|
|
12
|
+
export * from "./nodes/agent-tool-hydration.js";
|
|
13
|
+
export * from "./nodes/generators.js";
|
|
14
|
+
export * from "./nodes/mistral.js";
|
|
15
|
+
// `openai.ts`, `gemini.ts` and `xai.ts` reuse class names (`EmbeddingNode`,
|
|
16
|
+
// `ChatComplete`, `ImageToText`); barrel callers get only the registration
|
|
17
|
+
// arrays. Use the `/openai`, `/gemini` and `/xai` subpath exports for the
|
|
18
|
+
// individual classes.
|
|
19
|
+
export { OPENAI_NODES } from "./nodes/openai.js";
|
|
20
|
+
export { GEMINI_NODES } from "./nodes/gemini.js";
|
|
21
|
+
export { XAI_NODES } from "./nodes/xai.js";
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AAEnC,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,sBAAsB;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ProcessingContext } from "@nodetool-ai/runtime";
|
|
2
|
+
import type { ToolLike } from "./agent-utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* A control tool is a normal {@link ToolLike} whose `process` dispatches a
|
|
5
|
+
* control event to a target node. `targetNodeId` is kept on the object for
|
|
6
|
+
* diagnostics/logging by the caller; execution flows through the generic
|
|
7
|
+
* `tool.process` path like any other tool.
|
|
8
|
+
*/
|
|
9
|
+
interface ControlTool extends ToolLike {
|
|
10
|
+
targetNodeId: string;
|
|
11
|
+
process: (context: ProcessingContext, params: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build control tools from `_control_context` input. Each tool's `process`
|
|
15
|
+
* filters the model's arguments to the node's declared properties, then
|
|
16
|
+
* dispatches a control event through the context and returns the result — so
|
|
17
|
+
* control tools run through the same generic `tool.process` path as any other
|
|
18
|
+
* tool (including plan mode's ToolLikeAdapter).
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildControlTools(controlContext: unknown): ControlTool[];
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=agent-control-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-control-tools.d.ts","sourceRoot":"","sources":["../../src/nodes/agent-control-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AASjD;;;;;GAKG;AACH,UAAU,WAAY,SAAQ,QAAQ;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,CACP,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC;AAuBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,OAAO,GAAG,WAAW,EAAE,CA2GxE"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createLogger } from "@nodetool-ai/config";
|
|
2
|
+
import { isObjectLike } from "@nodetool-ai/node-sdk";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Control tool support for Agent nodes with outgoing control edges
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
const log = createLogger("nodetool.base-nodes.agents");
|
|
7
|
+
/**
|
|
8
|
+
* Sanitize a node title to a valid tool name (snake_case, max 64 chars).
|
|
9
|
+
* Prefixed with `run_` to avoid collisions with provider-reserved built-in
|
|
10
|
+
* tool names (e.g. Gemini's native `google_search`, which would otherwise
|
|
11
|
+
* shadow our schema and pass `queries` instead of the node's actual props).
|
|
12
|
+
*/
|
|
13
|
+
function sanitizeControlToolName(name) {
|
|
14
|
+
const fallback = "run_node";
|
|
15
|
+
if (!name)
|
|
16
|
+
return fallback;
|
|
17
|
+
let s = name
|
|
18
|
+
.replace(/[^a-zA-Z0-9]/g, "_")
|
|
19
|
+
.replace(/([a-z])([A-Z])/g, "$1_$2")
|
|
20
|
+
.toLowerCase()
|
|
21
|
+
.replace(/_+/g, "_")
|
|
22
|
+
.replace(/^_+|_+$/g, "");
|
|
23
|
+
if (!s)
|
|
24
|
+
return fallback;
|
|
25
|
+
s = `run_${s}`;
|
|
26
|
+
if (s.length > 64)
|
|
27
|
+
s = s.slice(0, 64);
|
|
28
|
+
return s;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build control tools from `_control_context` input. Each tool's `process`
|
|
32
|
+
* filters the model's arguments to the node's declared properties, then
|
|
33
|
+
* dispatches a control event through the context and returns the result — so
|
|
34
|
+
* control tools run through the same generic `tool.process` path as any other
|
|
35
|
+
* tool (including plan mode's ToolLikeAdapter).
|
|
36
|
+
*/
|
|
37
|
+
export function buildControlTools(controlContext) {
|
|
38
|
+
if (!isObjectLike(controlContext))
|
|
39
|
+
return [];
|
|
40
|
+
const tools = [];
|
|
41
|
+
const usedNames = new Set();
|
|
42
|
+
for (const [targetId, info] of Object.entries(controlContext)) {
|
|
43
|
+
if (!isObjectLike(info))
|
|
44
|
+
continue;
|
|
45
|
+
const nodeInfo = info;
|
|
46
|
+
const nodeTitle = String(nodeInfo.node_title ?? nodeInfo.node_type ?? targetId);
|
|
47
|
+
const baseName = sanitizeControlToolName(nodeTitle);
|
|
48
|
+
let toolName = baseName;
|
|
49
|
+
let suffix = 2;
|
|
50
|
+
while (usedNames.has(toolName)) {
|
|
51
|
+
const suffixText = `_${suffix}`;
|
|
52
|
+
toolName = `${baseName.slice(0, 64 - suffixText.length)}${suffixText}`;
|
|
53
|
+
suffix++;
|
|
54
|
+
}
|
|
55
|
+
usedNames.add(toolName);
|
|
56
|
+
// Build input schema from control_actions.run.properties
|
|
57
|
+
const actions = (nodeInfo.control_actions ?? {});
|
|
58
|
+
const runAction = (actions.run ?? {});
|
|
59
|
+
const rawProperties = (runAction.properties ?? {});
|
|
60
|
+
const properties = {};
|
|
61
|
+
for (const [key, schema] of Object.entries(rawProperties)) {
|
|
62
|
+
if (isObjectLike(schema)) {
|
|
63
|
+
properties[key] = { ...schema };
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
properties[key] = { type: "string", description: String(schema) };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const inputSchema = {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties,
|
|
72
|
+
required: [],
|
|
73
|
+
additionalProperties: false
|
|
74
|
+
};
|
|
75
|
+
let description = `Control ${nodeTitle}: trigger execution with optional property overrides`;
|
|
76
|
+
const propNames = Object.keys(properties);
|
|
77
|
+
if (propNames.length > 0) {
|
|
78
|
+
description += `. Available properties: ${propNames.join(", ")}`;
|
|
79
|
+
}
|
|
80
|
+
const allowedProperties = new Set(propNames);
|
|
81
|
+
tools.push({
|
|
82
|
+
targetNodeId: targetId,
|
|
83
|
+
name: toolName,
|
|
84
|
+
description,
|
|
85
|
+
inputSchema,
|
|
86
|
+
async process(context, params) {
|
|
87
|
+
const callArgs = Object.fromEntries(Object.entries(params ?? {}).filter(([key]) => allowedProperties.has(key)));
|
|
88
|
+
log.info("Control tool dispatching", {
|
|
89
|
+
toolName,
|
|
90
|
+
targetNodeId: targetId,
|
|
91
|
+
argKeys: Object.keys(callArgs)
|
|
92
|
+
});
|
|
93
|
+
if (!context.hasControlEventSupport) {
|
|
94
|
+
return {
|
|
95
|
+
status: "error",
|
|
96
|
+
target_node_id: targetId,
|
|
97
|
+
error: "Control event dispatch is not available in this execution context"
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const result = await context.sendControlEvent(targetId, callArgs);
|
|
102
|
+
return {
|
|
103
|
+
status: "completed",
|
|
104
|
+
target_node_id: targetId,
|
|
105
|
+
result
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
return {
|
|
110
|
+
status: "error",
|
|
111
|
+
target_node_id: targetId,
|
|
112
|
+
error: err instanceof Error ? err.message : String(err)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
toProviderTool() {
|
|
117
|
+
return { name: toolName, description, inputSchema };
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return tools;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=agent-control-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-control-tools.js","sourceRoot":"","sources":["../../src/nodes/agent-control-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Message, MessageContent, ProcessingContext } from "@nodetool-ai/runtime";
|
|
2
|
+
import type { Chunk } from "@nodetool-ai/protocol";
|
|
3
|
+
import { Tool as AgentTool } from "@nodetool-ai/agents";
|
|
4
|
+
import type { ToolLike, ToolResult } from "./agent-utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* Adapter that wraps a ToolLike (from base-nodes) as an AgentTool (from @nodetool-ai/agents).
|
|
7
|
+
* This bridges the tool systems so Agent can use tools defined in the node graph.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ToolLikeAdapter extends AgentTool {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly description: string;
|
|
12
|
+
protected readonly jsonSchema: Record<string, unknown>;
|
|
13
|
+
private readonly _process;
|
|
14
|
+
private readonly _execute;
|
|
15
|
+
constructor(toolLike: ToolLike);
|
|
16
|
+
/**
|
|
17
|
+
* Delegate to the wrapped tool's own `execute` when it has one: that is
|
|
18
|
+
* where param stripping/coercion and `toolCallId` forwarding live, and
|
|
19
|
+
* double-wrapping through `process` would skip both.
|
|
20
|
+
*/
|
|
21
|
+
execute(context: ProcessingContext, params: Record<string, unknown> | null | undefined, options?: {
|
|
22
|
+
toolCallId?: string;
|
|
23
|
+
}): Promise<unknown>;
|
|
24
|
+
process(context: ProcessingContext, params: Record<string, unknown>): Promise<ToolResult>;
|
|
25
|
+
}
|
|
26
|
+
export interface AgentLoopOptions {
|
|
27
|
+
context: ProcessingContext;
|
|
28
|
+
providerId: string;
|
|
29
|
+
modelId: string;
|
|
30
|
+
systemPrompt: string;
|
|
31
|
+
prompt: string;
|
|
32
|
+
/**
|
|
33
|
+
* Tools the model may call. Each may be a fully-formed {@link ToolLike} (has
|
|
34
|
+
* `process` + `inputSchema`) OR a bare name-stub (`{ name }`) for a builtin
|
|
35
|
+
* tool registered via `registerBuiltinAgentToolClasses` — runAgentLoop
|
|
36
|
+
* hydrates stubs by name. Anything that can't be hydrated (no `process`) is
|
|
37
|
+
* logged and treated as an unknown tool by the model.
|
|
38
|
+
*/
|
|
39
|
+
tools: ToolLike[];
|
|
40
|
+
contentParts?: MessageContent[];
|
|
41
|
+
maxTokens?: number;
|
|
42
|
+
maxIterations?: number;
|
|
43
|
+
threadId?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Optional sink for streamed assistant text deltas (non-thinking). Lets a
|
|
46
|
+
* caller surface incremental output (e.g. a node `chunk` output) without
|
|
47
|
+
* changing the loop's accumulate-and-return contract.
|
|
48
|
+
*/
|
|
49
|
+
onText?: (delta: string) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Optional sink for each tool call the model makes, formatted as a
|
|
52
|
+
* `tool_call` {@link Chunk} (same shape the Agent node emits). Fired just
|
|
53
|
+
* before the tool runs.
|
|
54
|
+
*/
|
|
55
|
+
onToolCall?: (chunk: Chunk) => void;
|
|
56
|
+
}
|
|
57
|
+
export interface AgentLoopResult {
|
|
58
|
+
text: string;
|
|
59
|
+
messages: Message[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Run a streaming tool-use loop: the model streams text/tool-calls, tools
|
|
63
|
+
* execute, results feed back, repeat until no more tool calls or
|
|
64
|
+
* `maxIterations`. Returns the final assistant text plus the full message
|
|
65
|
+
* trail. Stream via `onText` / `onToolCall`.
|
|
66
|
+
*
|
|
67
|
+
* Tools (`options.tools`) may be real {@link ToolLike}s or bare `{ name }`
|
|
68
|
+
* stubs for registered builtin tools — they are hydrated here (see the `tools`
|
|
69
|
+
* field doc). This mirrors the AgentNode's `normalizeTools`; both paths now
|
|
70
|
+
* hydrate, so a tool reaches the loop the same way regardless of entry point.
|
|
71
|
+
*/
|
|
72
|
+
export declare function runAgentLoop(options: AgentLoopOptions): Promise<AgentLoopResult>;
|
|
73
|
+
//# sourceMappingURL=agent-loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../../src/nodes/agent-loop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,iBAAiB,EAElB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAY7D;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,SAAS;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGA;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAE/C,YAAY,QAAQ,EAAE,QAAQ,EAY7B;IAED;;;;OAIG;IACG,OAAO,CACX,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAClD,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO,GACpC,OAAO,CAAC,OAAO,CAAC,CAKlB;IAEK,OAAO,CACX,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,UAAU,CAAC,CAErB;CACF;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,cAAc,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAmI1B"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createLogger } from "@nodetool-ai/config";
|
|
2
|
+
import { Tool as AgentTool } from "@nodetool-ai/agents";
|
|
3
|
+
import { hydrateBuiltinAgentTools } from "./agent-tool-hydration.js";
|
|
4
|
+
import { classifyProviderStream, serializeToolResult, toProviderTools, toolCallChunk } from "./agent-utils.js";
|
|
5
|
+
import { meterProviderSpend } from "./provider-spend.js";
|
|
6
|
+
import { isCallable } from "@nodetool-ai/node-sdk";
|
|
7
|
+
const log = createLogger("nodetool.base-nodes.agents");
|
|
8
|
+
/**
|
|
9
|
+
* Adapter that wraps a ToolLike (from base-nodes) as an AgentTool (from @nodetool-ai/agents).
|
|
10
|
+
* This bridges the tool systems so Agent can use tools defined in the node graph.
|
|
11
|
+
*/
|
|
12
|
+
export class ToolLikeAdapter extends AgentTool {
|
|
13
|
+
name;
|
|
14
|
+
description;
|
|
15
|
+
jsonSchema;
|
|
16
|
+
_process;
|
|
17
|
+
_execute;
|
|
18
|
+
constructor(toolLike) {
|
|
19
|
+
super();
|
|
20
|
+
this.name = toolLike.name;
|
|
21
|
+
this.description = toolLike.description ?? "";
|
|
22
|
+
this.jsonSchema = toolLike.inputSchema ?? {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {}
|
|
25
|
+
};
|
|
26
|
+
this._execute = toolLike.execute;
|
|
27
|
+
this._process =
|
|
28
|
+
toolLike.process ??
|
|
29
|
+
(async () => ({ error: "Tool has no process implementation" }));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Delegate to the wrapped tool's own `execute` when it has one: that is
|
|
33
|
+
* where param stripping/coercion and `toolCallId` forwarding live, and
|
|
34
|
+
* double-wrapping through `process` would skip both.
|
|
35
|
+
*/
|
|
36
|
+
async execute(context, params, options = {}) {
|
|
37
|
+
if (this._execute) {
|
|
38
|
+
return this._execute(context, params ?? {}, options);
|
|
39
|
+
}
|
|
40
|
+
return super.execute(context, params, options);
|
|
41
|
+
}
|
|
42
|
+
async process(context, params) {
|
|
43
|
+
return this._process(context, params);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run a streaming tool-use loop: the model streams text/tool-calls, tools
|
|
48
|
+
* execute, results feed back, repeat until no more tool calls or
|
|
49
|
+
* `maxIterations`. Returns the final assistant text plus the full message
|
|
50
|
+
* trail. Stream via `onText` / `onToolCall`.
|
|
51
|
+
*
|
|
52
|
+
* Tools (`options.tools`) may be real {@link ToolLike}s or bare `{ name }`
|
|
53
|
+
* stubs for registered builtin tools — they are hydrated here (see the `tools`
|
|
54
|
+
* field doc). This mirrors the AgentNode's `normalizeTools`; both paths now
|
|
55
|
+
* hydrate, so a tool reaches the loop the same way regardless of entry point.
|
|
56
|
+
*/
|
|
57
|
+
export async function runAgentLoop(options) {
|
|
58
|
+
const { context, providerId, modelId, systemPrompt, prompt, tools, contentParts, maxTokens = 4096, maxIterations = 10 } = options;
|
|
59
|
+
if (!context || !isCallable(context.getProvider)) {
|
|
60
|
+
throw new Error("Processing context with provider access is required");
|
|
61
|
+
}
|
|
62
|
+
const userContent = [{ type: "text", text: prompt }];
|
|
63
|
+
if (contentParts) {
|
|
64
|
+
userContent.push(...contentParts);
|
|
65
|
+
}
|
|
66
|
+
const messages = [
|
|
67
|
+
{ role: "system", content: systemPrompt },
|
|
68
|
+
{ role: "user", content: userContent }
|
|
69
|
+
];
|
|
70
|
+
// Hydrate builtin tools passed as bare name-stubs ({ name }) into real Tool
|
|
71
|
+
// instances (same as the AgentNode path's normalizeTools). Without this a
|
|
72
|
+
// stub has no `process`/`inputSchema`, so the model gets a schemaless tool
|
|
73
|
+
// and every call is rejected as "Unknown tool". A real Tool passes through
|
|
74
|
+
// unchanged. Warn for anything still unrunnable so it fails loudly, not
|
|
75
|
+
// silently.
|
|
76
|
+
const resolvedTools = hydrateBuiltinAgentTools(tools);
|
|
77
|
+
for (const t of resolvedTools) {
|
|
78
|
+
if (!isCallable(t.process)) {
|
|
79
|
+
log.warn(`runAgentLoop received tool '${t.name}' with no process() and could ` +
|
|
80
|
+
"not hydrate it — the model cannot call it. Pass a real Tool or a " +
|
|
81
|
+
"registered builtin tool name.");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// The provider drives the tool-calling loop via generateLoop. This is what
|
|
85
|
+
// makes the Claude Agent SDK provider work: it registers `providerTools` as
|
|
86
|
+
// an in-process MCP server and runs the SDK's own loop, while normal
|
|
87
|
+
// providers run the standard completion loop. Each provider tool carries its
|
|
88
|
+
// own `execute` (generateLoop dispatches to it), so there is no harness-level
|
|
89
|
+
// executeTool callback. The stream surfaces text chunks (for onText),
|
|
90
|
+
// tool-call announcements (for onToolCall), and finalized message events
|
|
91
|
+
// (assistant turns + tool results) that we collect into the returned
|
|
92
|
+
// conversation. There is no terminal tool here — the loop ends when the model
|
|
93
|
+
// stops calling tools.
|
|
94
|
+
const providerTools = resolvedTools.length > 0
|
|
95
|
+
? toProviderTools(resolvedTools).map((pt, i) => {
|
|
96
|
+
const tool = resolvedTools[i];
|
|
97
|
+
return {
|
|
98
|
+
...pt,
|
|
99
|
+
execute: async (args) => {
|
|
100
|
+
if (!isCallable(tool.process)) {
|
|
101
|
+
return JSON.stringify({ error: `Unknown tool: ${tool.name}` });
|
|
102
|
+
}
|
|
103
|
+
const result = await tool.process(context, args);
|
|
104
|
+
return JSON.stringify(serializeToolResult(result));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
})
|
|
108
|
+
: undefined;
|
|
109
|
+
const provider = await context.getProvider(providerId);
|
|
110
|
+
// generateLoop owns its own copy of the message array internally, so rebuild
|
|
111
|
+
// the full returned conversation locally from the message events it streams.
|
|
112
|
+
const outMessages = [...messages];
|
|
113
|
+
let lastAssistantText = "";
|
|
114
|
+
let currentTurnText = "";
|
|
115
|
+
const stream = provider.generateLoop({
|
|
116
|
+
messages,
|
|
117
|
+
model: modelId,
|
|
118
|
+
tools: providerTools,
|
|
119
|
+
maxTokens,
|
|
120
|
+
threadId: options.threadId,
|
|
121
|
+
maxIterations,
|
|
122
|
+
// Run-level cancellation: without it a cancelled workflow leaves this
|
|
123
|
+
// loop (and its tool calls) running.
|
|
124
|
+
signal: context.signal
|
|
125
|
+
});
|
|
126
|
+
// Book this loop's token spend against the calling node, so the run leaves a
|
|
127
|
+
// prediction row. See `meterProviderSpend`.
|
|
128
|
+
const spend = meterProviderSpend(context, provider, modelId);
|
|
129
|
+
try {
|
|
130
|
+
for await (const event of classifyProviderStream(stream)) {
|
|
131
|
+
if (event.kind === "tool_call") {
|
|
132
|
+
options.onToolCall?.(toolCallChunk(event.toolCall));
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (event.kind === "text") {
|
|
136
|
+
// Only genuine text feeds the returned text / onText stream. Tool-call
|
|
137
|
+
// chunks (and audio, agent_status, etc.) carry content_type !== "text"
|
|
138
|
+
// and must not leak into the text output.
|
|
139
|
+
if (event.chunk.content_type === "text" && event.delta) {
|
|
140
|
+
currentTurnText += event.delta;
|
|
141
|
+
options.onText?.(event.delta);
|
|
142
|
+
}
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// thinking / audio events carry no returned text — ignore them here.
|
|
146
|
+
if (event.kind === "assistant_message" || event.kind === "tool_message") {
|
|
147
|
+
// A finalized message event. Append it to the returned trail; an
|
|
148
|
+
// assistant turn also closes the current text run so `text` reflects
|
|
149
|
+
// the model's last assistant message, not a concatenation.
|
|
150
|
+
outMessages.push(event.message);
|
|
151
|
+
if (event.kind === "assistant_message") {
|
|
152
|
+
if (currentTurnText)
|
|
153
|
+
lastAssistantText = currentTurnText;
|
|
154
|
+
currentTurnText = "";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
spend.report();
|
|
161
|
+
}
|
|
162
|
+
// A provider that runs its own loop may stream final text without a trailing
|
|
163
|
+
// assistant message event — keep that text.
|
|
164
|
+
if (currentTurnText)
|
|
165
|
+
lastAssistantText = currentTurnText;
|
|
166
|
+
return { text: lastAssistantText, messages: outMessages };
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=agent-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loop.js","sourceRoot":"","sources":["../../src/nodes/agent-loop.ts"],"names":[],"mappings":"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"}
|