@agentionai/agents 1.4.0 → 1.5.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,7 +75,7 @@ import { ClaudeAgent, OpenAiAgent } from '@agentionai/agents';
75
75
 
76
76
  ## Features
77
77
 
78
- - **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
+ - **Multi-Provider, No Lock-in** - Claude, OpenAI, Gemini, Mistral, plus local models via Ollama and llama.cpp—same interface. Switch models with one line. `listModels()` asks any provider what it currently offers, in one shared shape.
79
79
  - **Composable Context Management** - Tool result masking (lossless, free) + rolling summarization (auto-firing) + sub-agent delegation (token isolation by architecture).
80
80
  - **Streaming** - `executeStream()` on Claude, OpenAI, and all OpenAI-compatible agents. Yields `{ type: "text" | "reasoning" }` chunks; tool calls handled transparently.
81
81
  - **Built-In Tools** - Use provider-defined server-side tools (e.g. Anthropic's web search, bash, text editor) alongside your own.
@@ -67,6 +67,41 @@ export type TokenUsage = {
67
67
  */
68
68
  outputTokensPerSecond?: number;
69
69
  };
70
+ /**
71
+ * A model as reported by a provider's models endpoint, in a shape that is the
72
+ * same on every provider.
73
+ *
74
+ * Only `id` — the value you pass as `model` in an agent config — is guaranteed.
75
+ * Every other field is optional because no two providers report the same set:
76
+ * Anthropic gives a display name and release date but no context window,
77
+ * OpenAI gives an owner and a creation timestamp, Mistral and Gemini give
78
+ * context limits. The provider's own untouched entry is always available on
79
+ * `raw` for anything not covered here.
80
+ */
81
+ export type ModelInfo<TRaw = unknown> = {
82
+ /** Model identifier, as passed to the API in the `model` field. */
83
+ id: string;
84
+ /** Human-readable name, where the provider reports one. */
85
+ displayName?: string;
86
+ /** Release or creation date, where the provider reports one. */
87
+ created?: Date;
88
+ /** Owning organisation, where the provider reports one. */
89
+ ownedBy?: string;
90
+ /** Maximum input context in tokens, where the provider reports one. */
91
+ contextLength?: number;
92
+ /**
93
+ * Whether the model is currently held in memory, on servers that distinguish
94
+ * "offered" from "loaded" — llama.cpp's model router being the case in point,
95
+ * where an unloaded model is listed but has to be loaded before it answers.
96
+ *
97
+ * Undefined wherever the distinction does not exist or is not reported: every
98
+ * hosted provider, and a single-model `llama-server`, where the one model
99
+ * listed is by definition the loaded one.
100
+ */
101
+ loaded?: boolean;
102
+ /** The provider's unmodified entry for this model. */
103
+ raw: TRaw;
104
+ };
70
105
  /**
71
106
  * The base agent is what the other agents are inheriting from
72
107
  * Handles the BaseConfig
@@ -107,6 +142,19 @@ export declare abstract class BaseAgent<TInput = unknown, TOutput = unknown> ext
107
142
  protected abstract process(input: TInput): Promise<TOutput>;
108
143
  protected abstract handleResponse(response: unknown): Promise<unknown>;
109
144
  protected getToolDefinitions(): unknown[];
145
+ /**
146
+ * List the models the provider currently offers, straight from its models
147
+ * endpoint — the live answer, as opposed to the hand-maintained unions in
148
+ * `model-types.ts`.
149
+ *
150
+ * Overridden by every built-in agent; the base implementation throws so that
151
+ * a custom agent without a models endpoint fails with a clear message rather
152
+ * than silently returning nothing.
153
+ *
154
+ * @throws {ExecutionError} If the provider does not support listing, or the
155
+ * request fails.
156
+ */
157
+ listModels(): Promise<ModelInfo[]>;
110
158
  /**
111
159
  * Add an entry to history
112
160
  */
@@ -7,6 +7,7 @@ exports.BaseAgent = void 0;
7
7
  const events_1 = __importDefault(require("events"));
8
8
  const Tool_1 = require("../tools/Tool");
9
9
  const History_1 = require("../history/History");
10
+ const AgentError_1 = require("./errors/AgentError");
10
11
  /**
11
12
  * The base agent is what the other agents are inheriting from
12
13
  * Handles the BaseConfig
@@ -49,6 +50,21 @@ class BaseAgent extends events_1.default {
49
50
  getToolDefinitions() {
50
51
  return Array.from(this.tools.values()).map((tool) => tool.getPrompt());
51
52
  }
53
+ /**
54
+ * List the models the provider currently offers, straight from its models
55
+ * endpoint — the live answer, as opposed to the hand-maintained unions in
56
+ * `model-types.ts`.
57
+ *
58
+ * Overridden by every built-in agent; the base implementation throws so that
59
+ * a custom agent without a models endpoint fails with a clear message rather
60
+ * than silently returning nothing.
61
+ *
62
+ * @throws {ExecutionError} If the provider does not support listing, or the
63
+ * request fails.
64
+ */
65
+ async listModels() {
66
+ throw new AgentError_1.ExecutionError(`listModels() is not implemented for the '${this.vendor}' agent`);
67
+ }
52
68
  /**
53
69
  * Add an entry to history
54
70
  */
@@ -1,8 +1,8 @@
1
1
  import { Anthropic } from "@anthropic-ai/sdk";
2
- import { Message, ToolUnion, Usage } from "@anthropic-ai/sdk/resources";
2
+ import { Message, type ModelInfo as AnthropicModelInfo, ToolUnion, Usage } from "@anthropic-ai/sdk/resources";
3
3
  import { type ToolDefinition } from "../../tools/Tool";
4
4
  import { type BuiltInTool } from "../../tools/BuiltInTool";
5
- import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
5
+ import { BaseAgent, BaseAgentConfig, ModelInfo, TokenUsage } from "../BaseAgent";
6
6
  import { History, MessageContent } from "../../history/History";
7
7
  import { StreamChunk } from "../openai-compatible/OpenAICompatibleAgent";
8
8
  import { ClaudeModel } from "../model-types";
@@ -55,6 +55,14 @@ export declare class ClaudeAgent extends BaseAgent {
55
55
  private currentToolCallCount;
56
56
  constructor(config: Omit<AgentConfig, "vendor">, history?: History);
57
57
  protected getToolDefinitions(): ToolDefinition[];
58
+ /**
59
+ * List the models available to this API key, newest first.
60
+ *
61
+ * Anthropic reports a display name and release date but no context window,
62
+ * so `contextLength` is always undefined here. The result is fully
63
+ * paginated — the endpoint pages at 1000 models.
64
+ */
65
+ listModels(): Promise<ModelInfo<AnthropicModelInfo>[]>;
58
66
  /**
59
67
  * Combine locally-executed tool definitions with provider-defined
60
68
  * (server-side) built-in tools, in the shape Anthropic's API expects.
@@ -62,6 +62,30 @@ class ClaudeAgent extends BaseAgent_1.BaseAgent {
62
62
  getToolDefinitions() {
63
63
  return Array.from(this.tools.values()).map((tool) => tool.getPrompt());
64
64
  }
65
+ /**
66
+ * List the models available to this API key, newest first.
67
+ *
68
+ * Anthropic reports a display name and release date but no context window,
69
+ * so `contextLength` is always undefined here. The result is fully
70
+ * paginated — the endpoint pages at 1000 models.
71
+ */
72
+ async listModels() {
73
+ try {
74
+ const models = [];
75
+ for await (const model of this.client.models.list({ limit: 1000 })) {
76
+ models.push({
77
+ id: model.id,
78
+ displayName: model.display_name,
79
+ created: new Date(model.created_at),
80
+ raw: model,
81
+ });
82
+ }
83
+ return models;
84
+ }
85
+ catch (error) {
86
+ throw new AgentError_1.ExecutionError(`Failed to list Anthropic models: ${error instanceof Error ? error.message : "Unknown error"}`);
87
+ }
88
+ }
65
89
  /**
66
90
  * Combine locally-executed tool definitions with provider-defined
67
91
  * (server-side) built-in tools, in the shape Anthropic's API expects.
@@ -1,7 +1,29 @@
1
1
  import { FunctionDeclarationsTool, GenerateContentResult, Schema } from "@google/generative-ai";
2
- import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
2
+ import { BaseAgent, BaseAgentConfig, ModelInfo, TokenUsage } from "../BaseAgent";
3
3
  import { History, MessageContent } from "../../history/History";
4
4
  import { GeminiModel } from "../model-types";
5
+ /**
6
+ * One entry from the Generative Language API's `models.list` response.
7
+ *
8
+ * Declared here rather than imported: `@google/generative-ai` only covers
9
+ * content generation and ships no type for the models endpoint.
10
+ */
11
+ export type GeminiModelCard = {
12
+ /** Resource name, e.g. `"models/gemini-flash-latest"`. */
13
+ name: string;
14
+ baseModelId?: string;
15
+ version?: string;
16
+ displayName?: string;
17
+ description?: string;
18
+ inputTokenLimit?: number;
19
+ outputTokenLimit?: number;
20
+ /** e.g. `["generateContent", "countTokens"]` — an embedding model has neither. */
21
+ supportedGenerationMethods?: string[];
22
+ temperature?: number;
23
+ maxTemperature?: number;
24
+ topP?: number;
25
+ topK?: number;
26
+ };
5
27
  type AgentConfig = BaseAgentConfig & {
6
28
  apiKey: string;
7
29
  model?: GeminiModel;
@@ -34,6 +56,18 @@ export declare class GeminiAgent extends BaseAgent {
34
56
  /** Count of tool calls in current execution */
35
57
  private currentToolCallCount;
36
58
  constructor(config: Omit<AgentConfig, "vendor">, history?: History);
59
+ /**
60
+ * List the models available to this API key.
61
+ *
62
+ * Issued as a direct request to `/v1beta/models`: `@google/generative-ai`
63
+ * exposes no models endpoint, so there is no client method to call. Every
64
+ * page is followed, and the `"models/"` prefix is stripped from `id` so the
65
+ * value can be passed straight back as an agent's `model`.
66
+ *
67
+ * The list includes embedding models; filter on
68
+ * `raw.supportedGenerationMethods` for the ones this agent can drive.
69
+ */
70
+ listModels(): Promise<ModelInfo<GeminiModelCard>[]>;
37
71
  protected getToolDefinitionsForGemini(): FunctionDeclarationsTool | undefined;
38
72
  /**
39
73
  * Convert JSON Schema to Gemini's FunctionDeclarationSchema format
@@ -8,6 +8,8 @@ const AgentError_1 = require("../errors/AgentError");
8
8
  const transformers_1 = require("../../history/transformers");
9
9
  const VizReporter_1 = require("../../viz/VizReporter");
10
10
  const VizConfig_1 = require("../../viz/VizConfig");
11
+ /** Base URL of the Generative Language API, matching the SDK's own default. */
12
+ const GEMINI_API_BASE = "https://generativelanguage.googleapis.com";
11
13
  /**
12
14
  * Agent for Google Gemini models.
13
15
  *
@@ -45,12 +47,60 @@ class GeminiAgent extends BaseAgent_1.BaseAgent {
45
47
  candidateCount,
46
48
  responseMimeType,
47
49
  responseSchema,
50
+ defaultHeaders: config.defaultHeaders,
48
51
  };
49
52
  // Initialize the model
50
53
  this.generativeModel = this.client.getGenerativeModel({ model: this.config.model }, config.defaultHeaders ? { customHeaders: config.defaultHeaders } : undefined);
51
54
  // Add system message to history (skips if already exists with same content)
52
55
  this.addSystemMessage(this.getSystemMessage());
53
56
  }
57
+ /**
58
+ * List the models available to this API key.
59
+ *
60
+ * Issued as a direct request to `/v1beta/models`: `@google/generative-ai`
61
+ * exposes no models endpoint, so there is no client method to call. Every
62
+ * page is followed, and the `"models/"` prefix is stripped from `id` so the
63
+ * value can be passed straight back as an agent's `model`.
64
+ *
65
+ * The list includes embedding models; filter on
66
+ * `raw.supportedGenerationMethods` for the ones this agent can drive.
67
+ */
68
+ async listModels() {
69
+ try {
70
+ const models = [];
71
+ let pageToken;
72
+ do {
73
+ const url = new URL(`${GEMINI_API_BASE}/v1beta/models`);
74
+ url.searchParams.set("pageSize", "1000");
75
+ if (pageToken) {
76
+ url.searchParams.set("pageToken", pageToken);
77
+ }
78
+ const response = await fetch(url, {
79
+ headers: {
80
+ "x-goog-api-key": this.config.apiKey,
81
+ ...this.config.defaultHeaders,
82
+ },
83
+ });
84
+ if (!response.ok) {
85
+ throw new Error(`${response.status} ${response.statusText}: ${await response.text()}`);
86
+ }
87
+ const body = (await response.json());
88
+ for (const model of body.models ?? []) {
89
+ models.push({
90
+ id: model.name.replace(/^models\//, ""),
91
+ displayName: model.displayName,
92
+ contextLength: model.inputTokenLimit,
93
+ raw: model,
94
+ });
95
+ }
96
+ pageToken = body.nextPageToken;
97
+ } while (pageToken);
98
+ return models;
99
+ }
100
+ catch (error) {
101
+ throw new AgentError_1.ExecutionError(`Failed to list Gemini models: ${error instanceof Error ? error.message : "Unknown error"}`);
102
+ }
103
+ }
54
104
  getToolDefinitionsForGemini() {
55
105
  const tools = Array.from(this.tools.values());
56
106
  if (tools.length === 0) {
@@ -1,6 +1,56 @@
1
+ import { Model } from "openai/resources/models";
1
2
  import { History } from "../../history/History";
3
+ import { ModelInfo } from "../BaseAgent";
2
4
  import { OpenAICompatibleAgent, OpenAICompatibleConfig } from "../openai-compatible/OpenAICompatibleAgent";
3
5
  import { LlamaCppModel } from "../model-types";
6
+ /**
7
+ * The GGUF details `llama-server` reports for a model it has loaded. Absent
8
+ * from the listing for a model the router knows about but has not loaded.
9
+ */
10
+ export type LlamaCppModelMeta = {
11
+ vocab_type?: number;
12
+ n_vocab?: number;
13
+ /** Context the model was actually loaded with (`--ctx-size`). */
14
+ n_ctx?: number;
15
+ /** Context the model was trained with — its ceiling, not its current size. */
16
+ n_ctx_train?: number;
17
+ n_embd?: number;
18
+ n_params?: number;
19
+ /** On-disk size in bytes. */
20
+ size?: number;
21
+ /** Quantization, e.g. `"Q6_K"`. */
22
+ ftype?: string;
23
+ };
24
+ /**
25
+ * One entry from a llama.cpp server's `/v1/models`.
26
+ *
27
+ * Everything past the OpenAI-standard fields is optional because it depends on
28
+ * how the server was started: a single-model `llama-server` reports `meta` for
29
+ * the model it is serving and nothing else, while a server in model-router mode
30
+ * lists every model it can serve, each with a `status` saying whether it is
31
+ * currently loaded. Verified against llama.cpp b10148.
32
+ */
33
+ export type LlamaCppModelCard = Model & {
34
+ /** Alternative ids that resolve to this model. */
35
+ aliases?: string[];
36
+ tags?: string[];
37
+ /** Router mode only: whether the model is in memory, and how it is launched. */
38
+ status?: {
39
+ value: "loaded" | "unloaded" | (string & {});
40
+ /** The `llama-server` argv the router uses to bring this model up. */
41
+ args?: string[];
42
+ /** The preset block backing this model, as INI text. */
43
+ preset?: string;
44
+ };
45
+ architecture?: {
46
+ input_modalities?: string[];
47
+ output_modalities?: string[];
48
+ };
49
+ /** Where the router got the model — a config preset or the local HF cache. */
50
+ source?: "preset" | "cache" | (string & {});
51
+ can_remove?: boolean;
52
+ meta?: LlamaCppModelMeta;
53
+ };
4
54
  type LlamaCppConfig = Omit<OpenAICompatibleConfig, "baseURL" | "model" | "vendor"> & {
5
55
  /** Base URL of the llama.cpp server's OpenAI-compatible API (default: `http://localhost:8080/v1`) */
6
56
  baseURL?: string;
@@ -32,6 +82,20 @@ type LlamaCppConfig = Omit<OpenAICompatibleConfig, "baseURL" | "model" | "vendor
32
82
  export declare class LlamaCppAgent extends OpenAICompatibleAgent {
33
83
  constructor(config: LlamaCppConfig, history?: History);
34
84
  protected getVendorName(): string;
85
+ /**
86
+ * List the models the server offers, adding the two things llama.cpp reports
87
+ * beyond the OpenAI-standard fields:
88
+ *
89
+ * - `loaded` — in model-router mode a listed model is not necessarily in
90
+ * memory; an unloaded one has to be loaded before it answers. Left
91
+ * undefined by a single-model server, which reports no status at all.
92
+ * - `contextLength` — `meta.n_ctx`, the context the model was actually loaded
93
+ * with, falling back to the trained ceiling `n_ctx_train`. Only loaded
94
+ * models carry `meta`.
95
+ *
96
+ * The rest — launch args, presets, modalities, quantization — is on `raw`.
97
+ */
98
+ listModels(): Promise<ModelInfo<LlamaCppModelCard>[]>;
35
99
  }
36
100
  export {};
37
101
  //# sourceMappingURL=LlamaCppAgent.d.ts.map
@@ -39,6 +39,29 @@ class LlamaCppAgent extends OpenAICompatibleAgent_1.OpenAICompatibleAgent {
39
39
  getVendorName() {
40
40
  return "llama.cpp";
41
41
  }
42
+ /**
43
+ * List the models the server offers, adding the two things llama.cpp reports
44
+ * beyond the OpenAI-standard fields:
45
+ *
46
+ * - `loaded` — in model-router mode a listed model is not necessarily in
47
+ * memory; an unloaded one has to be loaded before it answers. Left
48
+ * undefined by a single-model server, which reports no status at all.
49
+ * - `contextLength` — `meta.n_ctx`, the context the model was actually loaded
50
+ * with, falling back to the trained ceiling `n_ctx_train`. Only loaded
51
+ * models carry `meta`.
52
+ *
53
+ * The rest — launch args, presets, modalities, quantization — is on `raw`.
54
+ */
55
+ async listModels() {
56
+ const models = (await super.listModels());
57
+ return models.map((model) => ({
58
+ ...model,
59
+ loaded: model.raw.status
60
+ ? model.raw.status.value === "loaded"
61
+ : undefined,
62
+ contextLength: model.raw.meta?.n_ctx ?? model.raw.meta?.n_ctx_train,
63
+ }));
64
+ }
42
65
  }
43
66
  exports.LlamaCppAgent = LlamaCppAgent;
44
67
  //# sourceMappingURL=LlamaCppAgent.js.map
@@ -1,7 +1,13 @@
1
- import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
1
+ import { BaseAgent, BaseAgentConfig, ModelInfo, TokenUsage } from "../BaseAgent";
2
2
  import { History, MessageContent } from "../../history/History";
3
- import { ChatCompletionResponse, Tool, UsageInfo } from "@mistralai/mistralai/models/components";
3
+ import { ChatCompletionResponse, ModelList, Tool, UsageInfo } from "@mistralai/mistralai/models/components";
4
4
  import { MistralModel } from "../model-types";
5
+ /**
6
+ * One entry from Mistral's `/v1/models` response — a base model card or a
7
+ * fine-tuned one. Derived from the SDK's `ModelList` rather than imported
8
+ * directly, since the SDK exports the union under the unhelpful name `Data`.
9
+ */
10
+ export type MistralModelCard = NonNullable<ModelList["data"]>[number];
5
11
  type AgentConfig = BaseAgentConfig & {
6
12
  apiKey: string;
7
13
  model?: MistralModel;
@@ -44,6 +50,13 @@ export declare class MistralAgent extends BaseAgent {
44
50
  /** Count of tool calls in current execution */
45
51
  private currentToolCallCount;
46
52
  constructor(config: Omit<AgentConfig, "vendor">, history?: History);
53
+ /**
54
+ * List the models available to this API key, base and fine-tuned alike.
55
+ *
56
+ * Mistral reports a context window, which lands on `contextLength`; the
57
+ * per-model `capabilities` flags (function calling, vision, …) are on `raw`.
58
+ */
59
+ listModels(): Promise<ModelInfo<MistralModelCard>[]>;
47
60
  protected getToolDefinitions(): Tool[];
48
61
  protected process(_input: string): Promise<string>;
49
62
  execute(input: string | MessageContent[]): Promise<string>;
@@ -80,6 +80,28 @@ class MistralAgent extends BaseAgent_1.BaseAgent {
80
80
  // Add system message to history (skips if already exists with same content)
81
81
  this.addSystemMessage(this.getSystemMessage());
82
82
  }
83
+ /**
84
+ * List the models available to this API key, base and fine-tuned alike.
85
+ *
86
+ * Mistral reports a context window, which lands on `contextLength`; the
87
+ * per-model `capabilities` flags (function calling, vision, …) are on `raw`.
88
+ */
89
+ async listModels() {
90
+ try {
91
+ const response = await this.client.models.list();
92
+ return (response.data ?? []).map((model) => ({
93
+ id: model.id,
94
+ displayName: model.name ?? undefined,
95
+ created: model.created ? new Date(model.created * 1000) : undefined,
96
+ ownedBy: model.ownedBy,
97
+ contextLength: model.maxContextLength,
98
+ raw: model,
99
+ }));
100
+ }
101
+ catch (error) {
102
+ throw new AgentError_1.ExecutionError(`Failed to list Mistral models: ${error instanceof Error ? error.message : "Unknown error"}`);
103
+ }
104
+ }
83
105
  getToolDefinitions() {
84
106
  return Array.from(this.tools.values()).map((tool) => ({
85
107
  type: components_1.ToolTypes.Function,
@@ -1,4 +1,4 @@
1
- import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
1
+ import { BaseAgent, BaseAgentConfig, ModelInfo, TokenUsage } from "../BaseAgent";
2
2
  import { History, MessageContent } from "../../history/History";
3
3
  import { OllamaModel } from "../model-types";
4
4
  type AgentConfig = BaseAgentConfig & {
@@ -56,8 +56,12 @@ export declare class OllamaAgent extends BaseAgent {
56
56
  private getClient;
57
57
  /**
58
58
  * List the models currently available on the Ollama server.
59
+ *
60
+ * `id` is the tag to pass as `model` (e.g. `"llama3.2:latest"`) and `created`
61
+ * carries the local `modified_at` timestamp — Ollama reports when a model was
62
+ * last pulled or changed on this machine, not when it was released.
59
63
  */
60
- listModels(): Promise<OllamaModelInfo[]>;
64
+ listModels(): Promise<ModelInfo<OllamaModelInfo>[]>;
61
65
  protected getToolDefinitions(): OllamaToolDefinition[];
62
66
  protected process(_input: string): Promise<string>;
63
67
  execute(input: string | MessageContent[]): Promise<string>;
@@ -113,12 +113,21 @@ class OllamaAgent extends BaseAgent_1.BaseAgent {
113
113
  }
114
114
  /**
115
115
  * List the models currently available on the Ollama server.
116
+ *
117
+ * `id` is the tag to pass as `model` (e.g. `"llama3.2:latest"`) and `created`
118
+ * carries the local `modified_at` timestamp — Ollama reports when a model was
119
+ * last pulled or changed on this machine, not when it was released.
116
120
  */
117
121
  async listModels() {
118
122
  try {
119
123
  const client = await this.getClient();
120
124
  const response = await client.list();
121
- return response.models;
125
+ return response.models.map((model) => ({
126
+ id: model.model,
127
+ displayName: model.name,
128
+ created: model.modified_at ? new Date(model.modified_at) : undefined,
129
+ raw: model,
130
+ }));
122
131
  }
123
132
  catch (error) {
124
133
  throw new AgentError_1.ExecutionError(`Failed to list Ollama models: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -1,6 +1,7 @@
1
- import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
1
+ import { BaseAgent, BaseAgentConfig, ModelInfo, TokenUsage } from "../BaseAgent";
2
2
  import { History, MessageContent } from "../../history/History";
3
3
  import { Tool, Response, ResponseUsage } from "openai/resources/responses/responses";
4
+ import type { Model as OpenAIModelCard } from "openai/resources/models";
4
5
  import { OpenAIModel, ReasoningEffort, ReasoningEffortFor } from "../model-types";
5
6
  import { StreamChunk } from "../openai-compatible/OpenAICompatibleAgent";
6
7
  type AgentConfig<M extends OpenAIModel = OpenAIModel> = BaseAgentConfig & {
@@ -67,6 +68,14 @@ export declare class OpenAiAgent<M extends OpenAIModel = OpenAIModel> extends Ba
67
68
  /** Count of tool calls in current execution */
68
69
  private currentToolCallCount;
69
70
  constructor(config: Omit<AgentConfig<M>, "vendor">, history?: History);
71
+ /**
72
+ * List the models available to this API key.
73
+ *
74
+ * The list covers everything the key can reach — chat, embedding, audio and
75
+ * image models alike — so filter by `id` if you only want the ones this
76
+ * agent can drive.
77
+ */
78
+ listModels(): Promise<ModelInfo<OpenAIModelCard>[]>;
70
79
  protected getToolDefinitions(): Tool[];
71
80
  /**
72
81
  * Build the `reasoning` field for a Responses API request, as an object to
@@ -87,6 +87,27 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
87
87
  // Add system message to history (skips if already exists with same content)
88
88
  this.addSystemMessage(this.getSystemMessage());
89
89
  }
90
+ /**
91
+ * List the models available to this API key.
92
+ *
93
+ * The list covers everything the key can reach — chat, embedding, audio and
94
+ * image models alike — so filter by `id` if you only want the ones this
95
+ * agent can drive.
96
+ */
97
+ async listModels() {
98
+ try {
99
+ const page = await this.client.models.list();
100
+ return page.data.map((model) => ({
101
+ id: model.id,
102
+ created: model.created ? new Date(model.created * 1000) : undefined,
103
+ ownedBy: model.owned_by,
104
+ raw: model,
105
+ }));
106
+ }
107
+ catch (error) {
108
+ throw new AgentError_1.ExecutionError(`Failed to list OpenAI models: ${error instanceof Error ? error.message : "Unknown error"}`);
109
+ }
110
+ }
90
111
  getToolDefinitions() {
91
112
  return Array.from(this.tools.values()).map((tool) => {
92
113
  const prompt = tool.getPrompt();
@@ -1,7 +1,7 @@
1
1
  import OpenAI from "openai";
2
2
  import { ChatCompletion, ChatCompletionTool } from "openai/resources/chat/completions";
3
3
  import { Model } from "openai/resources/models";
4
- import { BaseAgent, BaseAgentConfig, TokenUsage } from "../BaseAgent";
4
+ import { BaseAgent, BaseAgentConfig, ModelInfo, TokenUsage } from "../BaseAgent";
5
5
  import { AgentVendor } from "../AgentConfig";
6
6
  import { History, MessageContent } from "../../history/History";
7
7
  /**
@@ -43,8 +43,11 @@ export declare abstract class OpenAICompatibleAgent extends BaseAgent {
43
43
  protected buildExtraRequestParams(): Record<string, unknown>;
44
44
  /**
45
45
  * List the models available on the server via the `/v1/models` endpoint.
46
+ *
47
+ * Local servers vary in how much they fill in — llama.cpp reports little
48
+ * beyond the id — so most fields other than `id` are typically undefined.
46
49
  */
47
- listModels(): Promise<Model[]>;
50
+ listModels(): Promise<ModelInfo<Model>[]>;
48
51
  protected getToolDefinitions(): ChatCompletionTool[];
49
52
  protected process(_input: string): Promise<string>;
50
53
  execute(input: string | MessageContent[]): Promise<string>;
@@ -50,11 +50,19 @@ class OpenAICompatibleAgent extends BaseAgent_1.BaseAgent {
50
50
  }
51
51
  /**
52
52
  * List the models available on the server via the `/v1/models` endpoint.
53
+ *
54
+ * Local servers vary in how much they fill in — llama.cpp reports little
55
+ * beyond the id — so most fields other than `id` are typically undefined.
53
56
  */
54
57
  async listModels() {
55
58
  try {
56
59
  const page = await this.client.models.list();
57
- return page.data;
60
+ return page.data.map((model) => ({
61
+ id: model.id,
62
+ created: model.created ? new Date(model.created * 1000) : undefined,
63
+ ownedBy: model.owned_by,
64
+ raw: model,
65
+ }));
58
66
  }
59
67
  catch (error) {
60
68
  throw new AgentError_1.ExecutionError(`Failed to list ${this.getVendorName()} models: ${error instanceof Error ? error.message : "Unknown error"}`);
package/dist/gemini.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./core";
2
2
  export { GeminiAgent } from "./agents/google/GeminiAgent";
3
+ export type { GeminiModelCard } from "./agents/google/GeminiAgent";
3
4
  export { geminiTransformer } from "./history/transformers";
4
5
  //# sourceMappingURL=gemini.d.ts.map
package/dist/index.d.ts CHANGED
@@ -2,9 +2,13 @@ export * from "./agents/BaseAgent";
2
2
  export * from "./agents/anthropic/ClaudeAgent";
3
3
  export { OpenAiAgent } from "./agents/openai/OpenAiAgent";
4
4
  export { MistralAgent } from "./agents/mistral/MistralAgent";
5
+ export type { MistralModelCard } from "./agents/mistral/MistralAgent";
5
6
  export { GeminiAgent } from "./agents/google/GeminiAgent";
7
+ export type { GeminiModelCard } from "./agents/google/GeminiAgent";
6
8
  export { OllamaAgent } from "./agents/ollama/OllamaAgent";
9
+ export type { OllamaModelInfo } from "./agents/ollama/OllamaAgent";
7
10
  export { LlamaCppAgent } from "./agents/llamacpp/LlamaCppAgent";
11
+ export type { LlamaCppModelCard, LlamaCppModelMeta, } from "./agents/llamacpp/LlamaCppAgent";
8
12
  export { OpenAICompatibleAgent } from "./agents/openai-compatible/OpenAICompatibleAgent";
9
13
  export type { OpenAICompatibleConfig, StreamChunk } from "./agents/openai-compatible/OpenAICompatibleAgent";
10
14
  export * from "./agents/model-types";
@@ -1,5 +1,6 @@
1
1
  export * from "./core";
2
2
  export { LlamaCppAgent } from "./agents/llamacpp/LlamaCppAgent";
3
+ export type { LlamaCppModelCard, LlamaCppModelMeta, } from "./agents/llamacpp/LlamaCppAgent";
3
4
  export { OpenAICompatibleAgent } from "./agents/openai-compatible/OpenAICompatibleAgent";
4
5
  export type { OpenAICompatibleConfig, StreamChunk } from "./agents/openai-compatible/OpenAICompatibleAgent";
5
6
  export { chatCompletionsTransformer } from "./history/transformers";
package/dist/mistral.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./core";
2
2
  export { MistralAgent } from "./agents/mistral/MistralAgent";
3
+ export type { MistralModelCard } from "./agents/mistral/MistralAgent";
3
4
  export { mistralTransformer } from "./history/transformers";
4
5
  //# sourceMappingURL=mistral.d.ts.map
package/dist/ollama.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./core";
2
2
  export { OllamaAgent } from "./agents/ollama/OllamaAgent";
3
+ export type { OllamaModelInfo } from "./agents/ollama/OllamaAgent";
3
4
  export { ollamaTransformer } from "./history/transformers";
4
5
  //# sourceMappingURL=ollama.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agentionai/agents",
3
3
  "author": "Laurent Zuijdwijk",
4
- "version": "1.4.0",
4
+ "version": "1.5.0",
5
5
  "description": "Agent Library",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",