Commit graph

486 commits

Author SHA1 Message Date
Christian Klotz
0c611753d9
fix(ai): update Z.AI model test references 2026-07-31 22:48:17 +03:00
Christian Klotz
784653468c
Merge pull request #7364 from earendil-works/fix/codex-account-websocket
fix(ai): scope Codex sockets to accounts
2026-07-31 14:43:08 +03:00
David Brailovsky
a688e257c5 fix(ai): route Fireworks Kimi K3 through OpenAI compatibility
closes #7199

Co-authored-by: Fedir Skitsko <fedya@skitsko.com>
2026-07-31 12:47:07 +02:00
Christian Klotz
cfe6b6a058
fix(ai): scope Codex sockets to accounts
Fixes #7284

Co-authored-by: vince <vincelwt@users.noreply.github.com>
2026-07-31 12:58:56 +03:00
David Brailovsky
59ad3dead3
fix(ai): preserve Anthropic initial stream block content (#7358)
fixes #7283
2026-07-31 10:39:38 +02:00
jingtao
6138f5a079
fix(ai): keep signed empty text/thinking blocks in google history (#7362)
Gemini can attach thoughtSignature to a part whose visible text is
empty and requires it echoed back; convertMessages dropped such blocks
together with the signature, breaking the reasoning chain. With the
chain broken, gemini flash models intermittently end a mid-task turn
with a thought-only STOP and no tool call. Empty blocks are now dropped
only when they are unsigned, mirroring the anthropic converter.

Co-authored-by: Jingtao Xu <jingtaozf@gmail.com>
2026-07-31 10:30:38 +02:00
Erik Ogenvik
4523528b21
fix(ai): treat only plain objects as provider error bodies (#7205)
pickBodyText serialized any non-empty object into the error body. SDK error
fields can hold class instances instead of parsed bodies - AWS SDK v3's
$response.body is an HTTP stream/response wrapper - and stringifying one
produced garbage like {"_events":...} as the body, which then replaced
error.message in the composed display string. error.message is where the SDK
puts the real deserialized exception text ("Input is too long...", schema
validation details), so the one useful string was discarded for noise.

The existing pipe-based stream sniffing only covers node-style streams; web
ReadableStreams (pipeTo/pipeThrough, no pipe) and non-stream wrapper classes
slipped through. Require Object.prototype/null prototype before serializing
a candidate body - parsed JSON bodies are plain objects by construction, so
real gateway bodies still surface.
2026-07-31 09:38:54 +02:00
Brian
70bbe47a9d
feat(ai): preserve structured metadata for Bedrock provider errors (#7286)
* feat(ai): preserve structured metadata for Bedrock provider errors

A failed Bedrock turn only exposed `errorMessage`, so downstream runtimes
could not classify a provider failure or correlate it with AWS support
without parsing that string. The AWS SDK carries the HTTP status, the
modeled error code, and the request id on the thrown exception; the
provider dropped all three.

Attach them as a `bedrock_response_failure` diagnostic on the existing
`AssistantMessage.diagnostics` array. No new core type surface, and no
existing line changed: the diff is purely additive.

`errorMessage` stays byte-identical because `isRetryableAssistantError`
classifies retries by string-matching it, and `BEDROCK_ERROR_PREFIXES` is
documented as load-bearing for that.

Scope note: the serialized-stream noise in the original report
(`Validation error: 400: {"_events":...}`) was already fixed in v0.82.1 by
 #7081, which added the unread-stream guard in `normalizeProviderError`.
Verified against main: `errorMessage` is clean today. This change covers
only the remaining half of the issue, the missing structured metadata.

Details:
- Carries `details` only, no `error` block, as `pi_messages_rewrite` does.
  A modeled mid-stream exception is not an `Error` at all, so routing it
  through `extractDiagnosticError` would record `"[object Object]"` plus a
  stack trace pointing into the SDK. The readable text is in `errorMessage`.
- `errorCode` reads `error.name`, which is where the SDK puts the modeled
  code for both paths that expose one: service exceptions from
  `client.send()` (via `x-amzn-errortype`) and the plain `Error` the
  event-stream unmarshaller throws for an unmodeled stream error (via
  `:error-code`). All 13 modeled Bedrock errors end in `Exception`, so that
  suffix is the gate; it excludes transport failures such as `TimeoutError`
  and `CredentialsProviderError`, and the SDK's `Unknown` placeholder,
  without enumerating them.
- A modeled mid-stream exception reports only a request id, on purpose.
  `@smithy/core` `getMessageUnmarshaller` throws `deserializedException[code]`
  after reading the code into a local, and the JSON shape deserializer built
  that value as a bare object literal, so the code no longer exists by the
  time it reaches us. The request id from the initial response is used as a
  fallback so these failures stay correlatable.
- `details.status` matches the key `pi_messages_response_failure` uses.
- Header-derived values are dropped when over-long rather than truncated: a
  truncated request id is not a request id.
- Aborted turns emit no diagnostic.

closes #7224

* docs(ai): trim comment density in the Bedrock failure diagnostic

The added block sat at 52 percent comment against 14 percent for the rest
of bedrock-converse-stream.ts and 2-9 percent across the other providers.
Cut to the facts a future maintainer cannot infer from the code: why the
error code is not gated on `BedrockRuntimeServiceException`, why a modeled
mid-stream exception yields only a request id, and the `errorMessage`
byte-identity invariant. Now 29 percent of a 27-line block.

Test comments trimmed the same way, 15 percent to 4 percent, matching
bedrock-custom-headers.test.ts. No behavior change; all tests unchanged
and passing.

---------

Co-authored-by: Brian Stanley <brian.stanley@kavak.com>
2026-07-30 22:32:20 +02:00
Mario Zechner
2c30412420 fix(ai): support streams without finish reasons 2026-07-30 22:23:46 +02:00
Armin Ronacher
34239180ac
fix(ai): preserve function arguments with empty custom payloads
Prefer function payloads when malformed OpenAI-compatible tool-call deltas also include an empty custom object, preserving parsed arguments.

Fixes #7160

Co-authored-by: Sunny Young <isunnyyoung@gmail.com>
2026-07-29 23:54:14 +02:00
David Brailovsky
d7b02636a0
Merge pull request #7272 from earendil-works/preserve-original-stop-reason
Adds AssistantMessage.rawStopReason and preserves provider original stop reasons.
Improves certain cases of error messages.
For mistral, change unmapped finish reasons to be "error" instead of "stop".

fixes #7255
2026-07-29 18:34:59 +02:00
David Brailovsky
5a2539a7bd update error messages copy to be more generic 2026-07-29 16:29:37 +00:00
David Brailovsky
4c1a0b92e5 fix(ai): use Qwen thinking controls for token plan reasoning models
fixes #6998 #6951
2026-07-29 14:58:48 +00:00
David Brailovsky
5a53f086ee fix(ai): preserve raw Mistral stop reasons
Treat unmapped Mistral finish reasons as provider errors instead of successful stops.
2026-07-29 14:05:29 +02:00
David Brailovsky
e5ef8d0654 fix(ai): preserve raw OpenAI response statuses 2026-07-29 13:56:21 +02:00
David Brailovsky
fe1c9b6d52 fix(ai): preserve raw OpenAI completion stop reasons 2026-07-29 13:52:14 +02:00
David Brailovsky
637737ca71 fix(ai): preserve raw Bedrock stop reasons 2026-07-29 13:49:42 +02:00
David Brailovsky
926eb15c18 fix(ai): preserve raw Anthropic stop reasons 2026-07-29 13:41:03 +02:00
David Brailovsky
23cb385b67 fix(ai): preserve google providers raw stop reason 2026-07-29 11:31:53 +00:00
Petr Houška
f9476a61e5
fix(ai): update TypeBox nullable array validation (#7243)
Bump TypeBox to 1.3.7 so compiled validators guard array-specific keywords when null is accepted, and cover tool-argument validation with a regression test.

Breaking for extensions: TypeBox 1.3 removes deprecated APIs including Type.Base, Type.Awaited, Type.Promise, Type.AsyncIterator, Type.Iterator, Type.Options, and Value.Mutate. Extensions using these through Pi's bundled TypeBox aliases must migrate to supported TypeBox APIs.

Fixes #7003
2026-07-29 10:31:07 +02:00
Armin Ronacher
027a584790 feat(ai): add per-request fetch injection 2026-07-28 18:51:44 +02:00
HyeokjaeLee
2fe21b407f
fix(ai): send max_tokens for Z.AI providers (#7174)
* fix(ai): send max_tokens for Z.AI providers

Z.AI (zai, zai-coding-cn, api.z.ai, open.bigmodel.cn) ignores
max_completion_tokens and only honors max_tokens, so the configured
output cap never applied and Z.AI fell back to its 65536 default.
Add isZai to detectCompat's useMaxTokens condition.

* fix(ai): set zai max_tokens compat in model generator

Per review feedback: the model generator now maps Z.AI to max_tokens, so
regenerated Z.AI model entries carry compat.maxTokensField="max_tokens"
(Z.AI ignores max_completion_tokens). The runtime detectCompat change is
kept as a fallback for custom/self-hosted Z.AI base URLs not in the catalog,
matching how moonshot/together/nvidia are handled in both places.
2026-07-28 14:43:41 +02:00
Christian Basch
b63403a50f
fix(ai): prefer configured Bedrock profile over ambient AWS keys (#7176)
Bedrock profile configured via pi's auth flow was ignored when ambient
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY were set, because pi forced
config.credentials from those keys and the SDK treats explicit
credentials as overriding config.profile.

Fixes #6957
2026-07-28 08:38:35 +02:00
Cristina Poncela Cubeiro
99e34013d1
feat: auth print (#7168)
Some checks are pending
CI / build-check-test (push) Waiting to run
2026-07-27 16:13:06 +02:00
Rafael
61da9e2f37
feat(ai): add manual redirect URL fallback to OpenRouter OAuth login (#7114)
The OpenRouter PKCE flow only completed through the loopback callback
server, so remote/headless sessions (e.g. pi over SSH) could never
finish login: the browser runs on another machine and cannot reach
127.0.0.1 on the host running pi.

Race the callback server against a manual_code prompt, matching the
existing Anthropic and OpenAI Codex flows. Users can paste the final
redirect URL (or the bare authorization code) and the flow exchanges
it with the same PKCE verifier. A claimed callback keeps priority so
a pasted code cannot interrupt an in-flight exchange.

The callback server object follows the OAuthServerInfo shape from the
OpenAI Codex flow: waitForCredential() resolves null when cancelWait()
hands the login over to manual entry, and close() is pure cleanup that
never settles the wait.

Refs #7078
2026-07-27 11:58:04 +02:00
Lucas Meijer
f9a49869c2
feat(ai): expose pending stop reason while streaming (#7151)
* feat(ai): expose pending streaming stop reason

Closes #7142

* manual tidy up of human facing copy
2026-07-27 11:56:15 +02:00
Jack Rose
60f6a8034d
feat(ai): add GitHub Copilot Claude Opus 5 support (#7158)
Route claude-opus-5 through the Anthropic Messages API with adaptive
thinking, the Copilot minimal thinking-level override, and pin the
extended 1M context window alongside the other Copilot Opus models.
2026-07-27 11:52:19 +02:00
Armin Ronacher
4cf0a729c4 fix(ai): keep the underlying cause in ModelsError messages
Auth failures surfaced only the wrapper text, so CI logs showed a bare
"OAuth refresh failed for openai-codex" with no provider response.
2026-07-25 12:41:15 +02:00
Burak Varlı
af3b934fa6
feat(ai): support Claude Opus 5 on Bedrock (#7081) 2026-07-25 08:25:23 +02:00
David Brailovsky
8eef62ed3e fix tests 2026-07-24 19:05:08 +00:00
David Brailovsky
7304d8f8af fix tests: use updated models 2026-07-24 18:52:56 +00:00
Armin Ronacher
a9f5b1c123 fix(ai): route Radius OAuth through gateway
Some checks are pending
CI / build-check-test (push) Waiting to run
2026-07-24 16:12:44 +02:00
Armin Ronacher
24e5cc04f4
fix(ai): support Anthropic bearer token env (#6148)
Fixes #5871
2026-07-24 15:13:22 +02:00
Armin Ronacher
24bace27cf
feat(ai): support constrained sampling (#6341)
Add the constrained sampling API and provider plumbing for OpenAI and Anthropic tool calls, including grammar sampling variants and model capability metadata.
2026-07-23 23:48:40 +02:00
Thomas Mustier
241431c69b
fix(agent,ai): don't cache write compaction or branch summaries (#6618)
avoid cache writes for compaction and branch summaries

Co-authored-by: Armin Ronacher <armin.ronacher@active-4.com>
2026-07-23 23:03:23 +02:00
David Brailovsky
ab55c15fbd
Merge pull request #7016 from earendil-works/fix/bundled-models-generated-time
fix bundled models generation time
2026-07-23 15:42:22 +02:00
David Brailovsky
bc3d364742 fix bundled models generation time
Fresh package installs could give bundled model catalog
files newer filesystem mtimes than the remote catalog’s Last-Modified timestamp,
causing Pi to ignore newer remote models.
Use the catalog’s recorded generation time instead of installation-dependent file metadata.
2026-07-23 13:34:51 +00:00
Petr Houška
7af8533c6f
fix(ai): make provider retries abortable (#6980)
Replace OpenAI and Anthropic SDK retries with local request retries that
preserve configured retry counts, enforce maxRetryDelayMs, and make retry
backoff interruptible through AbortSignal.

Alternatives considered: Racing SDK requests against AbortSignal would make
cancellation observable but would not let Pi enforce maxRetryDelayMs before
the SDK enters its retry sleep. Patching private SDK internals would be brittle,
while disabling provider retries entirely would ignore explicitly configured
maxRetries.

Also, align the custom OpenAI Codex retry loop with the documented
maxRetryDelayMs behavior. Oversized server-requested delays now fail immediately
instead of being clamped, allowing the visible, abortable agent-level retry
policy to handle the failure.

Fixes #6911
2026-07-23 12:25:37 +02:00
Saryev Rustam
7b52cef2e6
feat(ai): add OpenRouter OAuth support (#6927)
Closes #6814
2026-07-22 15:48:39 +02:00
Armin Ronacher
5dc40fee33 feat(ai): derive generated model types from JSON 2026-07-22 13:13:36 +02:00
David Brailovsky
906b40a753
Merge pull request #6955 from earendil-works/fix/handle-openai-previous-response-not-found-error
handle openai websocket previous_response_not_found error
2026-07-22 12:41:58 +02:00
David Brailovsky
c5dcb26000 handle openai websocket previous_response_not_found error
fixes #6931
2026-07-22 10:26:24 +00:00
Matthew
bc41f612da
fix(ai): cache OpenRouter tool results
closes #6940
2026-07-22 11:48:33 +02:00
Mario Zechner
6f95a33888 fix(ai): enable cache control for OpenRouter aliases
closes #6940
2026-07-22 11:46:21 +02:00
Christian Klotz
33e40c3e15
fix(ai): retry DNS transport failures (#6946)
Fixes #6904
2026-07-22 11:26:19 +02:00
zay
a5afc3f171
feat(ai): add Kimi Code subscription OAuth login (#6935)
Add a device authorization grant flow (RFC 8628) for the kimi-coding
provider, mirroring the official Kimi Code CLI: device authorization and
token polling against https://auth.kimi.com, refresh-token rotation with
retry/backoff, and Bearer auth via toAuth headers. The provider now
offers 'Sign in with Kimi Code' alongside the existing KIMI_API_KEY
auth. Host is overridable via KIMI_CODE_OAUTH_HOST / KIMI_OAUTH_HOST.

Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
2026-07-22 08:35:03 +02:00
David Brailovsky
1ae064099c
generate-models: use reasoning options from models.dev (#6928)
* generate-models: use reasoning options from models.dev

* fix tests
2026-07-22 08:33:34 +02:00
David Brailovsky
243f64be59 report aborted retry attempts as unsuccessful 2026-07-21 15:34:31 +00:00
David Brailovsky
162179af5a add branch/compact retries to agent-harness 2026-07-21 12:11:39 +00:00
David Brailovsky
8e53e0e49c compaction & branch summarization follow retry policy
fixes #6647

compaction (auto & manual) and branch summarization retry on transient failures.
use the same retry policy from settings.
emit events for the tui to show indication of retries
2026-07-21 10:07:20 +00:00