@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.
Files changed (71) hide show
  1. package/README.md +52 -0
  2. package/dist/.nodetool-build-stamp +1 -0
  3. package/dist/index.d.ts +18 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +22 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/nodes/agent-control-tools.d.ts +22 -0
  8. package/dist/nodes/agent-control-tools.d.ts.map +1 -0
  9. package/dist/nodes/agent-control-tools.js +123 -0
  10. package/dist/nodes/agent-control-tools.js.map +1 -0
  11. package/dist/nodes/agent-loop.d.ts +73 -0
  12. package/dist/nodes/agent-loop.d.ts.map +1 -0
  13. package/dist/nodes/agent-loop.js +168 -0
  14. package/dist/nodes/agent-loop.js.map +1 -0
  15. package/dist/nodes/agent-recommended-models.d.ts +152 -0
  16. package/dist/nodes/agent-recommended-models.d.ts.map +1 -0
  17. package/dist/nodes/agent-recommended-models.js +656 -0
  18. package/dist/nodes/agent-recommended-models.js.map +1 -0
  19. package/dist/nodes/agent-thinking.d.ts +29 -0
  20. package/dist/nodes/agent-thinking.d.ts.map +1 -0
  21. package/dist/nodes/agent-thinking.js +139 -0
  22. package/dist/nodes/agent-thinking.js.map +1 -0
  23. package/dist/nodes/agent-threads.d.ts +17 -0
  24. package/dist/nodes/agent-threads.d.ts.map +1 -0
  25. package/dist/nodes/agent-threads.js +93 -0
  26. package/dist/nodes/agent-threads.js.map +1 -0
  27. package/dist/nodes/agent-tool-hydration.d.ts +50 -0
  28. package/dist/nodes/agent-tool-hydration.d.ts.map +1 -0
  29. package/dist/nodes/agent-tool-hydration.js +106 -0
  30. package/dist/nodes/agent-tool-hydration.js.map +1 -0
  31. package/dist/nodes/agent-utils.d.ts +174 -0
  32. package/dist/nodes/agent-utils.d.ts.map +1 -0
  33. package/dist/nodes/agent-utils.js +553 -0
  34. package/dist/nodes/agent-utils.js.map +1 -0
  35. package/dist/nodes/agents.d.ts +402 -0
  36. package/dist/nodes/agents.d.ts.map +1 -0
  37. package/dist/nodes/agents.js +1491 -0
  38. package/dist/nodes/agents.js.map +1 -0
  39. package/dist/nodes/director.d.ts +126 -0
  40. package/dist/nodes/director.d.ts.map +1 -0
  41. package/dist/nodes/director.js +337 -0
  42. package/dist/nodes/director.js.map +1 -0
  43. package/dist/nodes/gemini.d.ts +171 -0
  44. package/dist/nodes/gemini.d.ts.map +1 -0
  45. package/dist/nodes/gemini.js +985 -0
  46. package/dist/nodes/gemini.js.map +1 -0
  47. package/dist/nodes/generators.d.ts +162 -0
  48. package/dist/nodes/generators.d.ts.map +1 -0
  49. package/dist/nodes/generators.js +966 -0
  50. package/dist/nodes/generators.js.map +1 -0
  51. package/dist/nodes/mistral.d.ts +109 -0
  52. package/dist/nodes/mistral.d.ts.map +1 -0
  53. package/dist/nodes/mistral.js +447 -0
  54. package/dist/nodes/mistral.js.map +1 -0
  55. package/dist/nodes/openai.d.ts +292 -0
  56. package/dist/nodes/openai.d.ts.map +1 -0
  57. package/dist/nodes/openai.js +1806 -0
  58. package/dist/nodes/openai.js.map +1 -0
  59. package/dist/nodes/provider-spend.d.ts +45 -0
  60. package/dist/nodes/provider-spend.d.ts.map +1 -0
  61. package/dist/nodes/provider-spend.js +69 -0
  62. package/dist/nodes/provider-spend.js.map +1 -0
  63. package/dist/nodes/shots.d.ts +108 -0
  64. package/dist/nodes/shots.d.ts.map +1 -0
  65. package/dist/nodes/shots.js +378 -0
  66. package/dist/nodes/shots.js.map +1 -0
  67. package/dist/nodes/xai.d.ts +99 -0
  68. package/dist/nodes/xai.d.ts.map +1 -0
  69. package/dist/nodes/xai.js +360 -0
  70. package/dist/nodes/xai.js.map +1 -0
  71. 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
@@ -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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"}