@combycode/llm-sdk 1.0.0 → 1.2.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
@@ -4,6 +4,72 @@ All notable changes to `@combycode/llm-sdk` are documented here. The format foll
4
4
  [Keep a Changelog](https://keepachangelog.com/) and the project adheres to
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ## [1.2.0] - 2026-07-05
10
+
11
+ ### Fixed
12
+ - Anthropic hosted code-execution **file outputs** now surface on `response.files` (verified
13
+ live). Three fixes, found by real-key testing: (1) the producer parsed the outdated
14
+ `code_execution_tool_result` shape, but the current `code_execution_20260521` tool emits
15
+ `bash_code_execution_tool_result` → `bash_code_execution_output.file_id` (now both are
16
+ handled); (2) code execution needs the beta endpoint — requests using `code_interpreter` now
17
+ hit `/v1/messages?beta=true`, without which no file outputs are returned; (3) `AgentLoop`'s
18
+ final response dropped `files` (and `moderation`) — both are now propagated from the final
19
+ LLM response in `complete()` and `stream()`.
20
+
21
+ ### Added
22
+ - `AgentLoopConfig.toolInputGuardrails` (`ToolInputGuardrail[]`) — per-tool-call input
23
+ guardrails that validate a call's arguments before the permission/approval check. A trip
24
+ denies just that call (error result to the model) without halting the run or invoking the
25
+ HITL approver; a pass runs the normal permission/approval/execution path.
26
+ - `AgentTool.customDataExtractor` — optional hook to derive out-of-band metadata from a
27
+ successful tool result, attached to that call's `ToolCallReport.customData`. The model never
28
+ sees it (for your own telemetry/routing/audit); a throwing extractor is swallowed.
29
+ - Code-execution **file outputs** now surface on `response.files` across **all** providers
30
+ (completes the channel shipped in 1.1, which had only the Anthropic producer):
31
+ - OpenAI Responses: code-interpreter image outputs (by URL) and downloadable container
32
+ files (`container_file_citation` → file id + name).
33
+ - Google: hosted code-execution `inlineData` artifacts (base64), routed to `files`
34
+ instead of `media` when the turn used code execution.
35
+ - xAI: inherited from the OpenAI Responses adapter.
36
+ - `FileOutput` gains a `url` field (for providers that return a fetchable URL).
37
+
38
+ ## [1.1.0] - 2026-06-30
39
+
40
+ ### Added
41
+ - Hosted MCP tool `tunnel_id` target (OpenAI Secure MCP Tunnel) — reach a private/local MCP
42
+ server with no public URL alongside the existing `server_url` / `connector_id` targets. The
43
+ `mcp` builtin already forwards `params`; added the exported `McpToolParams` type for editor
44
+ help and a regression test locking the forwarding. (Realtime MCP tooling tracked separately.)
45
+ - `ThinkingConfig.context` (`'auto' | 'current_turn' | 'all_turns'`) — maps to OpenAI's
46
+ Responses `reasoning.context`, controlling which prior-turn reasoning items are rendered back
47
+ to the model across a stateful conversation. OpenAI Responses-only; ignored by other providers.
48
+ - Inline moderation via the `moderation` request option on `complete()`/`stream()`
49
+ (parity with OpenAI's `moderation` request field, extended to all providers). Report-only:
50
+ results attach to `CompletionResponse.moderation` (`ModerationReport`) and never block the call.
51
+ Native on the OpenAI provider (one round-trip on both Responses and Chat Completions); emulated
52
+ via OpenAI's moderations endpoint on every other provider (`mode: 'native' | 'emulate'`).
53
+ Streaming supports three strategies (`buffer` default / `parallel` / `post`) trading latency for
54
+ how early the flag reaches the consumer, surfaced as a `moderation` stream event. Emulation
55
+ requires an OpenAI key (reused from the client when it is the OpenAI provider, else
56
+ `moderation.apiKey`); missing key throws.
57
+ - Unified `CompletionResponse.files` (`FileOutput[]`) - files produced by hosted tools
58
+ (code execution, etc.), independent of `media`. The Anthropic adapter surfaces
59
+ code-execution file outputs there by file id; OpenAI/Google/xAI producers to follow.
60
+ - Model catalog: new `ModelInfo.availability` field (`limited` / `preview`, vs default
61
+ generally-available) so gated / early-access models are distinguishable from the
62
+ `status` lifecycle. (Entries for specific limited/preview models are populated by the
63
+ catalog pipeline.)
64
+ - Anthropic: the unified `code_interpreter` builtin now maps to Anthropic's hosted
65
+ `code_execution` tool (GA on Messages) - it was previously silently skipped. Hosted
66
+ code execution is now usable across Anthropic / OpenAI / Google through one interface.
67
+ - Google service tier, both directions (parity with OpenAI/Anthropic): a requested
68
+ unified `serviceTier` (`flex`/`standard`/`priority`) maps to Google's top-level
69
+ request field, and the billed `usageMetadata.serviceTier` is read back into
70
+ `usage.serviceTier` / `usage.pricingTier` for tiered cost tracking.
71
+ (New `providers/google/tiers.ts`.)
72
+
7
73
  ## [1.0.0] - 2026-06-13
8
74
 
9
75
  First public release.
@@ -16,4 +82,6 @@ First public release.
16
82
  - Service tiers end to end (request → bill → cost).
17
83
  - Cross-environment: runs on Node, Bun, and the browser. ESM, zero runtime deps.
18
84
 
85
+ [1.2.0]: https://github.com/combycode/llm-sdk-ts/releases/tag/v1.2.0
86
+ [1.1.0]: https://github.com/combycode/llm-sdk-ts/releases/tag/v1.1.0
19
87
  [1.0.0]: https://github.com/combycode/llm-sdk-ts/releases/tag/v1.0.0
package/README.md CHANGED
@@ -28,7 +28,7 @@ Requires Node ≥ 18 or Bun ≥ 1.1.
28
28
  import { complete } from '@combycode/llm-sdk';
29
29
 
30
30
  const r = await complete({
31
- model: 'anthropic/claude-haiku-4-5', // provider/model, sent verbatim
31
+ model: 'anthropic/claude-haiku-4.5', // provider/model, sent verbatim
32
32
  apiKey: process.env.ANTHROPIC_API_KEY,
33
33
  prompt: 'Say hello in one word.',
34
34
  });
@@ -46,6 +46,31 @@ export interface Guardrail {
46
46
  /** Return a decision; throw only for unexpected infrastructure errors. */
47
47
  check(ctx: GuardrailCheckContext): Promise<GuardrailDecision>;
48
48
  }
49
+ /** Context for a tool-input guardrail: the specific tool call about to run. */
50
+ export interface ToolInputGuardrailContext {
51
+ toolName: string;
52
+ arguments: Record<string, unknown>;
53
+ callId: string;
54
+ step: number;
55
+ trace: TraceContext;
56
+ }
57
+ /** A tool-input guardrail decision. Unlike message-level guardrails it does NOT
58
+ * halt the run — a trip denies just this one tool call. */
59
+ export type ToolInputGuardrailDecision = {
60
+ pass: true;
61
+ } | {
62
+ pass: false;
63
+ reason: string;
64
+ };
65
+ /** Validates a tool call's arguments BEFORE it executes (and before any HITL
66
+ * approval interruption). On a trip the call is denied — the model receives the
67
+ * denial reason as an error tool result; the run continues and the approver is
68
+ * never consulted. Arguments are immutable once the model emits them, so a single
69
+ * pre-execution check is sufficient. */
70
+ export interface ToolInputGuardrail {
71
+ name: string;
72
+ check(ctx: ToolInputGuardrailContext): Promise<ToolInputGuardrailDecision> | ToolInputGuardrailDecision;
73
+ }
49
74
  export interface GuardrailTriggeredContext {
50
75
  runId: string;
51
76
  agentId: string;
@@ -5,7 +5,7 @@ import type { CacheConfig, ThinkingConfig } from '../llm/types/request';
5
5
  import type { ConversationHistory } from './history';
6
6
  import type { HistorySnapshot } from './history-types';
7
7
  import type { AgentTool } from './types';
8
- import type { Guardrail } from './guardrail-types';
8
+ import type { Guardrail, ToolInputGuardrail } from './guardrail-types';
9
9
  import type { PermissionPolicy } from '../plugins/permissions/policy';
10
10
  import type { ApprovalRequest, ApprovalDecision } from './approval-types';
11
11
  import type { Persistence } from '../plugins/persistence/types';
@@ -48,6 +48,10 @@ export interface AgentLoopConfig {
48
48
  * output guardrails run after each step's response is produced.
49
49
  * A tripwire decision halts the run with finishReason 'guardrail'. */
50
50
  guardrails?: Guardrail[];
51
+ /** Per-tool-call input guardrails. Each runs against a tool call's arguments
52
+ * BEFORE the permission/approval check and execution. A trip denies just that
53
+ * call (error result to the model) without halting the run or invoking `approve`. */
54
+ toolInputGuardrails?: ToolInputGuardrail[];
51
55
  /** Permission policy wired into the tool-execution path.
52
56
  * Called after lookup, before execution.
53
57
  * 'allow' -> proceed; 'deny' -> tool is blocked (error result to model);
@@ -39,6 +39,7 @@ export declare class AgentLoop {
39
39
  private _toolTimeout;
40
40
  private _maxSteps;
41
41
  private _guardrails;
42
+ private _toolInputGuardrails;
42
43
  private _policy;
43
44
  private _approve;
44
45
  private _checkpoint;
@@ -39,6 +39,11 @@ export interface AgentTool {
39
39
  definition: Tool;
40
40
  /** Execute the tool. Return string or structured content. */
41
41
  execute: (args: Record<string, unknown>, context: ToolExecutionContext) => Promise<string | ContentPart[]>;
42
+ /** Optional: derive out-of-band metadata from a successful tool result, attached
43
+ * to this call's `ToolCallReport.customData`. The MODEL NEVER SEES IT — it is for
44
+ * your own telemetry/routing/audit. Runs after `execute`; may be async. Errors are
45
+ * swallowed (opt-in convenience must never break the tool result). */
46
+ customDataExtractor?: (result: string | ContentPart[], args: Record<string, unknown>, context: Omit<ToolExecutionContext, 'signal'>) => unknown | Promise<unknown>;
42
47
  }
43
48
  export interface ToolExecutionContext {
44
49
  step: number;
@@ -65,6 +70,9 @@ export interface ToolCallReport {
65
70
  value: number | string | boolean;
66
71
  type: string;
67
72
  }>;
73
+ /** Out-of-band metadata from the tool's `customDataExtractor`, if any. Never sent
74
+ * to the model; present only when an extractor returned a value. */
75
+ customData?: unknown;
68
76
  }
69
77
  export interface StepReport {
70
78
  index: number;