d749d13
fix(anthropic): ToolChoiceNone should send tool_choice:{type:"none"} to API (#178)
Click to expand commit body
The Anthropic provider's toTools function was returning nil for
anthropicToolChoice when ToolChoiceNone was set, which meant
tool_choice was never included in the API request. The API defaults
to "auto", so the model could still make tool calls.
Now properly constructs ToolChoiceUnionParam with OfNone set using
anthropic.NewToolChoiceNoneParam().
Also adds test coverage for ToolChoiceNone.
* Closes #177
💘 Generated with Crush
Assisted-by: Kimi K2.5 via Crush <crush@charm.land>
Andrey Nering
created
1568c97
fix(anthropic): anthropic with vertex works with service account json keys (#157)
22c3e9a
fix(openai): subtract cached tokens from input tokens to avoid double counting (#176)
Click to expand commit body
OpenAI's API reports prompt_tokens/input_tokens INCLUDING cached tokens,
while also separately reporting cached_tokens in prompt_tokens_details.
This caused double-counting when users summed InputTokens + CacheReadTokens.
For example, if OpenAI reports:
- prompt_tokens: 1000 (includes 900 cached)
- cached_tokens: 900
Before this fix, fantasy reported:
- InputTokens: 1000
- CacheReadTokens: 900
After this fix, fantasy reports:
- InputTokens: 100 (non-cached only)
- CacheReadTokens: 900
This matches the behavior of Vercel AI SDK and prevents billing
miscalculations when pricing input tokens and cache read tokens separately.
See: https://platform.openai.com/docs/guides/prompt-caching#requirements
💘 Generated with Crush
Assisted-by: Kimi K2.5 via Crush <crush@charm.land>
Andrey Nering
created
0c8663f
feat(openai): add responses api `store`, `previous_response_id`, and `response.id` support (#175)
Click to expand commit body
Co-authored-by: Christian Rocha <christian@rocha.is>
This is currently already covered by `web-search` example.
Andrey Nering
created
6462ab9
feat(openai): add web search tool support for Responses API (#173)
Click to expand commit body
Add OpenAI web search as a provider-defined tool, mirroring the
Anthropic web search implementation pattern.
New files:
- providers/openai/web_search.go: WebSearchTool() helper with
SearchContextSize, AllowedDomains, and UserLocation options.
- examples/openai-web-search/main.go: Example using the agent
pattern with web search.
Changes to existing files:
- responses_options.go: WebSearchCallMetadata, WebSearchAction,
and WebSearchSource types registered for JSON round-tripping.
- responses_language_model.go:
- toResponsesTools(): Route ProviderDefinedTool web_search to
the OpenAI SDK WebSearchToolParam.
- Generate(): Emit ToolCallContent + ToolResultContent pair for
web_search_call output items. Source citations come from
url_citation annotations on message text.
- Stream(): Emit ToolInputStart/ToolInputEnd/ToolCall/ToolResult
lifecycle events for web_search_call items.
- toResponsesPrompt(): Round-trip provider-executed tool calls
via item_reference; skip SourceContent and provider-executed
ToolResultPart (already handled by the reference).
- providertests/provider_registry_test.go: Add metadata test case.
df8bcd9
chore(deps): bump the all group with 4 updates (#171)
Click to expand commit body
Bumps the all group with 4 updates: [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2), [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2), [github.com/openai/openai-go/v3](https://github.com/openai/openai-go) and [google.golang.org/genai](https://github.com/googleapis/go-genai).
Updates `github.com/aws/aws-sdk-go-v2` from 1.41.3 to 1.41.4
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.41.3...v1.41.4)
Updates `github.com/aws/aws-sdk-go-v2/config` from 1.32.11 to 1.32.12
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.32.11...config/v1.32.12)
Updates `github.com/openai/openai-go/v3` from 3.26.0 to 3.28.0
- [Release notes](https://github.com/openai/openai-go/releases)
- [Changelog](https://github.com/openai/openai-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/openai/openai-go/compare/v3.26.0...v3.28.0)
Updates `google.golang.org/genai` from 1.49.0 to 1.50.0
- [Release notes](https://github.com/googleapis/go-genai/releases)
- [Changelog](https://github.com/googleapis/go-genai/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/go-genai/compare/v1.49.0...v1.50.0)
---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
dependency-version: 1.41.4
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: all
- dependency-name: github.com/aws/aws-sdk-go-v2/config
dependency-version: 1.32.12
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: all
- dependency-name: github.com/openai/openai-go/v3
dependency-version: 3.28.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: all
- dependency-name: google.golang.org/genai
dependency-version: 1.50.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: all
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
dependabot[bot]
and
dependabot[bot]
created
eaa111e
chore(anthroipic): harden web_search coercion for json round-trips
Click to expand commit body
This guards against cases when web_search options could be silently
dropped when tool args pass through generic/JSON-shaped data, so domain
filters, max uses, and user location reliably reach Anthropic.
caf105e
test: re-record almost all fixtures (#167)
Andrey Nering
created
38eb77b
feat: add Anthropic web search tool support (server_tool_use + web_search_tool_result)
Click to expand commit body
- Handle ProviderDefinedTool with ID "web_search" in toTools(), mapping to
anthropic.WebSearchTool20250305Param with optional allowed/blocked domains
- Parse "server_tool_use" blocks in Generate() and Stream(), producing
ToolCallContent with ProviderExecuted=true
- Parse "web_search_tool_result" blocks, extracting SourceContent for each
search result and a ToolResultContent summary
- Stream server_tool_use via ToolInputStart/ToolInputEnd/ToolCall events
- Stream web_search_tool_result via Source events for each result item
- Skip provider-executed tool results and source content when building
Anthropic prompts (toPrompt) to avoid sending unrecognized block types
- Add ProviderExecuted field to ToolResultPart with JSON marshal/unmarshal
- Propagate ProviderExecuted from ToolResultContent to ToolResultPart in
agent's toResponseMessages()
a3b8a69
fix(openrouter): preserve anthropic reasoning signature in streaming
Click to expand commit body
Anthropic sends the reasoning signature chunk after tool_calls have
started. The streaming hook was ending reasoning prematurely on the
first tool_call chunk, so the late-arriving signature was lost. Track
the reasoning format and defer ending for anthropic streams until the
signature arrives. Also fix the agent stream assembler to not overwrite
provider metadata with nil on reasoning deltas.
💘 Generated with Crush
Assisted-by: Claude Opus 4.6 via Crush <crush@charm.land>
Andrey Nering
created
152acfe
fix: guard against nil EncryptedContent dereference in reasoning details
Click to expand commit body
Reasoning metadata can exist without encrypted content, causing a nil
pointer panic when building prompt messages for openrouter and vercel.
💘 Generated with Crush
Assisted-by: Claude Opus 4.6 via Crush <crush@charm.land>
This change to be better follow the convention:
* App name should not have spaces: `Charm Fantasy` -> `Charm-Fantasy`.
* Add comment `()` with app site.
Andrey Nering
created
e8560e6
fix(openai): use noDefaultUserAgent in all responses API calls
Click to expand commit body
💘 Generated with Crush
Assisted-by: Kimi K2.5 via Crush <crush@charm.land>
Christian Rocha
created
522e026
fix(openai): propagate noDefaultUserAgent to responsesLanguageModel
Click to expand commit body
💘 Generated with Crush
Assisted-by: Kimi K2.5 via Crush <crush@charm.land>
OpenRouter rejects API calls using a custom User Agent. This workaround
skips OpenRouter when setting a user agent.
Note that we've added two new methods accordingly, as OpenRouter uses
the openai package:
openai.WithSkipUserAgent()
openai.WithLanguageModelSkipUserAgent()