@wrongstack/providers 0.1.2 → 0.1.4

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 CHANGED
@@ -1,17 +1,21 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
1
+ MIT License
4
2
 
5
- Copyright 2026 ECOSTACK TECHNOLOGY OÜ
3
+ Copyright (c) 2026 ECOSTACK TECHNOLOGY OÜ
6
4
 
7
- Licensed under the Apache License, Version 2.0 (the "License");
8
- you may not use this file except in compliance with the License.
9
- You may obtain a copy of the License at
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
10
11
 
11
- http://www.apache.org/licenses/LICENSE-2.0
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
12
14
 
13
- Unless required by applicable law or agreed to in writing, software
14
- distributed under the License is distributed on an "AS IS" BASIS,
15
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- See the License for the specific language governing permissions and
17
- limitations under the License.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Provider, Capabilities, Request, Response, StreamEvent, ProviderError, TextBlock, Message, Tool, ModelsRegistry, StopReason, ContentBlock, Logger, ProviderFactory, ProviderConfig } from '@wrongstack/core';
1
+ import { Provider, Capabilities, Request, Response, StreamEvent, ProviderError, TextBlock, Message, Tool, WireFamily, ProviderFactory, Usage, StopReason, ModelsRegistry, ContentBlock, Logger, ProviderConfig } from '@wrongstack/core';
2
2
 
3
3
  /**
4
4
  * Minimal Server-Sent Events parser for HTTP streaming responses.
@@ -203,6 +203,157 @@ declare class GoogleProvider extends WireAdapter {
203
203
  private buildGenConfig;
204
204
  }
205
205
 
206
+ /**
207
+ * Declarative wire-format definition. Sufficient to add a new HTTP+SSE
208
+ * provider without subclassing `WireAdapter` — the boilerplate (HTTP errors,
209
+ * abort wiring, SSE body parsing) is shared.
210
+ *
211
+ * The shape covers the variation that actually matters between providers:
212
+ * - URL template (path, query)
213
+ * - Auth headers (x-api-key, Authorization, etc.)
214
+ * - Request body (field names, system-prompt placement, tool format)
215
+ * - SSE event translation (one wire event → 0+ canonical events)
216
+ *
217
+ * Anything more exotic (non-SSE streams, multipart bodies, OAuth flows) still
218
+ * needs a hand-written subclass — those cases are too varied to template.
219
+ *
220
+ * `S` is provider-internal state threaded across SSE events for one stream:
221
+ * accumulating partial tool-call JSON, tracking block kinds, carrying the
222
+ * model id forward from `message_start`, etc. Each `stream()` call gets a
223
+ * fresh `S` via `createStreamState`.
224
+ */
225
+ interface WireFormatConfig<S = Record<string, unknown>> {
226
+ /** Provider id (matches catalog id when the provider is in models.dev). */
227
+ id: string;
228
+ /** Wire family — used by the registry's factory list. */
229
+ family: WireFamily;
230
+ capabilities: Capabilities;
231
+ /** Used when the user doesn't override via config.baseUrl. */
232
+ defaultBaseUrl: string;
233
+ /** Build the HTTPS endpoint. Receives the (possibly user-overridden) base URL. */
234
+ buildUrl(baseUrl: string, req: Request): string;
235
+ /** Per-request headers. Default `content-type`/`accept` are provided already. */
236
+ buildHeaders(apiKey: string, req: Request): Record<string, string>;
237
+ /** Map a canonical Request onto the provider's body shape. */
238
+ buildBody(req: Request): Record<string, unknown>;
239
+ /** Construct fresh per-stream state. Called once per `stream()` call. */
240
+ createStreamState(fallbackModel: string): S;
241
+ /**
242
+ * Translate one SSE event into 0+ canonical events. Mutating `state` is
243
+ * expected — providers carry per-stream accumulators (partial tool JSON,
244
+ * current model id, usage) here.
245
+ */
246
+ parseStreamEvent(msg: SSEMessage, state: S): StreamEvent[];
247
+ /**
248
+ * Optional: yield any final events after the upstream stream closes
249
+ * (e.g. emit a synthetic `message_stop` when the wire format ends with
250
+ * `[DONE]` instead of an explicit terminator).
251
+ */
252
+ finalizeStream?(state: S): StreamEvent[];
253
+ /** Optional override; defaults to the shared HTTP error parser. */
254
+ normalizeError?(status: number, body: string): ProviderError;
255
+ }
256
+ /**
257
+ * Concrete Provider built from a declarative config. Extends WireAdapter to
258
+ * inherit the canonical HTTP + abort + error machinery.
259
+ */
260
+ declare class WireFormatProvider<S = Record<string, unknown>> extends WireAdapter {
261
+ readonly id: string;
262
+ readonly capabilities: Capabilities;
263
+ private readonly cfg;
264
+ constructor(cfg: WireFormatConfig<S>, opts: {
265
+ apiKey: string;
266
+ baseUrl?: string;
267
+ fetchImpl?: typeof fetch;
268
+ });
269
+ protected buildUrl(req: Request): string;
270
+ protected buildHeaders(req: Request): Record<string, string>;
271
+ protected buildBody(req: Request): Record<string, unknown>;
272
+ protected parseStream(body: Parameters<typeof parseSSE>[0], fallbackModel: string): AsyncIterable<StreamEvent>;
273
+ protected translateError(status: number, body: string): ProviderError;
274
+ private runStream;
275
+ }
276
+ /**
277
+ * Identity helper that gives authors type checking on the config literal.
278
+ * Use at module level:
279
+ *
280
+ * export const myProvider = defineWireFormat({
281
+ * id: 'mistral',
282
+ * family: 'openai-compatible',
283
+ * capabilities: { ... },
284
+ * ...
285
+ * });
286
+ */
287
+ declare function defineWireFormat<S = Record<string, unknown>>(cfg: WireFormatConfig<S>): WireFormatConfig<S>;
288
+ interface WireFactoryOptions {
289
+ /**
290
+ * Optional config-time override of the API key. When omitted, the factory
291
+ * reads `cfg.apiKey` (passed in at create time by the registry / config
292
+ * loader). Setting this here is useful in tests.
293
+ */
294
+ apiKey?: string;
295
+ /** Override the base URL at factory build time. */
296
+ baseUrl?: string;
297
+ }
298
+ /**
299
+ * Build a `ProviderFactory` from a declarative wire-format. Plug into
300
+ * `ProviderRegistry.register(...)` or use in `buildProviderFactoriesFromRegistry`
301
+ * for catalog-driven discovery.
302
+ */
303
+ declare function createWireFormatFactory(cfg: WireFormatConfig, opts?: WireFactoryOptions): ProviderFactory;
304
+
305
+ interface MistralStreamState {
306
+ model: string;
307
+ started: boolean;
308
+ toolCalls: Map<number, {
309
+ id?: string;
310
+ name?: string;
311
+ partial: string;
312
+ emittedStart: boolean;
313
+ }>;
314
+ }
315
+ declare const mistralWireFormat: WireFormatConfig<MistralStreamState>;
316
+
317
+ type BlockKind = 'text' | 'tool_use' | 'unknown';
318
+ interface AnthropicStreamState {
319
+ model: string;
320
+ usage: Usage;
321
+ stopReason: StopReason;
322
+ started: boolean;
323
+ blocks: Map<number, {
324
+ kind: BlockKind;
325
+ id?: string;
326
+ name?: string;
327
+ partial: string;
328
+ }>;
329
+ }
330
+ declare const anthropicWireFormat: WireFormatConfig<AnthropicStreamState>;
331
+
332
+ interface OpenAIStreamState {
333
+ model: string;
334
+ usage: Usage;
335
+ stopReason: StopReason;
336
+ started: boolean;
337
+ textOpen: boolean;
338
+ toolByIndex: Map<number, {
339
+ id: string;
340
+ name: string;
341
+ argBuf: string;
342
+ }>;
343
+ finalEmitted: boolean;
344
+ }
345
+ declare const openaiWireFormat: WireFormatConfig<OpenAIStreamState>;
346
+
347
+ interface GoogleStreamState {
348
+ model: string;
349
+ usage: Usage;
350
+ stopReason: StopReason;
351
+ started: boolean;
352
+ sawFunctionCall: boolean;
353
+ finalEmitted: boolean;
354
+ }
355
+ declare const googleWireFormat: WireFormatConfig<GoogleStreamState>;
356
+
206
357
  /**
207
358
  * Resolve capabilities for a (provider, model) pair using the family default
208
359
  * as a baseline and overlaying per-model facts from the ModelsRegistry.
@@ -308,4 +459,4 @@ declare function buildProviderFactoriesFromRegistry(opts: BuildFactoriesOptions)
308
459
  */
309
460
  declare function makeProviderFromConfig(id: string, cfg: ProviderConfig): Provider;
310
461
 
311
- export { AnthropicProvider, type AnthropicProviderOptions, type BuildFactoriesOptions, type CompatibilityQuirks, type ConvertOptions, GoogleProvider, type GoogleProviderOptions, type OpenAIChoice, type OpenAICompatibleOptions, OpenAICompatibleProvider, type OpenAIMessage, OpenAIProvider, type OpenAIProviderOptions, type OpenAIToolCall, WireAdapter, buildProviderFactoriesFromRegistry, capabilitiesFor, contentFromAnthropic, contentFromOpenAI, makeProviderFromConfig, messagesToOpenAI, normalizeAnthropic, normalizeOpenAI, parseProviderHttpError, toolsToAnthropic, toolsToOpenAI };
462
+ export { AnthropicProvider, type AnthropicProviderOptions, type BuildFactoriesOptions, type CompatibilityQuirks, type ConvertOptions, GoogleProvider, type GoogleProviderOptions, type OpenAIChoice, type OpenAICompatibleOptions, OpenAICompatibleProvider, type OpenAIMessage, OpenAIProvider, type OpenAIProviderOptions, type OpenAIToolCall, WireAdapter, type WireFactoryOptions, type WireFormatConfig, WireFormatProvider, anthropicWireFormat, buildProviderFactoriesFromRegistry, capabilitiesFor, contentFromAnthropic, contentFromOpenAI, createWireFormatFactory, defineWireFormat, googleWireFormat, makeProviderFromConfig, messagesToOpenAI, mistralWireFormat, normalizeAnthropic, normalizeOpenAI, openaiWireFormat, parseProviderHttpError, toolsToAnthropic, toolsToOpenAI };