@node-llm/core 1.9.0 → 1.11.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 +89 -6
- package/dist/agent/Agent.d.ts +191 -0
- package/dist/agent/Agent.d.ts.map +1 -0
- package/dist/agent/Agent.js +272 -0
- package/dist/aliases.d.ts +102 -9
- package/dist/aliases.d.ts.map +1 -1
- package/dist/aliases.js +102 -9
- package/dist/chat/Chat.d.ts +1 -0
- package/dist/chat/Chat.d.ts.map +1 -1
- package/dist/chat/Chat.js +184 -131
- package/dist/chat/ChatOptions.d.ts +2 -0
- package/dist/chat/ChatOptions.d.ts.map +1 -1
- package/dist/chat/ChatStream.d.ts.map +1 -1
- package/dist/chat/ChatStream.js +109 -66
- package/dist/chat/Tool.d.ts +43 -2
- package/dist/chat/Tool.d.ts.map +1 -1
- package/dist/chat/Tool.js +50 -0
- package/dist/chat/ToolHandler.d.ts +10 -5
- package/dist/chat/ToolHandler.d.ts.map +1 -1
- package/dist/chat/ToolHandler.js +10 -2
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/llm.d.ts +8 -1
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +156 -59
- package/dist/middlewares/CostGuardMiddleware.d.ts +24 -0
- package/dist/middlewares/CostGuardMiddleware.d.ts.map +1 -0
- package/dist/middlewares/CostGuardMiddleware.js +23 -0
- package/dist/middlewares/PIIMaskMiddleware.d.ts +23 -0
- package/dist/middlewares/PIIMaskMiddleware.d.ts.map +1 -0
- package/dist/middlewares/PIIMaskMiddleware.js +41 -0
- package/dist/middlewares/UsageLoggerMiddleware.d.ts +22 -0
- package/dist/middlewares/UsageLoggerMiddleware.d.ts.map +1 -0
- package/dist/middlewares/UsageLoggerMiddleware.js +30 -0
- package/dist/middlewares/index.d.ts +4 -0
- package/dist/middlewares/index.d.ts.map +1 -0
- package/dist/middlewares/index.js +3 -0
- package/dist/models/models.json +1458 -448
- package/dist/providers/BaseProvider.d.ts +6 -1
- package/dist/providers/BaseProvider.d.ts.map +1 -1
- package/dist/providers/BaseProvider.js +19 -0
- package/dist/providers/openai/OpenAIProvider.d.ts +1 -1
- package/dist/providers/openai/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/openai/OpenAIProvider.js +13 -2
- package/dist/types/Middleware.d.ts +106 -0
- package/dist/types/Middleware.d.ts.map +1 -0
- package/dist/types/Middleware.js +1 -0
- package/dist/utils/middleware-runner.d.ts +7 -0
- package/dist/utils/middleware-runner.d.ts.map +1 -0
- package/dist/utils/middleware-runner.js +23 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @node-llm/core
|
|
2
2
|
|
|
3
3
|
<p align="left">
|
|
4
|
-
<a href="https://
|
|
5
|
-
<img src="https://
|
|
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
|
|
|
@@ -104,6 +104,89 @@ const llm = createLLM({
|
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
|
107
|
+
## 🔌 Middleware System
|
|
108
|
+
|
|
109
|
+
NodeLLM 1.9.0 introduces a powerful lifecycle hook system for audit, security, and observability.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { createLLM, PIIMaskMiddleware, UsageLoggerMiddleware } from "@node-llm/core";
|
|
113
|
+
|
|
114
|
+
const llm = createLLM({
|
|
115
|
+
provider: "openai",
|
|
116
|
+
middlewares: [
|
|
117
|
+
new PIIMaskMiddleware(), // Redact emails/phone numbers automatically
|
|
118
|
+
new UsageLoggerMiddleware() // Log structured token usage & costs
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// All chats created from this instance inherit these middlewares
|
|
123
|
+
const chat = llm.chat("gpt-4o");
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Decisive Tool Safety
|
|
127
|
+
|
|
128
|
+
Middlewares can control the engine's recovery strategy during tool failures.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
const safetyMiddleware = {
|
|
132
|
+
name: "Audit",
|
|
133
|
+
onToolCallError: async (ctx, tool, error) => {
|
|
134
|
+
if (tool.function.name === "delete_user") return "STOP"; // Kill the loop
|
|
135
|
+
return "RETRY"; // Attempt recovery
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
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
|
+
|
|
107
190
|
## 💾 Ecosystem
|
|
108
191
|
|
|
109
192
|
Looking for persistence? use **[@node-llm/orm](https://www.npmjs.com/package/@node-llm/orm)**.
|
|
@@ -115,11 +198,11 @@ Looking for persistence? use **[@node-llm/orm](https://www.npmjs.com/package/@no
|
|
|
115
198
|
|
|
116
199
|
## 📚 Full Documentation
|
|
117
200
|
|
|
118
|
-
Visit **[
|
|
201
|
+
Visit **[nodellm.dev](https://nodellm.dev/)** for:
|
|
119
202
|
|
|
120
|
-
- [Deep Dive into Tool Calling](https://
|
|
121
|
-
- [Multi-modal Vision & Audio Guide](https://
|
|
122
|
-
- [Custom Provider Plugin System](https://
|
|
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)
|
|
123
206
|
|
|
124
207
|
---
|
|
125
208
|
|
|
@@ -0,0 +1,191 @@
|
|
|
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
|
+
* Configuration options that can be defined as static properties on Agent subclasses.
|
|
11
|
+
*/
|
|
12
|
+
export interface AgentConfig {
|
|
13
|
+
/** The model ID to use (e.g., "gpt-4o", "claude-sonnet-4-20250514") */
|
|
14
|
+
model?: string;
|
|
15
|
+
/** The provider to use (e.g., "openai", "anthropic") */
|
|
16
|
+
provider?: string;
|
|
17
|
+
/** System instructions for the agent */
|
|
18
|
+
instructions?: string;
|
|
19
|
+
/** Tools available to the agent */
|
|
20
|
+
tools?: ToolResolvable[];
|
|
21
|
+
/** Temperature for response generation (0.0 - 1.0) */
|
|
22
|
+
temperature?: number;
|
|
23
|
+
/** Extended thinking configuration */
|
|
24
|
+
thinking?: ThinkingConfig;
|
|
25
|
+
/** Output schema for structured responses */
|
|
26
|
+
schema?: z.ZodType | Schema | Record<string, unknown>;
|
|
27
|
+
/** Provider-specific parameters */
|
|
28
|
+
params?: Record<string, unknown>;
|
|
29
|
+
/** Custom headers for requests */
|
|
30
|
+
headers?: Record<string, string>;
|
|
31
|
+
/** Maximum tokens in response */
|
|
32
|
+
maxTokens?: number;
|
|
33
|
+
/** Maximum tool call iterations */
|
|
34
|
+
maxToolCalls?: number;
|
|
35
|
+
/** Assume model exists without validation */
|
|
36
|
+
assumeModelExists?: boolean;
|
|
37
|
+
/** Optional LLM instance to use instead of global NodeLLM */
|
|
38
|
+
llm?: NodeLLMCore;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Base class for creating reusable, class-configured agents.
|
|
42
|
+
*
|
|
43
|
+
* Define your agent configuration using static properties, then instantiate
|
|
44
|
+
* and use it anywhere in your application.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* class SupportAgent extends Agent {
|
|
49
|
+
* static model = "gpt-4o";
|
|
50
|
+
* static instructions = "You are a helpful support agent";
|
|
51
|
+
* static tools = [SearchDocs, LookupAccount];
|
|
52
|
+
* static temperature = 0.2;
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* const agent = new SupportAgent();
|
|
56
|
+
* const response = await agent.ask("How can I reset my password?");
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example Override configuration per instance:
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const agent = new SupportAgent({ model: "gpt-4o-mini" });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare abstract class Agent<S extends Record<string, unknown> = Record<string, unknown>> {
|
|
65
|
+
static model?: string;
|
|
66
|
+
static provider?: string;
|
|
67
|
+
static instructions?: string;
|
|
68
|
+
static tools?: ToolResolvable[];
|
|
69
|
+
static temperature?: number;
|
|
70
|
+
static thinking?: ThinkingConfig;
|
|
71
|
+
static schema?: z.ZodType | Schema | Record<string, unknown>;
|
|
72
|
+
static params?: Record<string, unknown>;
|
|
73
|
+
static headers?: Record<string, string>;
|
|
74
|
+
static maxTokens?: number;
|
|
75
|
+
static maxToolCalls?: number;
|
|
76
|
+
static assumeModelExists?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Hook called when the agent starts a new session (ask/stream).
|
|
79
|
+
* @param context - Initial context including messages/options
|
|
80
|
+
*/
|
|
81
|
+
static onStart(_context: {
|
|
82
|
+
messages: unknown[];
|
|
83
|
+
}): void | Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Hook called when the agent generates a reasoning trace (thinking).
|
|
86
|
+
* @param thinking - The content of the thinking trace
|
|
87
|
+
* @param result - The full response object containing the thinking
|
|
88
|
+
*/
|
|
89
|
+
static onThinking(_thinking: ThinkingResult, _result: ChatResponseString): void | Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Hook called when a tool execution starts.
|
|
92
|
+
* @param toolCall - The tool call object (id, function name, arguments)
|
|
93
|
+
*/
|
|
94
|
+
static onToolStart(_toolCall: unknown): void | Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Hook called when a tool execution ends.
|
|
97
|
+
* @param toolCall - The tool call object
|
|
98
|
+
* @param result - The result of the tool execution
|
|
99
|
+
*/
|
|
100
|
+
static onToolEnd(_toolCall: unknown, _result: unknown): void | Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Hook called when a tool execution encounters an error.
|
|
103
|
+
* @param toolCall - The tool call object
|
|
104
|
+
* @param error - The error that occurred
|
|
105
|
+
*/
|
|
106
|
+
static onToolError(_toolCall: unknown, _error: Error): void | Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Hook called when the agent completes a response turn.
|
|
109
|
+
* @param result - The final response object
|
|
110
|
+
*/
|
|
111
|
+
static onComplete(_result: ChatResponseString): void | Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Run the agent immediately with a prompt.
|
|
114
|
+
* Creates a new instance of the agent, runs the prompt, and disposes it.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const result = await TravelAgent.ask("Find flights to Paris");
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
static ask(message: string, options?: AskOptions): Promise<ChatResponseString>;
|
|
122
|
+
/**
|
|
123
|
+
* Stream the agent response immediately.
|
|
124
|
+
* Creates a new instance of the agent and streams the response.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* for await (const chunk of TravelAgent.stream("Write a poem")) {
|
|
129
|
+
* process.stdout.write(chunk.content);
|
|
130
|
+
* }
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
static stream(message: string, options?: AskOptions): import("../index.js").Stream<import("../providers/Provider.js").ChatChunk>;
|
|
134
|
+
/** The underlying Chat instance */
|
|
135
|
+
protected readonly chat: Chat<S>;
|
|
136
|
+
/**
|
|
137
|
+
* Create a new agent instance.
|
|
138
|
+
* @param overrides - Optional configuration to override static properties
|
|
139
|
+
*/
|
|
140
|
+
constructor(overrides?: Partial<AgentConfig & ChatOptions>);
|
|
141
|
+
/**
|
|
142
|
+
* Send a message to the agent and get a response.
|
|
143
|
+
* @param message - The user message
|
|
144
|
+
* @param options - Optional request options
|
|
145
|
+
*/
|
|
146
|
+
ask(message: string, options?: AskOptions): Promise<ChatResponseString>;
|
|
147
|
+
/**
|
|
148
|
+
* Alias for ask()
|
|
149
|
+
*/
|
|
150
|
+
say(message: string, options?: AskOptions): Promise<ChatResponseString>;
|
|
151
|
+
/**
|
|
152
|
+
* Stream a response from the agent.
|
|
153
|
+
* @param message - The user message
|
|
154
|
+
* @param options - Optional request options
|
|
155
|
+
*/
|
|
156
|
+
stream(message: string, options?: AskOptions): 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
|
+
* @example
|
|
178
|
+
* ```typescript
|
|
179
|
+
* const SupportAgent = defineAgent({
|
|
180
|
+
* model: "gpt-4o",
|
|
181
|
+
* instructions: "You are a helpful support agent",
|
|
182
|
+
* tools: [SearchDocs, LookupAccount],
|
|
183
|
+
* temperature: 0.2
|
|
184
|
+
* });
|
|
185
|
+
*
|
|
186
|
+
* const agent = new SupportAgent();
|
|
187
|
+
* const response = await agent.ask("Help me!");
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export declare function defineAgent<S extends Record<string, unknown> = Record<string, unknown>>(config: AgentConfig): new (overrides?: Partial<AgentConfig & ChatOptions>) => Agent<S>;
|
|
191
|
+
//# 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,272 @@
|
|
|
1
|
+
import { NodeLLM } from "../llm.js";
|
|
2
|
+
/**
|
|
3
|
+
* Base class for creating reusable, class-configured agents.
|
|
4
|
+
*
|
|
5
|
+
* Define your agent configuration using static properties, then instantiate
|
|
6
|
+
* and use it anywhere in your application.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* class SupportAgent extends Agent {
|
|
11
|
+
* static model = "gpt-4o";
|
|
12
|
+
* static instructions = "You are a helpful support agent";
|
|
13
|
+
* static tools = [SearchDocs, LookupAccount];
|
|
14
|
+
* static temperature = 0.2;
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* const agent = new SupportAgent();
|
|
18
|
+
* const response = await agent.ask("How can I reset my password?");
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @example Override configuration per instance:
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const agent = new SupportAgent({ model: "gpt-4o-mini" });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class Agent {
|
|
27
|
+
// Static configuration properties - override these in subclasses
|
|
28
|
+
static model;
|
|
29
|
+
static provider;
|
|
30
|
+
static instructions;
|
|
31
|
+
static tools;
|
|
32
|
+
static temperature;
|
|
33
|
+
static thinking;
|
|
34
|
+
static schema;
|
|
35
|
+
static params;
|
|
36
|
+
static headers;
|
|
37
|
+
static maxTokens;
|
|
38
|
+
static maxToolCalls;
|
|
39
|
+
static assumeModelExists;
|
|
40
|
+
/**
|
|
41
|
+
* Hook called when the agent starts a new session (ask/stream).
|
|
42
|
+
* @param context - Initial context including messages/options
|
|
43
|
+
*/
|
|
44
|
+
static onStart(_context) {
|
|
45
|
+
// Override in subclass
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Hook called when the agent generates a reasoning trace (thinking).
|
|
49
|
+
* @param thinking - The content of the thinking trace
|
|
50
|
+
* @param result - The full response object containing the thinking
|
|
51
|
+
*/
|
|
52
|
+
static onThinking(_thinking, _result) {
|
|
53
|
+
// Override in subclass
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Hook called when a tool execution starts.
|
|
57
|
+
* @param toolCall - The tool call object (id, function name, arguments)
|
|
58
|
+
*/
|
|
59
|
+
static onToolStart(_toolCall) {
|
|
60
|
+
// Override in subclass
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Hook called when a tool execution ends.
|
|
64
|
+
* @param toolCall - The tool call object
|
|
65
|
+
* @param result - The result of the tool execution
|
|
66
|
+
*/
|
|
67
|
+
static onToolEnd(_toolCall, _result) {
|
|
68
|
+
// Override in subclass
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Hook called when a tool execution encounters an error.
|
|
72
|
+
* @param toolCall - The tool call object
|
|
73
|
+
* @param error - The error that occurred
|
|
74
|
+
*/
|
|
75
|
+
static onToolError(_toolCall, _error) {
|
|
76
|
+
// Override in subclass
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Hook called when the agent completes a response turn.
|
|
80
|
+
* @param result - The final response object
|
|
81
|
+
*/
|
|
82
|
+
static onComplete(_result) {
|
|
83
|
+
// Override in subclass
|
|
84
|
+
}
|
|
85
|
+
// --- Static Execution API ---
|
|
86
|
+
/**
|
|
87
|
+
* Run the agent immediately with a prompt.
|
|
88
|
+
* Creates a new instance of the agent, runs the prompt, and disposes it.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const result = await TravelAgent.ask("Find flights to Paris");
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
static async ask(message, options) {
|
|
96
|
+
const Ctor = this;
|
|
97
|
+
const agent = new Ctor({});
|
|
98
|
+
return agent.ask(message, options);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Stream the agent response immediately.
|
|
102
|
+
* Creates a new instance of the agent and streams the response.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* for await (const chunk of TravelAgent.stream("Write a poem")) {
|
|
107
|
+
* process.stdout.write(chunk.content);
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
static stream(message, options) {
|
|
112
|
+
const Ctor = this;
|
|
113
|
+
const agent = new Ctor({});
|
|
114
|
+
return agent.stream(message, options);
|
|
115
|
+
}
|
|
116
|
+
/** The underlying Chat instance */
|
|
117
|
+
chat;
|
|
118
|
+
/**
|
|
119
|
+
* Create a new agent instance.
|
|
120
|
+
* @param overrides - Optional configuration to override static properties
|
|
121
|
+
*/
|
|
122
|
+
constructor(overrides = {}) {
|
|
123
|
+
const ctor = this.constructor;
|
|
124
|
+
// Build chat options from static properties + overrides
|
|
125
|
+
const chatOptions = {
|
|
126
|
+
provider: overrides.provider ?? ctor.provider,
|
|
127
|
+
assumeModelExists: overrides.assumeModelExists ?? ctor.assumeModelExists,
|
|
128
|
+
temperature: overrides.temperature ?? ctor.temperature,
|
|
129
|
+
maxTokens: overrides.maxTokens ?? ctor.maxTokens,
|
|
130
|
+
maxToolCalls: overrides.maxToolCalls ?? ctor.maxToolCalls,
|
|
131
|
+
headers: { ...ctor.headers, ...overrides.headers },
|
|
132
|
+
params: { ...ctor.params, ...overrides.params },
|
|
133
|
+
thinking: overrides.thinking ?? ctor.thinking,
|
|
134
|
+
messages: overrides.messages // Allow history injection
|
|
135
|
+
};
|
|
136
|
+
// Determine model
|
|
137
|
+
const model = overrides.model ?? ctor.model;
|
|
138
|
+
if (!model) {
|
|
139
|
+
throw new Error(`[Agent] No model specified. Set static model property or pass model in constructor.`);
|
|
140
|
+
}
|
|
141
|
+
// Use provided LLM instance or fall back to global NodeLLM
|
|
142
|
+
const llm = overrides.llm ?? NodeLLM;
|
|
143
|
+
this.chat = llm.chat(model, chatOptions);
|
|
144
|
+
// Apply instructions
|
|
145
|
+
const instructions = overrides.instructions ?? ctor.instructions;
|
|
146
|
+
if (instructions) {
|
|
147
|
+
this.chat.withInstructions(instructions);
|
|
148
|
+
}
|
|
149
|
+
// Apply tools
|
|
150
|
+
const tools = overrides.tools ?? ctor.tools;
|
|
151
|
+
if (tools && tools.length > 0) {
|
|
152
|
+
this.chat.withTools(tools);
|
|
153
|
+
}
|
|
154
|
+
// Apply schema
|
|
155
|
+
const schema = overrides.schema ?? ctor.schema;
|
|
156
|
+
if (schema) {
|
|
157
|
+
this.chat.withSchema(schema);
|
|
158
|
+
}
|
|
159
|
+
// Wire up global/static telemetry hooks
|
|
160
|
+
// Trigger onStart immediately
|
|
161
|
+
if (ctor.onStart) {
|
|
162
|
+
this.chat.beforeRequest(async (messages) => {
|
|
163
|
+
if (ctor.onStart) {
|
|
164
|
+
await ctor.onStart({ messages });
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (ctor.onToolStart) {
|
|
169
|
+
this.chat.onToolCallStart(async (toolCall) => {
|
|
170
|
+
await ctor.onToolStart(toolCall);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (ctor.onToolEnd) {
|
|
174
|
+
this.chat.onToolCallEnd(async (toolCall, result) => {
|
|
175
|
+
await ctor.onToolEnd(toolCall, result);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
if (ctor.onToolError) {
|
|
179
|
+
this.chat.onToolCallError(async (toolCall, error) => {
|
|
180
|
+
await ctor.onToolError(toolCall, error);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
if (ctor.onComplete || ctor.onThinking) {
|
|
184
|
+
this.chat.onEndMessage(async (msg) => {
|
|
185
|
+
if (msg.thinking && ctor.onThinking) {
|
|
186
|
+
await ctor.onThinking(msg.thinking, msg);
|
|
187
|
+
}
|
|
188
|
+
if (ctor.onComplete) {
|
|
189
|
+
await ctor.onComplete(msg);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Send a message to the agent and get a response.
|
|
196
|
+
* @param message - The user message
|
|
197
|
+
* @param options - Optional request options
|
|
198
|
+
*/
|
|
199
|
+
async ask(message, options) {
|
|
200
|
+
return this.chat.ask(message, options);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Alias for ask()
|
|
204
|
+
*/
|
|
205
|
+
async say(message, options) {
|
|
206
|
+
return this.ask(message, options);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Stream a response from the agent.
|
|
210
|
+
* @param message - The user message
|
|
211
|
+
* @param options - Optional request options
|
|
212
|
+
*/
|
|
213
|
+
stream(message, options) {
|
|
214
|
+
return this.chat.stream(message, options);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get the conversation history.
|
|
218
|
+
*/
|
|
219
|
+
get history() {
|
|
220
|
+
return this.chat.history;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get the model ID being used.
|
|
224
|
+
*/
|
|
225
|
+
get modelId() {
|
|
226
|
+
return this.chat.modelId;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get aggregate token usage across the conversation.
|
|
230
|
+
*/
|
|
231
|
+
get totalUsage() {
|
|
232
|
+
return this.chat.totalUsage;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Access the underlying Chat instance for advanced operations.
|
|
236
|
+
*/
|
|
237
|
+
get underlyingChat() {
|
|
238
|
+
return this.chat;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Helper function to define an agent inline without creating a class.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```typescript
|
|
246
|
+
* const SupportAgent = defineAgent({
|
|
247
|
+
* model: "gpt-4o",
|
|
248
|
+
* instructions: "You are a helpful support agent",
|
|
249
|
+
* tools: [SearchDocs, LookupAccount],
|
|
250
|
+
* temperature: 0.2
|
|
251
|
+
* });
|
|
252
|
+
*
|
|
253
|
+
* const agent = new SupportAgent();
|
|
254
|
+
* const response = await agent.ask("Help me!");
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export function defineAgent(config) {
|
|
258
|
+
return class extends Agent {
|
|
259
|
+
static model = config.model;
|
|
260
|
+
static provider = config.provider;
|
|
261
|
+
static instructions = config.instructions;
|
|
262
|
+
static tools = config.tools;
|
|
263
|
+
static temperature = config.temperature;
|
|
264
|
+
static thinking = config.thinking;
|
|
265
|
+
static schema = config.schema;
|
|
266
|
+
static params = config.params;
|
|
267
|
+
static headers = config.headers;
|
|
268
|
+
static maxTokens = config.maxTokens;
|
|
269
|
+
static maxToolCalls = config.maxToolCalls;
|
|
270
|
+
static assumeModelExists = config.assumeModelExists;
|
|
271
|
+
};
|
|
272
|
+
}
|