universal-llm-client 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +414 -0
- package/dist/ai-model.d.ts +53 -0
- package/dist/ai-model.d.ts.map +1 -0
- package/dist/ai-model.js +159 -0
- package/dist/ai-model.js.map +1 -0
- package/dist/auditor.d.ts +78 -0
- package/dist/auditor.d.ts.map +1 -0
- package/dist/auditor.js +104 -0
- package/dist/auditor.js.map +1 -0
- package/dist/client.d.ts +75 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +240 -0
- package/dist/client.js.map +1 -0
- package/dist/http.d.ts +47 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +186 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +324 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +63 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/mcp.d.ts +85 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +255 -0
- package/dist/mcp.js.map +1 -0
- package/dist/providers/google.d.ts +33 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +426 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.d.ts +26 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +304 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +20 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +251 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/router.d.ts +87 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +260 -0
- package/dist/router.js.map +1 -0
- package/dist/stream-decoder.d.ts +112 -0
- package/dist/stream-decoder.d.ts.map +1 -0
- package/dist/stream-decoder.js +238 -0
- package/dist/stream-decoder.js.map +1 -0
- package/dist/tools.d.ts +78 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +207 -0
- package/dist/tools.js.map +1 -0
- package/package.json +91 -0
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal LLM Client v3 — Router (Internal Failover Engine)
|
|
3
|
+
*
|
|
4
|
+
* Manages the ordered provider chain with:
|
|
5
|
+
* - Priority ordering
|
|
6
|
+
* - Per-provider retries
|
|
7
|
+
* - Health tracking with failure thresholds
|
|
8
|
+
* - Cooldown periods for unhealthy providers
|
|
9
|
+
* - Audit integration for every retry/failover event
|
|
10
|
+
*
|
|
11
|
+
* Not exposed publicly — AIModel delegates to it.
|
|
12
|
+
*/
|
|
13
|
+
import { BaseLLMClient } from './client.js';
|
|
14
|
+
import type { Auditor } from './auditor.js';
|
|
15
|
+
import type { LLMChatMessage, LLMChatResponse, ChatOptions, ModelMetadata } from './interfaces.js';
|
|
16
|
+
import type { DecodedEvent } from './stream-decoder.js';
|
|
17
|
+
export interface ProviderEntry {
|
|
18
|
+
/** Unique identifier for this provider entry */
|
|
19
|
+
id: string;
|
|
20
|
+
/** The underlying LLM client */
|
|
21
|
+
client: BaseLLMClient;
|
|
22
|
+
/** Priority (lower = tried first, defaults to insertion order) */
|
|
23
|
+
priority: number;
|
|
24
|
+
/** Override model name for this provider */
|
|
25
|
+
modelOverride?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface RouterConfig {
|
|
28
|
+
/** Max retries per provider before failover (default: 2) */
|
|
29
|
+
retriesPerProvider?: number;
|
|
30
|
+
/** Max consecutive failures before marking unhealthy (default: 3) */
|
|
31
|
+
maxFailures?: number;
|
|
32
|
+
/** Cooldown period in ms for unhealthy providers (default: 30000) */
|
|
33
|
+
cooldownMs?: number;
|
|
34
|
+
/** Auditor for observability */
|
|
35
|
+
auditor?: Auditor;
|
|
36
|
+
}
|
|
37
|
+
export interface ProviderStatus {
|
|
38
|
+
id: string;
|
|
39
|
+
healthy: boolean;
|
|
40
|
+
active: boolean;
|
|
41
|
+
consecutiveFailures: number;
|
|
42
|
+
cooldownUntil?: number;
|
|
43
|
+
model: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class Router {
|
|
46
|
+
private providers;
|
|
47
|
+
private health;
|
|
48
|
+
private auditor;
|
|
49
|
+
private config;
|
|
50
|
+
constructor(config?: RouterConfig);
|
|
51
|
+
addProvider(entry: ProviderEntry): void;
|
|
52
|
+
removeProvider(id: string): void;
|
|
53
|
+
setAuditor(auditor: Auditor): void;
|
|
54
|
+
getStatus(): ProviderStatus[];
|
|
55
|
+
/**
|
|
56
|
+
* Execute a function against providers with automatic failover.
|
|
57
|
+
* Tries each available provider in priority order.
|
|
58
|
+
*/
|
|
59
|
+
execute<T>(fn: (client: BaseLLMClient) => Promise<T>, context?: string): Promise<T>;
|
|
60
|
+
/**
|
|
61
|
+
* Execute a streaming function with failover.
|
|
62
|
+
* On failure, retries with the next provider from the beginning.
|
|
63
|
+
*/
|
|
64
|
+
executeStream(fn: (client: BaseLLMClient) => AsyncGenerator<DecodedEvent, LLMChatResponse | void, unknown>, context?: string): AsyncGenerator<DecodedEvent, LLMChatResponse | void, unknown>;
|
|
65
|
+
chat(messages: LLMChatMessage[], options?: ChatOptions): Promise<LLMChatResponse>;
|
|
66
|
+
chatWithTools(messages: LLMChatMessage[], options?: ChatOptions & {
|
|
67
|
+
maxIterations?: number;
|
|
68
|
+
}): Promise<LLMChatResponse>;
|
|
69
|
+
chatStream(messages: LLMChatMessage[], options?: ChatOptions): AsyncGenerator<DecodedEvent, LLMChatResponse | void, unknown>;
|
|
70
|
+
embed(text: string): Promise<number[]>;
|
|
71
|
+
embedArray(texts: string[]): Promise<number[][]>;
|
|
72
|
+
getModels(): Promise<string[]>;
|
|
73
|
+
getModelInfo(): Promise<ModelMetadata>;
|
|
74
|
+
registerTool(name: string, description: string, parameters: import('./interfaces.js').LLMFunction['parameters'], handler: import('./interfaces.js').ToolHandler): void;
|
|
75
|
+
registerTools(tools: Array<{
|
|
76
|
+
name: string;
|
|
77
|
+
description: string;
|
|
78
|
+
parameters: import('./interfaces.js').LLMFunction['parameters'];
|
|
79
|
+
handler: import('./interfaces.js').ToolHandler;
|
|
80
|
+
}>): void;
|
|
81
|
+
private isAvailable;
|
|
82
|
+
private getAvailableProviders;
|
|
83
|
+
private getNextAvailableAfter;
|
|
84
|
+
private recordSuccess;
|
|
85
|
+
private recordFailure;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal LLM Client v3 — Router (Internal Failover Engine)
|
|
3
|
+
*
|
|
4
|
+
* Manages the ordered provider chain with:
|
|
5
|
+
* - Priority ordering
|
|
6
|
+
* - Per-provider retries
|
|
7
|
+
* - Health tracking with failure thresholds
|
|
8
|
+
* - Cooldown periods for unhealthy providers
|
|
9
|
+
* - Audit integration for every retry/failover event
|
|
10
|
+
*
|
|
11
|
+
* Not exposed publicly — AIModel delegates to it.
|
|
12
|
+
*/
|
|
13
|
+
import { NoopAuditor } from './auditor.js';
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Router
|
|
16
|
+
// ============================================================================
|
|
17
|
+
export class Router {
|
|
18
|
+
providers = [];
|
|
19
|
+
health = new Map();
|
|
20
|
+
auditor;
|
|
21
|
+
config;
|
|
22
|
+
constructor(config = {}) {
|
|
23
|
+
this.auditor = config.auditor ?? new NoopAuditor();
|
|
24
|
+
this.config = {
|
|
25
|
+
retriesPerProvider: config.retriesPerProvider ?? 2,
|
|
26
|
+
maxFailures: config.maxFailures ?? 3,
|
|
27
|
+
cooldownMs: config.cooldownMs ?? 30000,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// ========================================================================
|
|
31
|
+
// Provider Management
|
|
32
|
+
// ========================================================================
|
|
33
|
+
addProvider(entry) {
|
|
34
|
+
this.providers.push(entry);
|
|
35
|
+
this.health.set(entry.id, {
|
|
36
|
+
healthy: true,
|
|
37
|
+
consecutiveFailures: 0,
|
|
38
|
+
});
|
|
39
|
+
// Re-sort by priority
|
|
40
|
+
this.providers.sort((a, b) => a.priority - b.priority);
|
|
41
|
+
}
|
|
42
|
+
removeProvider(id) {
|
|
43
|
+
this.providers = this.providers.filter(p => p.id !== id);
|
|
44
|
+
this.health.delete(id);
|
|
45
|
+
}
|
|
46
|
+
setAuditor(auditor) {
|
|
47
|
+
this.auditor = auditor;
|
|
48
|
+
}
|
|
49
|
+
getStatus() {
|
|
50
|
+
return this.providers.map(p => ({
|
|
51
|
+
id: p.id,
|
|
52
|
+
healthy: this.isAvailable(p.id),
|
|
53
|
+
active: true,
|
|
54
|
+
consecutiveFailures: this.health.get(p.id)?.consecutiveFailures ?? 0,
|
|
55
|
+
cooldownUntil: this.health.get(p.id)?.cooldownUntil,
|
|
56
|
+
model: p.modelOverride ?? p.client.model,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
// ========================================================================
|
|
60
|
+
// Execution with Failover
|
|
61
|
+
// ========================================================================
|
|
62
|
+
/**
|
|
63
|
+
* Execute a function against providers with automatic failover.
|
|
64
|
+
* Tries each available provider in priority order.
|
|
65
|
+
*/
|
|
66
|
+
async execute(fn, context = 'execute') {
|
|
67
|
+
const available = this.getAvailableProviders();
|
|
68
|
+
if (available.length === 0) {
|
|
69
|
+
throw new Error('No available LLM providers. All providers are unhealthy or in cooldown.');
|
|
70
|
+
}
|
|
71
|
+
let lastError;
|
|
72
|
+
for (const provider of available) {
|
|
73
|
+
for (let attempt = 0; attempt <= this.config.retriesPerProvider; attempt++) {
|
|
74
|
+
try {
|
|
75
|
+
if (attempt > 0) {
|
|
76
|
+
this.auditor.record({
|
|
77
|
+
timestamp: Date.now(),
|
|
78
|
+
type: 'retry',
|
|
79
|
+
provider: provider.id,
|
|
80
|
+
model: provider.modelOverride ?? provider.client.model,
|
|
81
|
+
metadata: { attempt, context },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const result = await fn(provider.client);
|
|
85
|
+
this.recordSuccess(provider.id);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
90
|
+
this.auditor.record({
|
|
91
|
+
timestamp: Date.now(),
|
|
92
|
+
type: 'error',
|
|
93
|
+
provider: provider.id,
|
|
94
|
+
model: provider.modelOverride ?? provider.client.model,
|
|
95
|
+
error: lastError.message,
|
|
96
|
+
metadata: { attempt, context },
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// All retries exhausted for this provider
|
|
101
|
+
this.recordFailure(provider.id);
|
|
102
|
+
// Try next provider (failover)
|
|
103
|
+
const nextProvider = this.getNextAvailableAfter(provider.id);
|
|
104
|
+
if (nextProvider) {
|
|
105
|
+
this.auditor.record({
|
|
106
|
+
timestamp: Date.now(),
|
|
107
|
+
type: 'failover',
|
|
108
|
+
provider: provider.id,
|
|
109
|
+
metadata: {
|
|
110
|
+
from: provider.id,
|
|
111
|
+
nextProvider: nextProvider.id,
|
|
112
|
+
context,
|
|
113
|
+
reason: lastError?.message,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
throw lastError ?? new Error('All providers failed');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Execute a streaming function with failover.
|
|
122
|
+
* On failure, retries with the next provider from the beginning.
|
|
123
|
+
*/
|
|
124
|
+
async *executeStream(fn, context = 'stream') {
|
|
125
|
+
const available = this.getAvailableProviders();
|
|
126
|
+
if (available.length === 0) {
|
|
127
|
+
throw new Error('No available LLM providers for streaming.');
|
|
128
|
+
}
|
|
129
|
+
let lastError;
|
|
130
|
+
for (const provider of available) {
|
|
131
|
+
try {
|
|
132
|
+
const stream = fn(provider.client);
|
|
133
|
+
let returnValue;
|
|
134
|
+
// We need to yield all values and capture the return
|
|
135
|
+
while (true) {
|
|
136
|
+
const result = await stream.next();
|
|
137
|
+
if (result.done) {
|
|
138
|
+
returnValue = result.value;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
yield result.value;
|
|
142
|
+
}
|
|
143
|
+
this.recordSuccess(provider.id);
|
|
144
|
+
return returnValue;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
148
|
+
this.recordFailure(provider.id);
|
|
149
|
+
this.auditor.record({
|
|
150
|
+
timestamp: Date.now(),
|
|
151
|
+
type: 'failover',
|
|
152
|
+
provider: provider.id,
|
|
153
|
+
error: lastError.message,
|
|
154
|
+
metadata: { context },
|
|
155
|
+
});
|
|
156
|
+
// Continue to next provider
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
throw lastError ?? new Error('All providers failed for streaming');
|
|
160
|
+
}
|
|
161
|
+
// ========================================================================
|
|
162
|
+
// Convenience Methods
|
|
163
|
+
// ========================================================================
|
|
164
|
+
async chat(messages, options) {
|
|
165
|
+
return this.execute(client => client.chat(messages, options), 'chat');
|
|
166
|
+
}
|
|
167
|
+
async chatWithTools(messages, options) {
|
|
168
|
+
return this.execute(client => client.chatWithTools(messages, options), 'chatWithTools');
|
|
169
|
+
}
|
|
170
|
+
async *chatStream(messages, options) {
|
|
171
|
+
return yield* this.executeStream(client => client.chatStream(messages, options), 'chatStream');
|
|
172
|
+
}
|
|
173
|
+
async embed(text) {
|
|
174
|
+
return this.execute(client => client.embed(text), 'embed');
|
|
175
|
+
}
|
|
176
|
+
async embedArray(texts) {
|
|
177
|
+
return this.execute(client => client.embedArray(texts), 'embedArray');
|
|
178
|
+
}
|
|
179
|
+
async getModels() {
|
|
180
|
+
// Aggregate models from all providers
|
|
181
|
+
const allModels = [];
|
|
182
|
+
for (const provider of this.providers) {
|
|
183
|
+
try {
|
|
184
|
+
const models = await provider.client.getModels();
|
|
185
|
+
allModels.push(...models);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Skip unavailable providers
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return [...new Set(allModels)];
|
|
192
|
+
}
|
|
193
|
+
async getModelInfo() {
|
|
194
|
+
return this.execute(client => client.getModelInfo(), 'getModelInfo');
|
|
195
|
+
}
|
|
196
|
+
// ========================================================================
|
|
197
|
+
// Tool Registration (broadcast to all providers)
|
|
198
|
+
// ========================================================================
|
|
199
|
+
registerTool(name, description, parameters, handler) {
|
|
200
|
+
for (const provider of this.providers) {
|
|
201
|
+
provider.client.registerTool(name, description, parameters, handler);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
registerTools(tools) {
|
|
205
|
+
for (const provider of this.providers) {
|
|
206
|
+
provider.client.registerTools(tools);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// ========================================================================
|
|
210
|
+
// Health Management
|
|
211
|
+
// ========================================================================
|
|
212
|
+
isAvailable(id) {
|
|
213
|
+
const h = this.health.get(id);
|
|
214
|
+
if (!h)
|
|
215
|
+
return false;
|
|
216
|
+
if (h.healthy)
|
|
217
|
+
return true;
|
|
218
|
+
// Check if cooldown has expired
|
|
219
|
+
if (h.cooldownUntil && Date.now() >= h.cooldownUntil) {
|
|
220
|
+
// Reset for re-testing
|
|
221
|
+
h.healthy = true;
|
|
222
|
+
h.consecutiveFailures = 0;
|
|
223
|
+
h.cooldownUntil = undefined;
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
getAvailableProviders() {
|
|
229
|
+
return this.providers.filter(p => this.isAvailable(p.id));
|
|
230
|
+
}
|
|
231
|
+
getNextAvailableAfter(currentId) {
|
|
232
|
+
const idx = this.providers.findIndex(p => p.id === currentId);
|
|
233
|
+
for (let i = idx + 1; i < this.providers.length; i++) {
|
|
234
|
+
if (this.isAvailable(this.providers[i].id)) {
|
|
235
|
+
return this.providers[i];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
recordSuccess(id) {
|
|
241
|
+
const h = this.health.get(id);
|
|
242
|
+
if (h) {
|
|
243
|
+
h.healthy = true;
|
|
244
|
+
h.consecutiveFailures = 0;
|
|
245
|
+
h.cooldownUntil = undefined;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
recordFailure(id) {
|
|
249
|
+
const h = this.health.get(id);
|
|
250
|
+
if (!h)
|
|
251
|
+
return;
|
|
252
|
+
h.consecutiveFailures++;
|
|
253
|
+
h.lastFailure = Date.now();
|
|
254
|
+
if (h.consecutiveFailures >= this.config.maxFailures) {
|
|
255
|
+
h.healthy = false;
|
|
256
|
+
h.cooldownUntil = Date.now() + this.config.cooldownMs;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal LLM Client v3 — Stream Decoder
|
|
3
|
+
*
|
|
4
|
+
* Pluggable interface for decoding raw LLM token streams into typed events.
|
|
5
|
+
* Consumers select their strategy per-call: passthrough for raw speed,
|
|
6
|
+
* standard-chat for structured tool calls, or interleaved-reasoning
|
|
7
|
+
* for models that emit <think>/<progress> tags.
|
|
8
|
+
*/
|
|
9
|
+
import type { LLMToolCall } from './interfaces.js';
|
|
10
|
+
/** Clean, typed events emitted by a stream decoder */
|
|
11
|
+
export type DecodedEvent = {
|
|
12
|
+
type: 'text';
|
|
13
|
+
content: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: 'thinking';
|
|
16
|
+
content: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'progress';
|
|
19
|
+
content: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: 'tool_call';
|
|
22
|
+
calls: LLMToolCall[];
|
|
23
|
+
};
|
|
24
|
+
/** Callback invoked by the decoder as events become available */
|
|
25
|
+
export type DecoderCallback = (event: DecodedEvent) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Transform raw LLM tokens into clean typed events.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* const decoder = createDecoder('standard-chat', callback);
|
|
31
|
+
* for (const token of stream) decoder.push(token);
|
|
32
|
+
* decoder.flush();
|
|
33
|
+
* const clean = decoder.getCleanContent();
|
|
34
|
+
*/
|
|
35
|
+
export interface StreamDecoder {
|
|
36
|
+
/** Feed a raw token from the LLM stream */
|
|
37
|
+
push(token: string): void;
|
|
38
|
+
/** Signal end of stream — flush any buffered state */
|
|
39
|
+
flush(): void;
|
|
40
|
+
/** Get the accumulated clean text (all structural tags stripped) */
|
|
41
|
+
getCleanContent(): string;
|
|
42
|
+
/** Get accumulated reasoning/thinking content (if any) */
|
|
43
|
+
getReasoning(): string | undefined;
|
|
44
|
+
}
|
|
45
|
+
export type DecoderType = 'passthrough' | 'standard-chat' | 'interleaved-reasoning';
|
|
46
|
+
/**
|
|
47
|
+
* Bare-bones decoder for raw text completions.
|
|
48
|
+
* No parsing, no tag awareness. All tokens → text events.
|
|
49
|
+
*/
|
|
50
|
+
export declare class PassthroughDecoder implements StreamDecoder {
|
|
51
|
+
private content;
|
|
52
|
+
private readonly callback;
|
|
53
|
+
constructor(callback: DecoderCallback);
|
|
54
|
+
push(token: string): void;
|
|
55
|
+
flush(): void;
|
|
56
|
+
getCleanContent(): string;
|
|
57
|
+
getReasoning(): string | undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Decoder for standard LLM chat patterns — text streaming with native
|
|
61
|
+
* reasoning and structured API tool calls. No text-level tag parsing.
|
|
62
|
+
*
|
|
63
|
+
* Streamed tokens are clean text → emitted as `text` events.
|
|
64
|
+
* Native reasoning tokens → accepted via `pushReasoning()`.
|
|
65
|
+
* Structured tool calls → accepted via `pushToolCalls()`.
|
|
66
|
+
*/
|
|
67
|
+
export declare class StandardChatDecoder implements StreamDecoder {
|
|
68
|
+
private content;
|
|
69
|
+
private reasoning;
|
|
70
|
+
private readonly callback;
|
|
71
|
+
constructor(callback: DecoderCallback);
|
|
72
|
+
push(token: string): void;
|
|
73
|
+
/** Feed native reasoning tokens from the provider */
|
|
74
|
+
pushReasoning(content: string): void;
|
|
75
|
+
/** Feed structured tool calls from the provider API response */
|
|
76
|
+
pushToolCalls(calls: LLMToolCall[]): void;
|
|
77
|
+
flush(): void;
|
|
78
|
+
getCleanContent(): string;
|
|
79
|
+
getReasoning(): string | undefined;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Decoder for models that emit interleaved reasoning tags in text.
|
|
83
|
+
* Parses <think>...</think> and <progress>...</progress> tags from the
|
|
84
|
+
* raw token stream and emits typed events for each.
|
|
85
|
+
*
|
|
86
|
+
* Handles streaming where tags may be split across chunks.
|
|
87
|
+
*/
|
|
88
|
+
export declare class InterleavedReasoningDecoder implements StreamDecoder {
|
|
89
|
+
private buffer;
|
|
90
|
+
private content;
|
|
91
|
+
private reasoning;
|
|
92
|
+
private readonly callback;
|
|
93
|
+
private inThink;
|
|
94
|
+
private inProgress;
|
|
95
|
+
constructor(callback: DecoderCallback);
|
|
96
|
+
push(token: string): void;
|
|
97
|
+
flush(): void;
|
|
98
|
+
getCleanContent(): string;
|
|
99
|
+
getReasoning(): string | undefined;
|
|
100
|
+
private processBuffer;
|
|
101
|
+
private findEarliest;
|
|
102
|
+
private couldBePartialTag;
|
|
103
|
+
}
|
|
104
|
+
export interface DecoderOptions {
|
|
105
|
+
/** Known tool names for text-based tool call recovery */
|
|
106
|
+
knownToolNames?: Set<string>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create a stream decoder by type.
|
|
110
|
+
*/
|
|
111
|
+
export declare function createDecoder(type: DecoderType, callback: DecoderCallback, _options?: DecoderOptions): StreamDecoder;
|
|
112
|
+
//# sourceMappingURL=stream-decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-decoder.d.ts","sourceRoot":"","sources":["../src/stream-decoder.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAMnD,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC;AAElD,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAM5D;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC1B,2CAA2C;IAC3C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,sDAAsD;IACtD,KAAK,IAAI,IAAI,CAAC;IACd,oEAAoE;IACpE,eAAe,IAAI,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,YAAY,IAAI,MAAM,GAAG,SAAS,CAAC;CACtC;AAMD,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,eAAe,GAAG,uBAAuB,CAAC;AAMpF;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IACpD,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;gBAE/B,QAAQ,EAAE,eAAe;IAIrC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzB,KAAK,IAAI,IAAI;IAIb,eAAe,IAAI,MAAM;IAIzB,YAAY,IAAI,MAAM,GAAG,SAAS;CAGrC;AAMD;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACrD,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;gBAE/B,QAAQ,EAAE,eAAe;IAIrC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzB,qDAAqD;IACrD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKpC,gEAAgE;IAChE,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI;IAIzC,KAAK,IAAI,IAAI;IAIb,eAAe,IAAI,MAAM;IAIzB,YAAY,IAAI,MAAM,GAAG,SAAS;CAGrC;AAMD;;;;;;GAMG;AACH,qBAAa,2BAA4B,YAAW,aAAa;IAC7D,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEf,QAAQ,EAAE,eAAe;IAIrC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzB,KAAK,IAAI,IAAI;IAgBb,eAAe,IAAI,MAAM;IAIzB,YAAY,IAAI,MAAM,GAAG,SAAS;IAIlC,OAAO,CAAC,aAAa;IAyFrB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,iBAAiB;CAM5B;AAMD,MAAM,WAAW,cAAc;IAC3B,yDAAyD;IACzD,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,wBAAgB,aAAa,CACzB,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,cAAc,GAC1B,aAAa,CAWf"}
|