chore(deps): update dependencies

This commit is contained in:
Peter Steinberger
2026-01-08 04:55:01 +00:00
parent 69ac4e072e
commit 5d21e8c891
6 changed files with 615 additions and 592 deletions

View File

@@ -222,6 +222,7 @@
- Agent: add `skipBootstrap` config option. Thanks @onutc for PR #292. - Agent: add `skipBootstrap` config option. Thanks @onutc for PR #292.
- UI: add favicon.ico derived from the macOS app icon. Thanks @jeffersonwarrior for PR #305. - UI: add favicon.ico derived from the macOS app icon. Thanks @jeffersonwarrior for PR #305.
- Tooling: replace tsx with bun for TypeScript execution. Thanks @obviyus for PR #278. - Tooling: replace tsx with bun for TypeScript execution. Thanks @obviyus for PR #278.
- Deps: refresh workspace dependencies (pi-* 0.38, carbon 0.13, Vite 7.3.1, TypeBox 0.34.47).
- Deps: bump pi-* stack, Slack SDK, discord-api-types, file-type, zod, and Biome. - Deps: bump pi-* stack, Slack SDK, discord-api-types, file-type, zod, and Biome.
- Skills: add CodexBar model usage helper with macOS requirement metadata. - Skills: add CodexBar model usage helper with macOS requirement metadata.
- Skills: add 1Password CLI skill with op examples. - Skills: add 1Password CLI skill with op examples.

View File

@@ -85,21 +85,21 @@
}, },
"packageManager": "pnpm@10.23.0", "packageManager": "pnpm@10.23.0",
"dependencies": { "dependencies": {
"@buape/carbon": "0.0.0-beta-20260107085330", "@buape/carbon": "0.13.0",
"@clack/prompts": "^0.11.0", "@clack/prompts": "^0.11.0",
"@grammyjs/runner": "^2.0.3", "@grammyjs/runner": "^2.0.3",
"@grammyjs/transformer-throttler": "^1.2.1", "@grammyjs/transformer-throttler": "^1.2.1",
"@homebridge/ciao": "^1.3.4", "@homebridge/ciao": "^1.3.4",
"@mariozechner/pi-agent-core": "^0.37.2", "@mariozechner/pi-agent-core": "^0.38.0",
"@mariozechner/pi-ai": "^0.37.2", "@mariozechner/pi-ai": "^0.38.0",
"@mariozechner/pi-coding-agent": "^0.37.2", "@mariozechner/pi-coding-agent": "^0.38.0",
"@mariozechner/pi-tui": "^0.37.2", "@mariozechner/pi-tui": "^0.38.0",
"@sinclair/typebox": "0.34.46", "@sinclair/typebox": "0.34.47",
"@slack/bolt": "^4.6.0", "@slack/bolt": "^4.6.0",
"@slack/web-api": "^7.13.0", "@slack/web-api": "^7.13.0",
"@whiskeysockets/baileys": "7.0.0-rc.9", "@whiskeysockets/baileys": "7.0.0-rc.9",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"body-parser": "^2.2.1", "body-parser": "^2.2.2",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"chokidar": "^5.0.0", "chokidar": "^5.0.0",
"chromium-bidi": "12.0.1", "chromium-bidi": "12.0.1",
@@ -119,7 +119,7 @@
"qrcode-terminal": "^0.12.0", "qrcode-terminal": "^0.12.0",
"sharp": "^0.34.5", "sharp": "^0.34.5",
"tslog": "^4.10.2", "tslog": "^4.10.2",
"undici": "^7.18.0", "undici": "^7.18.2",
"ws": "^8.19.0", "ws": "^8.19.0",
"zod": "^4.3.5" "zod": "^4.3.5"
}, },
@@ -143,10 +143,10 @@
"lucide": "^0.562.0", "lucide": "^0.562.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"ollama": "^0.6.3", "ollama": "^0.6.3",
"oxlint": "^1.37.0", "oxlint": "^1.38.0",
"oxlint-tsgolint": "^0.10.1", "oxlint-tsgolint": "^0.10.1",
"quicktype-core": "^23.2.6", "quicktype-core": "^23.2.6",
"rolldown": "1.0.0-beta.58", "rolldown": "1.0.0-beta.59",
"signal-utils": "^0.21.1", "signal-utils": "^0.21.1",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"typescript": "^5.9.3", "typescript": "^5.9.3",
@@ -155,14 +155,11 @@
}, },
"pnpm": { "pnpm": {
"overrides": { "overrides": {
"@sinclair/typebox": "0.34.46" "@sinclair/typebox": "0.34.47"
}, },
"patchedDependencies": { "patchedDependencies": {
"@mariozechner/pi-ai": "patches/@mariozechner__pi-ai.patch", "@mariozechner/pi-ai": "patches/@mariozechner__pi-ai.patch",
"@mariozechner/pi-agent-core": "patches/@mariozechner__pi-agent-core.patch", "@mariozechner/pi-agent-core": "patches/@mariozechner__pi-agent-core.patch"
"@mariozechner/pi-coding-agent": "patches/@mariozechner__pi-coding-agent.patch",
"qrcode-terminal": "patches/qrcode-terminal.patch",
"playwright-core@1.57.0": "patches/playwright-core@1.57.0.patch"
} }
}, },
"vitest": { "vitest": {

View File

@@ -1,17 +1,49 @@
diff --git a/dist/agent.d.ts b/dist/agent.d.ts
index fcfb19924ef6ce233aa55795e3687ce23938c5a6..a63daea868c5b3b7f7bb9272576c65c6ad95da8a 100644
--- a/dist/agent.d.ts
+++ b/dist/agent.d.ts
@@ -38,6 +38,10 @@ export interface AgentOptions {
* Useful for expiring tokens (e.g., GitHub Copilot OAuth).
*/
getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
+ /**
+ * Extra params to pass to the provider API (e.g., Z.AI GLM thinking mode params).
+ */
+ extraParams?: Record<string, unknown>;
/**
* Custom token budgets for thinking levels (token-based providers only).
*/
@@ -56,6 +60,8 @@ export declare class Agent {
streamFn: StreamFn;
private _sessionId?;
getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
+ /** Extra params to pass to the provider API. */
+ extraParams?: Record<string, unknown>;
private runningPrompt?;
private resolveRunningPrompt?;
private _thinkingBudgets?;
diff --git a/dist/agent.js b/dist/agent.js diff --git a/dist/agent.js b/dist/agent.js
index 0000000..1111111 100644 index 34ceb4ddcbc53d83edd82d774a76d9bf469b42f3..ecd8b7641c71523296890e11ac0cf0855a0dadd5 100644
--- a/dist/agent.js --- a/dist/agent.js
+++ b/dist/agent.js +++ b/dist/agent.js
@@ -42,6 +42,8 @@ export class Agent { @@ -33,6 +33,7 @@ export class Agent {
this.followUpMode = opts.followUpMode || "one-at-a-time"; streamFn;
_sessionId;
getApiKey;
+ extraParams;
runningPrompt;
resolveRunningPrompt;
_thinkingBudgets;
@@ -45,6 +46,8 @@ export class Agent {
this.streamFn = opts.streamFn || streamSimple; this.streamFn = opts.streamFn || streamSimple;
this._sessionId = opts.sessionId;
this.getApiKey = opts.getApiKey; this.getApiKey = opts.getApiKey;
+ // PATCH: Support extraParams for provider-specific features (e.g., GLM-4.7 thinking mode) + // PATCH: Support extraParams for provider-specific features (e.g., GLM-4.7 thinking mode)
+ this.extraParams = opts.extraParams; + this.extraParams = opts.extraParams;
this._thinkingBudgets = opts.thinkingBudgets;
} }
get state() { /**
return this._state; @@ -225,6 +228,8 @@ export class Agent {
@@ -193,6 +195,8 @@ export class Agent {
convertToLlm: this.convertToLlm, convertToLlm: this.convertToLlm,
transformContext: this.transformContext, transformContext: this.transformContext,
getApiKey: this.getApiKey, getApiKey: this.getApiKey,
@@ -20,27 +52,3 @@ index 0000000..1111111 100644
getSteeringMessages: async () => { getSteeringMessages: async () => {
if (this.steeringMode === "one-at-a-time") { if (this.steeringMode === "one-at-a-time") {
if (this.steeringQueue.length > 0) { if (this.steeringQueue.length > 0) {
diff --git a/dist/agent.d.ts b/dist/agent.d.ts
index 0000000..1111111 100644
--- a/dist/agent.d.ts
+++ b/dist/agent.d.ts
@@ -33,6 +33,10 @@ export interface AgentOptions {
* Useful for expiring tokens (e.g., GitHub Copilot OAuth).
*/
getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
+ /**
+ * Extra params to pass to the provider API (e.g., Z.AI GLM thinking mode params).
+ */
+ extraParams?: Record<string, unknown>;
}
export declare class Agent {
private _state;
@@ -45,6 +49,8 @@ export declare class Agent {
private followUpMode;
streamFn: StreamFn;
getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
+ /** Extra params to pass to the provider API. */
+ extraParams?: Record<string, unknown>;
private runningPrompt?;
private resolveRunningPrompt?;
constructor(opts?: AgentOptions);

View File

@@ -1,28 +1,57 @@
diff --git a/dist/providers/google-gemini-cli.js b/dist/providers/google-gemini-cli.js
index b1d6a340e1817b6f5404c2a23efa49139249f754..9dd692688fd73d378802af9600e459abbce6a17e 100644
--- a/dist/providers/google-gemini-cli.js
+++ b/dist/providers/google-gemini-cli.js
@@ -168,7 +168,12 @@ export const streamGoogleGeminiCli = (model, context, options) => {
break; // Success, exit retry loop
}
const errorText = await response.text();
- // Check if retryable
+ // PATCH: Fail immediately on 429 to let caller rotate accounts
+ if (response.status === 429) {
+ console.log(`[pi-ai] 429 rate limit - failing fast to rotate account`);
+ throw new Error(`Cloud Code Assist API error (${response.status}): ${errorText}`);
+ }
+ // Check if retryable (non-429 errors)
if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) {
// Use server-provided delay or exponential backoff
const serverDelay = extractRetryDelay(errorText);
@@ -183,6 +188,10 @@ export const streamGoogleGeminiCli = (model, context, options) => {
if (error instanceof Error && error.message === "Request was aborted") {
throw error;
}
+ // PATCH: Don't retry 429 errors - let caller rotate accounts
+ if (error instanceof Error && error.message.includes("429")) {
+ throw error;
+ }
lastError = error instanceof Error ? error : new Error(String(error));
// Network errors are retryable
if (attempt < MAX_RETRIES) {
diff --git a/dist/providers/google-shared.js b/dist/providers/google-shared.js diff --git a/dist/providers/google-shared.js b/dist/providers/google-shared.js
index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce582363124 100644 index dbb9c0e263919c9184a5f1c7dfde47d1c3a37ff4..f1866f423f30a4dfbe812d052679abd1f011769f 100644
--- a/dist/providers/google-shared.js --- a/dist/providers/google-shared.js
+++ b/dist/providers/google-shared.js +++ b/dist/providers/google-shared.js
@@ -10,13 +10,27 @@ import { transformMessages } from "./transorm-messages.js"; @@ -41,13 +41,27 @@ export function retainThoughtSignature(existing, incoming) {
export function convertMessages(model, context) { export function convertMessages(model, context) {
const contents = []; const contents = [];
const transformedMessages = transformMessages(context.messages, model); const transformedMessages = transformMessages(context.messages, model);
+
+ /** + /**
+ * Helper to add content while merging consecutive messages of the same role. + * Helper to add content while merging consecutive messages of the same role.
+ * Gemini/Cloud Code Assist requires strict role alternation (user/model/user/model). + * Gemini/Cloud Code Assist requires strict role alternation (user/model/user/model).
+ * Consecutive messages of the same role cause "function call turn" errors. + * Consecutive messages of the same role cause "function call turn" errors.
+ */ + */
+ function addContent(role, parts) { + function addContent(role, parts) {
+ if (parts.length === 0) return; + if (parts.length === 0)
+ return;
+ const lastContent = contents[contents.length - 1]; + const lastContent = contents[contents.length - 1];
+ if (lastContent?.role === role) { + if (lastContent?.role === role) {
+ // Merge into existing message of same role + // Merge into existing message of same role
+ lastContent.parts.push(...parts); + lastContent.parts.push(...parts);
+ } else { + }
+ else {
+ contents.push({ role, parts }); + contents.push({ role, parts });
+ } + }
+ } + }
+
for (const msg of transformedMessages) { for (const msg of transformedMessages) {
if (msg.role === "user") { if (msg.role === "user") {
if (typeof msg.content === "string") { if (typeof msg.content === "string") {
@@ -34,7 +63,7 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
} }
else { else {
const parts = msg.content.map((item) => { const parts = msg.content.map((item) => {
@@ -35,10 +49,7 @@ export function convertMessages(model, context) { @@ -66,10 +80,7 @@ export function convertMessages(model, context) {
const filteredParts = !model.input.includes("image") ? parts.filter((p) => p.text !== undefined) : parts; const filteredParts = !model.input.includes("image") ? parts.filter((p) => p.text !== undefined) : parts;
if (filteredParts.length === 0) if (filteredParts.length === 0)
continue; continue;
@@ -46,7 +75,7 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
} }
} }
else if (msg.role === "assistant") { else if (msg.role === "assistant") {
@@ -51,9 +62,19 @@ export function convertMessages(model, context) { @@ -82,9 +93,19 @@ export function convertMessages(model, context) {
parts.push({ text: sanitizeSurrogates(block.text) }); parts.push({ text: sanitizeSurrogates(block.text) });
} }
else if (block.type === "thinking") { else if (block.type === "thinking") {
@@ -64,12 +93,12 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
+ // and will mimic <thinking> tags if we convert to text + // and will mimic <thinking> tags if we convert to text
+ continue; + continue;
+ } + }
+ else if (block.thinkingSignature && isClaude) { + if (block.thinkingSignature && isClaude) {
+ // Claude via Antigravity requires the signature + // Claude via Antigravity requires the signature
parts.push({ parts.push({
thought: true, thought: true,
text: sanitizeSurrogates(block.thinking), text: sanitizeSurrogates(block.thinking),
@@ -61,6 +82,7 @@ export function convertMessages(model, context) { @@ -92,6 +113,7 @@ export function convertMessages(model, context) {
}); });
} }
else { else {
@@ -77,7 +106,7 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
parts.push({ parts.push({
text: `<thinking>\n${sanitizeSurrogates(block.thinking)}\n</thinking>`, text: `<thinking>\n${sanitizeSurrogates(block.thinking)}\n</thinking>`,
}); });
@@ -85,10 +107,7 @@ export function convertMessages(model, context) { @@ -116,10 +138,7 @@ export function convertMessages(model, context) {
} }
if (parts.length === 0) if (parts.length === 0)
continue; continue;
@@ -89,7 +118,7 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
} }
else if (msg.role === "toolResult") { else if (msg.role === "toolResult") {
// Extract text and image content // Extract text and image content
@@ -125,27 +144,94 @@ export function convertMessages(model, context) { @@ -156,27 +175,97 @@ export function convertMessages(model, context) {
} }
// Cloud Code Assist API requires all function responses to be in a single user turn. // Cloud Code Assist API requires all function responses to be in a single user turn.
// Check if the last content is already a user turn with function responses and merge. // Check if the last content is already a user turn with function responses and merge.
@@ -124,43 +153,43 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
+ * and converts to a format compatible with Google's function declarations. + * and converts to a format compatible with Google's function declarations.
+ */ + */
+function sanitizeSchemaForGoogle(schema) { +function sanitizeSchemaForGoogle(schema) {
+ if (!schema || typeof schema !== 'object') { + if (!schema || typeof schema !== "object") {
+ return schema; + return schema;
+ } + }
+ // If it's an array, sanitize each element + // If it's an array, sanitize each element
+ if (Array.isArray(schema)) { + if (Array.isArray(schema)) {
+ return schema.map(item => sanitizeSchemaForGoogle(item)); + return schema.map((item) => sanitizeSchemaForGoogle(item));
+ } + }
+ const sanitized = {}; + const sanitized = {};
+ // List of unsupported JSON Schema keywords that Google's API doesn't understand + // List of unsupported JSON Schema keywords that Google's API doesn't understand
+ const unsupportedKeywords = [ + const unsupportedKeywords = [
+ 'patternProperties', + "patternProperties",
+ 'const', + "const",
+ 'anyOf', + "anyOf",
+ 'oneOf', + "oneOf",
+ 'allOf', + "allOf",
+ 'not', + "not",
+ '$schema', + "$schema",
+ '$id', + "$id",
+ '$ref', + "$ref",
+ '$defs', + "$defs",
+ 'definitions', + "definitions",
+ 'if', + "if",
+ 'then', + "then",
+ 'else', + "else",
+ 'dependentSchemas', + "dependentSchemas",
+ 'dependentRequired', + "dependentRequired",
+ 'unevaluatedProperties', + "unevaluatedProperties",
+ 'unevaluatedItems', + "unevaluatedItems",
+ 'contentEncoding', + "contentEncoding",
+ 'contentMediaType', + "contentMediaType",
+ 'contentSchema', + "contentSchema",
+ 'deprecated', + "deprecated",
+ 'readOnly', + "readOnly",
+ 'writeOnly', + "writeOnly",
+ 'examples', + "examples",
+ '$comment', + "$comment",
+ 'additionalProperties', + "additionalProperties",
+ ]; + ];
+ // TODO(steipete): lossy schema scrub; revisit when Google supports these keywords. + // TODO(steipete): lossy schema scrub; revisit when Google supports these keywords.
+ for (const [key, value] of Object.entries(schema)) { + for (const [key, value] of Object.entries(schema)) {
@@ -169,30 +198,33 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
+ continue; + continue;
+ } + }
+ // Recursively sanitize nested objects + // Recursively sanitize nested objects
+ if (key === 'properties' && typeof value === 'object' && value !== null) { + if (key === "properties" && typeof value === "object" && value !== null) {
+ sanitized[key] = {}; + sanitized[key] = {};
+ for (const [propKey, propValue] of Object.entries(value)) { + for (const [propKey, propValue] of Object.entries(value)) {
+ sanitized[key][propKey] = sanitizeSchemaForGoogle(propValue); + sanitized[key][propKey] = sanitizeSchemaForGoogle(propValue);
+ } + }
+ } else if (key === 'items' && typeof value === 'object') { + }
+ else if (key === "items" && typeof value === "object") {
+ sanitized[key] = sanitizeSchemaForGoogle(value); + sanitized[key] = sanitizeSchemaForGoogle(value);
+ } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) { + }
+ else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
+ sanitized[key] = sanitizeSchemaForGoogle(value); + sanitized[key] = sanitizeSchemaForGoogle(value);
+ } else { + }
+ else {
+ sanitized[key] = value; + sanitized[key] = value;
+ } + }
+ } + }
+ // Ensure type: "object" is present when properties or required exist + // Ensure type: "object" is present when properties or required exist
+ // Google API requires type to be set when these fields are present + // Google API requires type to be set when these fields are present
+ if (('properties' in sanitized || 'required' in sanitized) && !('type' in sanitized)) { + if (("properties" in sanitized || "required" in sanitized) && !("type" in sanitized)) {
+ sanitized.type = 'object'; + sanitized.type = "object";
+ } + }
+ return sanitized; + return sanitized;
+} +}
/** /**
* Convert tools to Gemini function declarations format. * Convert tools to Gemini function declarations format.
*/ */
@@ -157,7 +243,7 @@ export function convertTools(tools) { @@ -188,7 +277,7 @@ export function convertTools(tools) {
functionDeclarations: tools.map((tool) => ({ functionDeclarations: tools.map((tool) => ({
name: tool.name, name: tool.name,
description: tool.description, description: tool.description,
@@ -201,8 +233,37 @@ index 7bc0a9f5d6241f191cd607ecb37b3acac8d58267..56866774e47444b5d333961c9b20fce5
})), })),
}, },
]; ];
diff --git a/dist/providers/openai-completions.d.ts b/dist/providers/openai-completions.d.ts
index 723addf341696b5d69c079202e571e9917685ce4..a1d0584a70a7d1fad1332026e301e56ef4f700a8 100644
--- a/dist/providers/openai-completions.d.ts
+++ b/dist/providers/openai-completions.d.ts
@@ -7,6 +7,8 @@ export interface OpenAICompletionsOptions extends StreamOptions {
};
};
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh";
+ /** Extra params to pass directly to the API (e.g., Z.AI GLM thinking mode params) */
+ extraParams?: Record<string, unknown>;
}
export declare const streamOpenAICompletions: StreamFunction<"openai-completions">;
//# sourceMappingURL=openai-completions.d.ts.map
diff --git a/dist/providers/openai-completions.js b/dist/providers/openai-completions.js
index 2590381cc5544c4e73c24c1c9a5853202f31361b..b76e1087dd31ccf099e02b1214b9e12d371b9b2d 100644
--- a/dist/providers/openai-completions.js
+++ b/dist/providers/openai-completions.js
@@ -335,6 +335,11 @@ function buildParams(model, context, options) {
if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
params.reasoning_effort = options.reasoningEffort;
}
+ // PATCH: Support arbitrary extra params for provider-specific features
+ // (e.g., Z.AI GLM-4.7 thinking: { type: "enabled", clear_thinking: boolean })
+ if (options?.extraParams && typeof options.extraParams === "object") {
+ Object.assign(params, options.extraParams);
+ }
return params;
}
function convertMessages(model, context, compat) {
diff --git a/dist/providers/openai-responses.js b/dist/providers/openai-responses.js diff --git a/dist/providers/openai-responses.js b/dist/providers/openai-responses.js
index 20fb0a22aaa28f7ff7c2f44a8b628fa1d9d7d936..31bae0aface1319487ce62d35f1f3b6ed334863e 100644 index 20fb0a22aaa28f7ff7c2f44a8b628fa1d9d7d936..c2bc63f483f3285b00755901ba97db810221cea6 100644
--- a/dist/providers/openai-responses.js --- a/dist/providers/openai-responses.js
+++ b/dist/providers/openai-responses.js +++ b/dist/providers/openai-responses.js
@@ -486,7 +486,6 @@ function convertTools(tools) { @@ -486,7 +486,6 @@ function convertTools(tools) {
@@ -213,69 +274,16 @@ index 20fb0a22aaa28f7ff7c2f44a8b628fa1d9d7d936..31bae0aface1319487ce62d35f1f3b6e
})); }));
} }
function mapStopReason(status) { function mapStopReason(status) {
diff --git a/dist/providers/google-gemini-cli.js b/dist/providers/google-gemini-cli.js
--- a/dist/providers/google-gemini-cli.js
+++ b/dist/providers/google-gemini-cli.js
@@ -168,7 +168,12 @@ async function* streamCompletion(params, options) {
break; // Success, exit retry loop
}
const errorText = await response.text();
- // Check if retryable
+ // PATCH: Fail immediately on 429 to let caller rotate accounts
+ if (response.status === 429) {
+ console.log(`[pi-ai] 429 rate limit - failing fast to rotate account`);
+ throw new Error(`Cloud Code Assist API error (${response.status}): ${errorText}`);
+ }
+ // Check if retryable (non-429 errors)
if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) {
// Use server-provided delay or exponential backoff
const serverDelay = extractRetryDelay(errorText);
@@ -183,6 +188,10 @@ async function* streamCompletion(params, options) {
if (error instanceof Error && error.message === "Request was aborted") {
throw error;
}
+ // PATCH: Don't retry 429 errors - let caller rotate accounts
+ if (error instanceof Error && error.message.includes("429")) {
+ throw error;
+ }
lastError = error instanceof Error ? error : new Error(String(error));
// Network errors are retryable
if (attempt < MAX_RETRIES) {
diff --git a/dist/stream.js b/dist/stream.js diff --git a/dist/stream.js b/dist/stream.js
index da54f4270e9b8d9e9cf1f902af976cc239601d4c..7ed71597c3369f8e3c1a3da0eb870a68215b714d 100644
--- a/dist/stream.js --- a/dist/stream.js
+++ b/dist/stream.js +++ b/dist/stream.js
@@ -105,6 +105,8 @@ function mapOptionsForApi(model, options, apiKey) { @@ -108,6 +108,8 @@ function mapOptionsForApi(model, options, apiKey) {
maxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),
signal: options?.signal, signal: options?.signal,
apiKey: apiKey || options?.apiKey, apiKey: apiKey || options?.apiKey,
sessionId: options?.sessionId,
+ // PATCH: Pass extraParams through to provider-specific API handlers + // PATCH: Pass extraParams through to provider-specific API handlers
+ extraParams: options?.extraParams, + extraParams: options?.extraParams,
}; };
// Helper to clamp xhigh to high for providers that don't support it // Helper to clamp xhigh to high for providers that don't support it
const clampReasoning = (effort) => (effort === "xhigh" ? "high" : effort); const clampReasoning = (effort) => (effort === "xhigh" ? "high" : effort);
diff --git a/dist/providers/openai-completions.js b/dist/providers/openai-completions.js
--- a/dist/providers/openai-completions.js
+++ b/dist/providers/openai-completions.js
@@ -333,6 +333,11 @@ function buildParams(model, context, options) {
if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
params.reasoning_effort = options.reasoningEffort;
}
+ // PATCH: Support arbitrary extra params for provider-specific features
+ // (e.g., Z.AI GLM-4.7 thinking: { type: "enabled", clear_thinking: boolean })
+ if (options?.extraParams && typeof options.extraParams === 'object') {
+ Object.assign(params, options.extraParams);
+ }
return params;
}
function convertMessages(model, context, compat) {
diff --git a/dist/providers/openai-completions.d.ts b/dist/providers/openai-completions.d.ts
--- a/dist/providers/openai-completions.d.ts
+++ b/dist/providers/openai-completions.d.ts
@@ -7,5 +7,7 @@ export interface OpenAICompletionsOptions extends StreamOptions {
};
};
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh";
+ /** Extra params to pass directly to the API (e.g., Z.AI GLM thinking mode params) */
+ extraParams?: Record<string, unknown>;
}
export declare const streamOpenAICompletions: StreamFunction<"openai-completions">;

891
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,7 @@
"@vitest/browser-playwright": "4.0.16", "@vitest/browser-playwright": "4.0.16",
"playwright": "^1.57.0", "playwright": "^1.57.0",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"vite": "7.3.0", "vite": "7.3.1",
"vitest": "4.0.16" "vitest": "4.0.16"
} }
} }