@combycode/llm-sdk 1.2.0 → 1.4.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/CHANGELOG.md CHANGED
@@ -6,6 +6,47 @@ All notable changes to `@combycode/llm-sdk` are documented here. The format foll
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.4.0] - 2026-07-06
10
+
11
+ ### Fixed
12
+ - **xAI hosted code-execution files** now surface on `response.files` (parity with the other
13
+ providers). xAI returns code-interpreter output files inline inside the `code_interpreter_call`
14
+ `logs` JSON (`output_files:[{file_name, mime_type, data:[…bytes]}]`) and only when the request
15
+ asks for them — so `XAIResponsesAdapter` now sends `include:['code_interpreter_call.outputs']`
16
+ when `code_interpreter` is used and extracts the inline bytes into `FileOutput`. Verified live on
17
+ `complete()` and `stream()`. `OpenAIResponsesAdapter.filesFromOutputItem` is now a `protected`
18
+ overridable method so Responses-compatible providers can extend file extraction.
19
+
20
+ ### Added
21
+ - **Adapter-sourced builtin-tool capabilities in the catalog.** Every tool-capable (chat-family)
22
+ model now carries `capabilities.builtinTools` — `['web_search', 'code_interpreter']` for
23
+ anthropic/openai/google/xai, `['web_search']` for openrouter (it doesn't route hosted code
24
+ execution) — injected at catalog load from a single provider map (`PROVIDER_BUILTIN_TOOLS`) that
25
+ mirrors what the adapters actually support. New `catalog.builtinToolsFor()` /
26
+ `supportsBuiltinTool()` accessors and `select('web_search')` / `select('code_interpreter')`
27
+ queries (`search` stays an alias for `web_search`). Non-tool models (embeddings/tts/image) get
28
+ none. A reliable per-model source can refine this later.
29
+
30
+ ## [1.3.0] - 2026-07-06
31
+
32
+ ### Added
33
+ - **Streaming file parity.** `stream()` now surfaces hosted code-execution output files with the
34
+ same coverage as `complete()`: a new `{ type: 'file', file }` `StreamEvent` is emitted as each
35
+ file finalizes mid-stream, and the files are collected onto the streamed final response's
36
+ `files` (via `onCompletion` / the agent final response). New `ProviderAdapter.createStreamParser()`
37
+ returns a per-stream parser so adapters can hold per-stream state — used by Google to route an
38
+ inline code-execution artifact (whose "code ran" marker and bytes arrive in separate SSE events)
39
+ to `files` rather than conversational `media`. Verified live on Anthropic, OpenAI, and Google.
40
+ - **File-content retrieval** for hosted-tool output files. `CompleteResult`, `LLMClient`, and
41
+ the agent result now expose `retrieveFile(file)` → `{ blob, name, mimeType, size }` and
42
+ `streamFile(file)` → `{ stream, name, mimeType, size }`, resolving a `FileOutput`'s inline
43
+ `data`, `url`, or provider file `id` through the same model + key the call used — no
44
+ re-passing credentials. `streamFile` pipes large files to a sink without buffering. Name /
45
+ mime / size come from the download response headers (Content-Disposition / Content-Type /
46
+ Content-Length, with a filename-extension mime fallback). New network `responseType: 'stream'`
47
+ returns the raw body and releases the queue slot immediately. Exports `RetrievedFile`,
48
+ `FileStream`. Auth is sent only to the provider's own host.
49
+
9
50
  ## [1.2.0] - 2026-07-05
10
51
 
11
52
  ### Fixed
package/README.md CHANGED
@@ -64,6 +64,28 @@ for await (const ev of llm.stream('Count to 5.')) {
64
64
  }
65
65
  ```
66
66
 
67
+ ### Hosted code execution + output files
68
+
69
+ Run the provider's code interpreter and pull the files it produces (charts, CSVs) — one
70
+ interface, any provider. `retrieveFile` / `streamFile` fetch the bytes plus `name` / `mimeType`
71
+ / `size`, bound to the same model + key:
72
+
73
+ ```ts
74
+ import { complete } from '@combycode/llm-sdk';
75
+
76
+ const { response, retrieveFile } = await complete({
77
+ model: 'anthropic/claude-haiku-4.5',
78
+ apiKey: process.env.ANTHROPIC_API_KEY,
79
+ prompt: 'Plot y = x**2 for x in 1..5, save a PNG, and return the file.',
80
+ tools: [{ type: 'code_interpreter' }],
81
+ maxTokens: 6000,
82
+ });
83
+
84
+ for (const file of response.files ?? []) {
85
+ const { blob, name, mimeType, size } = await retrieveFile(file); // or streamFile for large files
86
+ }
87
+ ```
88
+
67
89
  ## Documentation
68
90
 
69
91
  Full guide pages covering all export groups:
@@ -77,6 +99,8 @@ Full guide pages covering all export groups:
77
99
  - [Cost Tracking + estimate()](./docs/guide/cost.md)
78
100
  - [Observability / Telemetry](./docs/guide/telemetry.md)
79
101
  - [Media / Files / Batch](./docs/guide/media-files-batch.md)
102
+ - [Hosted Code Execution](./docs/guide/code-execution.md)
103
+ - [Retrieving Output Files](./docs/guide/retrieving-files.md)
80
104
  - [MCP (Model Context Protocol)](./docs/guide/mcp.md)
81
105
  - [Context Guard + Permissions + Persistence + Cache](./docs/guide/context-guard.md)
82
106
  - [OpenAI-Compatible Server](./docs/guide/server.md)
@@ -13,7 +13,8 @@
13
13
  import { HookBus } from '../bus/hook-bus';
14
14
  import { type ContentPart, type Message } from '../llm/types/messages';
15
15
  import type { ExecuteOptions } from '../llm/types/options';
16
- import { type CompletionResponse } from '../llm/types/response';
16
+ import { type CompletionResponse, type FileOutput } from '../llm/types/response';
17
+ import type { FileStream, RetrievedFile } from '../llm/files/retrieve';
17
18
  import type { LLMClient } from '../llm/client';
18
19
  import { ConversationHistory } from './history';
19
20
  import type { AgentLoopSnapshot, AgentRunReport, AgentStreamEvent, AgentTool } from './types';
@@ -52,6 +53,14 @@ export declare class AgentLoop {
52
53
  destroy(): void;
53
54
  /** Model is owned by client. */
54
55
  get model(): string;
56
+ /** Fetch a hosted-tool output file from the run's `response.files` — its bytes
57
+ * as a `Blob` plus `name` / `mimeType` / `size`. Delegates to the underlying
58
+ * client, so it uses this agent's provider + key (same as `retrieveFile` on a
59
+ * `complete()` result). */
60
+ retrieveFile(file: FileOutput): Promise<RetrievedFile>;
61
+ /** Stream a hosted-tool output file (large files) — a `ReadableStream` plus
62
+ * best-effort `name` / `mimeType` / `size`. Delegates to the underlying client. */
63
+ streamFile(file: FileOutput): Promise<FileStream>;
55
64
  get system(): string;
56
65
  set system(v: string);
57
66
  get context(): string;
@@ -18,7 +18,8 @@ import type { AgentTool } from '../agent/types';
18
18
  import type { LLMClientConfig } from '../llm/client-config';
19
19
  import type { AudioOptions } from '../llm/types/audio';
20
20
  import type { ContentPart, Message } from '../llm/types/messages';
21
- import type { CompletionResponse } from '../llm/types/response';
21
+ import type { CompletionResponse, FileOutput } from '../llm/types/response';
22
+ import type { FileStream, RetrievedFile } from '../llm/files/retrieve';
22
23
  import type { ProviderName } from '../llm/types/provider';
23
24
  import type { ServiceTier } from '../llm/types/tiers';
24
25
  import type { BuiltinTool } from '../llm/types/tools';
@@ -82,5 +83,11 @@ export interface CompleteResult<T = unknown> {
82
83
  * otherwise `undefined`. The generic on `complete<T>(...)` types this. */
83
84
  parsed?: T;
84
85
  response: CompletionResponse;
86
+ /** Fetch a hosted-tool output file (from `response.files`): bytes (`Blob`) +
87
+ * `name` / `mimeType` / `size` — bound to the SAME model + key this call used. */
88
+ retrieveFile(file: FileOutput): Promise<RetrievedFile>;
89
+ /** Stream a hosted-tool output file (`ReadableStream` + `name` / `mimeType` /
90
+ * `size`) — for large files piped straight to a sink. Same model + key. */
91
+ streamFile(file: FileOutput): Promise<FileStream>;
85
92
  }
86
93
  export declare function complete<T = unknown>(opts: CompleteOptions): Promise<CompleteResult<T>>;