@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.
@@ -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
+
@@ -14,7 +14,7 @@ import type {
14
14
  StateInstance,
15
15
  FunctionRegistryType,
16
16
  UsageCost,
17
- CrewConfigInput,
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
- * Represents a crew of agents with shared state functionality.
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: CrewConfigInput;
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 {CrewConfigInput} crewConfig - Either a path to the agent config file or a JSON object with crew configuration.
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: CrewConfigInput,
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
  }
@@ -1,6 +1,16 @@
1
1
  import { CurrentDateTime, DaysBetweenDates } from './dateTime.js';
2
2
 
3
- // Built-in functions
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 { CrewConfigInput, AgentConfig } from './types.js';
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
- * The configuration for an AxCrew.
18
- *
19
- * @property {AgentConfig[]} crew - The agents that make up the crew.
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
- interface AxCrewConfig {
22
- crew: AgentConfig[];
23
- }
36
+ const _AxCrewFunctions: typeof AxCrewFunctions = AxCrewFunctions;
24
37
 
25
38
  export {
26
- AxCrew,
27
- AxCrewFunctions,
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
- // Canonical provider slugs supported by ai() factory
10
- export type Provider =
11
- // Canonical slugs per docs
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 input type for the agent config. This can be a path to a JSON file or a JSON object.
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
- type CrewConfigInput = string | { crew: AgentConfig[] };
235
+ interface AxCrewConfig {
236
+ crew: AgentConfig[]
237
+ }
215
238
 
216
239
  export {
217
240
  type AgentConfig,
218
- type CrewConfigInput,
241
+ type AxCrewConfig,
219
242
  type AggregatedMetrics,
220
243
  type StateInstance,
221
244
  type FunctionRegistryType,
@@ -1,5 +0,0 @@
1
- interface ProviderApiKeys {
2
- [key: string]: string | undefined;
3
- }
4
- declare const PROVIDER_API_KEYS: ProviderApiKeys;
5
- export { PROVIDER_API_KEYS, };
@@ -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, };
@@ -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
- };