diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index b8eb492e..75229f3a 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed - Preserved OpenAI Responses assistant `phase` metadata (`commentary`, `final_answer`) across turns by encoding `id` and `phase` in `textSignature` for session persistence and replay, with backward compatibility for legacy plain signatures ([#1819](https://github.com/badlogic/pi-mono/issues/1819)). +- Switched the Mistral provider from the OpenAI-compatible completions path to Mistral's native SDK and conversations API, preserving native thinking blocks and Mistral-specific message semantics across turns ([#1716](https://github.com/badlogic/pi-mono/issues/1716)). - Fixed Antigravity endpoint fallback: 403/404 responses now cascade to the next endpoint instead of throwing immediately, added `autopush-cloudcode-pa.sandbox` endpoint to the fallback list, and removed extra fingerprint headers (`X-Goog-Api-Client`, `Client-Metadata`) from Antigravity requests ([#1830](https://github.com/badlogic/pi-mono/issues/1830)). - Fixed `@mariozechner/pi-ai/oauth` package exports to point directly at built `dist` files, avoiding broken TypeScript resolution through unpublished wrapper targets ([#1856](https://github.com/badlogic/pi-mono/issues/1856)). - Fixed Gemini 3 unsigned tool call replay: use `skip_thought_signature_validator` sentinel instead of converting function calls to text, preserving structured tool call context across multi-turn conversations ([#1829](https://github.com/badlogic/pi-mono/issues/1829)). diff --git a/packages/ai/src/providers/mistral.ts b/packages/ai/src/providers/mistral.ts index 96a961aa..29e141f1 100644 --- a/packages/ai/src/providers/mistral.ts +++ b/packages/ai/src/providers/mistral.ts @@ -1,4 +1,3 @@ -import { createHash } from "node:crypto"; import { Mistral } from "@mistralai/mistralai"; import type { RequestOptions } from "@mistralai/mistralai/lib/sdks.js"; import type { @@ -25,6 +24,7 @@ import type { ToolCall, } from "../types.js"; import { AssistantMessageEventStream } from "../utils/event-stream.js"; +import { shortHash } from "../utils/hash.js"; import { parseStreamingJson } from "../utils/json-parse.js"; import { sanitizeSurrogates } from "../utils/sanitize-unicode.js"; import { buildBaseOptions, clampReasoning } from "./simple-options.js"; @@ -165,7 +165,9 @@ function deriveMistralToolCallId(id: string, attempt: number): string { if (attempt === 0 && normalized.length === MISTRAL_TOOL_CALL_ID_LENGTH) return normalized; const seedBase = normalized || id; const seed = attempt === 0 ? seedBase : `${seedBase}:${attempt}`; - return createHash("sha256").update(seed).digest("hex").slice(0, MISTRAL_TOOL_CALL_ID_LENGTH); + return shortHash(seed) + .replace(/[^a-zA-Z0-9]/g, "") + .slice(0, MISTRAL_TOOL_CALL_ID_LENGTH); } function formatMistralError(error: unknown): string { diff --git a/packages/ai/src/providers/openai-responses-shared.ts b/packages/ai/src/providers/openai-responses-shared.ts index 01c01d4c..1d52ddf6 100644 --- a/packages/ai/src/providers/openai-responses-shared.ts +++ b/packages/ai/src/providers/openai-responses-shared.ts @@ -27,6 +27,7 @@ import type { Usage, } from "../types.js"; import type { AssistantMessageEventStream } from "../utils/event-stream.js"; +import { shortHash } from "../utils/hash.js"; import { parseStreamingJson } from "../utils/json-parse.js"; import { sanitizeSurrogates } from "../utils/sanitize-unicode.js"; import { transformMessages } from "./transform-messages.js"; @@ -35,20 +36,6 @@ import { transformMessages } from "./transform-messages.js"; // Utilities // ============================================================================= -/** Fast deterministic hash to shorten long strings */ -function shortHash(str: string): string { - let h1 = 0xdeadbeef; - let h2 = 0x41c6ce57; - for (let i = 0; i < str.length; i++) { - const ch = str.charCodeAt(i); - h1 = Math.imul(h1 ^ ch, 2654435761); - h2 = Math.imul(h2 ^ ch, 1597334677); - } - h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909); - h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909); - return (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36); -} - function encodeTextSignatureV1(id: string, phase?: TextSignatureV1["phase"]): string { const payload: TextSignatureV1 = { v: 1, id }; if (phase) payload.phase = phase; diff --git a/packages/ai/src/utils/hash.ts b/packages/ai/src/utils/hash.ts new file mode 100644 index 00000000..1ff55e8b --- /dev/null +++ b/packages/ai/src/utils/hash.ts @@ -0,0 +1,13 @@ +/** Fast deterministic hash to shorten long strings */ +export function shortHash(str: string): string { + let h1 = 0xdeadbeef; + let h2 = 0x41c6ce57; + for (let i = 0; i < str.length; i++) { + const ch = str.charCodeAt(i); + h1 = Math.imul(h1 ^ ch, 2654435761); + h2 = Math.imul(h2 ^ ch, 1597334677); + } + h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909); + h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909); + return (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36); +} diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 1e56447f..6409adde 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed - Fixed GPT-5.3 Codex follow-up turns dropping OpenAI Responses assistant `phase` metadata by preserving replayable signatures in session history and forwarding `phase` back to the Responses API ([#1819](https://github.com/badlogic/pi-mono/issues/1819)). +- Updated Mistral integration to use the native SDK-backed provider and conversations API, including coding-agent model/provider wiring and Mistral setup documentation ([#1716](https://github.com/badlogic/pi-mono/issues/1716)). - Fixed Antigravity reliability: endpoint cascade on 403/404, added autopush sandbox fallback, removed extra fingerprint headers ([#1830](https://github.com/badlogic/pi-mono/issues/1830)). - Fixed `@mariozechner/pi-ai/oauth` extension imports in published installs by resolving the subpath directly from built `dist` files instead of package-root wrapper shims ([#1856](https://github.com/badlogic/pi-mono/issues/1856)). - Fixed Gemini 3 multi-turn tool use losing structured context by using `skip_thought_signature_validator` sentinel for unsigned function calls instead of text fallback ([#1829](https://github.com/badlogic/pi-mono/issues/1829)).