@amitdeshmukh/ax-crew 5.0.0 → 6.0.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/CHANGELOG.md +22 -0
- package/README.md +7 -59
- package/dist/agents/agentConfig.d.ts +6 -6
- package/dist/agents/agentConfig.js +41 -122
- package/dist/agents/compose.d.ts +15 -0
- package/dist/agents/compose.js +58 -0
- package/dist/agents/index.d.ts +20 -4
- package/dist/agents/index.js +19 -3
- package/dist/functions/index.d.ts +11 -0
- package/dist/functions/index.js +11 -1
- package/dist/index.d.ts +25 -8
- package/dist/index.js +26 -1
- package/dist/types.d.ts +40 -6
- package/examples/basic-researcher-writer.ts +5 -3
- package/examples/mcp-agent.ts +20 -43
- package/examples/perplexityDeepSearch.ts +6 -5
- package/examples/providerArgs.ts +2 -1
- package/examples/search-tweets.ts +5 -4
- package/examples/solve-math-problem.ts +7 -5
- package/examples/streaming.ts +2 -2
- package/package.json +4 -4
- package/src/agents/agentConfig.ts +46 -140
- package/src/agents/compose.ts +80 -0
- package/src/agents/index.ts +22 -6
- package/src/functions/index.ts +11 -1
- package/src/index.ts +25 -11
- package/src/types.ts +44 -21
- package/dist/config/index.d.ts +0 -5
- package/dist/config/index.js +0 -30
- package/src/config/index.ts +0 -40
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ai } from '@ax-llm/ax';
|
|
2
|
+
import type { AxAI } from '@ax-llm/ax';
|
|
3
|
+
import type { AxCrewConfig } from '../types.js';
|
|
4
|
+
|
|
5
|
+
type BuildProviderArgs = {
|
|
6
|
+
provider: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
config: any;
|
|
9
|
+
apiURL?: string;
|
|
10
|
+
providerArgs?: Record<string, unknown>;
|
|
11
|
+
options?: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function instantiateProvider({
|
|
15
|
+
provider,
|
|
16
|
+
apiKey,
|
|
17
|
+
config,
|
|
18
|
+
apiURL,
|
|
19
|
+
providerArgs,
|
|
20
|
+
options,
|
|
21
|
+
}: BuildProviderArgs): AxAI<any> {
|
|
22
|
+
const args: any = { name: provider as any, apiKey, config, options };
|
|
23
|
+
if (apiURL) args.apiURL = apiURL;
|
|
24
|
+
if (providerArgs && typeof providerArgs === 'object') Object.assign(args, providerArgs);
|
|
25
|
+
return ai(args) as unknown as AxAI<any>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function buildProvidersFromConfig(cfg: AxCrewConfig): AxAI<any>[] {
|
|
29
|
+
const services: AxAI<any>[] = [];
|
|
30
|
+
for (const agent of cfg.crew) {
|
|
31
|
+
const apiKeyName = agent.providerKeyName;
|
|
32
|
+
if (!apiKeyName) throw new Error(`Provider key name is missing for agent ${agent.name}`);
|
|
33
|
+
const apiKey = resolveApiKey(apiKeyName) || '';
|
|
34
|
+
if (!apiKey) throw new Error(`API key '${apiKeyName}' not set for agent ${agent.name}`);
|
|
35
|
+
|
|
36
|
+
const service = instantiateProvider({
|
|
37
|
+
provider: String(agent.provider).toLowerCase(),
|
|
38
|
+
apiKey,
|
|
39
|
+
config: agent.ai,
|
|
40
|
+
apiURL: agent.apiURL,
|
|
41
|
+
providerArgs: (agent as any).providerArgs,
|
|
42
|
+
options: agent.options,
|
|
43
|
+
});
|
|
44
|
+
services.push(service);
|
|
45
|
+
}
|
|
46
|
+
return services;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
// Provider discovery helpers consolidated here (previously in src/providers.ts)
|
|
51
|
+
export function discoverProvidersFromConfig(cfg: AxCrewConfig): string[] {
|
|
52
|
+
const providers = new Set<string>();
|
|
53
|
+
for (const agent of cfg.crew) {
|
|
54
|
+
providers.add(String(agent.provider).toLowerCase());
|
|
55
|
+
}
|
|
56
|
+
return Array.from(providers);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function listSelectableProviders(cfg: AxCrewConfig): string[] {
|
|
60
|
+
return discoverProvidersFromConfig(cfg);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function resolveApiKey(varName: string): string | undefined {
|
|
64
|
+
try {
|
|
65
|
+
// Prefer Node env when available
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
if (typeof process !== 'undefined' && process?.env) {
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
return process.env[varName];
|
|
72
|
+
}
|
|
73
|
+
// Fallback: allow global exposure in browser builds (e.g., injected at runtime)
|
|
74
|
+
return (globalThis as any)?.[varName];
|
|
75
|
+
} catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
package/src/agents/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
StateInstance,
|
|
15
15
|
FunctionRegistryType,
|
|
16
16
|
UsageCost,
|
|
17
|
-
|
|
17
|
+
AxCrewConfig,
|
|
18
18
|
MCPTransportConfig,
|
|
19
19
|
} from "../types.js";
|
|
20
20
|
|
|
@@ -260,10 +260,26 @@ class StatefulAxAgent extends AxAgent<any, any> {
|
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
/**
|
|
263
|
-
*
|
|
263
|
+
* AxCrew orchestrates a set of Ax agents that share state,
|
|
264
|
+
* tools (functions), optional MCP servers, streaming, and a built-in metrics
|
|
265
|
+
* registry for tokens, requests, and estimated cost.
|
|
266
|
+
*
|
|
267
|
+
* Typical usage:
|
|
268
|
+
* const crew = new AxCrew(config, AxCrewFunctions)
|
|
269
|
+
* await crew.addAllAgents()
|
|
270
|
+
* const planner = crew.agents?.get("Planner")
|
|
271
|
+
* const res = await planner?.forward({ task: "Plan something" })
|
|
272
|
+
*
|
|
273
|
+
* Key behaviors:
|
|
274
|
+
* - Validates and instantiates agents from a config-first model
|
|
275
|
+
* - Shares a mutable state object across all agents in the crew
|
|
276
|
+
* - Supports sub-agents and a function registry per agent
|
|
277
|
+
* - Tracks per-agent and crew-level metrics via MetricsRegistry
|
|
278
|
+
* - Provides helpers to add agents (individually, a subset, or all) and
|
|
279
|
+
* to reset metrics/costs when needed
|
|
264
280
|
*/
|
|
265
281
|
class AxCrew {
|
|
266
|
-
private crewConfig:
|
|
282
|
+
private crewConfig: AxCrewConfig;
|
|
267
283
|
functionsRegistry: FunctionRegistryType = {};
|
|
268
284
|
crewId: string;
|
|
269
285
|
agents: Map<string, StatefulAxAgent> | null;
|
|
@@ -271,12 +287,12 @@ class AxCrew {
|
|
|
271
287
|
|
|
272
288
|
/**
|
|
273
289
|
* Creates an instance of AxCrew.
|
|
274
|
-
* @param {
|
|
290
|
+
* @param {AxCrewConfig} crewConfig - JSON object with crew configuration.
|
|
275
291
|
* @param {FunctionRegistryType} [functionsRegistry={}] - The registry of functions to use in the crew.
|
|
276
292
|
* @param {string} [crewId=uuidv4()] - The unique identifier for the crew.
|
|
277
293
|
*/
|
|
278
294
|
constructor(
|
|
279
|
-
crewConfig:
|
|
295
|
+
crewConfig: AxCrewConfig,
|
|
280
296
|
functionsRegistry: FunctionRegistryType = {},
|
|
281
297
|
crewId: string = uuidv4()
|
|
282
298
|
) {
|
|
@@ -286,7 +302,7 @@ class AxCrew {
|
|
|
286
302
|
}
|
|
287
303
|
|
|
288
304
|
// Validate each agent in the crew
|
|
289
|
-
crewConfig.crew.forEach(agent => {
|
|
305
|
+
crewConfig.crew.forEach((agent: any) => {
|
|
290
306
|
if (!agent.name || agent.name.trim() === '') {
|
|
291
307
|
throw new Error('Agent name cannot be empty');
|
|
292
308
|
}
|
package/src/functions/index.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { CurrentDateTime, DaysBetweenDates } from './dateTime.js';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Built-in function registry for AxCrew agents.
|
|
5
|
+
*
|
|
6
|
+
* Contains common utility tools/functions that can be referenced by name from
|
|
7
|
+
* agent configs (e.g., "functions": ["CurrentDateTime", "DaysBetweenDates"]).
|
|
8
|
+
* You can pass this object to the AxCrew constructor or merge with your
|
|
9
|
+
* own registry.
|
|
10
|
+
* Example:
|
|
11
|
+
* const crew = new AxCrew(config, AxCrewFunctions); or
|
|
12
|
+
* const crew = new AxCrew(config, { ...AxCrewFunctions, ...myFunctions });
|
|
13
|
+
*/
|
|
4
14
|
const AxCrewFunctions = {
|
|
5
15
|
CurrentDateTime,
|
|
6
16
|
DaysBetweenDates
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AxCrew } from './agents/index.js';
|
|
2
2
|
import { AxCrewFunctions } from './functions/index.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { AxCrewConfig, AgentConfig } from './types.js';
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
6
|
UsageCost,
|
|
@@ -9,28 +9,42 @@ import type {
|
|
|
9
9
|
StateInstance,
|
|
10
10
|
FunctionRegistryType
|
|
11
11
|
} from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Metrics types and helpers for request counts, token usage, and estimated cost.
|
|
14
|
+
*
|
|
15
|
+
* Re-exports the metrics module for convenience:
|
|
16
|
+
* - Types: TokenUsage, MetricsSnapshot, etc.
|
|
17
|
+
* - Namespace: MetricsRegistry (record/snapshot/reset helpers)
|
|
18
|
+
*/
|
|
12
19
|
export * from './metrics/index.js';
|
|
20
|
+
/**
|
|
21
|
+
* MetricsRegistry provides functions to record requests, tokens, and cost,
|
|
22
|
+
* and to snapshot/reset metrics at agent or crew granularity.
|
|
23
|
+
*/
|
|
13
24
|
export { MetricsRegistry } from './metrics/index.js';
|
|
14
25
|
|
|
15
|
-
// Main AxCrew configuration interface
|
|
16
26
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
|
|
27
|
+
* Create and manage a crew of Ax agents that share state and metrics.
|
|
28
|
+
* See the `AxCrew` class for full documentation.
|
|
29
|
+
*/
|
|
30
|
+
const _AxCrew: typeof AxCrew = AxCrew;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Built-in function registry with common tools that can be referenced by name
|
|
34
|
+
* from agent configs, or extended with your own functions.
|
|
20
35
|
*/
|
|
21
|
-
|
|
22
|
-
crew: AgentConfig[];
|
|
23
|
-
}
|
|
36
|
+
const _AxCrewFunctions: typeof AxCrewFunctions = AxCrewFunctions;
|
|
24
37
|
|
|
25
38
|
export {
|
|
26
|
-
AxCrew
|
|
27
|
-
|
|
39
|
+
/** See class JSDoc on the `AxCrew` implementation. */
|
|
40
|
+
_AxCrew as AxCrew,
|
|
41
|
+
/** Built-in function registry; see file docs in `src/functions/index.ts`. */
|
|
42
|
+
_AxCrewFunctions as AxCrewFunctions,
|
|
28
43
|
FunctionRegistryType,
|
|
29
44
|
// Type exports
|
|
30
45
|
type AggregatedMetrics,
|
|
31
46
|
type AggregatedCosts,
|
|
32
47
|
type AgentConfig,
|
|
33
|
-
type CrewConfigInput,
|
|
34
48
|
type AxCrewConfig,
|
|
35
49
|
type StateInstance,
|
|
36
50
|
type UsageCost,
|
package/src/types.ts
CHANGED
|
@@ -3,26 +3,13 @@ import type {
|
|
|
3
3
|
AxSignature,
|
|
4
4
|
AxModelConfig,
|
|
5
5
|
AxMCPStreamableHTTPTransportOptions,
|
|
6
|
-
AxProgramForwardOptions
|
|
6
|
+
AxProgramForwardOptions,
|
|
7
|
+
AxAIArgs
|
|
7
8
|
} from '@ax-llm/ax';
|
|
8
9
|
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
| 'openai'
|
|
13
|
-
| 'anthropic'
|
|
14
|
-
| 'google-gemini'
|
|
15
|
-
| 'mistral'
|
|
16
|
-
| 'groq'
|
|
17
|
-
| 'cohere'
|
|
18
|
-
| 'together'
|
|
19
|
-
| 'deepseek'
|
|
20
|
-
| 'ollama'
|
|
21
|
-
| 'huggingface'
|
|
22
|
-
| 'openrouter'
|
|
23
|
-
| 'azure-openai'
|
|
24
|
-
| 'reka'
|
|
25
|
-
| 'x-grok'
|
|
10
|
+
// Provider ids are derived from Ax's factory arg type so new providers added in Ax
|
|
11
|
+
// are picked up at compile time without updating AxCrew.
|
|
12
|
+
export type Provider = AxAIArgs<any>['name'];
|
|
26
13
|
|
|
27
14
|
/**
|
|
28
15
|
* A state instance that is shared between agents.
|
|
@@ -209,13 +196,49 @@ interface AgentConfig {
|
|
|
209
196
|
}
|
|
210
197
|
|
|
211
198
|
/**
|
|
212
|
-
* The
|
|
199
|
+
* The configuration object for an AxCrew instance.
|
|
200
|
+
*
|
|
201
|
+
* @property {AgentConfig[]} crew - The agents that make up the crew.
|
|
202
|
+
* @example
|
|
203
|
+
* const config: AxCrewConfig = {
|
|
204
|
+
* crew: [
|
|
205
|
+
* {
|
|
206
|
+
* name: "Agent1",
|
|
207
|
+
* description: "Agent 1 description",
|
|
208
|
+
* signature: "signature",
|
|
209
|
+
* provider: "provider",
|
|
210
|
+
* providerKeyName: "providerKeyName",
|
|
211
|
+
* ai: {
|
|
212
|
+
* model: "model",
|
|
213
|
+
* temperature: 0,
|
|
214
|
+
* },
|
|
215
|
+
* options: {
|
|
216
|
+
* debug: true,
|
|
217
|
+
* },
|
|
218
|
+
* functions: ["function1", "function2"],
|
|
219
|
+
* agents: ["agent2"],
|
|
220
|
+
* },
|
|
221
|
+
* {
|
|
222
|
+
* name: "Agent2",
|
|
223
|
+
* description: "Agent 2 description",
|
|
224
|
+
* signature: "signature",
|
|
225
|
+
* provider: "provider",
|
|
226
|
+
* providerKeyName: "providerKeyName",
|
|
227
|
+
* ai: {
|
|
228
|
+
* model: "model",
|
|
229
|
+
* temperature: 0,
|
|
230
|
+
* }
|
|
231
|
+
* ]
|
|
232
|
+
* }
|
|
233
|
+
* const crew = new AxCrew(config);
|
|
213
234
|
*/
|
|
214
|
-
|
|
235
|
+
interface AxCrewConfig {
|
|
236
|
+
crew: AgentConfig[]
|
|
237
|
+
}
|
|
215
238
|
|
|
216
239
|
export {
|
|
217
240
|
type AgentConfig,
|
|
218
|
-
type
|
|
241
|
+
type AxCrewConfig,
|
|
219
242
|
type AggregatedMetrics,
|
|
220
243
|
type StateInstance,
|
|
221
244
|
type FunctionRegistryType,
|
package/dist/config/index.d.ts
DELETED
package/dist/config/index.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
|
-
dotenv.config();
|
|
3
|
-
// AI API keys
|
|
4
|
-
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
|
|
5
|
-
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
|
|
6
|
-
const AZURE_OPENAI_API_KEY = process.env.AZURE_OPENAI_API_KEY;
|
|
7
|
-
const COHERE_API_KEY = process.env.COHERE_API_KEY;
|
|
8
|
-
const DEEPSEEK_API_KEY = process.env.DEEPSEEK_API_KEY;
|
|
9
|
-
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
|
|
10
|
-
const GROQ_API_KEY = process.env.GROQ_API_KEY;
|
|
11
|
-
const TOGETHER_API_KEY = process.env.TOGETHER_API_KEY;
|
|
12
|
-
const MISTRAL_API_KEY = process.env.MISTRAL_API_KEY;
|
|
13
|
-
const HUGGINGFACE_API_KEY = process.env.HUGGINGFACE_API_KEY;
|
|
14
|
-
const REKA_API_KEY = process.env.REKA_API_KEY;
|
|
15
|
-
const GROK_API_KEY = process.env.GROK_API_KEY;
|
|
16
|
-
const PROVIDER_API_KEYS = {
|
|
17
|
-
COHERE_API_KEY,
|
|
18
|
-
GEMINI_API_KEY,
|
|
19
|
-
OPENAI_API_KEY,
|
|
20
|
-
AZURE_OPENAI_API_KEY,
|
|
21
|
-
ANTHROPIC_API_KEY,
|
|
22
|
-
DEEPSEEK_API_KEY,
|
|
23
|
-
GROQ_API_KEY,
|
|
24
|
-
TOGETHER_API_KEY,
|
|
25
|
-
MISTRAL_API_KEY,
|
|
26
|
-
HUGGINGFACE_API_KEY,
|
|
27
|
-
REKA_API_KEY,
|
|
28
|
-
GROK_API_KEY
|
|
29
|
-
};
|
|
30
|
-
export { PROVIDER_API_KEYS, };
|
package/src/config/index.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
|
-
dotenv.config();
|
|
3
|
-
|
|
4
|
-
// AI API keys
|
|
5
|
-
const ANTHROPIC_API_KEY: string | undefined = process.env.ANTHROPIC_API_KEY;
|
|
6
|
-
const OPENAI_API_KEY: string | undefined = process.env.OPENAI_API_KEY;
|
|
7
|
-
const AZURE_OPENAI_API_KEY: string | undefined = process.env.AZURE_OPENAI_API_KEY;
|
|
8
|
-
const COHERE_API_KEY: string | undefined = process.env.COHERE_API_KEY;
|
|
9
|
-
const DEEPSEEK_API_KEY: string | undefined = process.env.DEEPSEEK_API_KEY;
|
|
10
|
-
const GEMINI_API_KEY: string | undefined = process.env.GEMINI_API_KEY;
|
|
11
|
-
const GROQ_API_KEY: string | undefined = process.env.GROQ_API_KEY;
|
|
12
|
-
const TOGETHER_API_KEY: string | undefined = process.env.TOGETHER_API_KEY;
|
|
13
|
-
const MISTRAL_API_KEY: string | undefined = process.env.MISTRAL_API_KEY;
|
|
14
|
-
const HUGGINGFACE_API_KEY: string | undefined = process.env.HUGGINGFACE_API_KEY;
|
|
15
|
-
const REKA_API_KEY: string | undefined = process.env.REKA_API_KEY;
|
|
16
|
-
const GROK_API_KEY: string | undefined = process.env.GROK_API_KEY;
|
|
17
|
-
// Note: Ollama typically doesn't require an API key for local usage
|
|
18
|
-
|
|
19
|
-
interface ProviderApiKeys {
|
|
20
|
-
[key: string]: string | undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const PROVIDER_API_KEYS: ProviderApiKeys = {
|
|
24
|
-
COHERE_API_KEY,
|
|
25
|
-
GEMINI_API_KEY,
|
|
26
|
-
OPENAI_API_KEY,
|
|
27
|
-
AZURE_OPENAI_API_KEY,
|
|
28
|
-
ANTHROPIC_API_KEY,
|
|
29
|
-
DEEPSEEK_API_KEY,
|
|
30
|
-
GROQ_API_KEY,
|
|
31
|
-
TOGETHER_API_KEY,
|
|
32
|
-
MISTRAL_API_KEY,
|
|
33
|
-
HUGGINGFACE_API_KEY,
|
|
34
|
-
REKA_API_KEY,
|
|
35
|
-
GROK_API_KEY
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export {
|
|
39
|
-
PROVIDER_API_KEYS,
|
|
40
|
-
};
|