@revealui/ai 0.6.3 → 0.7.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.
Files changed (52) hide show
  1. package/README.md +5 -4
  2. package/dist/a2a/card.d.ts +9 -0
  3. package/dist/a2a/card.d.ts.map +1 -1
  4. package/dist/a2a/card.js +11 -2
  5. package/dist/embeddings/index.d.ts +8 -0
  6. package/dist/embeddings/index.d.ts.map +1 -1
  7. package/dist/embeddings/index.js +3 -2
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -0
  11. package/dist/llm/cache-utils.d.ts +11 -25
  12. package/dist/llm/cache-utils.d.ts.map +1 -1
  13. package/dist/llm/cache-utils.js +27 -27
  14. package/dist/llm/client.d.ts +28 -8
  15. package/dist/llm/client.d.ts.map +1 -1
  16. package/dist/llm/client.js +92 -13
  17. package/dist/llm/providers/anthropic.d.ts +30 -0
  18. package/dist/llm/providers/anthropic.d.ts.map +1 -0
  19. package/dist/llm/providers/anthropic.js +45 -0
  20. package/dist/llm/providers/base.d.ts +80 -27
  21. package/dist/llm/providers/base.d.ts.map +1 -1
  22. package/dist/llm/providers/base.js +5 -1
  23. package/dist/llm/providers/groq.d.ts +2 -1
  24. package/dist/llm/providers/groq.d.ts.map +1 -1
  25. package/dist/llm/providers/groq.js +14 -0
  26. package/dist/llm/providers/inference-snaps.d.ts +2 -1
  27. package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
  28. package/dist/llm/providers/inference-snaps.js +15 -0
  29. package/dist/llm/providers/ollama.d.ts +2 -1
  30. package/dist/llm/providers/ollama.d.ts.map +1 -1
  31. package/dist/llm/providers/ollama.js +14 -0
  32. package/dist/llm/providers/openai-compat.d.ts +18 -1
  33. package/dist/llm/providers/openai-compat.d.ts.map +1 -1
  34. package/dist/llm/providers/openai-compat.js +50 -3
  35. package/dist/llm/providers/openai.d.ts +27 -0
  36. package/dist/llm/providers/openai.d.ts.map +1 -0
  37. package/dist/llm/providers/openai.js +41 -0
  38. package/dist/llm/resolve.d.ts +97 -0
  39. package/dist/llm/resolve.d.ts.map +1 -0
  40. package/dist/llm/resolve.js +218 -0
  41. package/dist/llm/server.d.ts +1 -0
  42. package/dist/llm/server.d.ts.map +1 -1
  43. package/dist/llm/server.js +2 -0
  44. package/dist/llm/token-counter.d.ts +18 -0
  45. package/dist/llm/token-counter.d.ts.map +1 -1
  46. package/dist/llm/token-counter.js +16 -13
  47. package/dist/orchestration/runtime.d.ts +6 -12
  48. package/dist/orchestration/runtime.d.ts.map +1 -1
  49. package/dist/orchestration/runtime.js +4 -16
  50. package/dist/orchestration/streaming-runtime.js +1 -1
  51. package/dist/skills/types.d.ts +6 -6
  52. package/package.json +7 -7
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Anthropic Provider
3
+ *
4
+ * Thin wrapper over OpenAICompatProvider using Anthropic's OpenAI-compatible
5
+ * surface at https://api.anthropic.com/v1. No proprietary Anthropic SDK — the
6
+ * fleet posture is "No proprietary provider SDKs" (see client.ts). Anthropic
7
+ * exposes an OpenAI-compatible chat/completions endpoint, so the same base
8
+ * implementation that serves Groq/Ollama/inference-snaps serves Anthropic too.
9
+ *
10
+ * Docs: https://docs.anthropic.com/en/api/openai-sdk
11
+ */
12
+ import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message, ReasonerCapabilities } from './base.js';
13
+ export interface AnthropicProviderConfig extends Omit<LLMProviderConfig, 'apiKey'> {
14
+ apiKey: string;
15
+ /** Defaults to https://api.anthropic.com/v1 */
16
+ baseURL?: string;
17
+ /** Defaults to claude-sonnet-4-6 (conservative documented default; overridable) */
18
+ model?: string;
19
+ timeout?: number;
20
+ maxRetries?: number;
21
+ }
22
+ export declare class AnthropicProvider implements LLMProvider {
23
+ private inner;
24
+ constructor(config: AnthropicProviderConfig);
25
+ capabilities(): ReasonerCapabilities;
26
+ chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
27
+ stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
28
+ embed(_text: string | string[], _options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
29
+ }
30
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,KAAK,CAAuB;gBAExB,MAAM,EAAE,uBAAuB;IAQ3C,YAAY,IAAI,oBAAoB;IAepC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAIhF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAG9F"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Anthropic Provider
3
+ *
4
+ * Thin wrapper over OpenAICompatProvider using Anthropic's OpenAI-compatible
5
+ * surface at https://api.anthropic.com/v1. No proprietary Anthropic SDK — the
6
+ * fleet posture is "No proprietary provider SDKs" (see client.ts). Anthropic
7
+ * exposes an OpenAI-compatible chat/completions endpoint, so the same base
8
+ * implementation that serves Groq/Ollama/inference-snaps serves Anthropic too.
9
+ *
10
+ * Docs: https://docs.anthropic.com/en/api/openai-sdk
11
+ */
12
+ import { OpenAICompatProvider } from './openai-compat.js';
13
+ export class AnthropicProvider {
14
+ inner;
15
+ constructor(config) {
16
+ this.inner = new OpenAICompatProvider({
17
+ ...config,
18
+ baseURL: config.baseURL ?? 'https://api.anthropic.com/v1',
19
+ model: config.model ?? 'claude-sonnet-4-6',
20
+ });
21
+ }
22
+ capabilities() {
23
+ return {
24
+ providerTag: 'anthropic',
25
+ tools: true,
26
+ parallelToolCalls: false,
27
+ vision: false,
28
+ streaming: true,
29
+ // Anthropic exposes no embeddings endpoint on its OpenAI-compat surface.
30
+ embeddings: false,
31
+ reasoningEffort: false,
32
+ promptCache: false,
33
+ structuredOutput: false,
34
+ };
35
+ }
36
+ chat(messages, options) {
37
+ return this.inner.chat(messages, options);
38
+ }
39
+ stream(messages, options) {
40
+ return this.inner.stream(messages, options);
41
+ }
42
+ embed(_text, _options) {
43
+ throw new Error('Anthropic does not expose an embeddings endpoint. Use OpenAI or Ollama.');
44
+ }
45
+ }
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * LLM Provider Base Interface
3
3
  *
4
- * Abstract interface for all LLM providers (OpenAI, Anthropic, etc.)
4
+ * The agnostic Reasoner port (ADR 2026-06-25). Providers are negotiated by
5
+ * `capabilities()`, never by provider-name string. The control vocabulary is neutral
6
+ * and capability-gated (`effort`, `cache`/`cacheHint`); genuinely unportable knobs ride
7
+ * the namespaced opaque `providerOptions` channel; cross-provider usage (e.g. cache token
8
+ * stats) stays neutral in `LLMResponse.usage`.
5
9
  */
6
10
  /**
7
11
  * A plain text content part - used in multipart messages.
@@ -36,10 +40,11 @@ export interface Message {
36
40
  name?: string;
37
41
  toolCalls?: ToolCall[];
38
42
  toolCallId?: string;
39
- /** Anthropic prompt caching - marks content for caching (5min TTL, 90% cost reduction) */
40
- cacheControl?: {
41
- type: 'ephemeral';
42
- };
43
+ /**
44
+ * Neutral cache breakpoint hint (gated by the `promptCache` capability). An adapter
45
+ * that supports prompt caching maps this to its native cache-control; others ignore it.
46
+ */
47
+ cache?: boolean;
43
48
  }
44
49
  export interface ToolCall {
45
50
  id: string;
@@ -58,7 +63,11 @@ export interface LLMResponse {
58
63
  promptTokens: number;
59
64
  completionTokens: number;
60
65
  totalTokens: number;
61
- /** Anthropic cache stats */
66
+ /**
67
+ * Cross-provider cache usage (neutral; gated by `promptCache`). Populated by any
68
+ * caching provider - Anthropic cache tokens, OpenAI `cached_tokens`, Gemini
69
+ * `cachedContentTokenCount`. Read by the cost path; stays in neutral `usage`.
70
+ */
62
71
  cacheCreationTokens?: number;
63
72
  cacheReadTokens?: number;
64
73
  };
@@ -81,22 +90,66 @@ export interface LLMProviderConfig {
81
90
  maxTokens?: number;
82
91
  }
83
92
  /**
84
- * Base interface for LLM providers
93
+ * Reasoning-depth hint (neutral, capability-gated by `reasoningEffort`).
94
+ *
95
+ * This is a *reasoning-depth* axis, NOT output entropy or length - adapters must never
96
+ * remap it to `temperature`/`maxTokens`. An adapter with a reasoning axis maps it to its
97
+ * native control (e.g. a thinking-token budget); an adapter without one advertises
98
+ * `reasoningEffort: false` and treats `effort` as a no-op.
85
99
  */
86
- export interface LLMProvider {
87
- /**
88
- * Chat completion
89
- */
100
+ export type ReasoningEffort = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
101
+ /**
102
+ * Runtime-queryable capability record. The loop branches on these, never on a
103
+ * provider-name string. Conformance-tested (transport tier) so a provider cannot lie:
104
+ * advertise-true-but-not-wired fails the positive assertion; advertise-false-but-emits-a-
105
+ * native-field fails the inertness assertion.
106
+ */
107
+ export interface ReasonerCapabilities {
108
+ /** Stable adapter id; also the only `providerOptions` namespace this adapter may read ('x-<tag>'). */
109
+ readonly providerTag: string;
110
+ readonly tools: boolean;
111
+ /** Implies `tools` (consistency invariant). */
112
+ readonly parallelToolCalls: boolean;
113
+ /** Implies the adapter accepts `ContentPart[]` message content. */
114
+ readonly vision: boolean;
115
+ readonly streaming: boolean;
116
+ readonly embeddings: boolean;
117
+ readonly reasoningEffort: boolean;
118
+ readonly promptCache: boolean;
119
+ readonly structuredOutput: boolean;
120
+ /** Max context window in tokens; undefined = unknown (loop budgets conservatively). */
121
+ readonly contextWindow?: number;
122
+ }
123
+ /**
124
+ * Namespaced opaque extension for genuinely unportable, request-shaped knobs.
125
+ *
126
+ * Core/loop code MUST pass this through and MUST NOT read any key - per-namespace schema
127
+ * lives in the owning adapter. A known-namespace registry (typed keys) rather than a bare
128
+ * `x-*` string convention, so a typo'd namespace fails loudly instead of silently no-opping.
129
+ */
130
+ export interface ProviderOptions {
131
+ 'x-anthropic'?: unknown;
132
+ 'x-openai'?: unknown;
133
+ 'x-google'?: unknown;
134
+ }
135
+ /**
136
+ * The Reasoner port - one swappable reasoning step plus the side capabilities
137
+ * (embeddings/streaming). The loop negotiates by `capabilities()`, never by name.
138
+ */
139
+ export interface Reasoner {
140
+ /** Runtime-queryable, conformance-tested capability record. */
141
+ capabilities(): ReasonerCapabilities;
142
+ /** Chat completion. */
90
143
  chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
91
- /**
92
- * Generate embeddings
93
- */
144
+ /** Generate embeddings. */
94
145
  embed(text: string | string[], options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
95
- /**
96
- * Stream chat completion
97
- */
146
+ /** Stream chat completion. */
98
147
  stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
99
148
  }
149
+ /**
150
+ * @deprecated Use `Reasoner`. Alias retained one release cycle for external callers.
151
+ */
152
+ export type LLMProvider = Reasoner;
100
153
  export interface LLMChatOptions {
101
154
  temperature?: number;
102
155
  maxTokens?: number;
@@ -107,14 +160,12 @@ export interface LLMChatOptions {
107
160
  name: string;
108
161
  };
109
162
  };
110
- /** Enable prompt caching (Anthropic only) - caches system prompts and tools */
111
- enableCache?: boolean;
112
- /**
113
- * Extended thinking token budget (Anthropic only).
114
- * Enables Claude's internal reasoning before responding.
115
- * Typical values: 512 (minimal) → 31999 (xhigh). 0 or undefined = disabled.
116
- */
117
- thinkingBudget?: number;
163
+ /** Neutral reasoning-depth hint (gated by `reasoningEffort`). No-op where unsupported. */
164
+ effort?: ReasoningEffort;
165
+ /** Neutral prompt-cache hint for the stable prefix - system + tools (gated by `promptCache`). */
166
+ cacheHint?: boolean;
167
+ /** Opaque, namespaced provider extension. Core never reads it; the adapter owns the schema. */
168
+ providerOptions?: ProviderOptions;
118
169
  }
119
170
  export interface LLMEmbedOptions {
120
171
  model?: string;
@@ -123,8 +174,10 @@ export interface LLMStreamOptions {
123
174
  temperature?: number;
124
175
  maxTokens?: number;
125
176
  tools?: ToolDefinition[];
126
- /** Enable prompt caching (Anthropic only) - caches system prompts and tools */
127
- enableCache?: boolean;
177
+ /** Neutral reasoning-depth hint (gated by `reasoningEffort`). No-op where unsupported. */
178
+ effort?: ReasoningEffort;
179
+ /** Opaque, namespaced provider extension. Core never reads it; the adapter owns the schema. */
180
+ providerOptions?: ProviderOptions;
128
181
  }
129
182
  export interface ToolDefinition {
130
183
  type: 'function';
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/base.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,10 @@
1
1
  /**
2
2
  * LLM Provider Base Interface
3
3
  *
4
- * Abstract interface for all LLM providers (OpenAI, Anthropic, etc.)
4
+ * The agnostic Reasoner port (ADR 2026-06-25). Providers are negotiated by
5
+ * `capabilities()`, never by provider-name string. The control vocabulary is neutral
6
+ * and capability-gated (`effort`, `cache`/`cacheHint`); genuinely unportable knobs ride
7
+ * the namespaced opaque `providerOptions` channel; cross-provider usage (e.g. cache token
8
+ * stats) stays neutral in `LLMResponse.usage`.
5
9
  */
6
10
  export {};
@@ -5,7 +5,7 @@
5
5
  * Free tier: 6,000 TPM / 500k TPD.
6
6
  * Sign up: console.groq.com
7
7
  */
8
- import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message } from './base.js';
8
+ import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message, ReasonerCapabilities } from './base.js';
9
9
  export interface GroqProviderConfig extends Omit<LLMProviderConfig, 'apiKey'> {
10
10
  apiKey: string;
11
11
  /** Defaults to https://api.groq.com/openai/v1 */
@@ -16,6 +16,7 @@ export interface GroqProviderConfig extends Omit<LLMProviderConfig, 'apiKey'> {
16
16
  export declare class GroqProvider implements LLMProvider {
17
17
  private inner;
18
18
  constructor(config: GroqProviderConfig);
19
+ capabilities(): ReasonerCapabilities;
19
20
  chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
20
21
  stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
21
22
  embed(_text: string | string[], _options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"groq.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/groq.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACR,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,YAAa,YAAW,WAAW;IAC9C,OAAO,CAAC,KAAK,CAAuB;gBAExB,MAAM,EAAE,kBAAkB;IAQtC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAIhF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAG9F"}
1
+ {"version":3,"file":"groq.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/groq.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,YAAa,YAAW,WAAW;IAC9C,OAAO,CAAC,KAAK,CAAuB;gBAExB,MAAM,EAAE,kBAAkB;IAQtC,YAAY,IAAI,oBAAoB;IAepC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAIhF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAG9F"}
@@ -15,6 +15,20 @@ export class GroqProvider {
15
15
  model: config.model ?? 'qwen/qwen3-32b',
16
16
  });
17
17
  }
18
+ capabilities() {
19
+ // Profile for the default model (qwen/qwen3-32b). Groq exposes no embeddings endpoint.
20
+ return {
21
+ providerTag: 'groq',
22
+ tools: true,
23
+ parallelToolCalls: false,
24
+ vision: false,
25
+ streaming: true,
26
+ embeddings: false,
27
+ reasoningEffort: false,
28
+ promptCache: false,
29
+ structuredOutput: false,
30
+ };
31
+ }
18
32
  chat(messages, options) {
19
33
  return this.inner.chat(messages, options);
20
34
  }
@@ -24,7 +24,7 @@
24
24
  *
25
25
  * Docs: https://documentation.ubuntu.com/inference-snaps
26
26
  */
27
- import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message } from './base.js';
27
+ import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message, ReasonerCapabilities } from './base.js';
28
28
  export interface InferenceSnapsProviderConfig extends Omit<LLMProviderConfig, 'apiKey'> {
29
29
  apiKey?: string;
30
30
  /** Base URL of the inference-snaps service, e.g. http://localhost:9090/v1 */
@@ -39,6 +39,7 @@ export declare class InferenceSnapsProvider implements LLMProvider {
39
39
  private embedModel;
40
40
  private baseURL;
41
41
  constructor(config: InferenceSnapsProviderConfig);
42
+ capabilities(): ReasonerCapabilities;
42
43
  chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
43
44
  stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
44
45
  embed(text: string | string[], _options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"inference-snaps.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/inference-snaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACR,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,sBAAuB,YAAW,WAAW;IACxD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,4BAA4B;IAahD,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAI1E,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,QAAQ,CAAC,EAAE,eAAe,GACzB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAsBpC"}
1
+ {"version":3,"file":"inference-snaps.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/inference-snaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,sBAAuB,YAAW,WAAW;IACxD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,4BAA4B;IAahD,YAAY,IAAI,oBAAoB;IAgBpC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAI1E,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,QAAQ,CAAC,EAAE,eAAe,GACzB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAsBpC"}
@@ -41,6 +41,21 @@ export class InferenceSnapsProvider {
41
41
  model: config.model ?? 'gemma3',
42
42
  });
43
43
  }
44
+ capabilities() {
45
+ // Profile for the default model (gemma3, text-only). Per-model capability
46
+ // negotiation (e.g. qwen-vl vision, deepseek-r1 reasoningEffort) is a follow-up.
47
+ return {
48
+ providerTag: 'inference-snaps',
49
+ tools: true,
50
+ parallelToolCalls: false,
51
+ vision: false,
52
+ streaming: true,
53
+ embeddings: true,
54
+ reasoningEffort: false,
55
+ promptCache: false,
56
+ structuredOutput: false,
57
+ };
58
+ }
44
59
  chat(messages, options) {
45
60
  return this.inner.chat(messages, options);
46
61
  }
@@ -5,7 +5,7 @@
5
5
  * No API key required. Zero cost, fully offline.
6
6
  * Install: https://ollama.com
7
7
  */
8
- import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message } from './base.js';
8
+ import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message, ReasonerCapabilities } from './base.js';
9
9
  export interface OllamaProviderConfig extends Omit<LLMProviderConfig, 'apiKey'> {
10
10
  apiKey?: string;
11
11
  /** Defaults to http://localhost:11434/v1 */
@@ -20,6 +20,7 @@ export declare class OllamaProvider implements LLMProvider {
20
20
  private embedModel;
21
21
  private baseURL;
22
22
  constructor(config: OllamaProviderConfig);
23
+ capabilities(): ReasonerCapabilities;
23
24
  chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
24
25
  stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
25
26
  embed(text: string | string[], _options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/ollama.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACR,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,oBAAoB;IAaxC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAI1E,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,QAAQ,CAAC,EAAE,eAAe,GACzB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAsBpC"}
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/ollama.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,oBAAoB;IAaxC,YAAY,IAAI,oBAAoB;IAepC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAI1E,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,QAAQ,CAAC,EAAE,eAAe,GACzB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAsBpC"}
@@ -22,6 +22,20 @@ export class OllamaProvider {
22
22
  model: config.model ?? 'gemma4:e2b',
23
23
  });
24
24
  }
25
+ capabilities() {
26
+ // Profile for the default model (gemma4:e2b, text-only).
27
+ return {
28
+ providerTag: 'ollama',
29
+ tools: true,
30
+ parallelToolCalls: false,
31
+ vision: false,
32
+ streaming: true,
33
+ embeddings: true,
34
+ reasoningEffort: false,
35
+ promptCache: false,
36
+ structuredOutput: false,
37
+ };
38
+ }
25
39
  chat(messages, options) {
26
40
  return this.inner.chat(messages, options);
27
41
  }
@@ -5,13 +5,30 @@
5
5
  * format. Used by: Ollama, Groq, Inference Snaps.
6
6
  * NOT for direct OpenAI usage - RevealUI uses open-source models only.
7
7
  */
8
- import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message } from './base.js';
8
+ import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message, ReasonerCapabilities } from './base.js';
9
9
  export interface OpenAICompatConfig extends LLMProviderConfig {
10
+ /** Per-request timeout in ms applied to connection setup. Default 60_000. */
11
+ timeout?: number;
12
+ /** Retries on connection/timeout errors (not on HTTP error responses). Default 1. */
13
+ maxRetries?: number;
10
14
  }
11
15
  export declare class OpenAICompatProvider implements LLMProvider {
12
16
  private config;
13
17
  private baseURL;
18
+ private timeoutMs;
19
+ private maxRetries;
14
20
  constructor(config: OpenAICompatConfig);
21
+ /**
22
+ * fetch() with a connection-setup timeout and bounded retries. The timeout
23
+ * aborts a hung connection (the localhost-default failure mode that otherwise
24
+ * burns the whole serverless duration) and is cleared once headers arrive, so
25
+ * a legitimately long streaming body is not truncated. Retries fire only on a
26
+ * thrown fetch error (connection refused, DNS, timeout) — never on an HTTP
27
+ * error response, which the caller inspects — so a POST is re-sent only when
28
+ * no response was received.
29
+ */
30
+ private fetchWithResilience;
31
+ capabilities(): ReasonerCapabilities;
15
32
  chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
16
33
  embed(text: string | string[], options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
17
34
  stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
@@ -1 +1 @@
1
- {"version":3,"file":"openai-compat.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/openai-compat.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EAET,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EAER,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;CAAG;AAqDhE,qBAAa,oBAAqB,YAAW,WAAW;IACtD,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,kBAAkB;IAUhC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IA6EzE,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;IAyC5B,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAuFvF,OAAO,CAAC,cAAc;CA4BvB"}
1
+ {"version":3,"file":"openai-compat.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/openai-compat.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EAET,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EAErB,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAwDD,qBAAa,oBAAqB,YAAW,WAAW;IACtD,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,kBAAkB;IAYtC;;;;;;;;OAQG;YACW,mBAAmB;IAgBjC,YAAY,IAAI,oBAAoB;IAgB9B,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IA6EzE,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;IAyC5B,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAuFvF,OAAO,CAAC,cAAc;CA4BvB"}
@@ -5,6 +5,8 @@
5
5
  * format. Used by: Ollama, Groq, Inference Snaps.
6
6
  * NOT for direct OpenAI usage - RevealUI uses open-source models only.
7
7
  */
8
+ const DEFAULT_TIMEOUT_MS = 60_000;
9
+ const DEFAULT_MAX_RETRIES = 1;
8
10
  const authorizationHeader = 'Authorization';
9
11
  const maxTokensKey = 'max_tokens';
10
12
  const toolChoiceKey = 'tool_choice';
@@ -31,15 +33,60 @@ const isFunctionToolCall = (call) => {
31
33
  export class OpenAICompatProvider {
32
34
  config;
33
35
  baseURL;
36
+ timeoutMs;
37
+ maxRetries;
34
38
  constructor(config) {
35
39
  this.config = config;
36
40
  if (!config.baseURL) {
37
41
  throw new Error('OpenAICompatProvider requires a baseURL - use a specific provider (InferenceSnapsProvider, OllamaProvider, etc.)');
38
42
  }
39
43
  this.baseURL = config.baseURL;
44
+ this.timeoutMs = config.timeout ?? DEFAULT_TIMEOUT_MS;
45
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
46
+ }
47
+ /**
48
+ * fetch() with a connection-setup timeout and bounded retries. The timeout
49
+ * aborts a hung connection (the localhost-default failure mode that otherwise
50
+ * burns the whole serverless duration) and is cleared once headers arrive, so
51
+ * a legitimately long streaming body is not truncated. Retries fire only on a
52
+ * thrown fetch error (connection refused, DNS, timeout) — never on an HTTP
53
+ * error response, which the caller inspects — so a POST is re-sent only when
54
+ * no response was received.
55
+ */
56
+ async fetchWithResilience(url, init) {
57
+ let lastError;
58
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
59
+ const controller = new AbortController();
60
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
61
+ try {
62
+ return await fetch(url, { ...init, signal: controller.signal });
63
+ }
64
+ catch (error) {
65
+ lastError = error;
66
+ }
67
+ finally {
68
+ clearTimeout(timeoutId);
69
+ }
70
+ }
71
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
72
+ }
73
+ capabilities() {
74
+ // Base OpenAI-compatible profile. Concrete providers (Groq, Ollama, inference-snaps)
75
+ // override per their endpoint and default model.
76
+ return {
77
+ providerTag: 'openai-compat',
78
+ tools: true,
79
+ parallelToolCalls: false,
80
+ vision: false,
81
+ streaming: true,
82
+ embeddings: true,
83
+ reasoningEffort: false,
84
+ promptCache: false,
85
+ structuredOutput: false,
86
+ };
40
87
  }
41
88
  async chat(messages, options) {
42
- const response = await fetch(`${this.baseURL}/chat/completions`, {
89
+ const response = await this.fetchWithResilience(`${this.baseURL}/chat/completions`, {
43
90
  method: 'POST',
44
91
  headers: {
45
92
  'Content-Type': 'application/json',
@@ -107,7 +154,7 @@ export class OpenAICompatProvider {
107
154
  async embed(text, options) {
108
155
  const texts = Array.isArray(text) ? text : [text];
109
156
  const model = options?.model || 'text-embedding-3-small';
110
- const response = await fetch(`${this.baseURL}/embeddings`, {
157
+ const response = await this.fetchWithResilience(`${this.baseURL}/embeddings`, {
111
158
  method: 'POST',
112
159
  headers: {
113
160
  'Content-Type': 'application/json',
@@ -140,7 +187,7 @@ export class OpenAICompatProvider {
140
187
  return Array.isArray(text) ? embeddings : embeddings[0];
141
188
  }
142
189
  async *stream(messages, options) {
143
- const response = await fetch(`${this.baseURL}/chat/completions`, {
190
+ const response = await this.fetchWithResilience(`${this.baseURL}/chat/completions`, {
144
191
  method: 'POST',
145
192
  headers: {
146
193
  'Content-Type': 'application/json',
@@ -0,0 +1,27 @@
1
+ /**
2
+ * OpenAI Provider
3
+ *
4
+ * Thin wrapper over OpenAICompatProvider targeting OpenAI's native
5
+ * chat/completions + embeddings API at https://api.openai.com/v1. OpenAI is the
6
+ * reference OpenAI-compatible surface, so the shared base implementation serves
7
+ * it directly — no proprietary SDK (fleet posture in client.ts).
8
+ */
9
+ import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message, ReasonerCapabilities } from './base.js';
10
+ export interface OpenAIProviderConfig extends Omit<LLMProviderConfig, 'apiKey'> {
11
+ apiKey: string;
12
+ /** Defaults to https://api.openai.com/v1 */
13
+ baseURL?: string;
14
+ /** Defaults to gpt-4o (conservative documented default; overridable) */
15
+ model?: string;
16
+ timeout?: number;
17
+ maxRetries?: number;
18
+ }
19
+ export declare class OpenAIProvider implements LLMProvider {
20
+ private inner;
21
+ constructor(config: OpenAIProviderConfig);
22
+ capabilities(): ReasonerCapabilities;
23
+ chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
24
+ stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
25
+ embed(text: string | string[], options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
26
+ }
27
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAuB;gBAExB,MAAM,EAAE,oBAAoB;IAQxC,YAAY,IAAI,oBAAoB;IAcpC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAIhF,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAG5F"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * OpenAI Provider
3
+ *
4
+ * Thin wrapper over OpenAICompatProvider targeting OpenAI's native
5
+ * chat/completions + embeddings API at https://api.openai.com/v1. OpenAI is the
6
+ * reference OpenAI-compatible surface, so the shared base implementation serves
7
+ * it directly — no proprietary SDK (fleet posture in client.ts).
8
+ */
9
+ import { OpenAICompatProvider } from './openai-compat.js';
10
+ export class OpenAIProvider {
11
+ inner;
12
+ constructor(config) {
13
+ this.inner = new OpenAICompatProvider({
14
+ ...config,
15
+ baseURL: config.baseURL ?? 'https://api.openai.com/v1',
16
+ model: config.model ?? 'gpt-4o',
17
+ });
18
+ }
19
+ capabilities() {
20
+ return {
21
+ providerTag: 'openai',
22
+ tools: true,
23
+ parallelToolCalls: false,
24
+ vision: false,
25
+ streaming: true,
26
+ embeddings: true,
27
+ reasoningEffort: false,
28
+ promptCache: false,
29
+ structuredOutput: false,
30
+ };
31
+ }
32
+ chat(messages, options) {
33
+ return this.inner.chat(messages, options);
34
+ }
35
+ stream(messages, options) {
36
+ return this.inner.stream(messages, options);
37
+ }
38
+ embed(text, options) {
39
+ return this.inner.embed(text, options);
40
+ }
41
+ }