@agentionai/agents 0.13.0 → 1.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/README.md CHANGED
@@ -75,6 +75,7 @@ import { ClaudeAgent, OpenAiAgent } from '@agentionai/agents';
75
75
  ## Features
76
76
 
77
77
  - **Multi-Provider, No Lock-in** - Claude, OpenAI, Gemini, Mistral, plus local models via Ollama and llama.cpp—same interface. Switch models with one line.
78
+ - **Streaming** - `executeStream()` on Claude, OpenAI, and all OpenAI-compatible agents. Yields `{ type: "text" | "reasoning" }` chunks; tool calls handled transparently.
78
79
  - **Built-In Tools** - Use provider-defined server-side tools (e.g. Anthropic's web search, bash, text editor) alongside your own.
79
80
  - **Composable, Not Magical** - Agents are objects. Pipelines are arrays. No hidden state, no surprises.
80
81
  - **Multimodal / Vision** - Send images alongside text with a unified `MessageContent[]` API across all providers.
@@ -119,7 +120,7 @@ const agent = new GeminiAgent({
119
120
  const response = await agent.execute("What's the weather in Paris?");
120
121
  ```
121
122
 
122
- ### Local Models (Ollama / llama.cpp)
123
+ ### Local Models (Ollama / llama.cpp / OpenAI-compatible servers)
123
124
 
124
125
  Run models on your own machine — no API key required. Same agent interface as every other provider:
125
126
 
@@ -151,6 +152,21 @@ const response = await ollama.execute('What can you run locally?');
151
152
  const models = await ollama.listModels();
152
153
  ```
153
154
 
155
+ **Custom OpenAI-compatible server** (vLLM, LM Studio, Together AI, Groq, …): extend `OpenAICompatibleAgent` directly:
156
+
157
+ ```typescript
158
+ import { OpenAICompatibleAgent, OpenAICompatibleConfig } from '@agentionai/agents/llamacpp';
159
+
160
+ class VLLMAgent extends OpenAICompatibleAgent {
161
+ constructor(config: Omit<OpenAICompatibleConfig, 'vendor'>) {
162
+ super({ ...config, vendor: 'llamacpp', baseURL: config.baseURL ?? 'http://localhost:8000/v1' });
163
+ }
164
+ protected getVendorName() { return 'vLLM'; }
165
+ }
166
+ ```
167
+
168
+ [Full guide →](https://docs.agention.ai/guide/agents#custom-openai-compatible-agents)
169
+
154
170
  ### Built-In Tools
155
171
 
156
172
  Use a provider's own server-side tools (executed by the provider, not locally) alongside your custom tools:
@@ -171,6 +187,27 @@ const agent = new ClaudeAgent({
171
187
  const response = await agent.execute('What happened in the news today?');
172
188
  ```
173
189
 
190
+ ### Streaming
191
+
192
+ All three major providers support streaming via `executeStream()`, which returns an `AsyncGenerator<StreamChunk>`. Each chunk is `{ type: "text" | "reasoning"; content: string }` — text for visible output, reasoning for internal thinking tokens (DeepSeek R1, Claude extended thinking, OpenAI o-series).
193
+
194
+ ```typescript
195
+ import { ClaudeAgent } from '@agentionai/agents/claude';
196
+
197
+ const agent = new ClaudeAgent({
198
+ apiKey: process.env.ANTHROPIC_API_KEY,
199
+ id: 'assistant',
200
+ name: 'Assistant',
201
+ description: 'You are a helpful assistant.',
202
+ });
203
+
204
+ for await (const chunk of agent.executeStream('Tell me a story')) {
205
+ if (chunk.type === 'text') process.stdout.write(chunk.content);
206
+ }
207
+ ```
208
+
209
+ Tool calls are handled transparently — the generator continues streaming after each round-trip. The same API works across `ClaudeAgent`, `OpenAiAgent`, and `LlamaCppAgent` / any `OpenAICompatibleAgent` subclass.
210
+
174
211
  ### Multi-Agent Pipeline
175
212
 
176
213
  Chain agents together with different providers and models:
@@ -73,6 +73,16 @@ export interface ClaudeSpecificConfig {
73
73
  * implementation detail that can change.
74
74
  */
75
75
  authType?: "apiKey" | "oauth";
76
+ /**
77
+ * Enable extended thinking by setting a thinking token budget. When set (> 0), the
78
+ * agent requests `thinking: { type: "enabled", budget_tokens }` and surfaces thinking
79
+ * tokens as `"reasoning"` chunks from `executeStream()`.
80
+ *
81
+ * Constraints (enforced by Anthropic): `budget_tokens` must be ≥ 1024 and strictly less
82
+ * than `maxTokens`. When enabled, `temperature`/`topP`/`topK` are not sent (the API
83
+ * requires default sampling with thinking).
84
+ */
85
+ thinkingBudgetTokens?: number;
76
86
  }
77
87
  /**
78
88
  * Vendor-specific configuration for OpenAI
@@ -10,6 +10,8 @@ export declare class AgentEvent {
10
10
  static MAX_RETRIES_EXCEEDED: string;
11
11
  static MAX_TOKENS_EXCEEDED: string;
12
12
  static TOOL_ERROR: string;
13
+ static CHUNK: string;
14
+ static REASONING_CHUNK: string;
13
15
  private defaultPrevented;
14
16
  constructor(target: BaseAgent<any>);
15
17
  preventDefault(): void;
@@ -23,4 +23,6 @@ AgentEvent.RETRY = "retry";
23
23
  AgentEvent.MAX_RETRIES_EXCEEDED = "max_retries_exceeded";
24
24
  AgentEvent.MAX_TOKENS_EXCEEDED = "max_tokens_exceeded";
25
25
  AgentEvent.TOOL_ERROR = "tool_error";
26
+ AgentEvent.CHUNK = "chunk";
27
+ AgentEvent.REASONING_CHUNK = "reasoning_chunk";
26
28
  //# sourceMappingURL=AgentEvent.js.map
@@ -1,8 +1,10 @@
1
+ import { Anthropic } from "@anthropic-ai/sdk";
1
2
  import { Message, ToolUnion, Usage } from "@anthropic-ai/sdk/resources";
2
3
  import { type ToolDefinition } from "../../tools/Tool";
3
4
  import { type BuiltInTool } from "../../tools/BuiltInTool";
4
5
  import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
5
6
  import { History, MessageContent } from "../../history/History";
7
+ import { StreamChunk } from "../openai-compatible/OpenAICompatibleAgent";
6
8
  import { ClaudeModel } from "../model-types";
7
9
  type AgentConfig = BaseAgentConfig & {
8
10
  apiKey: string;
@@ -22,6 +24,12 @@ type AgentConfig = BaseAgentConfig & {
22
24
  * @see lib/tools/BuiltInTool.ts
23
25
  */
24
26
  builtInTools?: BuiltInTool[];
27
+ /**
28
+ * Enable extended thinking with this token budget (≥ 1024, and strictly less than
29
+ * `maxTokens`). When set, thinking tokens are streamed as `"reasoning"` chunks and
30
+ * `temperature`/`topP`/`topK` are omitted (required by the API when thinking is on).
31
+ */
32
+ thinkingBudgetTokens?: number;
25
33
  };
26
34
  /**
27
35
  * Agent for Anthropic models.
@@ -54,10 +62,56 @@ export declare class ClaudeAgent extends BaseAgent {
54
62
  * (server-side) built-in tools, in the shape Anthropic's API expects.
55
63
  */
56
64
  protected getAllToolDefinitions(): ToolUnion[];
65
+ /**
66
+ * Build the common `messages.create` params (shared by `execute()` and
67
+ * `executeStream()`), excluding `stream`. When extended thinking is enabled
68
+ * (`thinkingBudgetTokens > 0`) the API requires default sampling, so
69
+ * `temperature`/`top_p`/`top_k` are omitted in favour of the `thinking` block.
70
+ */
71
+ protected buildMessageParams(): {
72
+ thinking: {
73
+ type: "enabled";
74
+ budget_tokens: number;
75
+ };
76
+ model: string & ClaudeModel;
77
+ system: string | undefined;
78
+ max_tokens: number;
79
+ messages: Anthropic.Messages.MessageParam[];
80
+ tools: Anthropic.Messages.ToolUnion[];
81
+ stop_sequences: string[] | undefined;
82
+ metadata: Record<string, string> | undefined;
83
+ } | {
84
+ temperature: number | undefined;
85
+ top_p: number | undefined;
86
+ top_k: number | undefined;
87
+ model: string & ClaudeModel;
88
+ system: string | undefined;
89
+ max_tokens: number;
90
+ messages: Anthropic.Messages.MessageParam[];
91
+ tools: Anthropic.Messages.ToolUnion[];
92
+ stop_sequences: string[] | undefined;
93
+ metadata: Record<string, string> | undefined;
94
+ };
57
95
  protected process(_input: string): Promise<string>;
58
96
  execute(input: string | MessageContent[]): Promise<string>;
59
97
  protected handleResponse(response: Message): Promise<string>;
60
98
  private handleToolUse;
99
+ /**
100
+ * Stream a response as an async generator of `StreamChunk` objects.
101
+ * Yields `{ type: "text" }` for visible output and `{ type: "reasoning" }` for
102
+ * extended thinking tokens (models with thinking enabled). Tool calls are handled
103
+ * transparently — the generator continues streaming after each round-trip.
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * for await (const chunk of agent.executeStream("Explain recursion")) {
108
+ * if (chunk.type === "text") process.stdout.write(chunk.content);
109
+ * else process.stderr.write(`[thinking] ${chunk.content}`);
110
+ * }
111
+ * ```
112
+ */
113
+ executeStream(input: string | MessageContent[]): AsyncGenerator<StreamChunk>;
114
+ private streamTurn;
61
115
  protected parseUsage(input: Usage): TokenUsage;
62
116
  }
63
117
  export {};
@@ -38,6 +38,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
38
38
  const metadata = config.metadata ?? vendorConfig.metadata;
39
39
  const builtInTools = config.builtInTools ?? vendorConfig.builtInTools;
40
40
  const authType = config.authType ?? vendorConfig.authType ?? "apiKey";
41
+ const thinkingBudgetTokens = config.thinkingBudgetTokens ?? vendorConfig.thinkingBudgetTokens;
41
42
  this.client = new sdk_1.Anthropic(authType === "oauth"
42
43
  ? { authToken: config.apiKey }
43
44
  : { apiKey: config.apiKey });
@@ -48,6 +49,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
48
49
  metadata,
49
50
  builtInTools,
50
51
  authType,
52
+ thinkingBudgetTokens,
51
53
  apiKey: config.apiKey,
52
54
  temperature: config.temperature,
53
55
  topP: config.topP,
@@ -70,6 +72,37 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
70
72
  ...(this.config.builtInTools ?? []),
71
73
  ];
72
74
  }
75
+ /**
76
+ * Build the common `messages.create` params (shared by `execute()` and
77
+ * `executeStream()`), excluding `stream`. When extended thinking is enabled
78
+ * (`thinkingBudgetTokens > 0`) the API requires default sampling, so
79
+ * `temperature`/`top_p`/`top_k` are omitted in favour of the `thinking` block.
80
+ */
81
+ buildMessageParams() {
82
+ const messages = transformers_1.anthropicTransformer.toProvider(this.history.getEntries());
83
+ const thinkingEnabled = (this.config.thinkingBudgetTokens ?? 0) > 0;
84
+ return {
85
+ model: this.config.model,
86
+ system: this.history.getSystemMessage(),
87
+ max_tokens: this.config.maxTokens,
88
+ messages,
89
+ tools: this.getAllToolDefinitions(),
90
+ stop_sequences: this.config.stopSequences,
91
+ metadata: this.config.metadata,
92
+ ...(thinkingEnabled
93
+ ? {
94
+ thinking: {
95
+ type: "enabled",
96
+ budget_tokens: this.config.thinkingBudgetTokens,
97
+ },
98
+ }
99
+ : {
100
+ temperature: this.config.temperature,
101
+ top_p: this.config.topP,
102
+ top_k: this.config.topK,
103
+ }),
104
+ };
105
+ }
73
106
  async process(_input) {
74
107
  return "";
75
108
  }
@@ -102,20 +135,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
102
135
  // mid-loop. endExecution() in the finally block enforces limits once.
103
136
  this.history.beginExecution();
104
137
  try {
105
- const messages = transformers_1.anthropicTransformer.toProvider(this.history.getEntries());
106
- const systemMessage = this.history.getSystemMessage();
107
- const response = await this.client.messages.create({
108
- model: this.config.model,
109
- system: systemMessage,
110
- max_tokens: this.config.maxTokens,
111
- messages,
112
- tools: this.getAllToolDefinitions(),
113
- temperature: this.config.temperature,
114
- top_p: this.config.topP,
115
- top_k: this.config.topK,
116
- stop_sequences: this.config.stopSequences,
117
- metadata: this.config.metadata,
118
- });
138
+ const response = (await this.client.messages.create(this.buildMessageParams()));
119
139
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, response);
120
140
  return await this.handleResponse(response);
121
141
  }
@@ -212,19 +232,7 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
212
232
  this.addMessageToHistory("user", toolResults);
213
233
  // Continue conversation with tool results
214
234
  try {
215
- const messages = transformers_1.anthropicTransformer.toProvider(this.history.getEntries());
216
- const newResponse = await this.client.messages.create({
217
- model: this.config.model,
218
- system: this.history.getSystemMessage(),
219
- max_tokens: this.config.maxTokens,
220
- messages,
221
- tools: this.getAllToolDefinitions(),
222
- temperature: this.config.temperature,
223
- top_p: this.config.topP,
224
- top_k: this.config.topK,
225
- stop_sequences: this.config.stopSequences,
226
- metadata: this.config.metadata,
227
- });
235
+ const newResponse = (await this.client.messages.create(this.buildMessageParams()));
228
236
  this.emit(AgentEvent_1.AgentEvent.AFTER_EXECUTE, newResponse);
229
237
  return this.handleResponse(newResponse);
230
238
  }
@@ -305,6 +313,206 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
305
313
  }));
306
314
  return results;
307
315
  }
316
+ /**
317
+ * Stream a response as an async generator of `StreamChunk` objects.
318
+ * Yields `{ type: "text" }` for visible output and `{ type: "reasoning" }` for
319
+ * extended thinking tokens (models with thinking enabled). Tool calls are handled
320
+ * transparently — the generator continues streaming after each round-trip.
321
+ *
322
+ * @example
323
+ * ```typescript
324
+ * for await (const chunk of agent.executeStream("Explain recursion")) {
325
+ * if (chunk.type === "text") process.stdout.write(chunk.content);
326
+ * else process.stderr.write(`[thinking] ${chunk.content}`);
327
+ * }
328
+ * ```
329
+ */
330
+ async *executeStream(input) {
331
+ this.emit(AgentEvent_1.AgentEvent.BEFORE_EXECUTE, input);
332
+ this.lastTokenUsage = undefined;
333
+ this.currentToolCallCount = 0;
334
+ const inputPreview = typeof input === "string" ? input : JSON.stringify(input);
335
+ if (VizConfig_1.vizConfig.isEnabled()) {
336
+ this.vizEventId = VizReporter_1.vizReporter.agentStart(this.id, this.name, this.config.model, "anthropic", inputPreview);
337
+ }
338
+ if (this.history.transient) {
339
+ this.history.clear();
340
+ this.addSystemMessage(this.getSystemMessage());
341
+ }
342
+ if (typeof input === "string") {
343
+ this.addTextToHistory("user", input);
344
+ }
345
+ else {
346
+ this.addMessageToHistory("user", input);
347
+ }
348
+ this.history.setSessionAnchor();
349
+ this.history.beginExecution();
350
+ try {
351
+ yield* this.streamTurn();
352
+ }
353
+ catch (error) {
354
+ if (error instanceof sdk_1.APIError) {
355
+ const apiError = new AgentError_1.ApiError(`Anthropic API error: ${error.message}`, error.status, error);
356
+ this.emit(AgentEvent_1.AgentEvent.ERROR, apiError);
357
+ if (this.vizEventId) {
358
+ VizReporter_1.vizReporter.agentError(this.vizEventId, "ApiError", apiError.message, error.status === 429);
359
+ this.vizEventId = undefined;
360
+ }
361
+ throw apiError;
362
+ }
363
+ // Errors raised inside streamTurn() (e.g. MaxTokensExceededError) are
364
+ // already emitted and viz-reported at the throw site — preserve their
365
+ // type rather than re-wrapping them in a generic ExecutionError.
366
+ if (error instanceof AgentError_1.AgentError) {
367
+ throw error;
368
+ }
369
+ const executionError = new AgentError_1.ExecutionError(`Anthropic error: ${error instanceof Error ? error.message : "Unknown error"}`);
370
+ this.emit(AgentEvent_1.AgentEvent.ERROR, executionError);
371
+ if (this.vizEventId) {
372
+ VizReporter_1.vizReporter.agentError(this.vizEventId, "ExecutionError", executionError.message, false);
373
+ this.vizEventId = undefined;
374
+ }
375
+ throw executionError;
376
+ }
377
+ finally {
378
+ this.history.endExecution();
379
+ }
380
+ }
381
+ async *streamTurn() {
382
+ const stream = await this.client.messages.create({
383
+ ...this.buildMessageParams(),
384
+ stream: true,
385
+ });
386
+ const blocks = new Map();
387
+ let textContent = "";
388
+ let stopReason = null;
389
+ let inputTokens = 0;
390
+ let outputTokens = 0;
391
+ for await (const event of stream) {
392
+ if (event.type === "message_start") {
393
+ const e = event;
394
+ inputTokens = e.message.usage.input_tokens;
395
+ outputTokens = e.message.usage.output_tokens;
396
+ }
397
+ if (event.type === "message_delta") {
398
+ const e = event;
399
+ stopReason = e.delta.stop_reason ?? stopReason;
400
+ outputTokens += e.usage?.output_tokens ?? 0;
401
+ }
402
+ if (event.type === "content_block_start") {
403
+ const e = event;
404
+ const block = e.content_block;
405
+ if (block.type === "tool_use") {
406
+ blocks.set(e.index, { kind: "tool_use", id: block.id, name: block.name, inputJson: "" });
407
+ }
408
+ else if (block.type === "text") {
409
+ blocks.set(e.index, { kind: "text", text: "" });
410
+ }
411
+ else if (block.type === "thinking") {
412
+ blocks.set(e.index, { kind: "thinking", thinking: "", signature: "" });
413
+ }
414
+ else if (block.type === "redacted_thinking") {
415
+ blocks.set(e.index, { kind: "redacted_thinking", data: block.data });
416
+ }
417
+ }
418
+ if (event.type === "content_block_delta") {
419
+ const e = event;
420
+ const delta = e.delta;
421
+ const acc = blocks.get(e.index);
422
+ if (delta.type === "text_delta") {
423
+ textContent += delta.text;
424
+ if (acc?.kind === "text")
425
+ acc.text += delta.text;
426
+ this.emit(AgentEvent_1.AgentEvent.CHUNK, delta.text);
427
+ yield { type: "text", content: delta.text };
428
+ }
429
+ else if (delta.type === "thinking_delta") {
430
+ if (acc?.kind === "thinking")
431
+ acc.thinking += delta.thinking;
432
+ this.emit(AgentEvent_1.AgentEvent.REASONING_CHUNK, delta.thinking);
433
+ yield { type: "reasoning", content: delta.thinking };
434
+ }
435
+ else if (delta.type === "signature_delta") {
436
+ if (acc?.kind === "thinking")
437
+ acc.signature += delta.signature;
438
+ }
439
+ else if (delta.type === "input_json_delta") {
440
+ if (acc?.kind === "tool_use")
441
+ acc.inputJson += delta.partial_json;
442
+ }
443
+ }
444
+ }
445
+ const usage = {
446
+ input_tokens: inputTokens,
447
+ output_tokens: outputTokens,
448
+ 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
+ }
458
+ if (stopReason === "max_tokens") {
459
+ const error = new AgentError_1.MaxTokensExceededError("Response exceeded maximum token limit", this.config.maxTokens || 1024);
460
+ this.emit(AgentEvent_1.AgentEvent.MAX_TOKENS_EXCEEDED, error);
461
+ this.emit(AgentEvent_1.AgentEvent.ERROR, error);
462
+ if (this.vizEventId) {
463
+ VizReporter_1.vizReporter.agentError(this.vizEventId, "MaxTokensExceededError", error.message, false);
464
+ this.vizEventId = undefined;
465
+ }
466
+ throw error;
467
+ }
468
+ // Rebuild the assistant turn in stream order (thinking → text → tool_use).
469
+ const orderedBlocks = Array.from(blocks.entries())
470
+ .sort(([a], [b]) => a - b)
471
+ .map(([, b]) => {
472
+ switch (b.kind) {
473
+ case "thinking":
474
+ return { type: "thinking", thinking: b.thinking, signature: b.signature };
475
+ case "redacted_thinking":
476
+ return { type: "redacted_thinking", data: b.data };
477
+ case "tool_use":
478
+ return {
479
+ type: "tool_use",
480
+ id: b.id,
481
+ name: b.name,
482
+ input: JSON.parse(b.inputJson || "{}"),
483
+ };
484
+ case "text":
485
+ return { type: "text", text: b.text, citations: [] };
486
+ }
487
+ });
488
+ // Fallback: preserve streamed text even if no text block start was observed.
489
+ if (textContent && !orderedBlocks.some((b) => b.type === "text")) {
490
+ orderedBlocks.push({ type: "text", text: textContent, citations: [] });
491
+ }
492
+ const toolUseBlocks = orderedBlocks.filter((b) => b.type === "tool_use");
493
+ if (stopReason === "tool_use" && toolUseBlocks.length > 0) {
494
+ this.emit(AgentEvent_1.AgentEvent.TOOL_USE, orderedBlocks);
495
+ this.currentToolCallCount += toolUseBlocks.length;
496
+ const assistantEntry = transformers_1.anthropicTransformer.fromProviderContent("assistant", orderedBlocks);
497
+ this.addToHistory(assistantEntry);
498
+ const toolResults = await this.handleToolUse(orderedBlocks);
499
+ this.addMessageToHistory("user", toolResults);
500
+ yield* this.streamTurn();
501
+ }
502
+ else {
503
+ const assistantEntry = transformers_1.anthropicTransformer.fromProviderContent("assistant", orderedBlocks);
504
+ this.addToHistory(assistantEntry);
505
+ this.emit(AgentEvent_1.AgentEvent.DONE, { content: textContent }, this.lastTokenUsage);
506
+ if (this.vizEventId) {
507
+ VizReporter_1.vizReporter.agentComplete(this.vizEventId, {
508
+ input: this.lastTokenUsage?.input_tokens || 0,
509
+ output: this.lastTokenUsage?.output_tokens || 0,
510
+ total: this.lastTokenUsage?.total_tokens || 0,
511
+ }, "end_turn", this.currentToolCallCount > 0, this.currentToolCallCount, textContent);
512
+ this.vizEventId = undefined;
513
+ }
514
+ }
515
+ }
308
516
  parseUsage(input) {
309
517
  return {
310
518
  input_tokens: input.input_tokens,
@@ -118,7 +118,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
118
118
  items: this.convertPropertyToSchema(prop.items),
119
119
  description,
120
120
  };
121
- case "object":
121
+ case "object": {
122
122
  const objProps = {};
123
123
  if (prop.properties) {
124
124
  const subProps = prop.properties;
@@ -132,6 +132,7 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
132
132
  description,
133
133
  required: prop.required,
134
134
  };
135
+ }
135
136
  default:
136
137
  return { type: generative_ai_1.SchemaType.STRING, description };
137
138
  }
@@ -1,13 +1,10 @@
1
- import { ChatCompletion, ChatCompletionTool } from "openai/resources/chat/completions";
2
- import { Model } from "openai/resources/models";
3
- import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
4
- import { History, MessageContent } from "../../history/History";
1
+ import { History } from "../../history/History";
2
+ import { OpenAICompatibleAgent, OpenAICompatibleConfig } from "../openai-compatible/OpenAICompatibleAgent";
5
3
  import { LlamaCppModel } from "../model-types";
6
- type AgentConfig = BaseAgentConfig & {
4
+ type LlamaCppConfig = Omit<OpenAICompatibleConfig, "baseURL" | "model" | "vendor"> & {
7
5
  /** Base URL of the llama.cpp server's OpenAI-compatible API (default: `http://localhost:8080/v1`) */
8
6
  baseURL?: string;
9
7
  model?: LlamaCppModel;
10
- maxTokens?: number;
11
8
  };
12
9
  /**
13
10
  * Agent for locally-hosted models served by a llama.cpp server (`llama-server`),
@@ -21,7 +18,6 @@ type AgentConfig = BaseAgentConfig & {
21
18
  * id: "1",
22
19
  * name: "Assistant",
23
20
  * description: "A helpful assistant",
24
- * apiKey: "",
25
21
  * baseURL: "http://localhost:8080/v1",
26
22
  * });
27
23
  *
@@ -33,28 +29,9 @@ type AgentConfig = BaseAgentConfig & {
33
29
  * const models = await agent.listModels();
34
30
  * ```
35
31
  */
36
- export declare class LlamaCppAgent extends BaseAgent {
37
- private client;
38
- protected config: Partial<AgentConfig>;
39
- /** Token usage from the last execution (for metrics tracking) */
40
- lastTokenUsage?: TokenUsage;
41
- /** Current visualization event ID */
42
- private vizEventId?;
43
- /** Count of tool calls in current execution */
44
- private currentToolCallCount;
45
- constructor(config: Omit<AgentConfig, "vendor">, history?: History);
46
- /**
47
- * List the models currently available on the llama.cpp server (via its
48
- * OpenAI-compatible `/v1/models` endpoint).
49
- */
50
- listModels(): Promise<Model[]>;
51
- protected getToolDefinitions(): ChatCompletionTool[];
52
- protected process(_input: string): Promise<string>;
53
- execute(input: string | MessageContent[]): Promise<string>;
54
- private callLlamaCpp;
55
- protected handleResponse(response: ChatCompletion): Promise<string>;
56
- private handleToolCalls;
57
- protected parseUsage(response: ChatCompletion): TokenUsage;
32
+ export declare class LlamaCppAgent extends OpenAICompatibleAgent {
33
+ constructor(config: LlamaCppConfig, history?: History);
34
+ protected getVendorName(): string;
58
35
  }
59
36
  export {};
60
37
  //# sourceMappingURL=LlamaCppAgent.d.ts.map