agent-ablation 0.2.0 → 0.3.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/dist/index.d.ts CHANGED
@@ -61,50 +61,384 @@ declare function fromRecords<T>(records: readonly T[] | T[], options: {
61
61
  confidenceOf?: (record: T, index: number) => number | undefined;
62
62
  }): Finding[];
63
63
 
64
+ /**
65
+ * Structural representation of a task output or message produced by a CrewAI agent.
66
+ */
67
+ interface CrewAITaskOutput {
68
+ /** The role or name of the agent that performed the task. */
69
+ agent?: string | {
70
+ role?: string;
71
+ name?: string;
72
+ } | null;
73
+ /** Raw string or structured output of the task. */
74
+ raw?: string;
75
+ /** Optional structured JSON / object output if configured with output_json/pydantic. */
76
+ json_dict?: Record<string, unknown> | null;
77
+ /** Optional numerical score or rating if present on the output. */
78
+ score?: number;
79
+ /** Optional tokens, cost or execution time telemetry. */
80
+ cost?: number;
81
+ tokens?: number;
82
+ latencyMs?: number;
83
+ /** Arbitrary metadata. */
84
+ [key: string]: unknown;
85
+ }
86
+ interface CrewAIAdapterOptions<TOutput extends CrewAITaskOutput = CrewAITaskOutput> {
87
+ /** Custom extractor for score if not directly in output.score */
88
+ scoreOf?: (output: TOutput) => number;
89
+ /** Custom extractor for agent name if not in output.agent */
90
+ agentIdOf?: (output: TOutput) => string;
91
+ /** Custom confidence extractor */
92
+ confidenceOf?: (output: TOutput) => number | undefined;
93
+ /** Cost extractor */
94
+ costOf?: (output: TOutput) => number | undefined;
95
+ /** Tokens extractor */
96
+ tokensOf?: (output: TOutput) => number | undefined;
97
+ }
98
+ /**
99
+ * Converts CrewAI task outputs or agent payloads into `Finding[]` objects.
100
+ */
101
+ declare function fromCrewAITasks<TOutput extends CrewAITaskOutput = CrewAITaskOutput>(outputs: readonly TOutput[] | TOutput[], options?: CrewAIAdapterOptions<TOutput>): Finding[];
102
+
103
+ /**
104
+ * Structural representation of a message from an AutoGen multi-agent chat session.
105
+ */
106
+ interface AutoGenMessage {
107
+ /** The name/role of the agent that authored the message. */
108
+ name?: string | null;
109
+ /** Content of the message, either string or object payload. */
110
+ content?: unknown;
111
+ /** Role string (e.g. "user", "assistant"). */
112
+ role?: string | null;
113
+ /** Optional metadata / context dictionary. */
114
+ context?: Record<string, unknown>;
115
+ [key: string]: unknown;
116
+ }
117
+ interface AutoGenAdapterOptions<TMessage extends AutoGenMessage = AutoGenMessage> {
118
+ /** Extractor for numeric score / rating from the message. */
119
+ scoreOf: (message: TMessage) => number;
120
+ /** Optional extractor for confidence rating. */
121
+ confidenceOf?: (message: TMessage) => number | undefined;
122
+ /** Optional extractor for token usage. */
123
+ tokensOf?: (message: TMessage) => number | undefined;
124
+ /** Optional extractor for dollar cost. */
125
+ costOf?: (message: TMessage) => number | undefined;
126
+ }
127
+ /**
128
+ * Converts AutoGen conversation history into `Finding[]` objects.
129
+ */
130
+ declare function fromAutoGenMessages<TMessage extends AutoGenMessage = AutoGenMessage>(messages: readonly TMessage[] | TMessage[], options: AutoGenAdapterOptions<TMessage>): Finding[];
131
+
132
+ /**
133
+ * Structural representation of a step or tool execution result in Vercel AI SDK / Agent runs.
134
+ */
135
+ interface AISDKStepResult {
136
+ /** Tool name or agent step identifier */
137
+ toolName?: string;
138
+ stepType?: string;
139
+ /** Result or args */
140
+ args?: unknown;
141
+ result?: unknown;
142
+ /** Token usage metadata if available */
143
+ usage?: {
144
+ promptTokens?: number;
145
+ completionTokens?: number;
146
+ totalTokens?: number;
147
+ };
148
+ /** Execution latency in ms */
149
+ latencyMs?: number;
150
+ [key: string]: unknown;
151
+ }
152
+ interface AISDKAdapterOptions<TStep extends AISDKStepResult = AISDKStepResult> {
153
+ /** Custom extractor for agent ID / tool name */
154
+ agentIdOf?: (step: TStep) => string;
155
+ /** Extractor for score */
156
+ scoreOf: (step: TStep) => number;
157
+ /** Optional confidence extractor */
158
+ confidenceOf?: (step: TStep) => number | undefined;
159
+ /** Optional cost extractor */
160
+ costOf?: (step: TStep) => number | undefined;
161
+ }
162
+ /**
163
+ * Converts Vercel AI SDK tool call steps or agent trace steps into `Finding[]` objects.
164
+ */
165
+ declare function fromAISDKSteps<TStep extends AISDKStepResult = AISDKStepResult>(steps: readonly TStep[] | TStep[], options: AISDKAdapterOptions<TStep>): Finding[];
166
+
167
+ interface ReportOptions {
168
+ /** Title for the report */
169
+ title?: string;
170
+ /** Whether to include ROI breakdown table */
171
+ includeRoi?: boolean;
172
+ /** Whether to include pruning recommendations */
173
+ includeRecommendations?: boolean;
174
+ }
175
+ /**
176
+ * Formats batch ablation results and ROI metrics into a GitHub / Dev.to-flavored Markdown report.
177
+ */
178
+ declare function formatMarkdownReport(summary: BatchAblationSummary, options?: ReportOptions): string;
179
+ /**
180
+ * Formats batch ablation results into an ASCII table string for CLI/terminal logs.
181
+ */
182
+ declare function formatAsciiTable(summary: BatchAblationSummary): string;
183
+
184
+ /**
185
+ * Represents a single finding or signal produced by an individual agent.
186
+ */
64
187
  interface Finding {
188
+ /** Unique identifier of the agent that produced this finding. */
65
189
  agentId: string;
190
+ /** Numerical score or risk rating produced by the agent. */
66
191
  score: number;
192
+ /** Optional confidence score (e.g. 0 to 1) associated with the finding. */
67
193
  confidence?: number;
194
+ /** Optional financial cost (in USD or custom currency unit) consumed to produce this finding. */
195
+ cost?: number;
196
+ /** Optional token count (prompt + completion) consumed to produce this finding. */
197
+ tokens?: number;
198
+ /** Optional execution time / latency in milliseconds. */
199
+ latencyMs?: number;
200
+ /** Arbitrary metadata associated with the finding (e.g. raw output or attributes). */
68
201
  metadata?: Record<string, unknown>;
69
202
  }
203
+ /**
204
+ * Pure function that aggregates a list of agent findings into a verdict.
205
+ *
206
+ * @typeParam TVerdict Type of the verdict produced by the decision function.
207
+ */
70
208
  type DecisionFn<TVerdict> = (findings: Finding[]) => TVerdict;
209
+ /**
210
+ * Async function that aggregates a list of agent findings into a verdict.
211
+ *
212
+ * @typeParam TVerdict Type of the verdict produced by the decision function.
213
+ */
214
+ type AsyncDecisionFn<TVerdict> = (findings: Finding[]) => Promise<TVerdict> | TVerdict;
215
+ /**
216
+ * Outcome of ablating a single agent from the panel.
217
+ *
218
+ * @typeParam TVerdict Type of the decision verdict.
219
+ */
71
220
  interface PerAgentAblation<TVerdict> {
221
+ /** Identifier of the agent that was removed in this ablation run. */
72
222
  removedAgentId: string;
223
+ /** Verdict produced by the decision function without this agent's finding. */
73
224
  verdictWithout: TVerdict;
225
+ /** Whether the verdict changed compared to the baseline verdict. */
74
226
  changed: boolean;
75
227
  }
228
+ /**
229
+ * Result of a leave-one-out ablation across all agents for a single decision.
230
+ *
231
+ * @typeParam TVerdict Type of the decision verdict.
232
+ */
76
233
  interface AblationResult<TVerdict> {
234
+ /** Original decision verdict produced with all findings present. */
77
235
  baseline: TVerdict;
236
+ /** Detailed per-agent ablation outcomes. */
78
237
  perAgent: PerAgentAblation<TVerdict>[];
238
+ /** Count of agents whose removal flipped the decision outcome. */
79
239
  loadBearingCount: number;
240
+ /** Total number of agents evaluated in this decision. */
80
241
  totalAgents: number;
242
+ /** Fraction of agents that were load-bearing (`loadBearingCount / totalAgents`). */
81
243
  loadBearingRatio: number;
82
244
  }
245
+ /**
246
+ * Detailed telemetry & ROI metrics for a single agent.
247
+ */
248
+ interface AgentRoiMetrics {
249
+ /** Total dollar cost consumed across all appearances. */
250
+ totalCost?: number;
251
+ /** Total tokens consumed across all appearances. */
252
+ totalTokens?: number;
253
+ /** Mean latency in milliseconds. */
254
+ averageLatencyMs?: number;
255
+ /** Dollar cost per verdict flip (totalCost / verdictFlips). */
256
+ costPerVerdictFlip?: number;
257
+ /** Tokens per verdict flip (totalTokens / verdictFlips). */
258
+ tokensPerVerdictFlip?: number;
259
+ /** Percentage of overall multi-agent pipeline cost consumed by this agent. */
260
+ costShare?: number;
261
+ /** Ratio of influence share to cost share (>1 means high efficiency, <1 means expensive relative to impact). */
262
+ efficiencyRatio?: number;
263
+ }
264
+ /**
265
+ * Pruning or optimization recommendation for an agent.
266
+ */
267
+ interface PruningRecommendation {
268
+ agentId: string;
269
+ recommendation: "prune" | "downgrade_model" | "keep";
270
+ reason: string;
271
+ }
272
+ /**
273
+ * Aggregated ROI metrics across all agents.
274
+ */
275
+ interface RoiSummary {
276
+ totalCost: number;
277
+ totalTokens: number;
278
+ agents: Record<string, AgentRoiMetrics>;
279
+ recommendations: PruningRecommendation[];
280
+ }
281
+ /**
282
+ * Accuracy and ground-truth metrics.
283
+ */
284
+ interface GroundTruthSummary {
285
+ baselineAccuracy: number;
286
+ correctBaselineCount: number;
287
+ totalEvaluated: number;
288
+ }
289
+ /**
290
+ * Statistics per agent including appearances, flips, and net accuracy impact.
291
+ */
292
+ interface PerAgentStats {
293
+ appearances: number;
294
+ flips: number;
295
+ protectiveFlips?: number;
296
+ correctiveFlips?: number;
297
+ netAccuracyImpact?: number;
298
+ role?: "Protective" | "Harmful" | "Neutral";
299
+ }
300
+ /**
301
+ * Summary metrics aggregated across a batch of ablation cases.
302
+ */
83
303
  interface BatchAblationSummary {
304
+ /** Total number of cases evaluated in the batch. */
84
305
  cases: number;
306
+ /** Mean load-bearing ratio across all evaluated cases. */
85
307
  averageLoadBearingRatio: number;
308
+ /** Map of agent IDs to the fraction of cases where removing that agent changed the outcome. */
86
309
  perAgentInfluence: Record<string, number>;
310
+ /** Detailed statistics per agent. */
311
+ perAgentStats?: Record<string, PerAgentStats>;
312
+ /** Optional ROI breakdown (if cost/token telemetry was provided in findings). */
313
+ roi?: RoiSummary;
314
+ /** Optional ground-truth accuracy metrics (if groundTruth was supplied). */
315
+ accuracy?: GroundTruthSummary;
87
316
  }
317
+ /**
318
+ * Options for batch ablation runs.
319
+ */
320
+ interface BatchAblationOptions<TVerdict> {
321
+ /** Custom comparator for verdicts (defaults to ===). */
322
+ equals?: (a: TVerdict, b: TVerdict) => boolean;
323
+ /** Array of ground truth verdicts corresponding 1:1 with cases. */
324
+ groundTruth?: TVerdict[];
325
+ }
326
+ /**
327
+ * Options for async and stochastic ablation runs.
328
+ */
329
+ interface AsyncAblationOptions<TVerdict> {
330
+ /** Custom comparator for verdicts (defaults to ===). */
331
+ equals?: (a: TVerdict, b: TVerdict) => boolean;
332
+ /** Number of stochastic samples to draw per decision (for non-deterministic LLM decide functions). Default: 1 */
333
+ samples?: number;
334
+ /** Custom aggregator for sample runs (defaults to majority voting). */
335
+ aggregateSamples?: (samples: TVerdict[]) => TVerdict;
336
+ /** Array of ground truth verdicts (for batch runs). */
337
+ groundTruth?: TVerdict[];
338
+ }
339
+ /**
340
+ * Resolves majority vote across multiple stochastic sample evaluations.
341
+ */
342
+ declare function majorityVote<TVerdict>(samples: TVerdict[], equals?: (a: TVerdict, b: TVerdict) => boolean): TVerdict;
88
343
  /**
89
344
  * Runs a leave-one-out ablation over `findings`: computes the baseline verdict,
90
345
  * then re-runs `decide` once per finding with that finding removed, comparing each
91
346
  * result back to the baseline via `equals`.
92
347
  *
93
- * `equals` defaults to `===`. If TVerdict is an object or otherwise compared by
94
- * reference (not a primitive like a string or number), you MUST supply your own
95
- * `equals` otherwise every ablation will spuriously read as "changed" because two
96
- * structurally identical objects are never `===` to one another, even when nothing
97
- * about the decision actually differed.
348
+ * @param findings Array of agent findings to ablate.
349
+ * @param decide Pure decision function mapping findings to a verdict.
350
+ * @param equals Optional comparator for verdicts (defaults to `===`).
351
+ * @returns Ablation results containing baseline verdict and per-agent outcomes.
98
352
  */
99
353
  declare function runAblation<TVerdict>(findings: Finding[], decide: DecisionFn<TVerdict>, equals?: (a: TVerdict, b: TVerdict) => boolean): AblationResult<TVerdict>;
354
+ /**
355
+ * Runs an asynchronous leave-one-out ablation over `findings`.
356
+ * Supports stochastic decision functions with repeated K-sampling and majority voting.
357
+ *
358
+ * @param findings Array of agent findings to ablate.
359
+ * @param decide Async decision function mapping findings to a verdict.
360
+ * @param options Configuration for equals comparison, samples, and sampling aggregation.
361
+ */
362
+ declare function runAblationAsync<TVerdict>(findings: Finding[], decide: AsyncDecisionFn<TVerdict>, options?: AsyncAblationOptions<TVerdict>): Promise<AblationResult<TVerdict>>;
363
+ /**
364
+ * Aggregates batch ablation results into summary metrics, ROI breakdown, and ground-truth accuracy impact.
365
+ */
366
+ declare function aggregateBatchResults<TVerdict>(cases: Finding[][], results: AblationResult<TVerdict>[], options?: BatchAblationOptions<TVerdict>): BatchAblationSummary;
100
367
  /**
101
368
  * Runs `runAblation` over a batch of independent cases and aggregates the results:
102
- * the mean load-bearing ratio across cases, and, per agent ID, the fraction of the
103
- * cases containing that agent in which removing it flipped the verdict.
369
+ * the mean load-bearing ratio across cases, per-agent influence, telemetry ROI, and ground-truth accuracy impact.
370
+ *
371
+ * @param cases Array of cases, where each case is an array of findings.
372
+ * @param decide Pure decision function mapping findings to a verdict.
373
+ * @param options Optional configuration object or comparator function.
374
+ * @returns Individual case results and aggregated batch summary.
104
375
  */
105
- declare function batchAblation<TVerdict>(cases: Finding[][], decide: DecisionFn<TVerdict>, equals?: (a: TVerdict, b: TVerdict) => boolean): {
376
+ declare function batchAblation<TVerdict>(cases: Finding[][], decide: DecisionFn<TVerdict>, options?: ((a: TVerdict, b: TVerdict) => boolean) | BatchAblationOptions<TVerdict>): {
106
377
  results: AblationResult<TVerdict>[];
107
378
  summary: BatchAblationSummary;
108
379
  };
380
+ /**
381
+ * Runs `runAblationAsync` over a batch of cases with async/stochastic decision functions.
382
+ */
383
+ declare function batchAblationAsync<TVerdict>(cases: Finding[][], decide: AsyncDecisionFn<TVerdict>, options?: AsyncAblationOptions<TVerdict>): Promise<{
384
+ results: AblationResult<TVerdict>[];
385
+ summary: BatchAblationSummary;
386
+ }>;
387
+ /**
388
+ * Result of a greedy backward elimination pass to find the minimal agent panel.
389
+ */
390
+ interface BackwardEliminationResult<TVerdict> {
391
+ /** Baseline verdict with all findings present. */
392
+ baseline: TVerdict;
393
+ /** Minimal subset of findings required to sustain the baseline verdict. */
394
+ minimalFindings: Finding[];
395
+ /** Agent IDs in the minimal subset. */
396
+ minimalAgentIds: string[];
397
+ /** Agents pruned during elimination in order of pruning. */
398
+ eliminatedAgentIds: string[];
399
+ /** Step-by-step trace of elimination rounds. */
400
+ steps: {
401
+ step: number;
402
+ eliminatedAgentId: string;
403
+ remainingAgentIds: string[];
404
+ verdict: TVerdict;
405
+ }[];
406
+ /** Whether elimination stopped because removing any further agent flips the verdict. */
407
+ stoppedDueToVerdictFlip: boolean;
408
+ }
409
+ /**
410
+ * Performs greedy backward elimination over an agent panel.
411
+ * Iteratively removes the least impactful agent while verifying that the verdict remains identical to the baseline.
412
+ * Stops when removing any remaining agent flips the verdict, revealing the minimal viable agent panel.
413
+ *
414
+ * @param findings Array of agent findings.
415
+ * @param decide Decision function.
416
+ * @param equals Optional verdict comparator.
417
+ */
418
+ declare function runBackwardElimination<TVerdict>(findings: Finding[], decide: DecisionFn<TVerdict>, equals?: (a: TVerdict, b: TVerdict) => boolean): BackwardEliminationResult<TVerdict>;
419
+ /**
420
+ * Async version of greedy backward elimination.
421
+ */
422
+ declare function runBackwardEliminationAsync<TVerdict>(findings: Finding[], decide: AsyncDecisionFn<TVerdict>, options?: AsyncAblationOptions<TVerdict>): Promise<BackwardEliminationResult<TVerdict>>;
423
+ /**
424
+ * Pairwise interaction ablation result.
425
+ */
426
+ interface PairwiseAblationItem<TVerdict> {
427
+ pair: [string, string];
428
+ verdictWithout: TVerdict;
429
+ changed: boolean;
430
+ /** True if removing neither agent alone changed the outcome, but removing both together did! */
431
+ isInteraction: boolean;
432
+ }
433
+ interface PairwiseAblationResult<TVerdict> {
434
+ baseline: TVerdict;
435
+ pairs: PairwiseAblationItem<TVerdict>[];
436
+ interactionCount: number;
437
+ }
438
+ /**
439
+ * Evaluates pairwise combinations (pairs of agents) to detect joint dependencies where neither agent alone is load-bearing,
440
+ * but removing both together flips the outcome.
441
+ */
442
+ declare function runPairwiseAblation<TVerdict>(findings: Finding[], decide: DecisionFn<TVerdict>, equals?: (a: TVerdict, b: TVerdict) => boolean): PairwiseAblationResult<TVerdict>;
109
443
 
110
- export { type AblationResult, type BatchAblationSummary, type DecisionFn, type Finding, type LangGraphAdapterOptions, type LangGraphAgentMessage, type PerAgentAblation, batchAblation, fromLangGraphMessages, fromRecords, runAblation };
444
+ export { type AISDKAdapterOptions, type AISDKStepResult, type AblationResult, type AgentRoiMetrics, type AsyncAblationOptions, type AsyncDecisionFn, type AutoGenAdapterOptions, type AutoGenMessage, type BackwardEliminationResult, type BatchAblationOptions, type BatchAblationSummary, type CrewAIAdapterOptions, type CrewAITaskOutput, type DecisionFn, type Finding, type GroundTruthSummary, type LangGraphAdapterOptions, type LangGraphAgentMessage, type PairwiseAblationItem, type PairwiseAblationResult, type PerAgentAblation, type PerAgentStats, type PruningRecommendation, type ReportOptions, type RoiSummary, aggregateBatchResults, batchAblation, batchAblationAsync, formatAsciiTable, formatMarkdownReport, fromAISDKSteps, fromAutoGenMessages, fromCrewAITasks, fromLangGraphMessages, fromRecords, majorityVote, runAblation, runAblationAsync, runBackwardElimination, runBackwardEliminationAsync, runPairwiseAblation };