Commit graph

86 commits

Author SHA1 Message Date
Mario Zechner
0fc6689dfb fix(ai): re-enable SDK retries for Anthropic provider
The SDK default of 2 retries handles transient HTTP failures quickly,
while coding-agent retries handle persistent errors with user feedback.
2025-12-20 09:56:11 +01:00
Cyril
6ff405a976 fix(ai): prevent double API version path in Google provider URL 2025-12-19 20:41:07 +00:00
Mario Zechner
0dbc1065ad Add Copilot-Vision-Request header for image requests
fixes #222
2025-12-19 05:12:40 +01:00
Mario Zechner
575dcb2676 Fix X-Initiator header logic for GitHub Copilot
Check last message role instead of any message in history.
This matches the original correct implementation from PR #200.

fixes #209
2025-12-19 05:08:28 +01:00
Aadish Verma
314ef34ebc
feat: implement thinking for some more copilot models (#234)
Signed-off-by: StarLight842 <mail@aadishv.dev>
2025-12-19 04:42:23 +01:00
Mario Zechner
98e5b4dce9
Merge pull request #221 from theBucky/fix/google-provider-baseurl
fix(ai): pass baseUrl to Google GenAI SDK via httpOptions
2025-12-18 15:40:05 +01:00
theBucky
aac68ba35c fix(ai): pass baseUrl to Google GenAI SDK via httpOptions
Previously, when using 'google-generative-ai' API with a custom baseUrl
in models.json, the baseUrl was ignored and requests always went to the
default Google endpoint.

Now the provider correctly passes model.baseUrl to the SDK's
httpOptions.baseUrl, enabling use of custom endpoints or API proxies.

Fixes #216
2025-12-18 22:03:43 +08:00
Mario Zechner
84018b0707 fix(ai): correct Gemini tool result format and improve type safety
- Fix tool result format for Gemini 3 Flash Preview compatibility
  - Use 'output' key for successful results (not 'result')
  - Use 'error' key for error results (not 'isError')
  - Per Google SDK documentation for FunctionResponse.response

- Improve type safety in google.ts provider
  - Add ImageContent import and use proper type guards
  - Replace 'as any' casts with proper typing
  - Import and use Schema type for tool parameters
  - Add proper typing for index deletion in error handler

- Add comprehensive test for Gemini 3 Flash tool calling
  - Tests successful tool call and result handling
  - Tests error tool result handling
  - Verifies fix for issue #213

Fixes #213
2025-12-18 13:43:39 +00:00
Markus Ylisiurunen
d690310587
Fix Gemini 3 Flash Preview thinking levels (#212)
* use the correct Gemini 3 Flash Preview thinking levels

* fix a build error

* add changelog entry

* regenerate models

* make less assumptions about future models
2025-12-18 13:03:28 +01:00
Mario Zechner
4894fa411c Release v0.23.2
Fixed Claude models via GitHub Copilot re-answering all previous prompts.

fixes #209
2025-12-17 17:56:00 +01:00
Ahmed Kamal
c2dea0ce8b
Add X-Initiator header for GitHub Copilot (#200) 2025-12-16 14:05:22 +01:00
Mario Zechner
fd5134f88c Release v0.22.2 2025-12-15 22:09:14 +01:00
Mario Zechner
a7e3b8625b Release v0.22.1 2025-12-15 21:53:27 +01:00
Mario Zechner
c5543f7586 GitHub Copilot: auto-enable models, fix gpt-5 API, normalize tool call IDs
- Auto-enable all models after /login via POST /models/{model}/policy
- Use openai-responses API for gpt-5/o3/o4 models (not accessible via completions)
- Normalize tool call IDs when switching between github-copilot models with different APIs
  (fixes #198: openai-responses generates 450+ char IDs with special chars that break other models)
- Update README with streamlined GitHub Copilot docs
2025-12-15 20:06:11 +01:00
Markus Ylisiurunen
6b48fa58d7
Support thinking level configuration for Gemini 3 Pro models (#176)
* support Google thinking level configuration for Gemini 3 Pro models

* relax model ID check for gemini 3 pro
2025-12-13 02:09:54 +01:00
Mario Zechner
078661c3b1 Restore assistant bridge message insertion for compat flag 2025-12-11 00:36:35 +01:00
Mario Zechner
bb445d24f1 Auto-retry on transient provider errors (overloaded, rate limit, 5xx)
- Add retry logic with exponential backoff (2s, 4s, 8s) in AgentSession
- Disable Anthropic SDK built-in retries (maxRetries: 0) to allow app-level handling
- TUI shows retry status with Escape to cancel
- RPC mode: add set_auto_retry, abort_retry commands and auto_retry_start/end events
- Configurable via settings.json: retry.enabled, retry.maxRetries, retry.baseDelayMs
- Exclude context overflow errors from retry (handled by compaction)

fixes #157
2025-12-10 23:36:46 +01:00
Mario Zechner
76312ea7e8 Fix Mistral 400 errors after aborted assistant messages
- Skip empty assistant messages (no content, no tool calls) to avoid
  Mistral's 'Assistant message must have either content or tool_calls'
  error
- Remove synthetic assistant bridge message after tool results (Mistral
  no longer requires this as of Dec 2024)
- Add test for empty assistant message handling

Follow-up to #165
2025-12-10 21:13:33 +01:00
Mario Zechner
99b4b1aca0 Add Mistral as AI provider
- Add Mistral to KnownProvider type and model generation
- Implement Mistral-specific compat handling in openai-completions:
  - requiresToolResultName: tool results need name field
  - requiresAssistantAfterToolResult: synthetic assistant message between tool/user
  - requiresThinkingAsText: thinking blocks as <thinking> text
  - requiresMistralToolIds: tool IDs must be exactly 9 alphanumeric chars
- Add MISTRAL_API_KEY environment variable support
- Add Mistral tests across all test files
- Update documentation (README, CHANGELOG) for both ai and coding-agent packages
- Remove client IDs from gemini.md, reference upstream source instead

Closes #165
2025-12-10 20:36:19 +01:00
Lukas Pitschl
a248e2547a
fix(ai): remove global process.env.ANTHROPIC_API_KEY deletion (#164)
* fix(ai): remove global process.env.ANTHROPIC_API_KEY deletion

The code was deleting process.env.ANTHROPIC_API_KEY to prevent the SDK
from using it when OAuth tokens were provided. However, this was a global
mutation that affected the entire Node.js process, causing the API key to
be unavailable after the first prompt.

The Anthropic SDK constructor already handles credential selection via
parameters (apiKey: null, authToken: token for OAuth vs apiKey: key for
regular keys), so the environment variable deletion was unnecessary.

* Update CHANGELOG.md for API key fix
2025-12-10 18:12:16 +01:00
Mario Zechner
238c5d34e4 Fix tsgo type issues: update tsgo, fix ReasoningEffort import, remove broken enum-test 2025-12-08 22:59:13 +01:00
Tiago Freitas
8f67e00160
fix: include empty tools param when conversation has tool history (#150)
Anthropic (via LiteLLM/proxy) requires the `tools` parameter to be
present when messages include tool_calls or tool role messages,
even if no tools are currently being provided.

This adds a `hasToolHistory()` helper to detect if the conversation
contains tool calls or tool results, and ensures `tools: []` is
included in the request params when needed.

Fixes #149

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Ubuntu <ubuntu@ip-172-31-50-87.us-west-2.compute.internal>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 21:30:43 +01:00
Mario Zechner
00370cab39 Add xhigh thinking level for OpenAI codex-max models
- Add 'xhigh' to ThinkingLevel type in ai and agent packages
- Map xhigh to reasoning_effort: 'max' for OpenAI providers
- Add thinkingXhigh color token to theme schema and built-in themes
- Show xhigh option only when using codex-max models
- Update CHANGELOG for both ai and coding-agent packages

closes #143
2025-12-08 21:12:54 +01:00
Mario Zechner
87a1a9ded4 Add OpenAICompat for openai-completions provider quirks
Fixes #133
2025-12-08 19:02:03 +01:00
Mario Zechner
8bec289dc6 Remove provider-level tool validation, add validateToolCall helper 2025-12-08 18:04:33 +01:00
Markus Ylisiurunen
0196308266 add option to skip provider tool call validation 2025-12-07 17:24:06 +02:00
Mario Zechner
86e5a70ec4 Add totalTokens field to Usage type
- Added totalTokens field to Usage interface in pi-ai
- Anthropic: computed as input + output + cacheRead + cacheWrite
- OpenAI/Google: uses native total_tokens/totalTokenCount
- Fixed openai-completions to compute totalTokens when reasoning tokens present
- Updated calculateContextTokens() to use totalTokens field
- Added comprehensive test covering 13 providers

fixes #130
2025-12-06 22:46:02 +01:00
Mario Zechner
989af79752 fix: normalize OpenAI token counting, add branch source tracking
pi-ai:
- Fixed usage.input to exclude cached tokens for OpenAI providers
- Previously input included cached tokens, causing double-counting
- Now input + output + cacheRead + cacheWrite correctly gives total context

coding-agent:
- Session header now includes branchedFrom field for branched sessions
- Updated compaction.md with refined implementation plan
- Updated session.md with branchedFrom documentation
2025-12-03 17:11:22 +01:00
Mario Zechner
de39f1f493 Add custom headers support for models.json
Fixes #39

- Added headers field to Model type (provider and model level)
- Model headers override provider headers when merged
- Supported in all APIs:
  - Anthropic: defaultHeaders
  - OpenAI (completions/responses): defaultHeaders
  - Google: httpOptions.headers
- Enables bypassing Cloudflare bot detection for proxied endpoints
- Updated documentation with examples

Also fixed:
- Mistral/Chutes syntax error (iif -> if)
- process.env.ANTHROPIC_API_KEY bug (use delete instead of = undefined)
2025-11-20 17:05:31 +01:00
butelo
b76f7a0f88 Merge branch 'main' into fix/chutes-ai-provider-400-error 2025-11-20 15:04:29 +01:00
butelo
bd1731c9ba fix 400 error when trying to use chutes ai provider 2025-11-20 14:56:22 +01:00
Mario Zechner
a11c1aa4ff Release v0.7.17 2025-11-18 17:49:12 +01:00
Mario Zechner
387cc97bac Fix Anthropic API rejection when resubmitting aborted thinking blocks
- Convert thinking blocks with missing/empty signatures to text blocks
- Prevents 400 error: 'Invalid signature in thinking block'
- Occurs when stream is aborted mid-thinking and message is resubmitted
2025-11-18 14:36:57 +01:00
Mario Zechner
063b7e0f11 chore: bump coding-agent to 0.7.14 - fix Anthropic OAuth and Mistral API compatibility 2025-11-17 12:46:59 +01:00
Mario Zechner
bf1a7d8571 Add 'pi' command alias and fix getApiKey import 2025-11-12 14:31:25 +01:00
Mario Zechner
00d8286523 Handle FinishReason.NO_IMAGE and fix optional chaining
- Add NO_IMAGE to error finish reasons in Google provider
- Fix non-null assertion after optional chaining in Anthropic provider
- Migrate biome config to 2.3.5
- Ignore Tailwind CSS file from biome checks
- Bump all packages to version 0.6.0
2025-11-12 10:58:03 +01:00
Mario Zechner
84dcab219b Add image support in tool results across all providers
Tool results now use content blocks and can include both text and images.
All providers (Anthropic, Google, OpenAI Completions, OpenAI Responses)
correctly pass images from tool results to LLMs.

- Update ToolResultMessage type to use content blocks
- Add placeholder text for image-only tool results in Google/Anthropic
- OpenAI providers send tool result + follow-up user message with images
- Fix Anthropic JSON parsing for empty tool arguments
- Add comprehensive tests for image-only and text+image tool results
- Update README with tool result content blocks API
2025-11-12 10:45:56 +01:00
Mario Zechner
bc8d994a7b Fix token statistics on abort for Anthropic provider
- Add handling for message_start event to capture initial token usage
- Fix message_delta to use assignment (=) instead of addition (+=)
  since Anthropic sends cumulative token counts, not incremental
- Add comprehensive tests for all providers (Google, OpenAI Completions,
  OpenAI Responses, Anthropic)
- Document OpenAI limitation: token stats only available at stream end

Fixes issue where aborted streams had zero token counts despite
Anthropic sending input tokens in the initial message_start event.
2025-10-26 21:22:24 +01:00
Mario Zechner
55dc0b6e08 Add timestamp to messages 2025-10-26 00:43:43 +02:00
Mario Zechner
4e7a340460 Add Unicode surrogate sanitization for all providers
Fixes issue where unpaired Unicode surrogates in tool results cause JSON serialization errors in API providers, particularly Anthropic.

- Add sanitizeSurrogates() utility function to remove unpaired surrogates
- Apply sanitization in all provider convertMessages() functions:
  - User message text content (string and text blocks)
  - Assistant message text and thinking blocks
  - Tool result output
  - System prompts
- Valid emoji (properly paired surrogates) are preserved
- Add comprehensive test suite covering all 8 providers

Previously only Google and Groq handled unpaired surrogates correctly.
Now all providers (Anthropic, OpenAI Completions/Responses, Google, xAI, Groq, Cerebras, zAI) sanitize text before API submission.
2025-10-13 14:26:54 +02:00
Mario Zechner
0496651308 Add Anthropic prompt caching, pluggable storage, and CORS proxy support
Storage Architecture:
- New pluggable storage system with backends (LocalStorage, ChromeStorage, IndexedDB)
- SettingsRepository for app settings (proxy config, etc.)
- ProviderKeysRepository for API key management
- AppStorage with global accessors (getAppStorage, setAppStorage, initAppStorage)

Transport Refactoring:
- Renamed DirectTransport → ProviderTransport (calls LLM providers with optional CORS proxy)
- Renamed ProxyTransport → AppTransport (uses app server with user auth)
- Updated TransportMode: "direct" → "provider", "proxy" → "app"

CORS Proxy Integration:
- ProviderTransport checks proxy.enabled/proxy.url from storage
- When enabled, modifies model baseUrl to route through proxy: {proxyUrl}/?url={originalBaseUrl}
- ProviderKeyInput test function also honors proxy settings
- Settings dialog with Proxy tab (Switch toggle, URL input, explanatory description)

Anthropic Prompt Caching:
- System prompt cached with cache_control markers (both OAuth and regular API keys)
- Last user message cached to cache conversation history
- Saves 90% on input tokens for cached content (10x cost reduction)

Settings Dialog Improvements:
- Configurable tab system with SettingsTab base class
- ApiKeysTab and ProxyTab as custom elements
- Switch toggle for proxy enable (instead of Checkbox)
- Explanatory paragraphs for each tab
- ApiKeyPromptDialog reuses ProviderKeyInput component

Removed:
- Deprecated ApiKeysDialog (replaced by ProviderKeyInput in SettingsDialog)
- Old storage-adapter and key-store (replaced by new storage architecture)
2025-10-05 23:00:36 +02:00
Mario Zechner
99983af597 Fix lints. 2025-10-03 23:21:59 +02:00
Mario Zechner
51f5448a5c Remove tool calls for which there are no results in subsequent user messages. 2025-10-01 22:18:30 +02:00
Mario Zechner
f55985f633 Fix GPT-5 no-reasoning mode. Somewhat. There's no real off-switch ... 2025-09-19 01:45:00 +02:00
Mario Zechner
9e86079386 Fix block indexing in Google provider impl 2025-09-19 00:10:43 +02:00
Mario Zechner
2296dc4052 refactor(ai): improve error handling and stop reason types
- Add 'aborted' as a distinct stop reason separate from 'error'
- Change AssistantMessage.error to errorMessage for clarity
- Update error event to include reason field ('error' | 'aborted')
- Map provider-specific safety/refusal reasons to 'error' stop reason
- Reorganize utility functions into utils/ directory
- Rename agent.ts to agent-loop.ts for better clarity
- Fix error handling in all providers to properly distinguish abort from error
2025-09-18 19:57:13 +02:00
Mario Zechner
39c626b6c9 feat(ai): add partial JSON parsing for streaming tool calls
- Added partial-json package for parsing incomplete JSON during streaming
- Tool call arguments now contain partially parsed JSON during toolcall_delta events
- Enables progressive UI updates (e.g., showing file paths before content is complete)
- Arguments are always valid objects (minimum empty {}), never undefined
- Full validation still occurs at toolcall_end when arguments are complete
- Updated all providers (Anthropic, OpenAI Completions/Responses) to use parseStreamingJson
- Added comprehensive documentation and examples in README
- Added test to verify arguments are always defined during streaming
2025-09-16 12:23:34 +02:00
Mario Zechner
e8370436d7 Replace Zod with TypeBox for schema validation
- Switch from Zod to TypeBox for tool parameter schemas
- TypeBox schemas can be serialized/deserialized as JSON
- Use AJV for runtime validation instead of Zod's parse
- Add StringEnum helper for Google API compatibility (avoids anyOf/const patterns)
- Export Type and Static from main package for convenience
- Update all tests and documentation to reflect TypeBox usage
2025-09-16 01:10:40 +02:00
Mario Zechner
73d2119606 fix: Adjust max tokens for Anthropic and improve Google tools handling
- Reduce default max tokens for Anthropic to 1/3 of model max
- Fix Google provider to properly handle empty tools array
- Ensure toolConfig is undefined when no tools are present
2025-09-15 00:34:52 +02:00
Mario Zechner
433b42ac91 Fix Biome config, don't submit empty assistant messages to completions endpoint. 2025-09-09 21:47:40 +02:00