@aragon-agent/core 0.1.3
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/CHANGELOG.md +126 -0
- package/LICENSE +21 -0
- package/README.md +147 -0
- package/dist/engine/agent-loop.d.ts +52 -0
- package/dist/engine/agent-loop.js +260 -0
- package/dist/engine/agent.d.ts +129 -0
- package/dist/engine/agent.js +283 -0
- package/dist/engine/message-manager.d.ts +26 -0
- package/dist/engine/message-manager.js +39 -0
- package/dist/engine/steering.d.ts +27 -0
- package/dist/engine/steering.js +51 -0
- package/dist/engine/watchdog.d.ts +24 -0
- package/dist/engine/watchdog.js +50 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +63 -0
- package/dist/llm/model-registry.d.ts +51 -0
- package/dist/llm/model-registry.js +277 -0
- package/dist/llm/provider.d.ts +72 -0
- package/dist/llm/provider.js +77 -0
- package/dist/llm/providers/anthropic.d.ts +23 -0
- package/dist/llm/providers/anthropic.js +420 -0
- package/dist/llm/providers/google.d.ts +22 -0
- package/dist/llm/providers/google.js +336 -0
- package/dist/llm/providers/index.d.ts +67 -0
- package/dist/llm/providers/index.js +127 -0
- package/dist/llm/providers/openai.d.ts +22 -0
- package/dist/llm/providers/openai.js +353 -0
- package/dist/llm/stream-utils.d.ts +33 -0
- package/dist/llm/stream-utils.js +132 -0
- package/dist/llm/types.d.ts +129 -0
- package/dist/llm/types.js +17 -0
- package/dist/sandbox/console-capture.d.ts +29 -0
- package/dist/sandbox/console-capture.js +56 -0
- package/dist/sandbox/http-bridge.d.ts +47 -0
- package/dist/sandbox/http-bridge.js +143 -0
- package/dist/sandbox/isolated-vm-sandbox.d.ts +50 -0
- package/dist/sandbox/isolated-vm-sandbox.js +226 -0
- package/dist/sandbox/tool-bridge.d.ts +42 -0
- package/dist/sandbox/tool-bridge.js +98 -0
- package/dist/sandbox/types.d.ts +84 -0
- package/dist/sandbox/types.js +8 -0
- package/dist/skills/constants.d.ts +122 -0
- package/dist/skills/constants.js +179 -0
- package/dist/skills/disclosure.d.ts +146 -0
- package/dist/skills/disclosure.js +788 -0
- package/dist/skills/frontmatter.d.ts +27 -0
- package/dist/skills/frontmatter.js +177 -0
- package/dist/skills/index.d.ts +21 -0
- package/dist/skills/index.js +18 -0
- package/dist/skills/skill-find-tool.d.ts +41 -0
- package/dist/skills/skill-find-tool.js +117 -0
- package/dist/skills/skill-registry.d.ts +96 -0
- package/dist/skills/skill-registry.js +208 -0
- package/dist/skills/skill-tool.d.ts +44 -0
- package/dist/skills/skill-tool.js +96 -0
- package/dist/skills/tool-policy.d.ts +91 -0
- package/dist/skills/tool-policy.js +272 -0
- package/dist/skills/types.d.ts +271 -0
- package/dist/skills/types.js +8 -0
- package/dist/skills/validate.d.ts +37 -0
- package/dist/skills/validate.js +264 -0
- package/dist/tools/executor.d.ts +54 -0
- package/dist/tools/executor.js +206 -0
- package/dist/tools/helpers.d.ts +69 -0
- package/dist/tools/helpers.js +87 -0
- package/dist/tools/registry.d.ts +58 -0
- package/dist/tools/registry.js +119 -0
- package/dist/tools/types.d.ts +140 -0
- package/dist/tools/types.js +7 -0
- package/dist/tools/validator.d.ts +46 -0
- package/dist/tools/validator.js +210 -0
- package/dist/types.d.ts +56 -0
- package/dist/types.js +7 -0
- package/package.json +115 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent — the main class for the Agent engine.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the agent loop, message management, steering/follow-up queues,
|
|
5
|
+
* tool registry/executor, and idle watchdog into a single cohesive API
|
|
6
|
+
* that provides a full agentic LLM execution engine.
|
|
7
|
+
*/
|
|
8
|
+
import type { Message, ThinkingLevel, UserMessage } from '../llm/types.js';
|
|
9
|
+
import type { ProviderRegistry } from '../llm/providers/index.js';
|
|
10
|
+
import type { AgentTool } from '../tools/types.js';
|
|
11
|
+
import type { AgentEventListener } from '../types.js';
|
|
12
|
+
import type { CodeActSandbox, ModelRef } from './agent-loop.js';
|
|
13
|
+
export interface AgentConfig {
|
|
14
|
+
/** The initial system prompt. */
|
|
15
|
+
systemPrompt: string;
|
|
16
|
+
/** Model reference (provider + model ID + optional base URL). */
|
|
17
|
+
model: ModelRef;
|
|
18
|
+
/** Tools available to the agent. */
|
|
19
|
+
tools: AgentTool[];
|
|
20
|
+
/** Extended thinking level (Anthropic). Defaults to 'off'. */
|
|
21
|
+
thinkingLevel?: ThinkingLevel;
|
|
22
|
+
/** The LLM provider registry for streaming completions. */
|
|
23
|
+
providerRegistry: ProviderRegistry;
|
|
24
|
+
/** Resolver for API keys by provider ID. */
|
|
25
|
+
getApiKey: (providerId: string) => string | undefined;
|
|
26
|
+
/** Optional CodeAct sandbox for JS code execution. */
|
|
27
|
+
sandbox?: CodeActSandbox;
|
|
28
|
+
/** Maximum output tokens per LLM call. `undefined` = use provider default. */
|
|
29
|
+
maxTokens?: number;
|
|
30
|
+
/** Timeout configuration. */
|
|
31
|
+
timeouts?: {
|
|
32
|
+
/** Single LLM call timeout (ms). Default: 300_000 (5 min). */
|
|
33
|
+
llmCallTimeout?: number;
|
|
34
|
+
/** Agent idle timeout — no events for this long triggers abort (ms). Default: 60_000 (60 s). */
|
|
35
|
+
idleTimeout?: number;
|
|
36
|
+
/** Per-tool execution timeout (ms). Default: 120_000 (2 min). */
|
|
37
|
+
toolTimeout?: number;
|
|
38
|
+
/** Code execution timeout (ms). Default: 30_000 (30 s). */
|
|
39
|
+
codeTimeout?: number;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export interface AgentState {
|
|
43
|
+
readonly systemPrompt: string;
|
|
44
|
+
readonly model: ModelRef;
|
|
45
|
+
readonly thinkingLevel: ThinkingLevel;
|
|
46
|
+
readonly tools: AgentTool[];
|
|
47
|
+
readonly messages: readonly Message[];
|
|
48
|
+
readonly isRunning: boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare class Agent {
|
|
51
|
+
private readonly messageManager;
|
|
52
|
+
private readonly messageQueueManager;
|
|
53
|
+
private readonly toolRegistry;
|
|
54
|
+
private readonly toolExecutor;
|
|
55
|
+
private readonly watchdog;
|
|
56
|
+
private readonly listeners;
|
|
57
|
+
private systemPrompt;
|
|
58
|
+
private model;
|
|
59
|
+
private thinkingLevel;
|
|
60
|
+
private currentTools;
|
|
61
|
+
private readonly providerRegistry;
|
|
62
|
+
private readonly getApiKeyFn;
|
|
63
|
+
private readonly sandbox?;
|
|
64
|
+
private maxTokens;
|
|
65
|
+
private readonly llmCallTimeout;
|
|
66
|
+
private readonly idleTimeout;
|
|
67
|
+
private readonly toolTimeout;
|
|
68
|
+
private readonly codeTimeout;
|
|
69
|
+
private abortController;
|
|
70
|
+
private running;
|
|
71
|
+
private idlePromiseResolvers;
|
|
72
|
+
constructor(config: AgentConfig);
|
|
73
|
+
get state(): AgentState;
|
|
74
|
+
/**
|
|
75
|
+
* Send a user message and run the Agent loop until completion.
|
|
76
|
+
* Always emits `agent_start` at the beginning and `agent_end` at the end,
|
|
77
|
+
* even if an error occurs.
|
|
78
|
+
*/
|
|
79
|
+
prompt(message: string | UserMessage): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Resume the Agent loop from the current message state.
|
|
82
|
+
* Useful for retrying after an error without re-sending the user message.
|
|
83
|
+
*/
|
|
84
|
+
continue(): Promise<void>;
|
|
85
|
+
/** Abort the currently running Agent loop. */
|
|
86
|
+
abort(): void;
|
|
87
|
+
/**
|
|
88
|
+
* Wait until the Agent is idle (not running).
|
|
89
|
+
* Resolves immediately if the Agent is already idle.
|
|
90
|
+
*/
|
|
91
|
+
waitForIdle(): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Subscribe to Agent events.
|
|
94
|
+
* @returns An unsubscribe function.
|
|
95
|
+
*/
|
|
96
|
+
subscribe(listener: AgentEventListener): () => void;
|
|
97
|
+
/** Inject a high-priority steering message (interrupts tool execution). */
|
|
98
|
+
steer(message: string): void;
|
|
99
|
+
/** Queue a low-priority follow-up message (consumed after end_turn). */
|
|
100
|
+
followUp(message: string): void;
|
|
101
|
+
setModel(model: ModelRef): void;
|
|
102
|
+
setSystemPrompt(prompt: string): void;
|
|
103
|
+
setThinkingLevel(level: ThinkingLevel): void;
|
|
104
|
+
setMaxTokens(value: number | undefined): void;
|
|
105
|
+
setTools(tools: AgentTool[]): void;
|
|
106
|
+
clearMessages(): void;
|
|
107
|
+
/** Append a single message to the conversation history (used by direct-mode flows). */
|
|
108
|
+
appendMessage(message: Message): void;
|
|
109
|
+
/** Replace the entire message history (used when loading a conversation from DB). */
|
|
110
|
+
replaceMessages(messages: Message[]): void;
|
|
111
|
+
/** Clear both steering and follow-up message queues. */
|
|
112
|
+
clearAllQueues(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Emit an event to all listeners and kick the watchdog.
|
|
115
|
+
* Listener errors are caught and logged to prevent crashing the loop.
|
|
116
|
+
*/
|
|
117
|
+
private emit;
|
|
118
|
+
/**
|
|
119
|
+
* Synchronize the ToolRegistry with the provided tool array.
|
|
120
|
+
* Removes tools no longer present and adds new ones.
|
|
121
|
+
*/
|
|
122
|
+
private syncToolRegistry;
|
|
123
|
+
/**
|
|
124
|
+
* Run the agent loop wrapped with lifecycle events and error handling.
|
|
125
|
+
* Guarantees: agent_start is emitted first, agent_end is always emitted
|
|
126
|
+
* in the finally block, and the watchdog is always stopped.
|
|
127
|
+
*/
|
|
128
|
+
private runLoopWithLifecycle;
|
|
129
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent — the main class for the Agent engine.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the agent loop, message management, steering/follow-up queues,
|
|
5
|
+
* tool registry/executor, and idle watchdog into a single cohesive API
|
|
6
|
+
* that provides a full agentic LLM execution engine.
|
|
7
|
+
*/
|
|
8
|
+
import { ToolRegistry } from '../tools/registry.js';
|
|
9
|
+
import { ToolExecutor } from '../tools/executor.js';
|
|
10
|
+
import { MessageManager } from './message-manager.js';
|
|
11
|
+
import { MessageQueueManager } from './steering.js';
|
|
12
|
+
import { IdleWatchdog } from './watchdog.js';
|
|
13
|
+
import { runAgentLoop } from './agent-loop.js';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Default timeouts
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
const DEFAULT_LLM_CALL_TIMEOUT = 300_000;
|
|
18
|
+
const DEFAULT_IDLE_TIMEOUT = 60_000;
|
|
19
|
+
const DEFAULT_TOOL_TIMEOUT = 120_000;
|
|
20
|
+
const DEFAULT_CODE_TIMEOUT = 30_000;
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Agent
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
export class Agent {
|
|
25
|
+
// --- Internal components ---
|
|
26
|
+
messageManager = new MessageManager();
|
|
27
|
+
messageQueueManager = new MessageQueueManager();
|
|
28
|
+
toolRegistry = new ToolRegistry();
|
|
29
|
+
toolExecutor;
|
|
30
|
+
watchdog;
|
|
31
|
+
listeners = new Set();
|
|
32
|
+
// --- Configuration (mutable via setters) ---
|
|
33
|
+
systemPrompt;
|
|
34
|
+
model;
|
|
35
|
+
thinkingLevel;
|
|
36
|
+
currentTools;
|
|
37
|
+
providerRegistry;
|
|
38
|
+
getApiKeyFn;
|
|
39
|
+
sandbox;
|
|
40
|
+
// --- LLM generation parameters ---
|
|
41
|
+
maxTokens;
|
|
42
|
+
// --- Timeouts ---
|
|
43
|
+
llmCallTimeout;
|
|
44
|
+
idleTimeout;
|
|
45
|
+
toolTimeout;
|
|
46
|
+
codeTimeout;
|
|
47
|
+
// --- Runtime state ---
|
|
48
|
+
abortController = null;
|
|
49
|
+
running = false;
|
|
50
|
+
idlePromiseResolvers = [];
|
|
51
|
+
constructor(config) {
|
|
52
|
+
this.systemPrompt = config.systemPrompt;
|
|
53
|
+
this.model = { ...config.model };
|
|
54
|
+
this.thinkingLevel = config.thinkingLevel ?? 'off';
|
|
55
|
+
this.currentTools = [...config.tools];
|
|
56
|
+
this.providerRegistry = config.providerRegistry;
|
|
57
|
+
this.getApiKeyFn = config.getApiKey;
|
|
58
|
+
this.sandbox = config.sandbox;
|
|
59
|
+
this.maxTokens = config.maxTokens;
|
|
60
|
+
// Timeouts
|
|
61
|
+
this.llmCallTimeout = config.timeouts?.llmCallTimeout ?? DEFAULT_LLM_CALL_TIMEOUT;
|
|
62
|
+
this.idleTimeout = config.timeouts?.idleTimeout ?? DEFAULT_IDLE_TIMEOUT;
|
|
63
|
+
this.toolTimeout = config.timeouts?.toolTimeout ?? DEFAULT_TOOL_TIMEOUT;
|
|
64
|
+
this.codeTimeout = config.timeouts?.codeTimeout ?? DEFAULT_CODE_TIMEOUT;
|
|
65
|
+
// Register initial tools
|
|
66
|
+
this.syncToolRegistry(config.tools);
|
|
67
|
+
// Tool executor
|
|
68
|
+
this.toolExecutor = new ToolExecutor(this.toolRegistry, {
|
|
69
|
+
defaultTimeout: this.toolTimeout,
|
|
70
|
+
});
|
|
71
|
+
// Watchdog — on timeout, abort the agent
|
|
72
|
+
this.watchdog = new IdleWatchdog(this.idleTimeout, () => {
|
|
73
|
+
console.error('[Agent] idle watchdog fired — aborting');
|
|
74
|
+
this.abort();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// =========================================================================
|
|
78
|
+
// Public readonly state
|
|
79
|
+
// =========================================================================
|
|
80
|
+
get state() {
|
|
81
|
+
return {
|
|
82
|
+
systemPrompt: this.systemPrompt,
|
|
83
|
+
model: { ...this.model },
|
|
84
|
+
thinkingLevel: this.thinkingLevel,
|
|
85
|
+
tools: [...this.currentTools],
|
|
86
|
+
messages: this.messageManager.getAll(),
|
|
87
|
+
isRunning: this.running,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// =========================================================================
|
|
91
|
+
// Core methods
|
|
92
|
+
// =========================================================================
|
|
93
|
+
/**
|
|
94
|
+
* Send a user message and run the Agent loop until completion.
|
|
95
|
+
* Always emits `agent_start` at the beginning and `agent_end` at the end,
|
|
96
|
+
* even if an error occurs.
|
|
97
|
+
*/
|
|
98
|
+
async prompt(message) {
|
|
99
|
+
if (this.running) {
|
|
100
|
+
throw new Error('Agent is already running. Call abort() first or wait for idle.');
|
|
101
|
+
}
|
|
102
|
+
const userMessage = typeof message === 'string'
|
|
103
|
+
? { role: 'user', content: message, timestamp: Date.now() }
|
|
104
|
+
: message;
|
|
105
|
+
this.messageManager.push(userMessage);
|
|
106
|
+
await this.runLoopWithLifecycle();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Resume the Agent loop from the current message state.
|
|
110
|
+
* Useful for retrying after an error without re-sending the user message.
|
|
111
|
+
*/
|
|
112
|
+
async continue() {
|
|
113
|
+
if (this.running) {
|
|
114
|
+
throw new Error('Agent is already running. Call abort() first or wait for idle.');
|
|
115
|
+
}
|
|
116
|
+
await this.runLoopWithLifecycle();
|
|
117
|
+
}
|
|
118
|
+
/** Abort the currently running Agent loop. */
|
|
119
|
+
abort() {
|
|
120
|
+
if (this.abortController) {
|
|
121
|
+
this.abortController.abort();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Wait until the Agent is idle (not running).
|
|
126
|
+
* Resolves immediately if the Agent is already idle.
|
|
127
|
+
*/
|
|
128
|
+
waitForIdle() {
|
|
129
|
+
if (!this.running) {
|
|
130
|
+
return Promise.resolve();
|
|
131
|
+
}
|
|
132
|
+
return new Promise((resolve) => {
|
|
133
|
+
this.idlePromiseResolvers.push(resolve);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// =========================================================================
|
|
137
|
+
// Event subscription
|
|
138
|
+
// =========================================================================
|
|
139
|
+
/**
|
|
140
|
+
* Subscribe to Agent events.
|
|
141
|
+
* @returns An unsubscribe function.
|
|
142
|
+
*/
|
|
143
|
+
subscribe(listener) {
|
|
144
|
+
this.listeners.add(listener);
|
|
145
|
+
return () => {
|
|
146
|
+
this.listeners.delete(listener);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// =========================================================================
|
|
150
|
+
// Message queues
|
|
151
|
+
// =========================================================================
|
|
152
|
+
/** Inject a high-priority steering message (interrupts tool execution). */
|
|
153
|
+
steer(message) {
|
|
154
|
+
this.messageQueueManager.pushSteering(message);
|
|
155
|
+
}
|
|
156
|
+
/** Queue a low-priority follow-up message (consumed after end_turn). */
|
|
157
|
+
followUp(message) {
|
|
158
|
+
this.messageQueueManager.pushFollowUp(message);
|
|
159
|
+
}
|
|
160
|
+
// =========================================================================
|
|
161
|
+
// State mutation
|
|
162
|
+
// =========================================================================
|
|
163
|
+
setModel(model) {
|
|
164
|
+
this.model = { ...model };
|
|
165
|
+
}
|
|
166
|
+
setSystemPrompt(prompt) {
|
|
167
|
+
this.systemPrompt = prompt;
|
|
168
|
+
}
|
|
169
|
+
setThinkingLevel(level) {
|
|
170
|
+
this.thinkingLevel = level;
|
|
171
|
+
}
|
|
172
|
+
setMaxTokens(value) {
|
|
173
|
+
this.maxTokens = value;
|
|
174
|
+
}
|
|
175
|
+
setTools(tools) {
|
|
176
|
+
this.currentTools = [...tools];
|
|
177
|
+
this.syncToolRegistry(tools);
|
|
178
|
+
}
|
|
179
|
+
clearMessages() {
|
|
180
|
+
this.messageManager.clear();
|
|
181
|
+
}
|
|
182
|
+
/** Append a single message to the conversation history (used by direct-mode flows). */
|
|
183
|
+
appendMessage(message) {
|
|
184
|
+
this.messageManager.push(message);
|
|
185
|
+
}
|
|
186
|
+
/** Replace the entire message history (used when loading a conversation from DB). */
|
|
187
|
+
replaceMessages(messages) {
|
|
188
|
+
this.messageManager.restore(messages);
|
|
189
|
+
}
|
|
190
|
+
/** Clear both steering and follow-up message queues. */
|
|
191
|
+
clearAllQueues() {
|
|
192
|
+
this.messageQueueManager.clearAll();
|
|
193
|
+
}
|
|
194
|
+
// =========================================================================
|
|
195
|
+
// Internal
|
|
196
|
+
// =========================================================================
|
|
197
|
+
/**
|
|
198
|
+
* Emit an event to all listeners and kick the watchdog.
|
|
199
|
+
* Listener errors are caught and logged to prevent crashing the loop.
|
|
200
|
+
*/
|
|
201
|
+
emit(event) {
|
|
202
|
+
for (const listener of this.listeners) {
|
|
203
|
+
try {
|
|
204
|
+
listener(event);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
console.error('[Agent] listener error:', err);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
this.watchdog.kick();
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Synchronize the ToolRegistry with the provided tool array.
|
|
214
|
+
* Removes tools no longer present and adds new ones.
|
|
215
|
+
*/
|
|
216
|
+
syncToolRegistry(tools) {
|
|
217
|
+
const newNames = new Set(tools.map((t) => t.name));
|
|
218
|
+
// Remove tools no longer in the set.
|
|
219
|
+
for (const existing of this.toolRegistry.getAll()) {
|
|
220
|
+
if (!newNames.has(existing.name)) {
|
|
221
|
+
this.toolRegistry.unregister(existing.name);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Add or update tools.
|
|
225
|
+
for (const tool of tools) {
|
|
226
|
+
if (this.toolRegistry.has(tool.name)) {
|
|
227
|
+
// Unregister and re-register to update the definition.
|
|
228
|
+
this.toolRegistry.unregister(tool.name);
|
|
229
|
+
}
|
|
230
|
+
this.toolRegistry.register(tool);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Run the agent loop wrapped with lifecycle events and error handling.
|
|
235
|
+
* Guarantees: agent_start is emitted first, agent_end is always emitted
|
|
236
|
+
* in the finally block, and the watchdog is always stopped.
|
|
237
|
+
*/
|
|
238
|
+
async runLoopWithLifecycle() {
|
|
239
|
+
this.running = true;
|
|
240
|
+
this.abortController = new AbortController();
|
|
241
|
+
this.watchdog.start();
|
|
242
|
+
this.emit({ type: 'agent_start' });
|
|
243
|
+
try {
|
|
244
|
+
await runAgentLoop({
|
|
245
|
+
providerRegistry: this.providerRegistry,
|
|
246
|
+
toolRegistry: this.toolRegistry,
|
|
247
|
+
toolExecutor: this.toolExecutor,
|
|
248
|
+
messageManager: this.messageManager,
|
|
249
|
+
messageQueueManager: this.messageQueueManager,
|
|
250
|
+
getApiKey: this.getApiKeyFn,
|
|
251
|
+
emit: (event) => this.emit(event),
|
|
252
|
+
sandbox: this.sandbox,
|
|
253
|
+
model: this.model,
|
|
254
|
+
systemPrompt: this.systemPrompt,
|
|
255
|
+
thinkingLevel: this.thinkingLevel,
|
|
256
|
+
maxTokens: this.maxTokens,
|
|
257
|
+
signal: this.abortController.signal,
|
|
258
|
+
timeouts: {
|
|
259
|
+
llmCallTimeout: this.llmCallTimeout,
|
|
260
|
+
toolTimeout: this.toolTimeout,
|
|
261
|
+
codeTimeout: this.codeTimeout,
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
console.error('[Agent] loop error:', err);
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
this.watchdog.stop();
|
|
270
|
+
this.running = false;
|
|
271
|
+
this.abortController = null;
|
|
272
|
+
this.emit({
|
|
273
|
+
type: 'agent_end',
|
|
274
|
+
messages: this.messageManager.getAll(),
|
|
275
|
+
});
|
|
276
|
+
// Resolve all pending waitForIdle() callers.
|
|
277
|
+
for (const resolve of this.idlePromiseResolvers) {
|
|
278
|
+
resolve();
|
|
279
|
+
}
|
|
280
|
+
this.idlePromiseResolvers = [];
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageManager — manages the conversation message history for an Agent.
|
|
3
|
+
*
|
|
4
|
+
* Provides append, read, clear, and restore operations over a mutable
|
|
5
|
+
* message array. The `getAll()` method returns a readonly view so
|
|
6
|
+
* consumers cannot accidentally mutate the internal state.
|
|
7
|
+
*/
|
|
8
|
+
import type { Message } from '../llm/types.js';
|
|
9
|
+
export declare class MessageManager {
|
|
10
|
+
private messages;
|
|
11
|
+
/** Append a message to the history. */
|
|
12
|
+
push(message: Message): void;
|
|
13
|
+
/** Return a readonly snapshot of all messages. */
|
|
14
|
+
getAll(): readonly Message[];
|
|
15
|
+
/** Remove all messages from the history. */
|
|
16
|
+
clear(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Replace the entire message history with an externally provided array.
|
|
19
|
+
* Used when restoring a conversation from persistent storage.
|
|
20
|
+
*/
|
|
21
|
+
restore(messages: Message[]): void;
|
|
22
|
+
/** Return the last `n` messages (or fewer if history is shorter). */
|
|
23
|
+
getLast(n: number): Message[];
|
|
24
|
+
/** The number of messages currently in the history. */
|
|
25
|
+
get length(): number;
|
|
26
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageManager — manages the conversation message history for an Agent.
|
|
3
|
+
*
|
|
4
|
+
* Provides append, read, clear, and restore operations over a mutable
|
|
5
|
+
* message array. The `getAll()` method returns a readonly view so
|
|
6
|
+
* consumers cannot accidentally mutate the internal state.
|
|
7
|
+
*/
|
|
8
|
+
export class MessageManager {
|
|
9
|
+
messages = [];
|
|
10
|
+
/** Append a message to the history. */
|
|
11
|
+
push(message) {
|
|
12
|
+
this.messages.push(message);
|
|
13
|
+
}
|
|
14
|
+
/** Return a readonly snapshot of all messages. */
|
|
15
|
+
getAll() {
|
|
16
|
+
return this.messages;
|
|
17
|
+
}
|
|
18
|
+
/** Remove all messages from the history. */
|
|
19
|
+
clear() {
|
|
20
|
+
this.messages = [];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Replace the entire message history with an externally provided array.
|
|
24
|
+
* Used when restoring a conversation from persistent storage.
|
|
25
|
+
*/
|
|
26
|
+
restore(messages) {
|
|
27
|
+
this.messages = [...messages];
|
|
28
|
+
}
|
|
29
|
+
/** Return the last `n` messages (or fewer if history is shorter). */
|
|
30
|
+
getLast(n) {
|
|
31
|
+
if (n <= 0)
|
|
32
|
+
return [];
|
|
33
|
+
return this.messages.slice(-n);
|
|
34
|
+
}
|
|
35
|
+
/** The number of messages currently in the history. */
|
|
36
|
+
get length() {
|
|
37
|
+
return this.messages.length;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageQueueManager — manages steering and follow-up message queues.
|
|
3
|
+
*
|
|
4
|
+
* Steering messages have high priority: they interrupt the current tool
|
|
5
|
+
* execution batch and are injected before the next LLM turn.
|
|
6
|
+
*
|
|
7
|
+
* Follow-up messages have low priority: they are consumed only when the
|
|
8
|
+
* Agent loop would otherwise exit (end_turn with no pending work).
|
|
9
|
+
*/
|
|
10
|
+
export declare class MessageQueueManager {
|
|
11
|
+
private readonly steeringQueue;
|
|
12
|
+
private readonly followUpQueue;
|
|
13
|
+
/** Enqueue a high-priority steering message. */
|
|
14
|
+
pushSteering(message: string): void;
|
|
15
|
+
/** Drain and return all pending steering messages (empties the queue). */
|
|
16
|
+
drainSteering(): string[];
|
|
17
|
+
/** Whether there are pending steering messages. */
|
|
18
|
+
hasSteering(): boolean;
|
|
19
|
+
/** Enqueue a low-priority follow-up message. */
|
|
20
|
+
pushFollowUp(message: string): void;
|
|
21
|
+
/** Drain and return all pending follow-up messages (empties the queue). */
|
|
22
|
+
drainFollowUp(): string[];
|
|
23
|
+
/** Whether there are pending follow-up messages. */
|
|
24
|
+
hasFollowUp(): boolean;
|
|
25
|
+
/** Clear both queues. */
|
|
26
|
+
clearAll(): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageQueueManager — manages steering and follow-up message queues.
|
|
3
|
+
*
|
|
4
|
+
* Steering messages have high priority: they interrupt the current tool
|
|
5
|
+
* execution batch and are injected before the next LLM turn.
|
|
6
|
+
*
|
|
7
|
+
* Follow-up messages have low priority: they are consumed only when the
|
|
8
|
+
* Agent loop would otherwise exit (end_turn with no pending work).
|
|
9
|
+
*/
|
|
10
|
+
export class MessageQueueManager {
|
|
11
|
+
steeringQueue = [];
|
|
12
|
+
followUpQueue = [];
|
|
13
|
+
// -----------------------------------------------------------------------
|
|
14
|
+
// Steering
|
|
15
|
+
// -----------------------------------------------------------------------
|
|
16
|
+
/** Enqueue a high-priority steering message. */
|
|
17
|
+
pushSteering(message) {
|
|
18
|
+
this.steeringQueue.push(message);
|
|
19
|
+
}
|
|
20
|
+
/** Drain and return all pending steering messages (empties the queue). */
|
|
21
|
+
drainSteering() {
|
|
22
|
+
return this.steeringQueue.splice(0);
|
|
23
|
+
}
|
|
24
|
+
/** Whether there are pending steering messages. */
|
|
25
|
+
hasSteering() {
|
|
26
|
+
return this.steeringQueue.length > 0;
|
|
27
|
+
}
|
|
28
|
+
// -----------------------------------------------------------------------
|
|
29
|
+
// Follow-up
|
|
30
|
+
// -----------------------------------------------------------------------
|
|
31
|
+
/** Enqueue a low-priority follow-up message. */
|
|
32
|
+
pushFollowUp(message) {
|
|
33
|
+
this.followUpQueue.push(message);
|
|
34
|
+
}
|
|
35
|
+
/** Drain and return all pending follow-up messages (empties the queue). */
|
|
36
|
+
drainFollowUp() {
|
|
37
|
+
return this.followUpQueue.splice(0);
|
|
38
|
+
}
|
|
39
|
+
/** Whether there are pending follow-up messages. */
|
|
40
|
+
hasFollowUp() {
|
|
41
|
+
return this.followUpQueue.length > 0;
|
|
42
|
+
}
|
|
43
|
+
// -----------------------------------------------------------------------
|
|
44
|
+
// Lifecycle
|
|
45
|
+
// -----------------------------------------------------------------------
|
|
46
|
+
/** Clear both queues. */
|
|
47
|
+
clearAll() {
|
|
48
|
+
this.steeringQueue.length = 0;
|
|
49
|
+
this.followUpQueue.length = 0;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IdleWatchdog — fires a callback if no activity occurs within a
|
|
3
|
+
* configurable timeout window.
|
|
4
|
+
*
|
|
5
|
+
* The Agent calls `kick()` on every emitted event to reset the timer.
|
|
6
|
+
* If the timer expires (no events for `timeoutMs`), the watchdog invokes
|
|
7
|
+
* the `onTimeout` callback which typically calls `Agent.abort()`.
|
|
8
|
+
*/
|
|
9
|
+
export declare class IdleWatchdog {
|
|
10
|
+
private timeoutMs;
|
|
11
|
+
private readonly onTimeout;
|
|
12
|
+
private timerId;
|
|
13
|
+
private running;
|
|
14
|
+
constructor(timeoutMs: number, onTimeout: () => void);
|
|
15
|
+
/** Reset the idle timer. Must be called on every Agent event. */
|
|
16
|
+
kick(): void;
|
|
17
|
+
/** Start the watchdog. Begins (or restarts) the idle timer. */
|
|
18
|
+
start(): void;
|
|
19
|
+
/** Stop the watchdog and cancel any pending timer. */
|
|
20
|
+
stop(): void;
|
|
21
|
+
/** Update the timeout duration. Takes effect on the next `kick()`. */
|
|
22
|
+
setTimeout(ms: number): void;
|
|
23
|
+
private clearTimer;
|
|
24
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IdleWatchdog — fires a callback if no activity occurs within a
|
|
3
|
+
* configurable timeout window.
|
|
4
|
+
*
|
|
5
|
+
* The Agent calls `kick()` on every emitted event to reset the timer.
|
|
6
|
+
* If the timer expires (no events for `timeoutMs`), the watchdog invokes
|
|
7
|
+
* the `onTimeout` callback which typically calls `Agent.abort()`.
|
|
8
|
+
*/
|
|
9
|
+
export class IdleWatchdog {
|
|
10
|
+
timeoutMs;
|
|
11
|
+
onTimeout;
|
|
12
|
+
timerId = null;
|
|
13
|
+
running = false;
|
|
14
|
+
constructor(timeoutMs, onTimeout) {
|
|
15
|
+
this.timeoutMs = timeoutMs;
|
|
16
|
+
this.onTimeout = onTimeout;
|
|
17
|
+
}
|
|
18
|
+
/** Reset the idle timer. Must be called on every Agent event. */
|
|
19
|
+
kick() {
|
|
20
|
+
if (!this.running)
|
|
21
|
+
return;
|
|
22
|
+
this.clearTimer();
|
|
23
|
+
this.timerId = setTimeout(() => {
|
|
24
|
+
this.onTimeout();
|
|
25
|
+
}, this.timeoutMs);
|
|
26
|
+
}
|
|
27
|
+
/** Start the watchdog. Begins (or restarts) the idle timer. */
|
|
28
|
+
start() {
|
|
29
|
+
this.running = true;
|
|
30
|
+
this.kick();
|
|
31
|
+
}
|
|
32
|
+
/** Stop the watchdog and cancel any pending timer. */
|
|
33
|
+
stop() {
|
|
34
|
+
this.running = false;
|
|
35
|
+
this.clearTimer();
|
|
36
|
+
}
|
|
37
|
+
/** Update the timeout duration. Takes effect on the next `kick()`. */
|
|
38
|
+
setTimeout(ms) {
|
|
39
|
+
this.timeoutMs = ms;
|
|
40
|
+
}
|
|
41
|
+
// -----------------------------------------------------------------------
|
|
42
|
+
// Internal
|
|
43
|
+
// -----------------------------------------------------------------------
|
|
44
|
+
clearTimer() {
|
|
45
|
+
if (this.timerId !== null) {
|
|
46
|
+
clearTimeout(this.timerId);
|
|
47
|
+
this.timerId = null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent core — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* This is the single entry point for importing agent-core functionality.
|
|
5
|
+
* Other tasks will expand this file as more modules are added (engine, tools,
|
|
6
|
+
* sandbox).
|
|
7
|
+
*/
|
|
8
|
+
export type { ContentPart, TextContentPart, ImageContentPart, ContentBlock, TextBlock, ThinkingBlock, ToolCallBlock, Message, UserMessage, AssistantMessage, ToolResultMessage, StopReason, TokenUsage, ThinkingLevel, StreamEvent, TextDeltaEvent, ThinkingStartEvent, ThinkingDeltaEvent, ToolCallStartEvent, ToolCallDeltaEvent, ToolCallEndEvent, DoneEvent, ErrorEvent, ToolDefinition, JSONSchema, ModelInfo, ModelCost, } from './llm/types.js';
|
|
9
|
+
export { THINKING_BUDGET } from './llm/types.js';
|
|
10
|
+
export type { LLMProvider, LLMRequest, LLMErrorType, } from './llm/provider.js';
|
|
11
|
+
export { LLMError, classifyHttpError, wrapFetchError, } from './llm/provider.js';
|
|
12
|
+
export type { SSEEvent } from './llm/stream-utils.js';
|
|
13
|
+
export { parseSSEStream, consumeStream, } from './llm/stream-utils.js';
|
|
14
|
+
export { ProviderRegistry, initProviders, getProviderRegistry, setProviderRegistry, streamLLM, completeLLM, } from './llm/providers/index.js';
|
|
15
|
+
export { AnthropicProvider } from './llm/providers/anthropic.js';
|
|
16
|
+
export { OpenAIProvider } from './llm/providers/openai.js';
|
|
17
|
+
export { GoogleProvider } from './llm/providers/google.js';
|
|
18
|
+
export { ModelRegistry, getModelRegistry, setModelRegistry, } from './llm/model-registry.js';
|
|
19
|
+
export type { JSONSchema7, ToolResultContent, ToolResult, ToolProgressUpdate, ToolExecutionContext, ToolExecuteFn, AgentTool, ToolDefinition as AgentToolDefinition, ToolRegistryEvent, ToolExecutionResult, } from './tools/types.js';
|
|
20
|
+
export { textResult, errorResult, imageResult, multiResult, defineTool, } from './tools/helpers.js';
|
|
21
|
+
export type { DefineToolConfig } from './tools/helpers.js';
|
|
22
|
+
export { ToolRegistry } from './tools/registry.js';
|
|
23
|
+
export type { ToolRegistryListener } from './tools/registry.js';
|
|
24
|
+
export { ToolParamValidator, ToolValidationError, formatValidationErrors, } from './tools/validator.js';
|
|
25
|
+
export type { ValidationError } from './tools/validator.js';
|
|
26
|
+
export { ToolExecutor } from './tools/executor.js';
|
|
27
|
+
export type { ToolExecutorOptions } from './tools/executor.js';
|
|
28
|
+
export { SkillRegistry } from './skills/skill-registry.js';
|
|
29
|
+
export { parseFrontmatter } from './skills/frontmatter.js';
|
|
30
|
+
export { validateSkillFrontmatter, validateStagedSkill } from './skills/validate.js';
|
|
31
|
+
export { renderSkillCatalog, renderSkillBody, renderSkillInvocation, renderSkillFindResults, rankCatalogRecords, applySkillArguments, suggestSkillNames, sanitizeForPromptBlock, } from './skills/disclosure.js';
|
|
32
|
+
export { createSkillTool } from './skills/skill-tool.js';
|
|
33
|
+
export { createSkillFindTool } from './skills/skill-find-tool.js';
|
|
34
|
+
export { computeToolPolicy, evaluateToolCall } from './skills/tool-policy.js';
|
|
35
|
+
export { SKILL_CATALOG_MAX_BYTES, SKILL_BODY_MAX_BYTES, SKILL_RESULT_MAX_BYTES, ALWAYS_SKILLS_MAX_BYTES, SKILL_MD_MAX_BYTES, SKILL_DESC_LINE_MAX, SKILL_FILES_MAX, SKILL_FIND_MAX_BYTES, SKILL_NAME_PATTERN, } from './skills/constants.js';
|
|
36
|
+
export type { SkillScope, SkillActivation, SkillFrontmatter, SkillRecord, SkillFileRef, SkillHost, SkillManifest, SkillValidationIssue, SkillCatalogOptions, SkillBodyOptions, SkillFindOptions, SkillIntegrity, SkillUsageStat, SkillUsageMap, SkillInvocationOptions, SkillPlatform, SkillPolicyView, SkillToolPolicyMode, ToolPolicyDecision, ToolPolicyInput, ToolPolicySource, ToolPolicyVerdict, } from './skills/types.js';
|
|
37
|
+
export type { AgentEvent, AgentEventListener, AgentStartEvent, AgentEndEvent, TurnStartEvent, TurnEndEvent, MessageUpdateEvent, ToolExecutionStartEvent, ToolExecutionEndEvent, CodeExecutionStartEvent, CodeExecutionEndEvent, } from './types.js';
|
|
38
|
+
export { Agent } from './engine/agent.js';
|
|
39
|
+
export type { AgentConfig, AgentState } from './engine/agent.js';
|
|
40
|
+
export type { ModelRef } from './engine/agent-loop.js';
|
|
41
|
+
export type { CodeActSandbox, CodeActResult } from './engine/agent-loop.js';
|
|
42
|
+
export { MessageManager } from './engine/message-manager.js';
|
|
43
|
+
export { MessageQueueManager } from './engine/steering.js';
|
|
44
|
+
export { IdleWatchdog } from './engine/watchdog.js';
|
|
45
|
+
export type { SandboxConfig, ExecuteOptions, ExecuteResult, ConsoleEntry, SandboxToolCall, } from './sandbox/types.js';
|
|
46
|
+
export { Agent as AragonAgent } from './engine/agent.js';
|