confused-ai-core 0.1.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/FEATURES.md +169 -0
- package/package.json +119 -0
- package/src/agent.ts +187 -0
- package/src/agentic/index.ts +87 -0
- package/src/agentic/runner.ts +386 -0
- package/src/agentic/types.ts +91 -0
- package/src/artifacts/artifact.ts +417 -0
- package/src/artifacts/index.ts +42 -0
- package/src/artifacts/media.ts +304 -0
- package/src/cli/index.ts +122 -0
- package/src/core/base-agent.ts +151 -0
- package/src/core/context-builder.ts +106 -0
- package/src/core/index.ts +8 -0
- package/src/core/schemas.ts +17 -0
- package/src/core/types.ts +158 -0
- package/src/create-agent.ts +309 -0
- package/src/debug-logger.ts +188 -0
- package/src/dx/agent.ts +88 -0
- package/src/dx/define-agent.ts +183 -0
- package/src/dx/dev-logger.ts +57 -0
- package/src/dx/index.ts +11 -0
- package/src/errors.ts +175 -0
- package/src/execution/engine.ts +522 -0
- package/src/execution/graph-builder.ts +362 -0
- package/src/execution/index.ts +8 -0
- package/src/execution/types.ts +257 -0
- package/src/execution/worker-pool.ts +308 -0
- package/src/extensions/index.ts +123 -0
- package/src/guardrails/allowlist.ts +155 -0
- package/src/guardrails/index.ts +17 -0
- package/src/guardrails/types.ts +159 -0
- package/src/guardrails/validator.ts +265 -0
- package/src/index.ts +74 -0
- package/src/knowledge/index.ts +5 -0
- package/src/knowledge/types.ts +52 -0
- package/src/learning/in-memory-store.ts +72 -0
- package/src/learning/index.ts +6 -0
- package/src/learning/types.ts +42 -0
- package/src/llm/cache.ts +300 -0
- package/src/llm/index.ts +22 -0
- package/src/llm/model-resolver.ts +81 -0
- package/src/llm/openai-provider.ts +313 -0
- package/src/llm/openrouter-provider.ts +29 -0
- package/src/llm/types.ts +131 -0
- package/src/memory/in-memory-store.ts +255 -0
- package/src/memory/index.ts +7 -0
- package/src/memory/types.ts +193 -0
- package/src/memory/vector-store.ts +251 -0
- package/src/observability/console-logger.ts +123 -0
- package/src/observability/index.ts +12 -0
- package/src/observability/metrics.ts +85 -0
- package/src/observability/otlp-exporter.ts +417 -0
- package/src/observability/tracer.ts +105 -0
- package/src/observability/types.ts +341 -0
- package/src/orchestration/agent-adapter.ts +33 -0
- package/src/orchestration/index.ts +34 -0
- package/src/orchestration/load-balancer.ts +151 -0
- package/src/orchestration/mcp-types.ts +59 -0
- package/src/orchestration/message-bus.ts +192 -0
- package/src/orchestration/orchestrator.ts +349 -0
- package/src/orchestration/pipeline.ts +66 -0
- package/src/orchestration/supervisor.ts +107 -0
- package/src/orchestration/swarm.ts +1099 -0
- package/src/orchestration/toolkit.ts +47 -0
- package/src/orchestration/types.ts +339 -0
- package/src/planner/classical-planner.ts +383 -0
- package/src/planner/index.ts +8 -0
- package/src/planner/llm-planner.ts +353 -0
- package/src/planner/types.ts +227 -0
- package/src/planner/validator.ts +297 -0
- package/src/production/circuit-breaker.ts +290 -0
- package/src/production/graceful-shutdown.ts +251 -0
- package/src/production/health.ts +333 -0
- package/src/production/index.ts +57 -0
- package/src/production/latency-eval.ts +62 -0
- package/src/production/rate-limiter.ts +287 -0
- package/src/production/resumable-stream.ts +289 -0
- package/src/production/types.ts +81 -0
- package/src/sdk/index.ts +374 -0
- package/src/session/db-driver.ts +50 -0
- package/src/session/in-memory-store.ts +235 -0
- package/src/session/index.ts +12 -0
- package/src/session/sql-store.ts +315 -0
- package/src/session/sqlite-store.ts +61 -0
- package/src/session/types.ts +153 -0
- package/src/tools/base-tool.ts +223 -0
- package/src/tools/browser-tool.ts +123 -0
- package/src/tools/calculator-tool.ts +265 -0
- package/src/tools/file-tools.ts +394 -0
- package/src/tools/github-tool.ts +432 -0
- package/src/tools/hackernews-tool.ts +187 -0
- package/src/tools/http-tool.ts +118 -0
- package/src/tools/index.ts +99 -0
- package/src/tools/jira-tool.ts +373 -0
- package/src/tools/notion-tool.ts +322 -0
- package/src/tools/openai-tool.ts +236 -0
- package/src/tools/registry.ts +131 -0
- package/src/tools/serpapi-tool.ts +234 -0
- package/src/tools/shell-tool.ts +118 -0
- package/src/tools/slack-tool.ts +327 -0
- package/src/tools/telegram-tool.ts +127 -0
- package/src/tools/types.ts +229 -0
- package/src/tools/websearch-tool.ts +335 -0
- package/src/tools/wikipedia-tool.ts +177 -0
- package/src/tools/yfinance-tool.ts +33 -0
- package/src/voice/index.ts +17 -0
- package/src/voice/voice-provider.ts +228 -0
- package/tests/artifact.test.ts +241 -0
- package/tests/circuit-breaker.test.ts +171 -0
- package/tests/health.test.ts +192 -0
- package/tests/llm-cache.test.ts +186 -0
- package/tests/rate-limiter.test.ts +161 -0
- package/tsconfig.json +29 -0
- package/vitest.config.ts +47 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Artifacts - Agno-Style Image, Audio, Video Support
|
|
3
|
+
*
|
|
4
|
+
* Production-grade media handling:
|
|
5
|
+
* - Image generation and storage
|
|
6
|
+
* - Audio transcription and synthesis artifacts
|
|
7
|
+
* - Video processing artifacts
|
|
8
|
+
* - URL and base64 support
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ArtifactStorage, BinaryArtifact, ArtifactMetadata } from './artifact.js';
|
|
12
|
+
|
|
13
|
+
/** Image generation result */
|
|
14
|
+
export interface ImageArtifact extends Omit<BinaryArtifact, 'type'> {
|
|
15
|
+
type: 'image';
|
|
16
|
+
/** Image width in pixels */
|
|
17
|
+
readonly width?: number;
|
|
18
|
+
/** Image height in pixels */
|
|
19
|
+
readonly height?: number;
|
|
20
|
+
/** Generation prompt (if AI-generated) */
|
|
21
|
+
readonly prompt?: string;
|
|
22
|
+
/** Negative prompt (if applicable) */
|
|
23
|
+
readonly negativePrompt?: string;
|
|
24
|
+
/** Model used for generation */
|
|
25
|
+
readonly model?: string;
|
|
26
|
+
/** Seed for reproducibility */
|
|
27
|
+
readonly seed?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Audio artifact */
|
|
31
|
+
export interface AudioArtifact extends Omit<BinaryArtifact, 'type'> {
|
|
32
|
+
type: 'audio';
|
|
33
|
+
/** Duration in seconds */
|
|
34
|
+
readonly durationSeconds?: number;
|
|
35
|
+
/** Sample rate in Hz */
|
|
36
|
+
readonly sampleRate?: number;
|
|
37
|
+
/** Number of channels */
|
|
38
|
+
readonly channels?: number;
|
|
39
|
+
/** Transcript (if available) */
|
|
40
|
+
readonly transcript?: string;
|
|
41
|
+
/** Voice ID (for TTS) */
|
|
42
|
+
readonly voiceId?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Video artifact */
|
|
46
|
+
export interface VideoArtifact extends Omit<BinaryArtifact, 'type'> {
|
|
47
|
+
type: 'video';
|
|
48
|
+
/** Duration in seconds */
|
|
49
|
+
readonly durationSeconds?: number;
|
|
50
|
+
/** Width in pixels */
|
|
51
|
+
readonly width?: number;
|
|
52
|
+
/** Height in pixels */
|
|
53
|
+
readonly height?: number;
|
|
54
|
+
/** Frame rate */
|
|
55
|
+
readonly fps?: number;
|
|
56
|
+
/** Thumbnail URL */
|
|
57
|
+
readonly thumbnailUrl?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// --- Media Artifact Helpers ---
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create an image artifact from URL
|
|
64
|
+
*/
|
|
65
|
+
export function createImageFromUrl(
|
|
66
|
+
name: string,
|
|
67
|
+
url: string,
|
|
68
|
+
options?: {
|
|
69
|
+
width?: number;
|
|
70
|
+
height?: number;
|
|
71
|
+
prompt?: string;
|
|
72
|
+
model?: string;
|
|
73
|
+
tags?: string[];
|
|
74
|
+
}
|
|
75
|
+
): Omit<ImageArtifact, 'id' | 'createdAt' | 'updatedAt' | 'version'> {
|
|
76
|
+
return {
|
|
77
|
+
name,
|
|
78
|
+
type: 'image',
|
|
79
|
+
content: url,
|
|
80
|
+
url,
|
|
81
|
+
mimeType: guessImageMimeType(url),
|
|
82
|
+
width: options?.width,
|
|
83
|
+
height: options?.height,
|
|
84
|
+
prompt: options?.prompt,
|
|
85
|
+
model: options?.model,
|
|
86
|
+
tags: options?.tags,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Create an image artifact from base64
|
|
92
|
+
*/
|
|
93
|
+
export function createImageFromBase64(
|
|
94
|
+
name: string,
|
|
95
|
+
base64: string,
|
|
96
|
+
mimeType: string,
|
|
97
|
+
options?: {
|
|
98
|
+
width?: number;
|
|
99
|
+
height?: number;
|
|
100
|
+
prompt?: string;
|
|
101
|
+
model?: string;
|
|
102
|
+
tags?: string[];
|
|
103
|
+
}
|
|
104
|
+
): Omit<ImageArtifact, 'id' | 'createdAt' | 'updatedAt' | 'version'> {
|
|
105
|
+
return {
|
|
106
|
+
name,
|
|
107
|
+
type: 'image',
|
|
108
|
+
content: base64,
|
|
109
|
+
base64,
|
|
110
|
+
mimeType,
|
|
111
|
+
width: options?.width,
|
|
112
|
+
height: options?.height,
|
|
113
|
+
prompt: options?.prompt,
|
|
114
|
+
model: options?.model,
|
|
115
|
+
tags: options?.tags,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Create an audio artifact from URL
|
|
121
|
+
*/
|
|
122
|
+
export function createAudioFromUrl(
|
|
123
|
+
name: string,
|
|
124
|
+
url: string,
|
|
125
|
+
options?: {
|
|
126
|
+
durationSeconds?: number;
|
|
127
|
+
transcript?: string;
|
|
128
|
+
voiceId?: string;
|
|
129
|
+
tags?: string[];
|
|
130
|
+
}
|
|
131
|
+
): Omit<AudioArtifact, 'id' | 'createdAt' | 'updatedAt' | 'version'> {
|
|
132
|
+
return {
|
|
133
|
+
name,
|
|
134
|
+
type: 'audio',
|
|
135
|
+
content: url,
|
|
136
|
+
url,
|
|
137
|
+
mimeType: guessAudioMimeType(url),
|
|
138
|
+
durationSeconds: options?.durationSeconds,
|
|
139
|
+
transcript: options?.transcript,
|
|
140
|
+
voiceId: options?.voiceId,
|
|
141
|
+
tags: options?.tags,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Create a video artifact from URL
|
|
147
|
+
*/
|
|
148
|
+
export function createVideoFromUrl(
|
|
149
|
+
name: string,
|
|
150
|
+
url: string,
|
|
151
|
+
options?: {
|
|
152
|
+
durationSeconds?: number;
|
|
153
|
+
width?: number;
|
|
154
|
+
height?: number;
|
|
155
|
+
fps?: number;
|
|
156
|
+
thumbnailUrl?: string;
|
|
157
|
+
tags?: string[];
|
|
158
|
+
}
|
|
159
|
+
): Omit<VideoArtifact, 'id' | 'createdAt' | 'updatedAt' | 'version'> {
|
|
160
|
+
return {
|
|
161
|
+
name,
|
|
162
|
+
type: 'video',
|
|
163
|
+
content: url,
|
|
164
|
+
url,
|
|
165
|
+
mimeType: guessVideoMimeType(url),
|
|
166
|
+
durationSeconds: options?.durationSeconds,
|
|
167
|
+
width: options?.width,
|
|
168
|
+
height: options?.height,
|
|
169
|
+
fps: options?.fps,
|
|
170
|
+
thumbnailUrl: options?.thumbnailUrl,
|
|
171
|
+
tags: options?.tags,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// --- Media Manager ---
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* MediaManager - handles media artifact operations
|
|
179
|
+
*/
|
|
180
|
+
export class MediaManager {
|
|
181
|
+
constructor(private readonly storage: ArtifactStorage) { }
|
|
182
|
+
|
|
183
|
+
/** Save an image artifact */
|
|
184
|
+
async saveImage(
|
|
185
|
+
name: string,
|
|
186
|
+
source: string | { base64: string; mimeType: string },
|
|
187
|
+
options?: {
|
|
188
|
+
width?: number;
|
|
189
|
+
height?: number;
|
|
190
|
+
prompt?: string;
|
|
191
|
+
model?: string;
|
|
192
|
+
tags?: string[];
|
|
193
|
+
}
|
|
194
|
+
): Promise<ImageArtifact> {
|
|
195
|
+
const artifact = typeof source === 'string'
|
|
196
|
+
? createImageFromUrl(name, source, options)
|
|
197
|
+
: createImageFromBase64(name, source.base64, source.mimeType, options);
|
|
198
|
+
|
|
199
|
+
return await this.storage.save(artifact) as ImageArtifact;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Save an audio artifact */
|
|
203
|
+
async saveAudio(
|
|
204
|
+
name: string,
|
|
205
|
+
url: string,
|
|
206
|
+
options?: {
|
|
207
|
+
durationSeconds?: number;
|
|
208
|
+
transcript?: string;
|
|
209
|
+
voiceId?: string;
|
|
210
|
+
tags?: string[];
|
|
211
|
+
}
|
|
212
|
+
): Promise<AudioArtifact> {
|
|
213
|
+
const artifact = createAudioFromUrl(name, url, options);
|
|
214
|
+
return await this.storage.save(artifact) as AudioArtifact;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Save a video artifact */
|
|
218
|
+
async saveVideo(
|
|
219
|
+
name: string,
|
|
220
|
+
url: string,
|
|
221
|
+
options?: {
|
|
222
|
+
durationSeconds?: number;
|
|
223
|
+
width?: number;
|
|
224
|
+
height?: number;
|
|
225
|
+
fps?: number;
|
|
226
|
+
thumbnailUrl?: string;
|
|
227
|
+
tags?: string[];
|
|
228
|
+
}
|
|
229
|
+
): Promise<VideoArtifact> {
|
|
230
|
+
const artifact = createVideoFromUrl(name, url, options);
|
|
231
|
+
return await this.storage.save(artifact) as VideoArtifact;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Get an image by ID */
|
|
235
|
+
async getImage(id: string): Promise<ImageArtifact | null> {
|
|
236
|
+
return await this.storage.get<ImageArtifact['content']>(id) as ImageArtifact | null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Get an audio by ID */
|
|
240
|
+
async getAudio(id: string): Promise<AudioArtifact | null> {
|
|
241
|
+
return await this.storage.get<AudioArtifact['content']>(id) as AudioArtifact | null;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** Get a video by ID */
|
|
245
|
+
async getVideo(id: string): Promise<VideoArtifact | null> {
|
|
246
|
+
return await this.storage.get<VideoArtifact['content']>(id) as VideoArtifact | null;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** List all images */
|
|
250
|
+
async listImages(limit?: number): Promise<ArtifactMetadata[]> {
|
|
251
|
+
return await this.storage.list({ type: 'image', limit });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** List all audio */
|
|
255
|
+
async listAudio(limit?: number): Promise<ArtifactMetadata[]> {
|
|
256
|
+
return await this.storage.list({ type: 'audio', limit });
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** List all videos */
|
|
260
|
+
async listVideos(limit?: number): Promise<ArtifactMetadata[]> {
|
|
261
|
+
return await this.storage.list({ type: 'video', limit });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// --- Helpers ---
|
|
266
|
+
|
|
267
|
+
function guessImageMimeType(url: string): string {
|
|
268
|
+
const ext = url.split('.').pop()?.toLowerCase();
|
|
269
|
+
const mimeTypes: Record<string, string> = {
|
|
270
|
+
jpg: 'image/jpeg',
|
|
271
|
+
jpeg: 'image/jpeg',
|
|
272
|
+
png: 'image/png',
|
|
273
|
+
gif: 'image/gif',
|
|
274
|
+
webp: 'image/webp',
|
|
275
|
+
svg: 'image/svg+xml',
|
|
276
|
+
bmp: 'image/bmp',
|
|
277
|
+
};
|
|
278
|
+
return mimeTypes[ext ?? ''] ?? 'image/png';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function guessAudioMimeType(url: string): string {
|
|
282
|
+
const ext = url.split('.').pop()?.toLowerCase();
|
|
283
|
+
const mimeTypes: Record<string, string> = {
|
|
284
|
+
mp3: 'audio/mpeg',
|
|
285
|
+
wav: 'audio/wav',
|
|
286
|
+
ogg: 'audio/ogg',
|
|
287
|
+
flac: 'audio/flac',
|
|
288
|
+
aac: 'audio/aac',
|
|
289
|
+
m4a: 'audio/mp4',
|
|
290
|
+
};
|
|
291
|
+
return mimeTypes[ext ?? ''] ?? 'audio/mpeg';
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function guessVideoMimeType(url: string): string {
|
|
295
|
+
const ext = url.split('.').pop()?.toLowerCase();
|
|
296
|
+
const mimeTypes: Record<string, string> = {
|
|
297
|
+
mp4: 'video/mp4',
|
|
298
|
+
webm: 'video/webm',
|
|
299
|
+
mov: 'video/quicktime',
|
|
300
|
+
avi: 'video/x-msvideo',
|
|
301
|
+
mkv: 'video/x-matroska',
|
|
302
|
+
};
|
|
303
|
+
return mimeTypes[ext ?? ''] ?? 'video/mp4';
|
|
304
|
+
}
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI entry point for Agent Framework
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { VERSION } from '../index.js';
|
|
9
|
+
|
|
10
|
+
const program = new Command();
|
|
11
|
+
|
|
12
|
+
program
|
|
13
|
+
.name('agent-framework')
|
|
14
|
+
.description('CLI for Agent Framework - A production-grade TypeScript agent framework')
|
|
15
|
+
.version(VERSION);
|
|
16
|
+
|
|
17
|
+
// Create agent command
|
|
18
|
+
program
|
|
19
|
+
.command('create')
|
|
20
|
+
.description('Create a new agent project')
|
|
21
|
+
.argument('<name>', 'Project name')
|
|
22
|
+
.option('-t, --template <template>', 'Project template', 'basic')
|
|
23
|
+
.option('-d, --directory <directory>', 'Target directory')
|
|
24
|
+
.action(async (name, options) => {
|
|
25
|
+
console.log(`Creating new agent project: ${name}`);
|
|
26
|
+
console.log(`Template: ${options.template}`);
|
|
27
|
+
console.log(`Directory: ${options.directory ?? name}`);
|
|
28
|
+
// TODO: Implement project scaffolding
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Run agent command
|
|
32
|
+
program
|
|
33
|
+
.command('run')
|
|
34
|
+
.description('Run an agent')
|
|
35
|
+
.argument('<file>', 'Agent file path')
|
|
36
|
+
.option('-i, --input <input>', 'Input prompt')
|
|
37
|
+
.option('-w, --watch', 'Watch for changes', false)
|
|
38
|
+
.action(async (file, options) => {
|
|
39
|
+
console.log(`Running agent: ${file}`);
|
|
40
|
+
if (options.input) {
|
|
41
|
+
console.log(`Input: ${options.input}`);
|
|
42
|
+
}
|
|
43
|
+
// TODO: Implement agent runner
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Test command
|
|
47
|
+
program
|
|
48
|
+
.command('test')
|
|
49
|
+
.description('Run agent tests')
|
|
50
|
+
.argument('[pattern]', 'Test file pattern')
|
|
51
|
+
.option('-w, --watch', 'Watch mode', false)
|
|
52
|
+
.option('-c, --coverage', 'Generate coverage report', false)
|
|
53
|
+
.action(async (pattern, _options) => {
|
|
54
|
+
console.log('Running tests...');
|
|
55
|
+
if (pattern) {
|
|
56
|
+
console.log(`Pattern: ${pattern}`);
|
|
57
|
+
}
|
|
58
|
+
// TODO: Implement test runner
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Validate command
|
|
62
|
+
program
|
|
63
|
+
.command('validate')
|
|
64
|
+
.description('Validate agent configuration')
|
|
65
|
+
.argument('<file>', 'Configuration file path')
|
|
66
|
+
.action(async (file) => {
|
|
67
|
+
console.log(`Validating: ${file}`);
|
|
68
|
+
// TODO: Implement validation
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Plan command
|
|
72
|
+
program
|
|
73
|
+
.command('plan')
|
|
74
|
+
.description('Generate execution plan for a goal')
|
|
75
|
+
.argument('<goal>', 'Goal to plan')
|
|
76
|
+
.option('-p, --planner <planner>', 'Planner type', 'classical')
|
|
77
|
+
.option('-o, --output <output>', 'Output file')
|
|
78
|
+
.action(async (goal, options) => {
|
|
79
|
+
console.log(`Planning: ${goal}`);
|
|
80
|
+
console.log(`Planner: ${options.planner}`);
|
|
81
|
+
// TODO: Implement plan generation
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Execute command
|
|
85
|
+
program
|
|
86
|
+
.command('execute')
|
|
87
|
+
.description('Execute a plan')
|
|
88
|
+
.argument('<file>', 'Plan file path')
|
|
89
|
+
.option('-p, --parallel', 'Enable parallel execution', false)
|
|
90
|
+
.option('-c, --concurrency <number>', 'Max concurrency', '4')
|
|
91
|
+
.action(async (file, options) => {
|
|
92
|
+
console.log(`Executing plan: ${file}`);
|
|
93
|
+
console.log(`Parallel: ${options.parallel}`);
|
|
94
|
+
console.log(`Concurrency: ${options.concurrency}`);
|
|
95
|
+
// TODO: Implement plan execution
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// List templates command
|
|
99
|
+
program
|
|
100
|
+
.command('list-templates')
|
|
101
|
+
.description('List available project templates')
|
|
102
|
+
.action(() => {
|
|
103
|
+
console.log('Available templates:');
|
|
104
|
+
console.log(' - basic: Simple agent with minimal setup');
|
|
105
|
+
console.log(' - advanced: Agent with memory, tools, and planning');
|
|
106
|
+
console.log(' - multi-agent: Multi-agent orchestration setup');
|
|
107
|
+
console.log(' - workflow: Workflow-based agent system');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Doctor command
|
|
111
|
+
program
|
|
112
|
+
.command('doctor')
|
|
113
|
+
.description('Check environment and dependencies')
|
|
114
|
+
.action(() => {
|
|
115
|
+
console.log('Checking environment...');
|
|
116
|
+
console.log(`Node.js version: ${process.version}`);
|
|
117
|
+
console.log(`Platform: ${process.platform}`);
|
|
118
|
+
console.log(`Architecture: ${process.arch}`);
|
|
119
|
+
// TODO: Implement environment checks
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
program.parse();
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base agent implementation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Agent,
|
|
7
|
+
AgentConfig,
|
|
8
|
+
AgentContext,
|
|
9
|
+
AgentInput,
|
|
10
|
+
AgentOutput,
|
|
11
|
+
AgentState,
|
|
12
|
+
ExecutionMetadata,
|
|
13
|
+
} from './types.js';
|
|
14
|
+
import { DebugLogger, createDebugLogger } from '../debug-logger.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Abstract base class providing common agent functionality
|
|
18
|
+
*/
|
|
19
|
+
export abstract class BaseAgent extends Agent {
|
|
20
|
+
protected startTime?: Date;
|
|
21
|
+
protected iterationCount = 0;
|
|
22
|
+
protected logger: DebugLogger;
|
|
23
|
+
|
|
24
|
+
constructor(config: AgentConfig) {
|
|
25
|
+
super(config);
|
|
26
|
+
this.logger = createDebugLogger(`Agent:${this.name}`, config.debug ?? false);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Main execution method with lifecycle hooks
|
|
31
|
+
*/
|
|
32
|
+
async run(input: AgentInput, ctx: AgentContext): Promise<AgentOutput> {
|
|
33
|
+
this.startTime = new Date();
|
|
34
|
+
this.iterationCount = 0;
|
|
35
|
+
|
|
36
|
+
this.logger.logStart('Agent execution', {
|
|
37
|
+
agentId: this.id,
|
|
38
|
+
prompt: input.prompt.slice(0, 100),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// Before execution hook
|
|
43
|
+
if (this.hooks.beforeExecution) {
|
|
44
|
+
this.logger.debug('Running beforeExecution hook');
|
|
45
|
+
await this.hooks.beforeExecution(input, ctx);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Set state to planning
|
|
49
|
+
this.logger.logStateChange('Agent', this.state, AgentState.PLANNING);
|
|
50
|
+
await this.setState(AgentState.PLANNING, ctx);
|
|
51
|
+
|
|
52
|
+
// Execute the agent-specific logic
|
|
53
|
+
this.logger.debug('Executing agent logic');
|
|
54
|
+
const result = await this.execute(input, ctx);
|
|
55
|
+
|
|
56
|
+
// Set state to completed
|
|
57
|
+
this.logger.logStateChange('Agent', this.state, AgentState.COMPLETED);
|
|
58
|
+
await this.setState(AgentState.COMPLETED, ctx);
|
|
59
|
+
|
|
60
|
+
const output = this.createOutput(result, AgentState.COMPLETED);
|
|
61
|
+
|
|
62
|
+
// After execution hook
|
|
63
|
+
if (this.hooks.afterExecution) {
|
|
64
|
+
this.logger.debug('Running afterExecution hook');
|
|
65
|
+
await this.hooks.afterExecution(output, ctx);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.logger.logComplete('Agent execution', output.metadata?.durationMs);
|
|
69
|
+
return output;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
// Set state to failed
|
|
72
|
+
this.logger.logStateChange('Agent', this.state, AgentState.FAILED);
|
|
73
|
+
await this.setState(AgentState.FAILED, ctx);
|
|
74
|
+
|
|
75
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
76
|
+
this.logger.error('Agent execution failed', undefined, { error: errorMessage });
|
|
77
|
+
|
|
78
|
+
const errorOutput = this.createOutput(errorMessage, AgentState.FAILED);
|
|
79
|
+
|
|
80
|
+
// Error hook
|
|
81
|
+
if (this.hooks.onError) {
|
|
82
|
+
await this.hooks.onError(error instanceof Error ? error : new Error(errorMessage), ctx);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return errorOutput;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Execute the agent's core logic - must be implemented by subclasses
|
|
91
|
+
*/
|
|
92
|
+
protected abstract execute(input: AgentInput, ctx: AgentContext): Promise<unknown>;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Increment iteration counter
|
|
96
|
+
*/
|
|
97
|
+
protected incrementIteration(): void {
|
|
98
|
+
this.iterationCount++;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Check if max iterations reached
|
|
103
|
+
*/
|
|
104
|
+
protected isMaxIterationsReached(): boolean {
|
|
105
|
+
if (!this.config.maxIterations) return false;
|
|
106
|
+
return this.iterationCount >= this.config.maxIterations;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Create an agent output with metadata
|
|
111
|
+
*/
|
|
112
|
+
protected createOutput(result: unknown, state: AgentState): AgentOutput {
|
|
113
|
+
const endTime = new Date();
|
|
114
|
+
const startTime = this.startTime ?? endTime;
|
|
115
|
+
const durationMs = endTime.getTime() - startTime.getTime();
|
|
116
|
+
|
|
117
|
+
const metadata: ExecutionMetadata = {
|
|
118
|
+
startTime,
|
|
119
|
+
endTime,
|
|
120
|
+
durationMs,
|
|
121
|
+
iterations: this.iterationCount,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
result,
|
|
126
|
+
state,
|
|
127
|
+
metadata,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Check if agent is currently executing
|
|
133
|
+
*/
|
|
134
|
+
isExecuting(): boolean {
|
|
135
|
+
return this.state === AgentState.EXECUTING || this.state === AgentState.PLANNING;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Check if agent has completed
|
|
140
|
+
*/
|
|
141
|
+
isCompleted(): boolean {
|
|
142
|
+
return this.state === AgentState.COMPLETED;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Check if agent has failed
|
|
147
|
+
*/
|
|
148
|
+
hasFailed(): boolean {
|
|
149
|
+
return this.state === AgentState.FAILED;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent context builder for fluent context creation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
AgentContext,
|
|
7
|
+
EntityId,
|
|
8
|
+
} from './types.js';
|
|
9
|
+
import type { MemoryStore } from '../memory/types.js';
|
|
10
|
+
import type { ToolRegistry } from '../tools/types.js';
|
|
11
|
+
import type { Planner } from '../planner/types.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Builder for creating AgentContext instances
|
|
15
|
+
*/
|
|
16
|
+
export class AgentContextBuilder {
|
|
17
|
+
private agentId: EntityId = `agent-${Date.now()}`;
|
|
18
|
+
private memory?: MemoryStore;
|
|
19
|
+
private tools?: ToolRegistry;
|
|
20
|
+
private planner?: Planner;
|
|
21
|
+
private metadata: Record<string, unknown> = {};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Set the agent ID
|
|
25
|
+
*/
|
|
26
|
+
withAgentId(agentId: EntityId): this {
|
|
27
|
+
this.agentId = agentId;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set the memory store
|
|
33
|
+
*/
|
|
34
|
+
withMemory(memory: MemoryStore): this {
|
|
35
|
+
this.memory = memory;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Set the tool registry
|
|
41
|
+
*/
|
|
42
|
+
withTools(tools: ToolRegistry): this {
|
|
43
|
+
this.tools = tools;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Set the planner
|
|
49
|
+
*/
|
|
50
|
+
withPlanner(planner: Planner): this {
|
|
51
|
+
this.planner = planner;
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Add metadata
|
|
57
|
+
*/
|
|
58
|
+
withMetadata(key: string, value: unknown): this {
|
|
59
|
+
this.metadata[key] = value;
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Add multiple metadata entries
|
|
65
|
+
*/
|
|
66
|
+
withMetadataEntries(entries: Record<string, unknown>): this {
|
|
67
|
+
this.metadata = { ...this.metadata, ...entries };
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Build the AgentContext
|
|
73
|
+
*/
|
|
74
|
+
build(): AgentContext {
|
|
75
|
+
if (!this.memory) {
|
|
76
|
+
throw new Error('Memory store is required');
|
|
77
|
+
}
|
|
78
|
+
if (!this.tools) {
|
|
79
|
+
throw new Error('Tool registry is required');
|
|
80
|
+
}
|
|
81
|
+
if (!this.planner) {
|
|
82
|
+
throw new Error('Planner is required');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
agentId: this.agentId,
|
|
87
|
+
memory: this.memory,
|
|
88
|
+
tools: this.tools,
|
|
89
|
+
planner: this.planner,
|
|
90
|
+
metadata: { ...this.metadata },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Create a builder from an existing context
|
|
96
|
+
*/
|
|
97
|
+
static fromContext(context: AgentContext): AgentContextBuilder {
|
|
98
|
+
const builder = new AgentContextBuilder();
|
|
99
|
+
builder.agentId = context.agentId;
|
|
100
|
+
builder.memory = context.memory;
|
|
101
|
+
builder.tools = context.tools;
|
|
102
|
+
builder.planner = context.planner;
|
|
103
|
+
builder.metadata = { ...context.metadata };
|
|
104
|
+
return builder;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe I/O: input_schema and output_schema (Zod) for agent runs.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
/** Input schema for agent run (e.g. prompt + optional structured fields) */
|
|
8
|
+
export type InputSchema<T = unknown> = z.ZodType<T>;
|
|
9
|
+
|
|
10
|
+
/** Output schema for agent run (e.g. structured response) */
|
|
11
|
+
export type OutputSchema<T = unknown> = z.ZodType<T>;
|
|
12
|
+
|
|
13
|
+
/** Parsed input from user when inputSchema is used */
|
|
14
|
+
export type ParsedInput<T> = T;
|
|
15
|
+
|
|
16
|
+
/** Parsed output from agent when outputSchema is used */
|
|
17
|
+
export type ParsedOutput<T> = T;
|