@artemiskit/adapter-deepagents 0.2.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/src/client.ts ADDED
@@ -0,0 +1,392 @@
1
+ /**
2
+ * DeepAgents Adapter
3
+ * Wraps DeepAgents multi-agent systems for ArtemisKit testing
4
+ */
5
+
6
+ import type {
7
+ AdapterConfig,
8
+ GenerateOptions,
9
+ GenerateResult,
10
+ ModelCapabilities,
11
+ ModelClient,
12
+ } from '@artemiskit/core';
13
+ import { nanoid } from 'nanoid';
14
+ import type {
15
+ DeepAgentsAdapterConfig,
16
+ DeepAgentsCallbacks,
17
+ DeepAgentsExecutionMetadata,
18
+ DeepAgentsMessage,
19
+ DeepAgentsOutput,
20
+ DeepAgentsSystem,
21
+ DeepAgentsTrace,
22
+ } from './types';
23
+
24
+ /**
25
+ * Adapter for testing DeepAgents multi-agent systems with ArtemisKit
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * import { DeepAgentsAdapter } from '@artemiskit/adapter-deepagents';
30
+ * import { createTeam } from 'deepagents';
31
+ *
32
+ * // Create a DeepAgents team
33
+ * const team = createTeam({
34
+ * agents: [researcher, writer, editor],
35
+ * workflow: 'sequential',
36
+ * });
37
+ *
38
+ * // Wrap with ArtemisKit adapter
39
+ * const adapter = new DeepAgentsAdapter(
40
+ * { provider: 'deepagents', name: 'content-team' },
41
+ * team
42
+ * );
43
+ *
44
+ * // Use in ArtemisKit tests
45
+ * const result = await adapter.generate({
46
+ * prompt: 'Write an article about AI testing',
47
+ * });
48
+ * ```
49
+ */
50
+ export class DeepAgentsAdapter implements ModelClient {
51
+ private system: DeepAgentsSystem;
52
+ private config: DeepAgentsAdapterConfig;
53
+ readonly provider = 'deepagents';
54
+
55
+ // Execution tracking
56
+ private traces: DeepAgentsTrace[] = [];
57
+ private messages: DeepAgentsMessage[] = [];
58
+
59
+ constructor(config: AdapterConfig, system: DeepAgentsSystem) {
60
+ this.config = config as DeepAgentsAdapterConfig;
61
+ this.system = system;
62
+ this.validateSystem(system);
63
+ }
64
+
65
+ /**
66
+ * Validate that the system has a usable execution method
67
+ */
68
+ private validateSystem(system: DeepAgentsSystem): void {
69
+ const hasMethod =
70
+ typeof system.invoke === 'function' ||
71
+ typeof system.run === 'function' ||
72
+ typeof system.execute === 'function';
73
+
74
+ if (!hasMethod) {
75
+ throw new Error('DeepAgents system must have an invoke(), run(), or execute() method');
76
+ }
77
+ }
78
+
79
+ async generate(options: GenerateOptions): Promise<GenerateResult> {
80
+ const startTime = Date.now();
81
+
82
+ // Reset tracking for this execution
83
+ this.traces = [];
84
+ this.messages = [];
85
+
86
+ // Prepare input
87
+ const input = this.prepareInput(options);
88
+
89
+ // Create callbacks for tracking if enabled
90
+ const callbacks = this.createCallbacks();
91
+
92
+ // Execute the system
93
+ const execConfig = {
94
+ timeout: this.config.executionTimeout ?? 300000,
95
+ callbacks,
96
+ };
97
+
98
+ const response = await this.executeSystem(input, execConfig);
99
+
100
+ const latencyMs = Date.now() - startTime;
101
+
102
+ // Extract output
103
+ const text = this.extractOutput(response);
104
+
105
+ // Build metadata
106
+ const metadata = this.extractMetadata(response);
107
+
108
+ // Extract token usage if available
109
+ const tokens = {
110
+ prompt: response.tokenUsage?.prompt ?? 0,
111
+ completion: response.tokenUsage?.completion ?? 0,
112
+ total: response.tokenUsage?.total ?? 0,
113
+ };
114
+
115
+ return {
116
+ id: nanoid(),
117
+ model: this.config.name || 'deepagents:system',
118
+ text,
119
+ tokens,
120
+ latencyMs,
121
+ finishReason: 'stop',
122
+ raw: {
123
+ response,
124
+ metadata,
125
+ },
126
+ };
127
+ }
128
+
129
+ /**
130
+ * Execute the DeepAgents system using available method
131
+ */
132
+ private async executeSystem(
133
+ input: Record<string, unknown>,
134
+ config: Record<string, unknown>
135
+ ): Promise<DeepAgentsOutput> {
136
+ // Try methods in order of preference
137
+ if (typeof this.system.invoke === 'function') {
138
+ return this.system.invoke(input, config);
139
+ }
140
+ if (typeof this.system.run === 'function') {
141
+ return this.system.run(input, config);
142
+ }
143
+ if (typeof this.system.execute === 'function') {
144
+ return this.system.execute(input, config);
145
+ }
146
+
147
+ throw new Error('No execution method available on DeepAgents system');
148
+ }
149
+
150
+ async *stream(options: GenerateOptions, onChunk: (chunk: string) => void): AsyncIterable<string> {
151
+ if (!this.system.stream) {
152
+ // Fallback to non-streaming
153
+ const result = await this.generate(options);
154
+ onChunk(result.text);
155
+ yield result.text;
156
+ return;
157
+ }
158
+
159
+ // Reset tracking
160
+ this.traces = [];
161
+ this.messages = [];
162
+
163
+ const input = this.prepareInput(options);
164
+ const stream = this.system.stream(input, {
165
+ timeout: this.config.executionTimeout ?? 300000,
166
+ });
167
+
168
+ for await (const event of stream) {
169
+ // Track events
170
+ if (event.type === 'agent_start' || event.type === 'agent_end') {
171
+ this.traces.push({
172
+ agent: event.agent || 'unknown',
173
+ action: event.type,
174
+ output: event.data,
175
+ timestamp: event.timestamp || Date.now(),
176
+ });
177
+ }
178
+
179
+ if (event.type === 'message' && event.data) {
180
+ const msgData = event.data as DeepAgentsMessage;
181
+ this.messages.push(msgData);
182
+ }
183
+
184
+ // Emit text content
185
+ if (event.type === 'token' && event.content) {
186
+ onChunk(event.content);
187
+ yield event.content;
188
+ }
189
+ }
190
+ }
191
+
192
+ async capabilities(): Promise<ModelCapabilities> {
193
+ return {
194
+ streaming: typeof this.system.stream === 'function',
195
+ functionCalling: true, // Multi-agent systems typically use tools
196
+ toolUse: true,
197
+ maxContext: 128000, // Varies by underlying models
198
+ vision: false, // Depends on underlying agents
199
+ jsonMode: false,
200
+ };
201
+ }
202
+
203
+ async close(): Promise<void> {
204
+ // No cleanup needed for most DeepAgents systems
205
+ }
206
+
207
+ /**
208
+ * Prepare input for the DeepAgents system
209
+ */
210
+ private prepareInput(options: GenerateOptions): Record<string, unknown> {
211
+ // Handle string prompts
212
+ if (typeof options.prompt === 'string') {
213
+ return {
214
+ task: options.prompt,
215
+ query: options.prompt,
216
+ input: options.prompt,
217
+ };
218
+ }
219
+
220
+ // Handle chat message array
221
+ const messages = options.prompt;
222
+ const lastUserMessage = messages.findLast((m) => m.role === 'user');
223
+ const systemMessage = messages.find((m) => m.role === 'system');
224
+
225
+ const input: Record<string, unknown> = {
226
+ task: lastUserMessage?.content || '',
227
+ query: lastUserMessage?.content || '',
228
+ input: lastUserMessage?.content || '',
229
+ };
230
+
231
+ if (systemMessage) {
232
+ input.context = { systemPrompt: systemMessage.content };
233
+ }
234
+
235
+ // Include full message history for context
236
+ input.messages = messages.map((m) => ({
237
+ role: m.role,
238
+ content: m.content,
239
+ }));
240
+
241
+ return input;
242
+ }
243
+
244
+ /**
245
+ * Extract text output from DeepAgents response
246
+ */
247
+ private extractOutput(response: DeepAgentsOutput): string {
248
+ // Check common output keys
249
+ const possibleKeys = ['result', 'output', 'response', 'answer', 'content'];
250
+
251
+ for (const key of possibleKeys) {
252
+ const value = response[key];
253
+ if (typeof value === 'string') {
254
+ return value;
255
+ }
256
+ }
257
+
258
+ // If we have traces, use the last agent's output
259
+ if (response.traces?.length) {
260
+ const lastTrace = response.traces[response.traces.length - 1];
261
+ if (lastTrace.output) {
262
+ return typeof lastTrace.output === 'string'
263
+ ? lastTrace.output
264
+ : JSON.stringify(lastTrace.output);
265
+ }
266
+ }
267
+
268
+ // Fallback to JSON
269
+ return JSON.stringify(response);
270
+ }
271
+
272
+ /**
273
+ * Create callbacks for execution tracking
274
+ */
275
+ private createCallbacks(): DeepAgentsCallbacks {
276
+ const callbacks: DeepAgentsCallbacks = {};
277
+
278
+ if (this.config.captureTraces !== false) {
279
+ callbacks.onAgentStart = (agent, input) => {
280
+ this.traces.push({
281
+ agent,
282
+ action: 'start',
283
+ input,
284
+ timestamp: Date.now(),
285
+ });
286
+ };
287
+
288
+ callbacks.onAgentEnd = (agent, output) => {
289
+ this.traces.push({
290
+ agent,
291
+ action: 'end',
292
+ output,
293
+ timestamp: Date.now(),
294
+ });
295
+ };
296
+
297
+ callbacks.onToolUse = (agent, tool, input) => {
298
+ this.traces.push({
299
+ agent,
300
+ action: 'tool_use',
301
+ input: { tool, toolInput: input },
302
+ toolsUsed: [tool],
303
+ timestamp: Date.now(),
304
+ });
305
+ };
306
+ }
307
+
308
+ if (this.config.captureMessages !== false) {
309
+ callbacks.onMessage = (from, to, message) => {
310
+ this.messages.push({
311
+ from,
312
+ to,
313
+ content: typeof message === 'string' ? message : JSON.stringify(message),
314
+ timestamp: Date.now(),
315
+ });
316
+ };
317
+ }
318
+
319
+ return callbacks;
320
+ }
321
+
322
+ /**
323
+ * Extract execution metadata
324
+ */
325
+ private extractMetadata(response: DeepAgentsOutput): DeepAgentsExecutionMetadata {
326
+ // Combine response traces with our tracked traces
327
+ const allTraces = [...(response.traces || []), ...this.traces];
328
+ const allMessages = [...(response.messages || []), ...this.messages];
329
+
330
+ // Extract unique agents
331
+ const agentsSet = new Set<string>();
332
+ for (const trace of allTraces) {
333
+ agentsSet.add(trace.agent);
334
+ }
335
+ for (const msg of allMessages) {
336
+ agentsSet.add(msg.from);
337
+ agentsSet.add(msg.to);
338
+ }
339
+ if (response.agents) {
340
+ for (const agent of response.agents) {
341
+ agentsSet.add(agent);
342
+ }
343
+ }
344
+
345
+ // Extract tools used
346
+ const toolsSet = new Set<string>();
347
+ let toolCallCount = 0;
348
+ for (const trace of allTraces) {
349
+ if (trace.toolsUsed) {
350
+ for (const tool of trace.toolsUsed) {
351
+ toolsSet.add(tool);
352
+ }
353
+ toolCallCount += trace.toolsUsed.length;
354
+ }
355
+ }
356
+
357
+ return {
358
+ name: this.config.name,
359
+ agentsInvolved: Array.from(agentsSet),
360
+ totalAgentCalls: allTraces.filter((t) => t.action === 'start' || t.action === 'end').length,
361
+ totalMessages: allMessages.length,
362
+ totalToolCalls: toolCallCount,
363
+ toolsUsed: Array.from(toolsSet),
364
+ traces: this.config.captureTraces !== false ? allTraces : undefined,
365
+ messages: this.config.captureMessages !== false ? allMessages : undefined,
366
+ executionTimeMs: response.executionTimeMs,
367
+ };
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Factory function to create a DeepAgents adapter
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * const adapter = createDeepAgentsAdapter(myTeam, {
377
+ * name: 'research-team',
378
+ * captureTraces: true,
379
+ * });
380
+ * ```
381
+ */
382
+ export function createDeepAgentsAdapter(
383
+ system: DeepAgentsSystem,
384
+ options?: Partial<DeepAgentsAdapterConfig>
385
+ ): DeepAgentsAdapter {
386
+ const config: DeepAgentsAdapterConfig = {
387
+ provider: 'deepagents',
388
+ ...options,
389
+ };
390
+
391
+ return new DeepAgentsAdapter(config, system);
392
+ }
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @artemiskit/adapter-deepagents
3
+ *
4
+ * DeepAgents.js adapter for ArtemisKit LLM evaluation toolkit.
5
+ * Enables testing of DeepAgents multi-agent systems.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { createDeepAgentsAdapter } from '@artemiskit/adapter-deepagents';
10
+ * import { createTeam } from 'deepagents';
11
+ *
12
+ * const team = createTeam({ agents: [researcher, writer] });
13
+ * const adapter = createDeepAgentsAdapter(team, { name: 'content-team' });
14
+ *
15
+ * // Use with ArtemisKit
16
+ * const result = await adapter.generate({ prompt: 'Create content' });
17
+ * ```
18
+ */
19
+
20
+ export { DeepAgentsAdapter, createDeepAgentsAdapter } from './client';
21
+ export type {
22
+ DeepAgentsAdapterConfig,
23
+ DeepAgentsSystem,
24
+ DeepAgentsInput,
25
+ DeepAgentsOutput,
26
+ DeepAgentsConfig,
27
+ DeepAgentsTrace,
28
+ DeepAgentsMessage,
29
+ DeepAgentsStreamEvent,
30
+ DeepAgentsCallbacks,
31
+ DeepAgentsExecutionMetadata,
32
+ } from './types';
package/src/types.ts ADDED
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Types for DeepAgents adapter
3
+ */
4
+
5
+ import type { BaseAdapterConfig } from '@artemiskit/core';
6
+
7
+ /**
8
+ * Configuration for DeepAgents adapter
9
+ */
10
+ export interface DeepAgentsAdapterConfig extends BaseAdapterConfig {
11
+ provider: 'deepagents';
12
+ /**
13
+ * Name identifier for the agent system (for logging/tracking)
14
+ */
15
+ name?: string;
16
+ /**
17
+ * Whether to capture agent traces and execution history
18
+ * @default true
19
+ */
20
+ captureTraces?: boolean;
21
+ /**
22
+ * Whether to capture inter-agent messages
23
+ * @default true
24
+ */
25
+ captureMessages?: boolean;
26
+ /**
27
+ * Maximum execution time in milliseconds
28
+ * @default 300000 (5 minutes)
29
+ */
30
+ executionTimeout?: number;
31
+ /**
32
+ * Custom input transformer function name
33
+ */
34
+ inputTransformer?: string;
35
+ /**
36
+ * Custom output transformer function name
37
+ */
38
+ outputTransformer?: string;
39
+ }
40
+
41
+ /**
42
+ * Generic interface for DeepAgents systems
43
+ * Supports multi-agent orchestration with invoke() or run() methods
44
+ */
45
+ export interface DeepAgentsSystem {
46
+ invoke?(input: DeepAgentsInput, config?: DeepAgentsConfig): Promise<DeepAgentsOutput>;
47
+ run?(input: DeepAgentsInput, config?: DeepAgentsConfig): Promise<DeepAgentsOutput>;
48
+ execute?(input: DeepAgentsInput, config?: DeepAgentsConfig): Promise<DeepAgentsOutput>;
49
+ stream?(input: DeepAgentsInput, config?: DeepAgentsConfig): AsyncIterable<DeepAgentsStreamEvent>;
50
+ }
51
+
52
+ /**
53
+ * Input format for DeepAgents systems
54
+ */
55
+ export interface DeepAgentsInput {
56
+ /** The main task/query to process */
57
+ task?: string;
58
+ query?: string;
59
+ input?: string;
60
+ message?: string;
61
+ /** Optional context/memory from previous interactions */
62
+ context?: Record<string, unknown>;
63
+ /** Optional metadata */
64
+ metadata?: Record<string, unknown>;
65
+ [key: string]: unknown;
66
+ }
67
+
68
+ /**
69
+ * Configuration for DeepAgents execution
70
+ */
71
+ export interface DeepAgentsConfig {
72
+ /** Maximum iterations for agent loops */
73
+ maxIterations?: number;
74
+ /** Timeout in milliseconds */
75
+ timeout?: number;
76
+ /** Enable verbose logging */
77
+ verbose?: boolean;
78
+ /** Callback handlers */
79
+ callbacks?: DeepAgentsCallbacks;
80
+ [key: string]: unknown;
81
+ }
82
+
83
+ /**
84
+ * Callback handlers for DeepAgents execution
85
+ */
86
+ export interface DeepAgentsCallbacks {
87
+ onAgentStart?: (agent: string, input: unknown) => void;
88
+ onAgentEnd?: (agent: string, output: unknown) => void;
89
+ onMessage?: (from: string, to: string, message: unknown) => void;
90
+ onToolUse?: (agent: string, tool: string, input: unknown) => void;
91
+ onError?: (agent: string, error: Error) => void;
92
+ }
93
+
94
+ /**
95
+ * Output from DeepAgents system execution
96
+ */
97
+ export interface DeepAgentsOutput {
98
+ /** Main result/output */
99
+ result?: string;
100
+ output?: string;
101
+ response?: string;
102
+ answer?: string;
103
+ /** Execution traces from agents */
104
+ traces?: DeepAgentsTrace[];
105
+ /** Messages exchanged between agents */
106
+ messages?: DeepAgentsMessage[];
107
+ /** Agents that participated in the execution */
108
+ agents?: string[];
109
+ /** Total execution time */
110
+ executionTimeMs?: number;
111
+ /** Token usage if available */
112
+ tokenUsage?: {
113
+ prompt?: number;
114
+ completion?: number;
115
+ total?: number;
116
+ };
117
+ /** Raw response data */
118
+ [key: string]: unknown;
119
+ }
120
+
121
+ /**
122
+ * Trace of a single agent's execution
123
+ */
124
+ export interface DeepAgentsTrace {
125
+ /** Agent identifier */
126
+ agent: string;
127
+ /** Action taken by the agent */
128
+ action: string;
129
+ /** Input to the action */
130
+ input?: unknown;
131
+ /** Output/result of the action */
132
+ output?: unknown;
133
+ /** Timestamp */
134
+ timestamp?: number;
135
+ /** Duration in milliseconds */
136
+ durationMs?: number;
137
+ /** Tools used during this action */
138
+ toolsUsed?: string[];
139
+ }
140
+
141
+ /**
142
+ * Message exchanged between agents
143
+ */
144
+ export interface DeepAgentsMessage {
145
+ /** Sender agent */
146
+ from: string;
147
+ /** Recipient agent */
148
+ to: string;
149
+ /** Message content */
150
+ content: string;
151
+ /** Message type */
152
+ type?: 'request' | 'response' | 'broadcast' | 'delegation';
153
+ /** Timestamp */
154
+ timestamp?: number;
155
+ }
156
+
157
+ /**
158
+ * Streaming event from DeepAgents
159
+ */
160
+ export interface DeepAgentsStreamEvent {
161
+ /** Event type */
162
+ type: 'agent_start' | 'agent_end' | 'message' | 'tool_use' | 'token' | 'error' | 'done';
163
+ /** Agent involved */
164
+ agent?: string;
165
+ /** Event data */
166
+ data?: unknown;
167
+ /** Text content (for token events) */
168
+ content?: string;
169
+ /** Timestamp */
170
+ timestamp?: number;
171
+ }
172
+
173
+ /**
174
+ * Metadata extracted from DeepAgents execution
175
+ */
176
+ export interface DeepAgentsExecutionMetadata {
177
+ /** System/workflow name */
178
+ name?: string;
179
+ /** Agents that participated */
180
+ agentsInvolved: string[];
181
+ /** Total agent invocations */
182
+ totalAgentCalls: number;
183
+ /** Total messages exchanged */
184
+ totalMessages: number;
185
+ /** Total tool calls across all agents */
186
+ totalToolCalls: number;
187
+ /** Unique tools used */
188
+ toolsUsed: string[];
189
+ /** Execution traces */
190
+ traces?: DeepAgentsTrace[];
191
+ /** Messages log */
192
+ messages?: DeepAgentsMessage[];
193
+ /** Total execution time */
194
+ executionTimeMs?: number;
195
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "noEmit": false,
9
+ "emitDeclarationOnly": true
10
+ },
11
+ "include": ["src/**/*"],
12
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
13
+ }