@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.
- package/README.md +5 -4
- package/dist/a2a/card.d.ts +9 -0
- package/dist/a2a/card.d.ts.map +1 -1
- package/dist/a2a/card.js +11 -2
- package/dist/embeddings/index.d.ts +8 -0
- package/dist/embeddings/index.d.ts.map +1 -1
- package/dist/embeddings/index.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/llm/cache-utils.d.ts +11 -25
- package/dist/llm/cache-utils.d.ts.map +1 -1
- package/dist/llm/cache-utils.js +27 -27
- package/dist/llm/client.d.ts +28 -8
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +92 -13
- package/dist/llm/providers/anthropic.d.ts +30 -0
- package/dist/llm/providers/anthropic.d.ts.map +1 -0
- package/dist/llm/providers/anthropic.js +45 -0
- package/dist/llm/providers/base.d.ts +80 -27
- package/dist/llm/providers/base.d.ts.map +1 -1
- package/dist/llm/providers/base.js +5 -1
- package/dist/llm/providers/groq.d.ts +2 -1
- package/dist/llm/providers/groq.d.ts.map +1 -1
- package/dist/llm/providers/groq.js +14 -0
- package/dist/llm/providers/inference-snaps.d.ts +2 -1
- package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
- package/dist/llm/providers/inference-snaps.js +15 -0
- package/dist/llm/providers/ollama.d.ts +2 -1
- package/dist/llm/providers/ollama.d.ts.map +1 -1
- package/dist/llm/providers/ollama.js +14 -0
- package/dist/llm/providers/openai-compat.d.ts +18 -1
- package/dist/llm/providers/openai-compat.d.ts.map +1 -1
- package/dist/llm/providers/openai-compat.js +50 -3
- package/dist/llm/providers/openai.d.ts +27 -0
- package/dist/llm/providers/openai.d.ts.map +1 -0
- package/dist/llm/providers/openai.js +41 -0
- package/dist/llm/resolve.d.ts +97 -0
- package/dist/llm/resolve.d.ts.map +1 -0
- package/dist/llm/resolve.js +218 -0
- package/dist/llm/server.d.ts +1 -0
- package/dist/llm/server.d.ts.map +1 -1
- package/dist/llm/server.js +2 -0
- package/dist/llm/token-counter.d.ts +18 -0
- package/dist/llm/token-counter.d.ts.map +1 -1
- package/dist/llm/token-counter.js +16 -13
- package/dist/orchestration/runtime.d.ts +6 -12
- package/dist/orchestration/runtime.d.ts.map +1 -1
- package/dist/orchestration/runtime.js +4 -16
- package/dist/orchestration/streaming-runtime.js +1 -1
- package/dist/skills/types.d.ts +6 -6
- 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
|
-
*
|
|
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
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
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
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
/**
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
/**
|
|
127
|
-
|
|
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":"AAAA
|
|
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
|
-
*
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
+
}
|