@combycode/llm-sdk 1.1.0 → 1.3.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.
@@ -26,5 +26,8 @@ export declare class AnthropicAdapter implements ProviderAdapter {
26
26
  private buildContentPart;
27
27
  parseResponse(raw: unknown, latencyMs: number): CompletionResponse;
28
28
  parseStreamEvent(event: SSEEvent): StreamEvent[];
29
+ /** Stateless — every event is self-contained (code-execution result blocks
30
+ * arrive complete in a single content_block_start). */
31
+ createStreamParser(): (event: SSEEvent) => StreamEvent[];
29
32
  private parseUsage;
30
33
  }
@@ -23,5 +23,12 @@ export declare class GoogleAdapter implements ProviderAdapter {
23
23
  private buildContent;
24
24
  parseResponse(raw: unknown, latencyMs: number): CompletionResponse;
25
25
  parseStreamEvent(event: SSEEvent): StreamEvent[];
26
+ /** Stateful — Google splits the code-execution marker (`executableCode` /
27
+ * `codeExecutionResult`) and the produced file (`inlineData`) across parts and
28
+ * often across SSE events. The closure remembers "code execution began in this
29
+ * stream" so a later `inlineData` blob is routed to `files` (a code-exec
30
+ * artifact) rather than `media` (conversational output). */
31
+ createStreamParser(): (event: SSEEvent) => StreamEvent[];
32
+ private streamEvents;
26
33
  private parseUsage;
27
34
  }
@@ -26,5 +26,7 @@ export declare class GoogleInteractionsAdapter implements ProviderAdapter {
26
26
  enableStreaming(providerReq: ProviderHttpRequest): void;
27
27
  parseResponse(raw: unknown, latencyMs: number): CompletionResponse;
28
28
  parseStreamEvent(event: SSEEvent): StreamEvent[];
29
+ /** Stateless — the Interactions adapter surfaces no code-execution file outputs. */
30
+ createStreamParser(): (event: SSEEvent) => StreamEvent[];
29
31
  private parseUsage;
30
32
  }
@@ -21,5 +21,7 @@ export declare class OpenAIAdapter implements ProviderAdapter {
21
21
  enableStreaming(providerReq: ProviderHttpRequest, _req: NormalizedRequest): void;
22
22
  parseResponse(raw: unknown, latencyMs: number): CompletionResponse;
23
23
  parseStreamEvent(event: SSEEvent): StreamEvent[];
24
+ /** Stateless — Chat Completions has no hosted code-execution file outputs. */
25
+ createStreamParser(): (event: SSEEvent) => StreamEvent[];
24
26
  private parseUsage;
25
27
  }
@@ -25,5 +25,8 @@ export declare class OpenAIResponsesAdapter implements ProviderAdapter {
25
25
  enableStreaming(providerReq: ProviderHttpRequest): void;
26
26
  parseResponse(raw: unknown, latencyMs: number): CompletionResponse;
27
27
  parseStreamEvent(event: SSEEvent): StreamEvent[];
28
+ /** Stateless — each output item finalizes with all its file annotations in a
29
+ * single response.output_item.done event. */
30
+ createStreamParser(): (event: SSEEvent) => StreamEvent[];
28
31
  protected parseUsage(u: Record<string, unknown> | undefined): Usage;
29
32
  }
@@ -25,8 +25,16 @@ export interface ProviderAdapter {
25
25
  buildRequest(req: NormalizedRequest): ProviderHttpRequest;
26
26
  /** Parse provider's raw HTTP response body to a normalized CompletionResponse. */
27
27
  parseResponse(raw: unknown, latencyMs: number): CompletionResponse;
28
- /** Convert one SSE event from the provider stream into zero or more StreamEvents. */
28
+ /** Convert one SSE event from the provider stream into zero or more StreamEvents.
29
+ * Stateless per-event primitive — see `createStreamParser` for the per-stream
30
+ * entry point the client actually calls. */
29
31
  parseStreamEvent(event: SSEEvent): StreamEvent[];
32
+ /** Create a per-stream parser. Returns a function that converts each SSE event
33
+ * into zero or more StreamEvents, holding any per-stream state (e.g. whether the
34
+ * turn has begun hosted code execution) in its closure. The client calls this
35
+ * once per `stream()` so each stream gets isolated state. Stateless adapters
36
+ * return `parseStreamEvent` bound to themselves. */
37
+ createStreamParser(): (event: SSEEvent) => StreamEvent[];
30
38
  /** Auth headers (Bearer / x-api-key / etc.). */
31
39
  authHeaders(): Record<string, string>;
32
40
  /** Base URL — provider's domain root. */
@@ -34,8 +34,15 @@ export interface FileOutput {
34
34
  mimeType?: string;
35
35
  /** Inline bytes (base64) when the provider returns the file inline; else absent. */
36
36
  data?: string;
37
+ /** URL to fetch the file when the provider returns one (e.g. OpenAI code-interpreter
38
+ * image outputs); else absent. */
39
+ url?: string;
37
40
  /** What produced it (e.g. 'code_execution'). */
38
41
  source?: string;
42
+ /** Provider-specific retrieval hints, used by `retrieveFile`/`streamFile` when the
43
+ * file is fetched by `id` (e.g. OpenAI container files set `{ containerId }`).
44
+ * Absent for providers that don't need extra context. */
45
+ ref?: Record<string, unknown>;
39
46
  }
40
47
  export type FinishReason = 'stop' | 'tool_use' | 'length' | 'content_filter' | 'error';
41
48
  export interface Usage {
@@ -1,6 +1,6 @@
1
1
  /** Universal streaming event types. */
2
2
  import type { ModerationEntry } from '../moderation/types';
3
- import type { Usage } from './response';
3
+ import type { FileOutput, Usage } from './response';
4
4
  export type MediaStreamType = 'image' | 'audio' | 'video';
5
5
  export type StreamEvent = {
6
6
  type: 'text';
@@ -41,6 +41,14 @@ export type StreamEvent = {
41
41
  type: 'media_end';
42
42
  mediaId?: string;
43
43
  }
44
+ /** A hosted-tool output file (e.g. a code-execution chart/CSV) became available.
45
+ * Carries the `FileOutput` descriptor (id / url / inline data + name / mimeType),
46
+ * not the bytes — fetch those via `retrieveFile` / `streamFile`. The same file
47
+ * is also collected onto the streamed final response's `files`. */
48
+ | {
49
+ type: 'file';
50
+ file: FileOutput;
51
+ }
44
52
  /** A moderation result for the input or output. `source` distinguishes a
45
53
  * provider-native result from a client-emulated one. Emitted by the moderation
46
54
  * option (report-only). */
@@ -15,8 +15,10 @@ export interface HttpRequest {
15
15
  model: string;
16
16
  /** How to parse the response body. Default 'json' (LLM responses, image-gen
17
17
  * with b64_json, video-status JSON). Use 'arraybuffer' for binary downloads
18
- * (TTS audio bytes, video file bytes). 'text' for plain-text responses. */
19
- responseType?: 'json' | 'arraybuffer' | 'text';
18
+ * (TTS audio bytes, video file bytes). 'text' for plain-text responses.
19
+ * 'stream' returns the raw `ReadableStream<Uint8Array>` body un-buffered (large
20
+ * file downloads that pipe straight to a sink). */
21
+ responseType?: 'json' | 'arraybuffer' | 'text' | 'stream';
20
22
  /** When the request body is already a Uint8Array / ArrayBuffer (binary
21
23
  * upload like multipart) the queue should NOT JSON.stringify it. Default
22
24
  * false → body is JSON.stringify'd. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combycode/llm-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Unified, pluggable AI SDK for accessing the LLMs of every major provider (Anthropic, OpenAI, Google, xAI, OpenRouter) through one API. Cross-environment: Node, Bun, and the browser.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",