@agentionai/agents 1.0.2 → 1.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.
@@ -35,7 +35,7 @@ type LlamaCppAgentConfig = Omit<BaseAgentConfig, "vendor" | "model"> & {
35
35
  };
36
36
  type AgentConfig = ClaudeAgentConfig | OpenAIAgentConfig | GeminiAgentConfig | MistralAgentConfig | OllamaAgentConfig | LlamaCppAgentConfig;
37
37
  export declare class Agent {
38
- static create(config: AgentConfig, history?: History): ClaudeAgent | GeminiAgent | OpenAiAgent | MistralAgent | OllamaAgent | LlamaCppAgent;
38
+ static create(config: AgentConfig, history?: History): ClaudeAgent | GeminiAgent | MistralAgent | OllamaAgent | LlamaCppAgent | OpenAiAgent<(string & {}) | "gpt-5-pro" | "gpt-5.2-pro" | "gpt-5.4-pro" | "gpt-5.5-pro" | "o1" | "o1-pro" | "o3" | "o3-mini" | "o4-mini" | "gpt-5" | "gpt-5-mini" | "gpt-5-nano" | "gpt-5.1" | "gpt-5.2" | "gpt-5.4" | "gpt-5.4-mini" | "gpt-5.4-nano" | "gpt-5.5" | "gpt-5.6" | "gpt-5.6-sol" | "gpt-5.6-terra" | "gpt-5.6-luna" | "gpt-4.1" | "gpt-4.1-mini" | "gpt-4.1-nano" | "gpt-4o" | "gpt-4o-mini" | "gpt-4o-2024-11-20" | "gpt-4o-2024-08-06" | "gpt-4o-2024-05-13" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo-1106" | "o1-preview" | "o1-mini">;
39
39
  }
40
40
  export {};
41
41
  //# sourceMappingURL=Agent.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { Tool } from "../tools/Tool";
2
2
  import { BuiltInTool } from "../tools/BuiltInTool";
3
3
  import { BaseAgent } from "./BaseAgent";
4
+ import type { ReasoningEffort } from "./model-types";
4
5
  /** Supported LLM vendors */
5
6
  export type AgentVendor = "openai" | "anthropic" | "mistral" | "gemini" | "ollama" | "llamacpp";
6
7
  /**
@@ -84,13 +85,28 @@ export interface ClaudeSpecificConfig {
84
85
  */
85
86
  thinkingBudgetTokens?: number;
86
87
  }
88
+ /**
89
+ * How much the model should think before answering, for OpenAI reasoning models.
90
+ *
91
+ * Which values a given model accepts is **model-dependent**; see
92
+ * {@link ReasoningEffortFor} for the per-model set and
93
+ * {@link OPENAI_REASONING_SUPPORT} for the verified matrix.
94
+ */
95
+ export type { ReasoningEffort, ReasoningEffortFor } from "./model-types";
87
96
  /**
88
97
  * Vendor-specific configuration for OpenAI
89
98
  */
90
99
  export interface OpenAISpecificConfig {
91
100
  disableParallelToolUse?: boolean;
101
+ /**
102
+ * Ask for the least reasoning the configured model supports.
103
+ *
104
+ * Resolved per model family — there is no single "off" value. Has no effect on
105
+ * models that do not support `reasoning.effort` at all. Takes precedence over
106
+ * {@link OpenAISpecificConfig.reasoningEffort}.
107
+ */
92
108
  disableReasoning?: boolean;
93
- reasoningEffort?: "low" | "medium" | "high";
109
+ reasoningEffort?: ReasoningEffort;
94
110
  seed?: number;
95
111
  user?: string;
96
112
  }
@@ -12,10 +12,52 @@ export interface BaseAgentConfig extends CommonAgentConfig {
12
12
  vendor: AgentVendor;
13
13
  vendorConfig?: VendorSpecificConfig;
14
14
  }
15
+ /**
16
+ * Token counts and timing for one or more provider API calls.
17
+ *
18
+ * Counts are always present. Timing fields are optional because their
19
+ * availability depends on the provider and on whether the call was streamed:
20
+ *
21
+ * - `totalMs` is always measured (wall clock around the API call).
22
+ * - `timeToFirstTokenMs` / `generationMs` require either a streamed response
23
+ * (measured locally) or a provider that reports its own timings
24
+ * (Ollama, llama.cpp).
25
+ *
26
+ * When usage from several calls is folded together (a tool-use loop, for
27
+ * example) the counts and durations are summed and the rates recomputed from
28
+ * those totals.
29
+ */
15
30
  export type TokenUsage = {
16
31
  input_tokens: number;
17
32
  output_tokens: number;
18
33
  total_tokens: number;
34
+ /**
35
+ * Reasoning/thinking tokens, where the provider reports them separately
36
+ * (OpenAI, Gemini). These are a subset of `output_tokens`, not an addition
37
+ * to them. Undefined when the provider does not break them out — Anthropic,
38
+ * for instance, folds thinking tokens into `output_tokens`.
39
+ */
40
+ reasoning_tokens?: number;
41
+ /**
42
+ * Milliseconds from sending the request to the first token of the response —
43
+ * prompt upload plus prompt processing.
44
+ */
45
+ timeToFirstTokenMs?: number;
46
+ /** Milliseconds spent generating the response after the first token. */
47
+ generationMs?: number;
48
+ /** Total wall-clock milliseconds spent in provider API calls. */
49
+ totalMs?: number;
50
+ /**
51
+ * Prompt processing throughput: `input_tokens` over `timeToFirstTokenMs`.
52
+ * Undefined when the time to first token is unknown.
53
+ */
54
+ inputTokensPerSecond?: number;
55
+ /**
56
+ * Generation throughput: `output_tokens` over `generationMs`. Falls back to
57
+ * `totalMs` when the first-token time is unknown (an unstreamed call), in
58
+ * which case it is an end-to-end rate rather than a pure generation rate.
59
+ */
60
+ outputTokensPerSecond?: number;
19
61
  };
20
62
  /**
21
63
  * The base agent is what the other agents are inheriting from
@@ -33,6 +75,16 @@ export declare abstract class BaseAgent<TInput = unknown, TOutput = unknown> ext
33
75
  protected vendor: AgentVendor;
34
76
  /** The model identifier for this agent */
35
77
  protected model: string;
78
+ /**
79
+ * Token counts and timings for the most recent `execute()` call, summed
80
+ * across every provider API call it made (including tool-use follow-ups).
81
+ * Reset at the start of each execution.
82
+ */
83
+ lastTokenUsage?: TokenUsage;
84
+ /** Start of the API call currently in flight, set by `startTurnTimer()`. */
85
+ private turnStartedAt?;
86
+ /** First-token timestamp of the call in flight, set by `markFirstToken()`. */
87
+ private turnFirstTokenAt?;
36
88
  /**
37
89
  * An Agent is the primary LLM entity.
38
90
  *
@@ -78,5 +130,35 @@ export declare abstract class BaseAgent<TInput = unknown, TOutput = unknown> ext
78
130
  getTools(): Tool<unknown>[];
79
131
  clearHistory(): void;
80
132
  protected abstract parseUsage(input: unknown): TokenUsage;
133
+ /**
134
+ * Clear accumulated usage. Called at the start of every `execute()` /
135
+ * `executeStream()` so `lastTokenUsage` describes a single execution.
136
+ */
137
+ protected resetTokenUsage(): void;
138
+ /**
139
+ * Mark the moment a provider API call is sent. Call this immediately before
140
+ * every request so the usage folded in afterwards can be timed.
141
+ */
142
+ protected startTurnTimer(): void;
143
+ /**
144
+ * Mark the arrival of the first token of a streamed response. Subsequent
145
+ * calls within the same turn are ignored, so it is safe to call on every
146
+ * chunk.
147
+ */
148
+ protected markFirstToken(): void;
149
+ /**
150
+ * Fold one API call's usage into `lastTokenUsage`, filling in any timings
151
+ * the provider did not report from the local turn timer.
152
+ *
153
+ * @returns the usage for this single call, with timings and rates filled in —
154
+ * `lastTokenUsage` holds the running total across calls.
155
+ */
156
+ protected accumulateUsage(usage: TokenUsage): TokenUsage;
157
+ /**
158
+ * Add locally measured timings to a provider-parsed usage object. Timings the
159
+ * provider reported itself (Ollama, llama.cpp) are kept as-is — they exclude
160
+ * network overhead and are more accurate than anything measured here.
161
+ */
162
+ private applyTurnTiming;
81
163
  }
82
164
  //# sourceMappingURL=BaseAgent.d.ts.map
@@ -120,6 +120,113 @@ class BaseAgent extends events_1.default {
120
120
  clearHistory() {
121
121
  this.history.clear();
122
122
  }
123
+ /**
124
+ * Clear accumulated usage. Called at the start of every `execute()` /
125
+ * `executeStream()` so `lastTokenUsage` describes a single execution.
126
+ */
127
+ resetTokenUsage() {
128
+ this.lastTokenUsage = undefined;
129
+ this.turnStartedAt = undefined;
130
+ this.turnFirstTokenAt = undefined;
131
+ }
132
+ /**
133
+ * Mark the moment a provider API call is sent. Call this immediately before
134
+ * every request so the usage folded in afterwards can be timed.
135
+ */
136
+ startTurnTimer() {
137
+ this.turnStartedAt = Date.now();
138
+ this.turnFirstTokenAt = undefined;
139
+ }
140
+ /**
141
+ * Mark the arrival of the first token of a streamed response. Subsequent
142
+ * calls within the same turn are ignored, so it is safe to call on every
143
+ * chunk.
144
+ */
145
+ markFirstToken() {
146
+ if (this.turnStartedAt !== undefined &&
147
+ this.turnFirstTokenAt === undefined) {
148
+ this.turnFirstTokenAt = Date.now();
149
+ }
150
+ }
151
+ /**
152
+ * Fold one API call's usage into `lastTokenUsage`, filling in any timings
153
+ * the provider did not report from the local turn timer.
154
+ *
155
+ * @returns the usage for this single call, with timings and rates filled in —
156
+ * `lastTokenUsage` holds the running total across calls.
157
+ */
158
+ accumulateUsage(usage) {
159
+ const timed = this.applyTurnTiming(usage);
160
+ const previous = this.lastTokenUsage;
161
+ const merged = previous
162
+ ? {
163
+ input_tokens: previous.input_tokens + timed.input_tokens,
164
+ output_tokens: previous.output_tokens + timed.output_tokens,
165
+ total_tokens: previous.total_tokens + timed.total_tokens,
166
+ reasoning_tokens: sumOptional(previous.reasoning_tokens, timed.reasoning_tokens),
167
+ timeToFirstTokenMs: sumOptional(previous.timeToFirstTokenMs, timed.timeToFirstTokenMs),
168
+ generationMs: sumOptional(previous.generationMs, timed.generationMs),
169
+ totalMs: sumOptional(previous.totalMs, timed.totalMs),
170
+ }
171
+ : { ...timed };
172
+ this.lastTokenUsage = withThroughput(merged);
173
+ this.turnStartedAt = undefined;
174
+ this.turnFirstTokenAt = undefined;
175
+ return withThroughput(timed);
176
+ }
177
+ /**
178
+ * Add locally measured timings to a provider-parsed usage object. Timings the
179
+ * provider reported itself (Ollama, llama.cpp) are kept as-is — they exclude
180
+ * network overhead and are more accurate than anything measured here.
181
+ */
182
+ applyTurnTiming(usage) {
183
+ if (this.turnStartedAt === undefined)
184
+ return usage;
185
+ const now = Date.now();
186
+ const timed = { ...usage };
187
+ timed.totalMs ?? (timed.totalMs = now - this.turnStartedAt);
188
+ if (this.turnFirstTokenAt !== undefined) {
189
+ timed.timeToFirstTokenMs ?? (timed.timeToFirstTokenMs = this.turnFirstTokenAt - this.turnStartedAt);
190
+ timed.generationMs ?? (timed.generationMs = now - this.turnFirstTokenAt);
191
+ }
192
+ return timed;
193
+ }
123
194
  }
124
195
  exports.BaseAgent = BaseAgent;
196
+ /**
197
+ * Add two values that may each be undefined, returning undefined only when
198
+ * neither side has a value (so "not reported" never reads as zero).
199
+ */
200
+ function sumOptional(a, b) {
201
+ if (a === undefined)
202
+ return b;
203
+ if (b === undefined)
204
+ return a;
205
+ return a + b;
206
+ }
207
+ /**
208
+ * Derive tokens-per-second rates from the counts and durations on a usage
209
+ * object. Recomputed from totals rather than averaged, so folding several calls
210
+ * together stays correct.
211
+ *
212
+ * Fields that stayed unknown are dropped rather than left as explicit
213
+ * `undefined`, keeping serialized usage free of empty keys.
214
+ */
215
+ function withThroughput(usage) {
216
+ const result = { ...usage };
217
+ if (result.timeToFirstTokenMs) {
218
+ result.inputTokensPerSecond =
219
+ result.input_tokens / (result.timeToFirstTokenMs / 1000);
220
+ }
221
+ const outputWindowMs = result.generationMs || result.totalMs;
222
+ if (outputWindowMs) {
223
+ result.outputTokensPerSecond =
224
+ result.output_tokens / (outputWindowMs / 1000);
225
+ }
226
+ for (const key of Object.keys(result)) {
227
+ if (result[key] === undefined)
228
+ delete result[key];
229
+ }
230
+ return result;
231
+ }
125
232
  //# sourceMappingURL=BaseAgent.js.map
@@ -49,8 +49,6 @@ type AgentConfig = BaseAgentConfig & {
49
49
  export declare class ClaudeAgent extends BaseAgent {
50
50
  private client;
51
51
  protected config: Partial<AgentConfig>;
52
- /** Token usage from the last execution (for metrics tracking) */
53
- lastTokenUsage?: TokenUsage;
54
52
  /** Current visualization event ID for tracking */
55
53
  private vizEventId?;
56
54
  /** Count of tool calls in current execution */
@@ -109,7 +109,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
109
109
  async execute(input) {
110
110
  this.emit(AgentEvent_1.AgentEvent.BEFORE_EXECUTE, input);
111
111
  // Reset token usage for this execution
112
- this.lastTokenUsage = undefined;
112
+ this.resetTokenUsage();
113
113
  this.currentToolCallCount = 0;
114
114
  // Normalise input to a display string for viz reporting
115
115
  const inputPreview = typeof input === "string" ? input : JSON.stringify(input);
@@ -135,6 +135,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
135
135
  // mid-loop. endExecution() in the finally block enforces limits once.
136
136
  this.history.beginExecution();
137
137
  try {
138
+ this.startTurnTimer();
138
139
  const response = (await this.client.messages.create(this.buildMessageParams()));
139
140
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, response);
140
141
  return await this.handleResponse(response);
@@ -167,16 +168,8 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
167
168
  }
168
169
  }
169
170
  async handleResponse(response) {
170
- const usage = this.parseUsage(response.usage);
171
171
  // Store token usage for metrics tracking
172
- if (this.lastTokenUsage) {
173
- this.lastTokenUsage.input_tokens += usage.input_tokens;
174
- this.lastTokenUsage.output_tokens += usage.output_tokens;
175
- this.lastTokenUsage.total_tokens += usage.total_tokens;
176
- }
177
- else {
178
- this.lastTokenUsage = { ...usage };
179
- }
172
+ const usage = this.accumulateUsage(this.parseUsage(response.usage));
180
173
  if (response.stop_reason === "max_tokens") {
181
174
  const error = new AgentError_1.MaxTokensExceededError("Response exceeded maximum token limit", this.config.maxTokens || 1024);
182
175
  this.emit(AgentEvent_1.AgentEvent.MAX_TOKENS_EXCEEDED, error);
@@ -232,6 +225,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
232
225
  this.addMessageToHistory("user", toolResults);
233
226
  // Continue conversation with tool results
234
227
  try {
228
+ this.startTurnTimer();
235
229
  const newResponse = (await this.client.messages.create(this.buildMessageParams()));
236
230
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, newResponse);
237
231
  return this.handleResponse(newResponse);
@@ -329,7 +323,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
329
323
  */
330
324
  async *executeStream(input) {
331
325
  this.emit(AgentEvent_1.AgentEvent.BEFORE_EXECUTE, input);
332
- this.lastTokenUsage = undefined;
326
+ this.resetTokenUsage();
333
327
  this.currentToolCallCount = 0;
334
328
  const inputPreview = typeof input === "string" ? input : JSON.stringify(input);
335
329
  if (VizConfig_1.vizConfig.isEnabled()) {
@@ -379,6 +373,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
379
373
  }
380
374
  }
381
375
  async *streamTurn() {
376
+ this.startTurnTimer();
382
377
  const stream = await this.client.messages.create({
383
378
  ...this.buildMessageParams(),
384
379
  stream: true,
@@ -416,6 +411,9 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
416
411
  }
417
412
  }
418
413
  if (event.type === "content_block_delta") {
414
+ // First generated content of the turn — thinking counts, since it is
415
+ // generation time either way.
416
+ this.markFirstToken();
419
417
  const e = event;
420
418
  const delta = e.delta;
421
419
  const acc = blocks.get(e.index);
@@ -442,19 +440,11 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
442
440
  }
443
441
  }
444
442
  }
445
- const usage = {
443
+ this.accumulateUsage({
446
444
  input_tokens: inputTokens,
447
445
  output_tokens: outputTokens,
448
446
  total_tokens: inputTokens + outputTokens,
449
- };
450
- if (this.lastTokenUsage) {
451
- this.lastTokenUsage.input_tokens += usage.input_tokens;
452
- this.lastTokenUsage.output_tokens += usage.output_tokens;
453
- this.lastTokenUsage.total_tokens += usage.total_tokens;
454
- }
455
- else {
456
- this.lastTokenUsage = { ...usage };
457
- }
447
+ });
458
448
  if (stopReason === "max_tokens") {
459
449
  const error = new AgentError_1.MaxTokensExceededError("Response exceeded maximum token limit", this.config.maxTokens || 1024);
460
450
  this.emit(AgentEvent_1.AgentEvent.MAX_TOKENS_EXCEEDED, error);
@@ -29,8 +29,6 @@ export declare class GeminiAgent extends BaseAgent {
29
29
  private client;
30
30
  private generativeModel;
31
31
  protected config: Partial<AgentConfig>;
32
- /** Token usage from the last execution (for metrics tracking) */
33
- lastTokenUsage?: TokenUsage;
34
32
  /** Current visualization event ID for tracking */
35
33
  private vizEventId?;
36
34
  /** Count of tool calls in current execution */
@@ -57,6 +55,7 @@ export declare class GeminiAgent extends BaseAgent {
57
55
  promptTokenCount?: number;
58
56
  candidatesTokenCount?: number;
59
57
  totalTokenCount?: number;
58
+ thoughtsTokenCount?: number;
60
59
  }): TokenUsage;
61
60
  }
62
61
  export {};
@@ -164,7 +164,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
164
164
  async execute(input) {
165
165
  this.emit(AgentEvent_1.AgentEvent.BEFORE_EXECUTE, input);
166
166
  // Reset token usage for this execution
167
- this.lastTokenUsage = undefined;
167
+ this.resetTokenUsage();
168
168
  this.currentToolCallCount = 0;
169
169
  const inputPreview = typeof input === "string" ? input : JSON.stringify(input);
170
170
  // Start visualization reporting
@@ -192,6 +192,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
192
192
  const contents = transformers_1.geminiTransformer.toProvider(this.history.getEntries());
193
193
  const systemMessage = this.history.getSystemMessage();
194
194
  const tools = this.getToolDefinitionsForGemini();
195
+ this.startTurnTimer();
195
196
  const response = await this.generativeModel.generateContent({
196
197
  contents,
197
198
  systemInstruction: systemMessage,
@@ -241,15 +242,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
241
242
  const result = response.response;
242
243
  // Parse and track usage
243
244
  if (result.usageMetadata) {
244
- const usage = this.parseUsage(result.usageMetadata);
245
- if (this.lastTokenUsage) {
246
- this.lastTokenUsage.input_tokens += usage.input_tokens;
247
- this.lastTokenUsage.output_tokens += usage.output_tokens;
248
- this.lastTokenUsage.total_tokens += usage.total_tokens;
249
- }
250
- else {
251
- this.lastTokenUsage = { ...usage };
252
- }
245
+ this.accumulateUsage(this.parseUsage(result.usageMetadata));
253
246
  }
254
247
  // Check for finish reason
255
248
  const candidate = result.candidates?.[0];
@@ -309,6 +302,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
309
302
  const newContents = transformers_1.geminiTransformer.toProvider(this.history.getEntries());
310
303
  const systemMessage = this.history.getSystemMessage();
311
304
  const tools = this.getToolDefinitionsForGemini();
305
+ this.startTurnTimer();
312
306
  const newResponse = await this.generativeModel.generateContent({
313
307
  contents: newContents,
314
308
  systemInstruction: systemMessage,
@@ -400,10 +394,17 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
400
394
  return results;
401
395
  }
402
396
  parseUsage(input) {
397
+ // Gemini excludes thought tokens from `candidatesTokenCount` but includes
398
+ // them in `totalTokenCount`. Fold them into `output_tokens` so
399
+ // input + output === total holds, matching how other providers report.
400
+ // `thoughtsTokenCount` is sent by thinking models but is not declared on
401
+ // the legacy SDK's `UsageMetadata`, hence the widened parameter type.
402
+ const thoughts = input.thoughtsTokenCount;
403
403
  return {
404
404
  input_tokens: input.promptTokenCount || 0,
405
- output_tokens: input.candidatesTokenCount || 0,
405
+ output_tokens: (input.candidatesTokenCount || 0) + (thoughts || 0),
406
406
  total_tokens: input.totalTokenCount || 0,
407
+ reasoning_tokens: thoughts,
407
408
  };
408
409
  }
409
410
  }
@@ -29,8 +29,6 @@ type AgentConfig = BaseAgentConfig & {
29
29
  export declare class MistralAgent extends BaseAgent {
30
30
  private client;
31
31
  protected config: Partial<AgentConfig>;
32
- /** Token usage from the last execution (for metrics tracking) */
33
- lastTokenUsage?: TokenUsage;
34
32
  /** Current visualization event ID for tracking */
35
33
  private vizEventId?;
36
34
  /** Count of tool calls in current execution */
@@ -73,7 +73,7 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
73
73
  async execute(input) {
74
74
  this.emit(AgentEvent_1.AgentEvent.BEFORE_EXECUTE, input);
75
75
  // Reset token usage for this execution
76
- this.lastTokenUsage = undefined;
76
+ this.resetTokenUsage();
77
77
  this.currentToolCallCount = 0;
78
78
  const inputPreview = typeof input === "string" ? input : JSON.stringify(input);
79
79
  // Start visualization reporting
@@ -99,6 +99,7 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
99
99
  this.history.beginExecution();
100
100
  try {
101
101
  const messages = transformers_1.mistralTransformer.toProvider(this.history.getEntries());
102
+ this.startTurnTimer();
102
103
  const response = await this.client.chat.complete({
103
104
  model: this.config.model,
104
105
  messages: messages,
@@ -147,16 +148,8 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
147
148
  throw error;
148
149
  }
149
150
  const choice = response.choices[0];
150
- const usage = this.parseUsage(response.usage);
151
151
  // Track token usage
152
- if (this.lastTokenUsage) {
153
- this.lastTokenUsage.input_tokens += usage.input_tokens;
154
- this.lastTokenUsage.output_tokens += usage.output_tokens;
155
- this.lastTokenUsage.total_tokens += usage.total_tokens;
156
- }
157
- else {
158
- this.lastTokenUsage = { ...usage };
159
- }
152
+ const usage = this.accumulateUsage(this.parseUsage(response.usage));
160
153
  if (choice.finishReason === "length") {
161
154
  const error = new AgentError_1.MaxTokensExceededError("Response exceeded maximum token limit", this.config.maxTokens || 1024);
162
155
  this.emit(AgentEvent_1.AgentEvent.MAX_TOKENS_EXCEEDED, error);
@@ -218,6 +211,7 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
218
211
  // Continue conversation
219
212
  try {
220
213
  const messages = transformers_1.mistralTransformer.toProvider(this.history.getEntries());
214
+ this.startTurnTimer();
221
215
  const newResponse = await this.client.chat.complete({
222
216
  model: this.config.model,
223
217
  messages: messages,
@@ -39,5 +39,81 @@ export type LlamaCppModel = "default" | "gpt-oss-20b" | "gpt-oss-120b" | "llama-
39
39
  * You can also provide any custom string for newer models not yet listed.
40
40
  * @see https://platform.openai.com/docs/models
41
41
  */
42
- export type OpenAIModel = "gpt-5.2" | "gpt-5" | "gpt-4.1" | "gpt-5-mini" | "gpt-5-nano" | "gpt-4o" | "gpt-4o-mini" | "gpt-4o-2024-11-20" | "gpt-4o-2024-08-06" | "gpt-4o-2024-05-13" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo-1106" | "o1" | "o1-preview" | "o1-mini" | "o3-mini" | (string & {});
42
+ export type OpenAIModel = OpenAIReasoningModel | "gpt-4.1" | "gpt-4.1-mini" | "gpt-4.1-nano" | "gpt-4o" | "gpt-4o-mini" | "gpt-4o-2024-11-20" | "gpt-4o-2024-08-06" | "gpt-4o-2024-05-13" | "gpt-4o-mini-2024-07-18" | "gpt-4-turbo" | "gpt-4-turbo-2024-04-09" | "gpt-4-turbo-preview" | "gpt-4-0125-preview" | "gpt-4-1106-preview" | "gpt-4" | "gpt-4-0613" | "gpt-3.5-turbo" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo-1106" | "o1-preview" | "o1-mini" | (string & {});
43
+ /**
44
+ * Every value the Responses API's `reasoning.effort` parameter defines.
45
+ *
46
+ * Which subset a given model accepts is model-dependent — see
47
+ * {@link OPENAI_REASONING_SUPPORT} and {@link ReasoningEffortFor}.
48
+ */
49
+ export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
50
+ /**
51
+ * Which reasoning efforts each OpenAI model accepts.
52
+ *
53
+ * There is no universal set and no universal "off" value: the families reject
54
+ * each other's minimum (`none` is rejected before `gpt-5.1`, `minimal` is
55
+ * rejected from `gpt-5.1` on, o-series takes neither), and `pro` variants drop
56
+ * the lower end. `effort: null` is not an off switch either — it means *unset*,
57
+ * so the model applies its own default.
58
+ *
59
+ * Each group's `efforts` are ordered lowest-first, so `efforts[0]` is the least
60
+ * reasoning that family will do.
61
+ *
62
+ * Every row was verified against the live Responses API on 2026-08-05. Models not
63
+ * listed here — non-reasoning models, and families released after this table was
64
+ * written — accept no `reasoning.effort` guess, so callers fall back to the full
65
+ * {@link ReasoningEffort} union and the runtime helper omits the parameter.
66
+ */
67
+ export declare const OPENAI_REASONING_SUPPORT: readonly [{
68
+ readonly models: readonly ["gpt-5-pro"];
69
+ readonly efforts: readonly ["high"];
70
+ }, {
71
+ readonly models: readonly ["gpt-5.2-pro", "gpt-5.4-pro", "gpt-5.5-pro"];
72
+ readonly efforts: readonly ["medium", "high", "xhigh"];
73
+ }, {
74
+ readonly models: readonly ["o1", "o1-pro", "o3", "o3-mini", "o4-mini"];
75
+ readonly efforts: readonly ["low", "medium", "high"];
76
+ }, {
77
+ readonly models: readonly ["gpt-5", "gpt-5-mini", "gpt-5-nano"];
78
+ readonly efforts: readonly ["minimal", "low", "medium", "high"];
79
+ }, {
80
+ readonly models: readonly ["gpt-5.1"];
81
+ readonly efforts: readonly ["none", "low", "medium", "high"];
82
+ }, {
83
+ readonly models: readonly ["gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5"];
84
+ readonly efforts: readonly ["none", "low", "medium", "high", "xhigh"];
85
+ }, {
86
+ readonly models: readonly ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"];
87
+ readonly efforts: readonly ["none", "low", "medium", "high", "xhigh", "max"];
88
+ }];
89
+ type ReasoningGroup = (typeof OPENAI_REASONING_SUPPORT)[number];
90
+ /** Every OpenAI model known to accept `reasoning.effort`. */
91
+ export type OpenAIReasoningModel = ReasoningGroup["models"][number];
92
+ /**
93
+ * Strip a dated snapshot suffix (`gpt-5-nano-2025-08-07` → `gpt-5-nano`) so
94
+ * pinned model ids resolve to the same support set as their alias. Snapshots
95
+ * always start `-20`, which keeps `gpt-5-mini` from looking like a snapshot of
96
+ * `gpt-5`.
97
+ */
98
+ type BaseModel<M extends string> = M extends `${infer Base}-20${string}` ? Base : M;
99
+ type EffortsOf<M extends string, G = ReasoningGroup> = G extends {
100
+ models: readonly (infer Models)[];
101
+ efforts: readonly (infer Efforts)[];
102
+ } ? BaseModel<M> extends Models ? Efforts : never : never;
103
+ /**
104
+ * The reasoning efforts a given model accepts.
105
+ *
106
+ * Resolves to the exact set for every model in {@link OPENAI_REASONING_SUPPORT},
107
+ * and to the full {@link ReasoningEffort} union for anything else — an unknown or
108
+ * newer model should not be blocked by a table that has gone stale.
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * type A = ReasoningEffortFor<"gpt-5-nano">; // "minimal" | "low" | "medium" | "high"
113
+ * type B = ReasoningEffortFor<"gpt-5.6-sol">; // adds "none", "xhigh", "max"; no "minimal"
114
+ * type C = ReasoningEffortFor<"gpt-5-pro">; // "high"
115
+ * ```
116
+ */
117
+ export type ReasoningEffortFor<M extends string> = [EffortsOf<M>] extends [never] ? ReasoningEffort : EffortsOf<M>;
118
+ export {};
43
119
  //# sourceMappingURL=model-types.d.ts.map
@@ -5,4 +5,37 @@
5
5
  * All types also accept custom string values for new/unlisted models.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.OPENAI_REASONING_SUPPORT = void 0;
9
+ /**
10
+ * Which reasoning efforts each OpenAI model accepts.
11
+ *
12
+ * There is no universal set and no universal "off" value: the families reject
13
+ * each other's minimum (`none` is rejected before `gpt-5.1`, `minimal` is
14
+ * rejected from `gpt-5.1` on, o-series takes neither), and `pro` variants drop
15
+ * the lower end. `effort: null` is not an off switch either — it means *unset*,
16
+ * so the model applies its own default.
17
+ *
18
+ * Each group's `efforts` are ordered lowest-first, so `efforts[0]` is the least
19
+ * reasoning that family will do.
20
+ *
21
+ * Every row was verified against the live Responses API on 2026-08-05. Models not
22
+ * listed here — non-reasoning models, and families released after this table was
23
+ * written — accept no `reasoning.effort` guess, so callers fall back to the full
24
+ * {@link ReasoningEffort} union and the runtime helper omits the parameter.
25
+ */
26
+ exports.OPENAI_REASONING_SUPPORT = [
27
+ { models: ["gpt-5-pro"], efforts: ["high"] },
28
+ { models: ["gpt-5.2-pro", "gpt-5.4-pro", "gpt-5.5-pro"], efforts: ["medium", "high", "xhigh"] },
29
+ { models: ["o1", "o1-pro", "o3", "o3-mini", "o4-mini"], efforts: ["low", "medium", "high"] },
30
+ { models: ["gpt-5", "gpt-5-mini", "gpt-5-nano"], efforts: ["minimal", "low", "medium", "high"] },
31
+ { models: ["gpt-5.1"], efforts: ["none", "low", "medium", "high"] },
32
+ {
33
+ models: ["gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5"],
34
+ efforts: ["none", "low", "medium", "high", "xhigh"],
35
+ },
36
+ {
37
+ models: ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"],
38
+ efforts: ["none", "low", "medium", "high", "xhigh", "max"],
39
+ },
40
+ ];
8
41
  //# sourceMappingURL=model-types.js.map
@@ -46,8 +46,6 @@ type OllamaToolDefinition = {
46
46
  */
47
47
  export declare class OllamaAgent extends BaseAgent {
48
48
  protected config: Partial<AgentConfig>;
49
- /** Token usage from the last execution (for metrics tracking) */
50
- lastTokenUsage?: TokenUsage;
51
49
  /** Current visualization event ID */
52
50
  private vizEventId?;
53
51
  /** Count of tool calls in current execution */