@node-llm/core 1.10.0 → 1.12.0

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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # @node-llm/core
2
2
 
3
3
  <p align="left">
4
- <a href="https://node-llm.eshaiju.com/">
5
- <img src="https://node-llm.eshaiju.com/assets/images/logo.jpg" alt="NodeLLM logo" width="300" />
4
+ <a href="https://nodellm.dev/">
5
+ <img src="https://nodellm.dev/assets/images/logo.jpg" alt="NodeLLM logo" width="300" />
6
6
  </a>
7
7
  </p>
8
8
 
@@ -139,6 +139,54 @@ const safetyMiddleware = {
139
139
 
140
140
  ---
141
141
 
142
+ ## 🤖 Agent Class
143
+
144
+ Define reusable, class-configured agents with a declarative DSL:
145
+
146
+ ```ts
147
+ import { Agent, Tool, z } from "@node-llm/core";
148
+
149
+ class LookupOrderTool extends Tool<{ orderId: string }> {
150
+ name = "lookup_order";
151
+ description = "Look up an order by ID";
152
+ schema = z.object({ orderId: z.string() });
153
+
154
+ async execute({ orderId }: { orderId: string }) {
155
+ return { status: "shipped", eta: "Tomorrow" };
156
+ }
157
+ }
158
+
159
+ class SupportAgent extends Agent {
160
+ static model = "gpt-4.1";
161
+ static instructions = "You are a helpful support agent.";
162
+ static tools = [LookupOrderTool];
163
+ static temperature = 0.2;
164
+ }
165
+
166
+ // Use anywhere in your app
167
+ const agent = new SupportAgent();
168
+ const response = await agent.ask("Where is order #123?");
169
+ console.log(response.content);
170
+ ```
171
+
172
+ ### ToolHalt - Early Loop Termination
173
+
174
+ Stop the agentic loop early when a definitive answer is found:
175
+
176
+ ```ts
177
+ class FinalAnswerTool extends Tool<{ answer: string }> {
178
+ name = "final_answer";
179
+ description = "Return the final answer to the user";
180
+ schema = z.object({ answer: z.string() });
181
+
182
+ async execute({ answer }: { answer: string }) {
183
+ return this.halt(answer); // Stops the loop, returns this result
184
+ }
185
+ }
186
+ ```
187
+
188
+ ---
189
+
142
190
  ## 💾 Ecosystem
143
191
 
144
192
  Looking for persistence? use **[@node-llm/orm](https://www.npmjs.com/package/@node-llm/orm)**.
@@ -150,11 +198,11 @@ Looking for persistence? use **[@node-llm/orm](https://www.npmjs.com/package/@no
150
198
 
151
199
  ## 📚 Full Documentation
152
200
 
153
- Visit **[node-llm.eshaiju.com](https://node-llm.eshaiju.com/)** for:
201
+ Visit **[nodellm.dev](https://nodellm.dev/)** for:
154
202
 
155
- - [Deep Dive into Tool Calling](https://node-llm.eshaiju.com/core-features/tools)
156
- - [Multi-modal Vision & Audio Guide](https://node-llm.eshaiju.com/core-features/multimodal)
157
- - [Custom Provider Plugin System](https://node-llm.eshaiju.com/advanced/custom-providers)
203
+ - [Deep Dive into Tool Calling](https://nodellm.dev/core-features/tools)
204
+ - [Multi-modal Vision & Audio Guide](https://nodellm.dev/core-features/multimodal)
205
+ - [Custom Provider Plugin System](https://nodellm.dev/advanced/custom-providers)
158
206
 
159
207
  ---
160
208
 
@@ -0,0 +1,178 @@
1
+ import { z } from "zod";
2
+ import { Chat, AskOptions } from "../chat/Chat.js";
3
+ import { ChatOptions } from "../chat/ChatOptions.js";
4
+ import { ChatResponseString } from "../chat/ChatResponse.js";
5
+ import { ToolResolvable } from "../chat/Tool.js";
6
+ import { ThinkingConfig, ThinkingResult } from "../providers/Provider.js";
7
+ import { Schema } from "../schema/Schema.js";
8
+ import { NodeLLMCore } from "../llm.js";
9
+ /**
10
+ * A value that can be a static T or a function that returns T based on inputs.
11
+ */
12
+ export type LazyValue<T, I = any> = T | ((inputs: I) => T);
13
+ /**
14
+ * Configuration options for Agent.
15
+ */
16
+ export interface AgentConfig<I = any> {
17
+ /** The model ID to use (e.g., "gpt-4o") */
18
+ model?: string;
19
+ /** The provider to use (e.g., "openai") */
20
+ provider?: string;
21
+ /** System instructions for the agent (can be lazy) */
22
+ instructions?: LazyValue<string, I>;
23
+ /** Tools available to the agent (can be lazy) */
24
+ tools?: LazyValue<ToolResolvable[], I>;
25
+ /** Temperature for response generation (0.0 - 1.0) */
26
+ temperature?: number;
27
+ /** Extended thinking configuration */
28
+ thinking?: ThinkingConfig;
29
+ /** Output schema for structured responses */
30
+ schema?: z.ZodType | Schema | Record<string, unknown>;
31
+ /** Provider-specific parameters */
32
+ params?: Record<string, unknown>;
33
+ /** Custom headers for requests */
34
+ headers?: Record<string, string>;
35
+ /** Maximum tokens in response */
36
+ maxTokens?: number;
37
+ /** Maximum tool call iterations */
38
+ maxToolCalls?: number;
39
+ /** Assume model exists without validation */
40
+ assumeModelExists?: boolean;
41
+ /** Optional LLM instance to use instead of global NodeLLM */
42
+ llm?: NodeLLMCore;
43
+ /** Optional initial inputs to resolve lazy config immediately */
44
+ inputs?: I;
45
+ }
46
+ /**
47
+ * Base class for creating reusable, class-configured agents.
48
+ */
49
+ export declare abstract class Agent<I extends Record<string, any> = Record<string, any>, S extends Record<string, unknown> = Record<string, unknown>> {
50
+ static model?: string;
51
+ static provider?: string;
52
+ static instructions?: LazyValue<string, any>;
53
+ static tools?: LazyValue<ToolResolvable[], any>;
54
+ static temperature?: number;
55
+ static thinking?: ThinkingConfig;
56
+ static schema?: z.ZodType | Schema | Record<string, unknown>;
57
+ static params?: Record<string, unknown>;
58
+ static headers?: Record<string, string>;
59
+ static maxTokens?: number;
60
+ static maxToolCalls?: number;
61
+ static assumeModelExists?: boolean;
62
+ /**
63
+ * Explicitly declare which inputs this agent expects.
64
+ * Useful for introspection and validation.
65
+ */
66
+ static inputs?: string[];
67
+ /**
68
+ * Hook called when the agent starts a new session (ask/stream).
69
+ */
70
+ static onStart(_context: {
71
+ messages: unknown[];
72
+ }): void | Promise<void>;
73
+ static onThinking(_thinking: ThinkingResult, _result: ChatResponseString): void | Promise<void>;
74
+ static onToolStart(_toolCall: unknown): void | Promise<void>;
75
+ static onToolEnd(_toolCall: unknown, _result: unknown): void | Promise<void>;
76
+ static onToolError(_toolCall: unknown, _error: Error): void | Promise<void>;
77
+ static onComplete(_result: ChatResponseString): void | Promise<void>;
78
+ /**
79
+ * Run the agent immediately with a prompt.
80
+ */
81
+ static ask<I extends Record<string, any>, S extends Record<string, any>>(this: new (overrides?: Partial<AgentConfig<I> & ChatOptions>) => Agent<I, S>, message: string, options?: AskOptions & {
82
+ inputs?: I;
83
+ }): Promise<ChatResponseString>;
84
+ /**
85
+ * Stream the agent response immediately.
86
+ */
87
+ static stream<I extends Record<string, any>, S extends Record<string, any>>(this: new (overrides?: Partial<AgentConfig<I> & ChatOptions>) => Agent<I, S>, message: string, options?: AskOptions & {
88
+ inputs?: I;
89
+ }): import("../index.js").Stream<import("../providers/Provider.js").ChatChunk>;
90
+ /** The underlying Chat instance */
91
+ protected readonly chat: Chat<S>;
92
+ /** Private reference to configuration overrides for lazy resolution */
93
+ private readonly config;
94
+ /**
95
+ * Create a new agent instance.
96
+ * @param overrides - Optional configuration to override static properties
97
+ */
98
+ constructor(overrides?: Partial<AgentConfig<I> & ChatOptions>);
99
+ /**
100
+ * Helper to resolve lazy instructions and tools based on inputs.
101
+ */
102
+ private resolveLazyConfig;
103
+ /**
104
+ * Add instructions to the agent (replaces or appends).
105
+ */
106
+ withInstructions(instructions: string, options?: {
107
+ replace?: boolean;
108
+ }): this;
109
+ /**
110
+ * Add tools to the agent.
111
+ */
112
+ withTools(tools: ToolResolvable[], options?: {
113
+ replace?: boolean;
114
+ }): this;
115
+ /**
116
+ * Alias for withTools([tool]).
117
+ */
118
+ use(tool: ToolResolvable): this;
119
+ /**
120
+ * Send a message to the agent and get a response.
121
+ */
122
+ ask(message: string, options?: AskOptions & {
123
+ inputs?: I;
124
+ }): Promise<ChatResponseString>;
125
+ /**
126
+ * Hook called when a tool call starts.
127
+ */
128
+ onToolCallStart(handler: (toolCall: any) => void | Promise<void>): this;
129
+ /**
130
+ * Hook called when a tool call ends.
131
+ */
132
+ onToolCallEnd(handler: (toolCall: any, result: any) => void | Promise<void>): this;
133
+ /**
134
+ * Hook called when a tool call errors.
135
+ */
136
+ onToolCallError(handler: (toolCall: any, error: Error) => any): this;
137
+ /**
138
+ * Hook called before a request.
139
+ */
140
+ beforeRequest(handler: (messages: any[]) => any): this;
141
+ /**
142
+ * Hook called after a response.
143
+ */
144
+ afterResponse(handler: (response: ChatResponseString) => any): this;
145
+ /**
146
+ * Alias for ask()
147
+ */
148
+ say(message: string, options?: AskOptions & {
149
+ inputs?: I;
150
+ }): Promise<ChatResponseString>;
151
+ /**
152
+ * Stream a response from the agent.
153
+ */
154
+ stream(message: string, options?: AskOptions & {
155
+ inputs?: I;
156
+ }): import("../index.js").Stream<import("../providers/Provider.js").ChatChunk>;
157
+ /**
158
+ * Get the conversation history.
159
+ */
160
+ get history(): readonly import("../index.js").Message[];
161
+ /**
162
+ * Get the model ID being used.
163
+ */
164
+ get modelId(): string;
165
+ /**
166
+ * Get aggregate token usage across the conversation.
167
+ */
168
+ get totalUsage(): import("../providers/Provider.js").Usage;
169
+ /**
170
+ * Access the underlying Chat instance for advanced operations.
171
+ */
172
+ get underlyingChat(): Chat<S>;
173
+ }
174
+ /**
175
+ * Helper function to define an agent inline without creating a class.
176
+ */
177
+ export declare function defineAgent<I extends Record<string, any> = Record<string, any>, S extends Record<string, unknown> = Record<string, unknown>>(config: AgentConfig<I>): new (overrides?: Partial<AgentConfig<I> & ChatOptions>) => Agent<I, S>;
178
+ //# sourceMappingURL=Agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Agent.d.ts","sourceRoot":"","sources":["../../src/agent/Agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,293 @@
1
+ import { NodeLLM } from "../llm.js";
2
+ /**
3
+ * Base class for creating reusable, class-configured agents.
4
+ */
5
+ export class Agent {
6
+ // Static configuration properties - override these in subclasses
7
+ static model;
8
+ static provider;
9
+ static instructions;
10
+ static tools;
11
+ static temperature;
12
+ static thinking;
13
+ static schema;
14
+ static params;
15
+ static headers;
16
+ static maxTokens;
17
+ static maxToolCalls;
18
+ static assumeModelExists;
19
+ /**
20
+ * Explicitly declare which inputs this agent expects.
21
+ * Useful for introspection and validation.
22
+ */
23
+ static inputs;
24
+ /**
25
+ * Hook called when the agent starts a new session (ask/stream).
26
+ */
27
+ static onStart(_context) {
28
+ // Override in subclass
29
+ }
30
+ static onThinking(_thinking, _result) {
31
+ // Override in subclass
32
+ }
33
+ static onToolStart(_toolCall) {
34
+ // Override in subclass
35
+ }
36
+ static onToolEnd(_toolCall, _result) {
37
+ // Override in subclass
38
+ }
39
+ static onToolError(_toolCall, _error) {
40
+ // Override in subclass
41
+ }
42
+ static onComplete(_result) {
43
+ // Override in subclass
44
+ }
45
+ // --- Static Execution API ---
46
+ /**
47
+ * Run the agent immediately with a prompt.
48
+ */
49
+ static async ask(message, options) {
50
+ const agent = new this({ ...options });
51
+ return agent.ask(message, options);
52
+ }
53
+ /**
54
+ * Stream the agent response immediately.
55
+ */
56
+ static stream(message, options) {
57
+ const agent = new this({ ...options });
58
+ return agent.stream(message, options);
59
+ }
60
+ /** The underlying Chat instance */
61
+ chat;
62
+ /** Private reference to configuration overrides for lazy resolution */
63
+ config;
64
+ /**
65
+ * Create a new agent instance.
66
+ * @param overrides - Optional configuration to override static properties
67
+ */
68
+ constructor(overrides = {}) {
69
+ this.config = overrides;
70
+ const ctor = this.constructor;
71
+ // Build chat options from static properties + overrides
72
+ const chatOptions = {
73
+ provider: overrides.provider ?? ctor.provider,
74
+ assumeModelExists: overrides.assumeModelExists ?? ctor.assumeModelExists,
75
+ temperature: overrides.temperature ?? ctor.temperature,
76
+ maxTokens: overrides.maxTokens ?? ctor.maxTokens,
77
+ maxToolCalls: overrides.maxToolCalls ?? ctor.maxToolCalls,
78
+ headers: { ...ctor.headers, ...overrides.headers },
79
+ params: { ...ctor.params, ...overrides.params },
80
+ thinking: overrides.thinking ?? ctor.thinking,
81
+ messages: overrides.messages
82
+ };
83
+ // Determine model
84
+ const model = overrides.model ?? ctor.model;
85
+ if (!model) {
86
+ throw new Error(`[Agent] No model specified. Set static model property or pass model in constructor.`);
87
+ }
88
+ const llm = overrides.llm ?? NodeLLM;
89
+ this.chat = llm.chat(model, chatOptions);
90
+ // Initial resolution if inputs are provided in constructor
91
+ if (overrides.inputs) {
92
+ this.resolveLazyConfig(overrides.inputs);
93
+ }
94
+ else {
95
+ // Fallback: apply static/direct instructions immediately if they aren't functions
96
+ const instructions = overrides.instructions ?? ctor.instructions;
97
+ if (instructions && typeof instructions !== "function") {
98
+ this.chat.withInstructions(instructions);
99
+ }
100
+ const tools = overrides.tools ?? ctor.tools;
101
+ if (tools && typeof tools !== "function" && tools.length > 0) {
102
+ this.chat.withTools(tools);
103
+ }
104
+ }
105
+ // Apply schema
106
+ const schema = overrides.schema ?? ctor.schema;
107
+ if (schema) {
108
+ this.chat.withSchema(schema);
109
+ }
110
+ // Wire up telemetry hooks
111
+ if (ctor.onStart) {
112
+ this.chat.beforeRequest(async (messages) => {
113
+ if (ctor.onStart)
114
+ await ctor.onStart({ messages });
115
+ });
116
+ }
117
+ if (ctor.onToolStart) {
118
+ this.chat.onToolCallStart(async (toolCall) => {
119
+ if (ctor.onToolStart)
120
+ await ctor.onToolStart(toolCall);
121
+ });
122
+ }
123
+ if (ctor.onToolEnd) {
124
+ this.chat.onToolCallEnd(async (toolCall, result) => {
125
+ if (ctor.onToolEnd)
126
+ await ctor.onToolEnd(toolCall, result);
127
+ });
128
+ }
129
+ if (ctor.onToolError) {
130
+ this.chat.onToolCallError(async (toolCall, error) => {
131
+ if (ctor.onToolError)
132
+ await ctor.onToolError(toolCall, error);
133
+ });
134
+ }
135
+ if (ctor.onComplete || ctor.onThinking) {
136
+ this.chat.onEndMessage(async (msg) => {
137
+ if (msg.thinking && ctor.onThinking) {
138
+ await ctor.onThinking(msg.thinking, msg);
139
+ }
140
+ if (ctor.onComplete) {
141
+ await ctor.onComplete(msg);
142
+ }
143
+ });
144
+ }
145
+ }
146
+ /**
147
+ * Helper to resolve lazy instructions and tools based on inputs.
148
+ */
149
+ resolveLazyConfig(inputs) {
150
+ if (!inputs)
151
+ return;
152
+ const ctor = this.constructor;
153
+ // 1. Resolve Instructions
154
+ let instructions = this.config.instructions ?? ctor.instructions;
155
+ if (typeof instructions === "function") {
156
+ instructions = instructions(inputs);
157
+ }
158
+ if (typeof instructions === "string") {
159
+ this.chat.withInstructions(instructions, { replace: true });
160
+ }
161
+ // 2. Resolve Tools
162
+ let tools = this.config.tools ?? ctor.tools;
163
+ if (typeof tools === "function") {
164
+ tools = tools(inputs);
165
+ }
166
+ if (Array.isArray(tools)) {
167
+ this.chat.withTools(tools, { replace: true });
168
+ }
169
+ }
170
+ // --- Fluent Configuration ---
171
+ /**
172
+ * Add instructions to the agent (replaces or appends).
173
+ */
174
+ withInstructions(instructions, options) {
175
+ this.chat.withInstructions(instructions, options);
176
+ return this;
177
+ }
178
+ /**
179
+ * Add tools to the agent.
180
+ */
181
+ withTools(tools, options) {
182
+ this.chat.withTools(tools, options);
183
+ return this;
184
+ }
185
+ /**
186
+ * Alias for withTools([tool]).
187
+ */
188
+ use(tool) {
189
+ return this.withTools([tool]);
190
+ }
191
+ /**
192
+ * Send a message to the agent and get a response.
193
+ */
194
+ async ask(message, options) {
195
+ if (options?.inputs) {
196
+ this.resolveLazyConfig(options.inputs);
197
+ }
198
+ return this.chat.ask(message, options);
199
+ }
200
+ /**
201
+ * Hook called when a tool call starts.
202
+ */
203
+ onToolCallStart(handler) {
204
+ this.chat.onToolCallStart(handler);
205
+ return this;
206
+ }
207
+ /**
208
+ * Hook called when a tool call ends.
209
+ */
210
+ onToolCallEnd(handler) {
211
+ this.chat.onToolCallEnd(handler);
212
+ return this;
213
+ }
214
+ /**
215
+ * Hook called when a tool call errors.
216
+ */
217
+ onToolCallError(handler) {
218
+ this.chat.onToolCallError(handler);
219
+ return this;
220
+ }
221
+ /**
222
+ * Hook called before a request.
223
+ */
224
+ beforeRequest(handler) {
225
+ this.chat.beforeRequest(handler);
226
+ return this;
227
+ }
228
+ /**
229
+ * Hook called after a response.
230
+ */
231
+ afterResponse(handler) {
232
+ this.chat.afterResponse(handler);
233
+ return this;
234
+ }
235
+ /**
236
+ * Alias for ask()
237
+ */
238
+ async say(message, options) {
239
+ return this.ask(message, options);
240
+ }
241
+ /**
242
+ * Stream a response from the agent.
243
+ */
244
+ stream(message, options) {
245
+ if (options?.inputs) {
246
+ this.resolveLazyConfig(options.inputs);
247
+ }
248
+ return this.chat.stream(message, options);
249
+ }
250
+ /**
251
+ * Get the conversation history.
252
+ */
253
+ get history() {
254
+ return this.chat.history;
255
+ }
256
+ /**
257
+ * Get the model ID being used.
258
+ */
259
+ get modelId() {
260
+ return this.chat.modelId;
261
+ }
262
+ /**
263
+ * Get aggregate token usage across the conversation.
264
+ */
265
+ get totalUsage() {
266
+ return this.chat.totalUsage;
267
+ }
268
+ /**
269
+ * Access the underlying Chat instance for advanced operations.
270
+ */
271
+ get underlyingChat() {
272
+ return this.chat;
273
+ }
274
+ }
275
+ /**
276
+ * Helper function to define an agent inline without creating a class.
277
+ */
278
+ export function defineAgent(config) {
279
+ return class extends Agent {
280
+ static model = config.model;
281
+ static provider = config.provider;
282
+ static instructions = config.instructions;
283
+ static tools = config.tools;
284
+ static temperature = config.temperature;
285
+ static thinking = config.thinking;
286
+ static schema = config.schema;
287
+ static params = config.params;
288
+ static headers = config.headers;
289
+ static maxTokens = config.maxTokens;
290
+ static maxToolCalls = config.maxToolCalls;
291
+ static assumeModelExists = config.assumeModelExists;
292
+ };
293
+ }