@amitdeshmukh/ax-crew 8.7.3 → 9.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,33 @@
1
+ import { AxSignature as AxSignatureClass } from "@ax-llm/ax";
2
+ import type { AxFunction } from "@ax-llm/ax";
3
+ import type { AxCrewConfig } from "../types.js";
4
+ /**
5
+ * Lightweight proxy that stands in for a real agent in the crew's agent map.
6
+ * It exposes the same `getFunction()` interface (built from the crew config)
7
+ * but defers the expensive `createAgent()` call — and therefore MCP server
8
+ * startup — until the Manager actually delegates to it.
9
+ *
10
+ * Usage: `crew.addLazyAgent("CreateChart")` instead of `crew.addAgent("CreateChart")`
11
+ */
12
+ declare class LazyStatefulAxAgent {
13
+ private realAgent;
14
+ private crewRef;
15
+ private agentName;
16
+ private description;
17
+ private signatureStr;
18
+ private func;
19
+ private _id;
20
+ constructor(crewRef: any, agentName: string, crewConfig: AxCrewConfig);
21
+ private resolve;
22
+ getFunction(): AxFunction;
23
+ getSignature(): AxSignatureClass<Record<string, any>, Record<string, any>>;
24
+ getId(): string;
25
+ setId(id: string): void;
26
+ getTraces(): any[];
27
+ setDemos(): void;
28
+ getUsage(): any[];
29
+ resetUsage(): void;
30
+ forward(...args: any[]): Promise<any>;
31
+ streamingForward(...args: any[]): any;
32
+ }
33
+ export { LazyStatefulAxAgent };
@@ -0,0 +1,78 @@
1
+ import { AxSignature as AxSignatureClass } from "@ax-llm/ax";
2
+ import { parseCrewConfig } from "./agentConfig.js";
3
+ /**
4
+ * Lightweight proxy that stands in for a real agent in the crew's agent map.
5
+ * It exposes the same `getFunction()` interface (built from the crew config)
6
+ * but defers the expensive `createAgent()` call — and therefore MCP server
7
+ * startup — until the Manager actually delegates to it.
8
+ *
9
+ * Usage: `crew.addLazyAgent("CreateChart")` instead of `crew.addAgent("CreateChart")`
10
+ */
11
+ class LazyStatefulAxAgent {
12
+ realAgent = null;
13
+ crewRef; // AxCrew — forward-declared to avoid circular ref
14
+ agentName;
15
+ description;
16
+ signatureStr;
17
+ func;
18
+ _id = "lazy";
19
+ constructor(crewRef, agentName, crewConfig) {
20
+ this.crewRef = crewRef;
21
+ this.agentName = agentName;
22
+ const agentDef = parseCrewConfig(crewConfig).crew.find((a) => a.name === agentName);
23
+ if (!agentDef) {
24
+ throw new Error(`Agent "${agentName}" not found in crew config`);
25
+ }
26
+ this.description = agentDef.description;
27
+ this.signatureStr = agentDef.signature;
28
+ // Build the tool schema from the signature's input fields
29
+ const sig = new AxSignatureClass(this.signatureStr);
30
+ const parameters = sig.toInputJSONSchema();
31
+ this.func = {
32
+ name: agentName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase(),
33
+ description: this.description,
34
+ parameters,
35
+ func: async (args) => {
36
+ const agent = await this.resolve();
37
+ return agent.forward(args);
38
+ },
39
+ };
40
+ }
41
+ async resolve() {
42
+ if (!this.realAgent) {
43
+ const agent = await this.crewRef.createAgent(this.agentName);
44
+ agent.setId(this._id);
45
+ this.realAgent = agent;
46
+ }
47
+ return this.realAgent;
48
+ }
49
+ // AxAgentic interface
50
+ getFunction() {
51
+ return this.func;
52
+ }
53
+ getSignature() {
54
+ return new AxSignatureClass(this.signatureStr);
55
+ }
56
+ // AxProgrammable / AxTunable stubs
57
+ getId() { return this._id; }
58
+ setId(id) { this._id = id; }
59
+ getTraces() { return this.realAgent?.getTraces() ?? []; }
60
+ setDemos() { }
61
+ getUsage() { return this.realAgent?.getUsage() ?? []; }
62
+ resetUsage() { this.realAgent?.resetUsage(); }
63
+ // Forward / streaming — resolve on demand
64
+ async forward(...args) {
65
+ const agent = await this.resolve();
66
+ return agent.forward(...args);
67
+ }
68
+ streamingForward(...args) {
69
+ // Must be sync to match the interface, so we wrap in an async generator
70
+ const self = this;
71
+ async function* lazyStream() {
72
+ const agent = await self.resolve();
73
+ yield* agent.streamingForward(...args);
74
+ }
75
+ return lazyStream();
76
+ }
77
+ }
78
+ export { LazyStatefulAxAgent };
@@ -0,0 +1,93 @@
1
+ import { AxAgent, AxAI } from "@ax-llm/ax";
2
+ import type { AxSignature, AxAgentic, AxFunction, AxProgramForwardOptions, AxProgramStreamingForwardOptions, AxGenStreamingOut } from "@ax-llm/ax";
3
+ import type { StateInstance, UsageCost, MCPTransportConfig, ACEConfig, AgentExecutionMode, AxCrewAxAgentOptions } from "../types.js";
4
+ export interface ParsedAgentConfig {
5
+ ai: AxAI;
6
+ name: string;
7
+ executionMode: AgentExecutionMode;
8
+ axAgentOptions?: AxCrewAxAgentOptions;
9
+ description: string;
10
+ definition?: string;
11
+ signature: string | AxSignature;
12
+ functions: (AxFunction | (new (state: Record<string, any>) => {
13
+ toFunction: () => AxFunction;
14
+ }) | undefined)[];
15
+ mcpServers?: Record<string, MCPTransportConfig>;
16
+ subAgentNames: string[];
17
+ examples?: Array<Record<string, any>>;
18
+ tracker?: any;
19
+ }
20
+ declare class StatefulAxAgent extends AxAgent<any, any> {
21
+ crewState: StateInstance;
22
+ axai: any;
23
+ private agentName;
24
+ private agentDefinition;
25
+ private executionMode;
26
+ private axGenProgram;
27
+ private costTracker?;
28
+ private debugEnabled;
29
+ private deferredToolManager?;
30
+ private static readonly modernAxAgentRuntime;
31
+ private aceConfig?;
32
+ private aceOptimizer?;
33
+ private acePlaybook?;
34
+ private aceBaseInstruction?;
35
+ private isAxAIService;
36
+ constructor(ai: AxAI, options: Readonly<{
37
+ name: string;
38
+ description: string;
39
+ executionMode?: AgentExecutionMode;
40
+ axAgentOptions?: AxCrewAxAgentOptions;
41
+ definition?: string;
42
+ signature: string | AxSignature;
43
+ agents?: AxAgentic<any, any>[] | undefined;
44
+ functions?: (AxFunction | (() => AxFunction))[] | undefined;
45
+ examples?: Array<Record<string, any>> | undefined;
46
+ mcpServers?: Record<string, MCPTransportConfig> | undefined;
47
+ debug?: boolean;
48
+ }>, state: StateInstance);
49
+ /**
50
+ * @deprecated Use setExamplesCompat() to avoid Ax runtime version coupling.
51
+ */
52
+ setExamples(examples: Readonly<Array<Record<string, any>>>): void;
53
+ setExamplesCompat(examples: Readonly<Array<Record<string, any>>>): void;
54
+ /**
55
+ * @deprecated Use setDescriptionCompat() to avoid Ax runtime version coupling.
56
+ */
57
+ setDescription(description: string): void;
58
+ setDescriptionCompat(description: string): void;
59
+ getUsage(): (import("@ax-llm/ax").AxModelUsage & {
60
+ ai: string;
61
+ model: string;
62
+ })[];
63
+ resetUsage(): void;
64
+ private resolveInvocationArgs;
65
+ /** Merge deferred tool step hooks into forward options */
66
+ private mergeStepHooks;
67
+ private executeForwardByMode;
68
+ private recordUsageMetrics;
69
+ private runForwardInvocation;
70
+ forward(values: Record<string, any>, options?: Readonly<AxProgramForwardOptions<any>>): Promise<Record<string, any>>;
71
+ forward(ai: AxAI, values: Record<string, any>, options?: Readonly<AxProgramForwardOptions<any>>): Promise<Record<string, any>>;
72
+ private runStreamingInvocation;
73
+ streamingForward(values: Record<string, any>, options?: Readonly<AxProgramStreamingForwardOptions<any>>): AxGenStreamingOut<any>;
74
+ streamingForward(ai: AxAI, values: Record<string, any>, options?: Readonly<AxProgramStreamingForwardOptions<any>>): AxGenStreamingOut<any>;
75
+ getLastUsageCost(): UsageCost | null;
76
+ getAccumulatedCosts(): UsageCost | null;
77
+ getMetrics(): import("../metrics/types.js").MetricsSnapshot;
78
+ resetMetrics(): void;
79
+ initACE(ace?: ACEConfig): Promise<void>;
80
+ optimizeOffline(params?: {
81
+ metric?: any;
82
+ examples?: any[];
83
+ }): Promise<void>;
84
+ applyOnlineUpdate(params: {
85
+ example: any;
86
+ prediction: any;
87
+ feedback?: string;
88
+ }): Promise<void>;
89
+ getPlaybook(): any | undefined;
90
+ applyPlaybook(pb: any): void;
91
+ private composeInstructionWithPlaybook;
92
+ }
93
+ export { StatefulAxAgent };
@@ -0,0 +1,473 @@
1
+ import { AxAgent, AxGen } from "@ax-llm/ax";
2
+ import { MetricsRegistry } from "../metrics/index.js";
3
+ // Extend the AxAgent class from ax-llm
4
+ class StatefulAxAgent extends AxAgent {
5
+ crewState;
6
+ axai;
7
+ agentName;
8
+ agentDefinition;
9
+ executionMode;
10
+ axGenProgram;
11
+ costTracker;
12
+ debugEnabled = false;
13
+ deferredToolManager;
14
+ static modernAxAgentRuntime = typeof AxAgent?.prototype?.getFunction === "function" &&
15
+ typeof AxAgent?.prototype?.setExamples !== "function";
16
+ // ACE-related optional state
17
+ aceConfig;
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ aceOptimizer;
20
+ acePlaybook;
21
+ aceBaseInstruction; // Original description before playbook injection
22
+ isAxAIService(obj) {
23
+ return !!obj && typeof obj.getName === 'function' && typeof obj.chat === 'function';
24
+ }
25
+ constructor(ai, options, state) {
26
+ const { examples, debug } = options;
27
+ const resolvedFunctions = (options.functions ?? []).map((fn) => typeof fn === "function" ? fn() : fn);
28
+ const resolvedAgents = (options.agents ?? []);
29
+ const effectiveDefinition = (options.definition ?? options.description).trim();
30
+ if (StatefulAxAgent.modernAxAgentRuntime) {
31
+ const configuredAgentOptions = (options.axAgentOptions ?? {});
32
+ const configuredAgentGraph = (configuredAgentOptions.agents ?? {});
33
+ const configuredFunctionGraph = (configuredAgentOptions.functions ?? {});
34
+ const configuredActorOptions = (configuredAgentOptions.actorOptions ?? {});
35
+ const configuredResponderOptions = (configuredAgentOptions.responderOptions ?? {});
36
+ const modernOptions = {
37
+ ...configuredAgentOptions,
38
+ debug: debug ?? configuredAgentOptions.debug ?? false,
39
+ contextFields: Array.isArray(configuredAgentOptions.contextFields)
40
+ ? configuredAgentOptions.contextFields
41
+ : [],
42
+ };
43
+ modernOptions.agents = {
44
+ ...configuredAgentGraph,
45
+ local: resolvedAgents,
46
+ };
47
+ modernOptions.functions = {
48
+ ...configuredFunctionGraph,
49
+ local: resolvedFunctions,
50
+ };
51
+ if (effectiveDefinition.length > 0) {
52
+ modernOptions.actorOptions = {
53
+ ...configuredActorOptions,
54
+ description: configuredActorOptions.description ?? effectiveDefinition,
55
+ };
56
+ modernOptions.responderOptions = {
57
+ ...configuredResponderOptions,
58
+ description: configuredResponderOptions.description ?? effectiveDefinition,
59
+ };
60
+ }
61
+ else {
62
+ modernOptions.actorOptions = configuredActorOptions;
63
+ modernOptions.responderOptions = configuredResponderOptions;
64
+ }
65
+ super({
66
+ ai,
67
+ agentIdentity: {
68
+ name: options.name,
69
+ description: options.description,
70
+ },
71
+ signature: options.signature,
72
+ }, modernOptions);
73
+ }
74
+ else {
75
+ super({
76
+ name: options.name,
77
+ description: options.description,
78
+ definition: options.definition,
79
+ signature: options.signature,
80
+ agents: resolvedAgents,
81
+ functions: resolvedFunctions,
82
+ debug: debug ?? false,
83
+ }, {});
84
+ }
85
+ this.crewState = state;
86
+ this.axai = ai;
87
+ this.agentName = options.name;
88
+ this.agentDefinition = effectiveDefinition;
89
+ this.executionMode = options.executionMode ?? "axgen";
90
+ this.debugEnabled = debug ?? false;
91
+ // Convert sub-agents to callable functions so AxGen can invoke them as tools
92
+ const subAgentFunctions = resolvedAgents
93
+ .map(agent => {
94
+ try {
95
+ return agent.getFunction();
96
+ }
97
+ catch {
98
+ return undefined;
99
+ }
100
+ })
101
+ .filter((fn) => fn !== undefined);
102
+ this.axGenProgram = new AxGen(options.signature, {
103
+ description: effectiveDefinition,
104
+ functions: [...resolvedFunctions, ...subAgentFunctions],
105
+ contextCache: { cacheBreakpoint: 'after-examples' },
106
+ });
107
+ for (const agent of resolvedAgents) {
108
+ try {
109
+ const childName = agent.getFunction().name;
110
+ this.axGenProgram.register(agent, childName);
111
+ }
112
+ catch {
113
+ // Best-effort registration for optimizer/introspection support.
114
+ }
115
+ }
116
+ // Apply examples to compatibility layer if provided
117
+ if (examples && examples.length > 0) {
118
+ this.setExamplesCompat(examples);
119
+ }
120
+ }
121
+ /**
122
+ * @deprecated Use setExamplesCompat() to avoid Ax runtime version coupling.
123
+ */
124
+ setExamples(examples) {
125
+ this.setExamplesCompat(examples);
126
+ }
127
+ setExamplesCompat(examples) {
128
+ this.axGenProgram.setExamples(examples);
129
+ const baseSetExamples = AxAgent.prototype.setExamples;
130
+ if (typeof baseSetExamples === "function") {
131
+ baseSetExamples.call(this, examples);
132
+ return;
133
+ }
134
+ const internalProgram = this.program;
135
+ if (typeof internalProgram?.setExamples === "function") {
136
+ internalProgram.setExamples(examples);
137
+ }
138
+ }
139
+ /**
140
+ * @deprecated Use setDescriptionCompat() to avoid Ax runtime version coupling.
141
+ */
142
+ setDescription(description) {
143
+ this.setDescriptionCompat(description);
144
+ }
145
+ setDescriptionCompat(description) {
146
+ this.agentDefinition = description;
147
+ this.axGenProgram.setDescription(description);
148
+ const baseSetDescription = AxAgent.prototype.setDescription;
149
+ if (typeof baseSetDescription === "function") {
150
+ baseSetDescription.call(this, description);
151
+ return;
152
+ }
153
+ const agentRuntime = this;
154
+ if (typeof agentRuntime.program?.setDescription === "function") {
155
+ agentRuntime.program.setDescription(description);
156
+ }
157
+ agentRuntime.actorDescription = description;
158
+ agentRuntime.responderDescription = description;
159
+ if (typeof agentRuntime._buildSplitPrograms === "function") {
160
+ agentRuntime._buildSplitPrograms();
161
+ }
162
+ }
163
+ getUsage() {
164
+ if (this.executionMode === "axgen") {
165
+ return this.axGenProgram.getUsage();
166
+ }
167
+ return super.getUsage();
168
+ }
169
+ resetUsage() {
170
+ this.axGenProgram.resetUsage();
171
+ super.resetUsage();
172
+ }
173
+ resolveInvocationArgs(first, second, third) {
174
+ const calledWithAI = this.isAxAIService(first);
175
+ const ai = (calledWithAI ? first : this.axai);
176
+ if (!ai) {
177
+ throw new Error(`No AI instance is configured for agent "${this.agentName}"`);
178
+ }
179
+ const values = (calledWithAI ? second : first);
180
+ const options = (calledWithAI ? third : second);
181
+ return { ai, values, options, calledWithAI };
182
+ }
183
+ /** Merge deferred tool step hooks into forward options */
184
+ mergeStepHooks(options) {
185
+ if (!this.deferredToolManager?.isActive)
186
+ return options;
187
+ const deferredHooks = this.deferredToolManager.getStepHooks();
188
+ const existingHooks = options?.stepHooks;
189
+ const mergedHooks = {
190
+ beforeStep: async (ctx) => {
191
+ await existingHooks?.beforeStep?.(ctx);
192
+ await deferredHooks.beforeStep?.(ctx);
193
+ },
194
+ afterStep: existingHooks?.afterStep,
195
+ afterFunctionExecution: async (ctx) => {
196
+ await existingHooks?.afterFunctionExecution?.(ctx);
197
+ await deferredHooks.afterFunctionExecution?.(ctx);
198
+ },
199
+ };
200
+ return { ...options, stepHooks: mergedHooks };
201
+ }
202
+ async executeForwardByMode(mode, ai, values, options) {
203
+ const opts = this.mergeStepHooks(options);
204
+ if (mode === "axgen") {
205
+ return this.axGenProgram.forward(ai, values, opts);
206
+ }
207
+ return super.forward(ai, values, opts);
208
+ }
209
+ recordUsageMetrics(labels, mode) {
210
+ const builtIn = mode === "axgen" ? this.axGenProgram.getUsage?.() : super.getUsage?.();
211
+ if (!Array.isArray(builtIn))
212
+ return;
213
+ const totals = builtIn.reduce((acc, u) => {
214
+ const pt = u.tokens?.promptTokens ?? u.promptTokens ?? 0;
215
+ const ct = u.tokens?.completionTokens ?? u.completionTokens ?? 0;
216
+ acc.promptTokens += typeof pt === "number" ? pt : 0;
217
+ acc.completionTokens += typeof ct === "number" ? ct : 0;
218
+ const model = u.model ||
219
+ this.axai?.getLastUsedChatModel?.() ||
220
+ this.axai?.defaults?.model;
221
+ if (model) {
222
+ acc.byModel[model] = (acc.byModel[model] || 0) + (pt + ct);
223
+ }
224
+ return acc;
225
+ }, { promptTokens: 0, completionTokens: 0, byModel: {} });
226
+ MetricsRegistry.recordTokens(labels, {
227
+ promptTokens: totals.promptTokens,
228
+ completionTokens: totals.completionTokens,
229
+ totalTokens: totals.promptTokens + totals.completionTokens,
230
+ });
231
+ const costTracker = this.costTracker;
232
+ try {
233
+ for (const [m, count] of Object.entries(totals.byModel)) {
234
+ costTracker?.trackTokens?.(count, m);
235
+ }
236
+ const totalUSD = Number(costTracker?.getCurrentCost?.() ?? 0);
237
+ if (!Number.isNaN(totalUSD) && totalUSD > 0) {
238
+ MetricsRegistry.recordEstimatedCost(labels, totalUSD);
239
+ }
240
+ }
241
+ catch { }
242
+ }
243
+ async runForwardInvocation(mode, first, second, third) {
244
+ const { ai, values, options, calledWithAI } = this.resolveInvocationArgs(first, second, third);
245
+ const start = performance.now();
246
+ const crewId = this.crewState?.crewId || this.crewState.get?.("crewId") || "default";
247
+ const labels = { crewId, agent: this.agentName };
248
+ const taskId = `task_${crewId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
249
+ // Track execution context in crew for ACE feedback routing
250
+ const crewInstance = this.crewState?.crew;
251
+ if (crewInstance) {
252
+ if (calledWithAI) {
253
+ const parentTaskId = this.crewState?.currentTaskId;
254
+ if (parentTaskId) {
255
+ crewInstance.trackAgentExecution(parentTaskId, this.agentName, values);
256
+ }
257
+ }
258
+ else {
259
+ crewInstance.trackAgentExecution(taskId, this.agentName, values);
260
+ this.crewState.currentTaskId = taskId;
261
+ }
262
+ }
263
+ if (this.debugEnabled) {
264
+ console.log(`[ACE Debug] forward() called, mode=${mode}, aceConfig=${!!this.aceConfig}`);
265
+ }
266
+ if (this.aceConfig) {
267
+ await this.composeInstructionWithPlaybook();
268
+ }
269
+ const result = await this.executeForwardByMode(mode, ai, values, options);
270
+ const durationMs = performance.now() - start;
271
+ MetricsRegistry.recordRequest(labels, false, durationMs);
272
+ this.recordUsageMetrics(labels, mode);
273
+ if (crewInstance) {
274
+ if (calledWithAI) {
275
+ const parentTaskId = this.crewState?.currentTaskId;
276
+ if (parentTaskId) {
277
+ crewInstance.recordAgentResult(parentTaskId, this.agentName, result);
278
+ }
279
+ }
280
+ else {
281
+ crewInstance.recordAgentResult(taskId, this.agentName, result);
282
+ delete this.crewState.currentTaskId;
283
+ result._taskId = taskId;
284
+ }
285
+ }
286
+ return result;
287
+ }
288
+ // Implementation
289
+ async forward(first, second, third) {
290
+ return this.runForwardInvocation(this.executionMode, first, second, third);
291
+ }
292
+ runStreamingInvocation(mode, first, second, third) {
293
+ const { ai, values, options } = this.resolveInvocationArgs(first, second, third);
294
+ const start = performance.now();
295
+ const crewId = this.crewState?.crewId || this.crewState.get?.("crewId") || "default";
296
+ const labels = { crewId, agent: this.agentName };
297
+ const opts = this.mergeStepHooks(options);
298
+ const createStream = () => mode === "axgen"
299
+ ? this.axGenProgram.streamingForward(ai, values, opts)
300
+ : super.streamingForward(ai, values, opts);
301
+ const wrappedGenerator = (async function* () {
302
+ if (this.aceConfig) {
303
+ await this.composeInstructionWithPlaybook();
304
+ }
305
+ const streamingResult = createStream();
306
+ try {
307
+ for await (const chunk of streamingResult) {
308
+ yield chunk;
309
+ }
310
+ }
311
+ finally {
312
+ const durationMs = performance.now() - start;
313
+ MetricsRegistry.recordRequest(labels, true, durationMs);
314
+ this.recordUsageMetrics(labels, mode);
315
+ }
316
+ }).bind(this)();
317
+ return wrappedGenerator;
318
+ }
319
+ // Implementation
320
+ streamingForward(first, second, third) {
321
+ return this.runStreamingInvocation(this.executionMode, first, second, third);
322
+ }
323
+ // Legacy cost API removed: rely on Ax trackers for cost reporting
324
+ getLastUsageCost() { return null; }
325
+ // Get the accumulated costs for all runs of this agent
326
+ getAccumulatedCosts() { return null; }
327
+ // Metrics API for this agent
328
+ getMetrics() {
329
+ const crewId = this.crewState?.crewId || (this.crewState.get?.('crewId')) || 'default';
330
+ return MetricsRegistry.snapshot({ crewId, agent: this.agentName });
331
+ }
332
+ resetMetrics() {
333
+ const crewId = this.crewState?.crewId || (this.crewState.get?.('crewId')) || 'default';
334
+ MetricsRegistry.reset({ crewId, agent: this.agentName });
335
+ }
336
+ // =============
337
+ // ACE API
338
+ // =============
339
+ async initACE(ace) {
340
+ this.aceConfig = ace;
341
+ if (!ace)
342
+ return;
343
+ try {
344
+ this.aceBaseInstruction =
345
+ this.agentDefinition || this.getSignature().getDescription() || '';
346
+ const { buildACEOptimizer, loadInitialPlaybook, createEmptyPlaybook } = await import('./ace.js');
347
+ this.aceOptimizer = buildACEOptimizer(this.axai, ace);
348
+ if (!ace.compileOnStart) {
349
+ this.aceOptimizer.program = this;
350
+ }
351
+ const initial = await loadInitialPlaybook(ace.persistence);
352
+ this.applyPlaybook(initial ?? createEmptyPlaybook());
353
+ if (this.debugEnabled) {
354
+ console.log(`[ACE Debug] Initialized for ${this.agentName}, base instruction: ${this.aceBaseInstruction?.slice(0, 50)}...`);
355
+ }
356
+ }
357
+ catch (error) {
358
+ console.warn(`Failed to initialize ACE for agent ${this.agentName}:`, error);
359
+ }
360
+ }
361
+ async optimizeOffline(params) {
362
+ if (!this.aceConfig || !this.aceOptimizer)
363
+ return;
364
+ try {
365
+ const { runOfflineCompile, resolveMetric } = await import('./ace.js');
366
+ const registry = this.__functionsRegistry;
367
+ const metric = params?.metric || resolveMetric(this.aceConfig.metric, registry || {});
368
+ const examples = params?.examples || [];
369
+ if (!metric || examples.length === 0) {
370
+ console.warn(`ACE offline compile skipped for ${this.agentName}: missing metric or examples`);
371
+ return;
372
+ }
373
+ const result = await runOfflineCompile({
374
+ program: this,
375
+ optimizer: this.aceOptimizer,
376
+ metric,
377
+ examples,
378
+ persistence: this.aceConfig.persistence
379
+ });
380
+ if (result?.artifact?.playbook) {
381
+ await this.applyPlaybook(result.artifact.playbook);
382
+ }
383
+ }
384
+ catch (error) {
385
+ console.warn(`ACE offline compile failed for ${this.agentName}:`, error);
386
+ }
387
+ }
388
+ async applyOnlineUpdate(params) {
389
+ if (!this.aceConfig)
390
+ return;
391
+ if (!params.feedback?.trim())
392
+ return;
393
+ try {
394
+ const { persistPlaybook, addFeedbackToPlaybook, createEmptyPlaybook } = await import('./ace.js');
395
+ let playbook = this.acePlaybook ?? this.aceOptimizer?.playbook;
396
+ if (!playbook) {
397
+ playbook = createEmptyPlaybook();
398
+ }
399
+ if (this.debugEnabled) {
400
+ console.log(`[ACE Debug] Adding feedback to playbook: "${params.feedback}"`);
401
+ }
402
+ const teacherAI = this.aceOptimizer?.teacherAI;
403
+ const aiForAnalysis = teacherAI ?? this.axai;
404
+ await addFeedbackToPlaybook(playbook, params.feedback, aiForAnalysis, this.debugEnabled);
405
+ this.applyPlaybook(playbook);
406
+ if (this.aceOptimizer) {
407
+ this.aceOptimizer.playbook = playbook;
408
+ }
409
+ if (this.aceConfig.persistence?.autoPersist) {
410
+ await persistPlaybook(playbook, this.aceConfig.persistence);
411
+ }
412
+ if (this.debugEnabled) {
413
+ console.log(`[ACE Debug] Playbook updated, sections: ${Object.keys(playbook.sections || {}).join(', ')}`);
414
+ }
415
+ }
416
+ catch (error) {
417
+ console.warn(`ACE online update failed for ${this.agentName}:`, error);
418
+ }
419
+ }
420
+ getPlaybook() {
421
+ return this.acePlaybook;
422
+ }
423
+ applyPlaybook(pb) {
424
+ this.acePlaybook = pb;
425
+ try {
426
+ this.aceOptimizer.playbook = pb;
427
+ }
428
+ catch {
429
+ // Ignore - optimizer may not be initialized yet
430
+ }
431
+ }
432
+ async composeInstructionWithPlaybook() {
433
+ const playbook = this.acePlaybook ?? this.aceOptimizer?.playbook;
434
+ if (this.debugEnabled) {
435
+ console.log(`[ACE Debug] composeInstructionWithPlaybook called`);
436
+ console.log(`[ACE Debug] playbook exists: ${!!playbook}, sections: ${playbook ? Object.keys(playbook.sections || {}).length : 0}`);
437
+ console.log(`[ACE Debug] baseInstruction: "${this.aceBaseInstruction?.slice(0, 50)}..."`);
438
+ }
439
+ if (!playbook)
440
+ return;
441
+ try {
442
+ const { renderPlaybook } = await import('./ace.js');
443
+ const rendered = renderPlaybook(playbook);
444
+ if (this.debugEnabled) {
445
+ console.log(`[ACE Debug] rendered playbook (${rendered.length} chars): ${rendered.slice(0, 100)}...`);
446
+ }
447
+ if (!rendered)
448
+ return;
449
+ const baseInstruction = this.aceBaseInstruction || '';
450
+ const combinedInstruction = [baseInstruction.trim(), '', rendered]
451
+ .filter((part) => part.trim().length > 0)
452
+ .join('\n\n');
453
+ if (this.debugEnabled) {
454
+ console.log(`[ACE Debug] combinedInstruction (${combinedInstruction.length} chars)`);
455
+ }
456
+ if (combinedInstruction.length >= 20) {
457
+ const program = this.program;
458
+ if (program?.setDescription) {
459
+ program.setDescription(combinedInstruction);
460
+ }
461
+ this.setDescription(combinedInstruction);
462
+ if (this.debugEnabled) {
463
+ console.log(`[ACE Debug] setDescription called successfully`);
464
+ console.log(`[ACE Debug] Verifying - signature desc length: ${this.getSignature().getDescription()?.length}`);
465
+ }
466
+ }
467
+ }
468
+ catch (error) {
469
+ console.warn('[ACE Debug] Failed to compose instruction:', error);
470
+ }
471
+ }
472
+ }
473
+ export { StatefulAxAgent };