@prestyj/ai 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -172,7 +172,7 @@ function formatError(err) {
172
172
  provider: err.provider,
173
173
  statusCode: err.statusCode,
174
174
  ...err.requestId ? { requestId: err.requestId } : {},
175
- guidance: "Request access via your Anthropic account team (see platform.claude.com/docs/en/about-claude/models/overview), or switch to claude-fable-5 with /model \u2014 same underlying model, generally available."
175
+ guidance: "Request access via your Anthropic account team (see platform.claude.com/docs/en/about-claude/models/overview), or switch to Claude Fable 5 via the model selector \u2014 same underlying model, generally available."
176
176
  };
177
177
  }
178
178
  if (isUsageLimitError(err)) {
@@ -214,7 +214,7 @@ function finaliseBySource(source, message, requestId, hint) {
214
214
  headline: "Network error \u2014 couldn't reach the provider.",
215
215
  source,
216
216
  message,
217
- guidance: hint ?? "Check your internet connection. Not a ezcoder issue \u2014 retry shortly.",
217
+ guidance: hint ?? "Check your internet connection. Not a EZ Coder issue \u2014 retry shortly.",
218
218
  ...requestId ? { requestId } : {}
219
219
  };
220
220
  case "auth":
@@ -222,7 +222,7 @@ function finaliseBySource(source, message, requestId, hint) {
222
222
  headline: "Authentication issue.",
223
223
  source,
224
224
  message,
225
- guidance: hint ?? "Run `ezcoder login` to refresh your credentials.",
225
+ guidance: hint ?? "Re-authenticate to refresh your credentials.",
226
226
  ...requestId ? { requestId } : {}
227
227
  };
228
228
  case "provider":
@@ -238,15 +238,15 @@ function finaliseBySource(source, message, requestId, hint) {
238
238
  headline: message,
239
239
  source,
240
240
  message: "",
241
- guidance: hint ?? "Only Kimi, Gemini, MiniMax, and MiMo-V2.5 can analyze video. Switch with /model.",
241
+ guidance: hint ?? "Only Kimi, Gemini, MiniMax, and MiMo-V2.5 can analyze video. Switch to one of those via the model selector.",
242
242
  ...requestId ? { requestId } : {}
243
243
  };
244
244
  case "ezcoder":
245
245
  return {
246
- headline: "ezcoder hit an unexpected error.",
246
+ headline: "EZ Coder hit an unexpected error.",
247
247
  source,
248
248
  message,
249
- guidance: hint ?? "This looks like a ezcoder bug \u2014 please report it to the developer (see /help).",
249
+ guidance: hint ?? "This looks like a EZ Coder bug \u2014 please report it to the developer (see /help).",
250
250
  ...requestId ? { requestId } : {}
251
251
  };
252
252
  }
@@ -277,36 +277,39 @@ function providerGuidance(provider, message, statusCode) {
277
277
  const status = provider ? PROVIDER_STATUS_URL[provider] : void 0;
278
278
  const lower = message.toLowerCase();
279
279
  if (statusCode === 401 || lower.includes("unauthorized") || lower.includes("invalid api key")) {
280
- return `Authentication failed with ${name}. Run \`ezcoder login\` to refresh your credentials.`;
280
+ return `Authentication failed with ${name}. Re-authenticate to refresh your credentials.`;
281
281
  }
282
282
  if (lower.includes("overloaded") || lower.includes("engine_overloaded")) {
283
- return `${name}'s servers are overloaded right now. Retry in a moment \u2014 not a ezcoder issue.`;
283
+ return `${name}'s servers are overloaded right now. Retry in a moment \u2014 not a EZ Coder issue.`;
284
284
  }
285
285
  if (lower.includes("insufficient balance") || lower.includes("quota exceeded") || lower.includes("recharge") || lower.includes("no resource package")) {
286
- return `Your ${name} account has a billing or quota issue \u2014 check your balance. Not a ezcoder issue.`;
286
+ return `Your ${name} account has a billing or quota issue \u2014 check your balance. Not a EZ Coder issue.`;
287
287
  }
288
288
  if (statusCode === 429 || lower.includes("rate limit") || lower.includes("too many requests")) {
289
- return `${name} rate limit hit. Wait a moment then retry \u2014 not a ezcoder issue.`;
289
+ return `${name} rate limit hit. Wait a moment then retry \u2014 not a EZ Coder issue.`;
290
290
  }
291
291
  if (statusCode === 502 || lower.includes("bad gateway")) {
292
- return `${name} returned a bad gateway. Retry \u2014 this is on their side, not ezcoder.`;
292
+ return `${name} returned a bad gateway. Retry \u2014 this is on their side, not EZ Coder.`;
293
293
  }
294
294
  if (statusCode === 503 || lower.includes("service unavailable")) {
295
- return `${name} is temporarily unavailable. Retry shortly \u2014 not a ezcoder issue.`;
295
+ return `${name} is temporarily unavailable. Retry shortly \u2014 not a EZ Coder issue.`;
296
296
  }
297
297
  if (statusCode === 500 || lower.includes("server_error") || lower.includes("500") && lower.includes("internal server error")) {
298
- return status ? `This is an error from ${name}, not ezcoder. Retry \u2014 if it keeps happening, check ${status}.` : `This is an error from ${name}, not ezcoder. Retry \u2014 if it keeps happening, try a different model with /model.`;
298
+ return status ? `This is an error from ${name}, not EZ Coder. Retry \u2014 if it keeps happening, check ${status}.` : `This is an error from ${name}, not EZ Coder. Retry \u2014 if it keeps happening, try a different model via the model selector.`;
299
299
  }
300
300
  if (lower.includes("timeout") || lower.includes("timed out")) {
301
- return `Request to ${name} timed out. Their servers may be slow \u2014 retry. Not a ezcoder issue.`;
301
+ return `Request to ${name} timed out. Their servers may be slow \u2014 retry. Not a EZ Coder issue.`;
302
302
  }
303
303
  if (lower.includes("does not recognize the requested model") || lower.includes("model") && (lower.includes("not exist") || lower.includes("not found") || lower.includes("no access"))) {
304
- return `${name} doesn't recognise this model on your account. Use /model to switch, or check your subscription tier.`;
304
+ return `${name} doesn't recognise this model on your account. Switch to a different model via the model selector, or check your subscription tier.`;
305
305
  }
306
306
  if (lower.includes("context_length_exceeded") || lower.includes("prompt is too long")) {
307
- return `Context window for this ${name} model is full. Run /compact to shrink history, or start a new session.`;
307
+ return `Context window for this ${name} model is full. Compact the conversation to shrink history, or start a new session.`;
308
308
  }
309
- return status ? `This is an error from ${name}, not ezcoder. Retry \u2014 if it persists, check ${status}.` : `This is an error from ${name}, not ezcoder. Retry \u2014 if it persists, try a different model with /model.`;
309
+ if (statusCode === 413 || lower.includes("request_too_large") || lower.includes("request exceeds the maximum size")) {
310
+ return `The request to ${name} is too large. Compact the conversation to shrink history, or start a new session.`;
311
+ }
312
+ return status ? `This is an error from ${name}, not EZ Coder. Retry \u2014 if it persists, check ${status}.` : `This is an error from ${name}, not EZ Coder. Retry \u2014 if it persists, try a different model via the model selector.`;
310
313
  }
311
314
 
312
315
  // src/providers/anthropic.ts
@@ -1091,6 +1094,12 @@ function parseToolArguments(argsJson) {
1091
1094
  // src/providers/anthropic.ts
1092
1095
  var NON_STREAMING_TIMEOUT_MS = 60 * 60 * 1e3;
1093
1096
  var anthropicClientCache = /* @__PURE__ */ new Map();
1097
+ function fineGrainedToolStreamingEnabled() {
1098
+ const raw = process.env.GG_FINE_GRAINED_TOOL_STREAMING ?? process.env.CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING;
1099
+ if (!raw) return false;
1100
+ const v = raw.trim().toLowerCase();
1101
+ return v === "1" || v === "true" || v === "yes" || v === "on";
1102
+ }
1094
1103
  function createClient(options) {
1095
1104
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
1096
1105
  const userAgent = isOAuth ? options.userAgent ?? "claude-cli/2.1.75 (external, cli)" : "";
@@ -1148,7 +1157,9 @@ async function prewarmAnthropicCache(options) {
1148
1157
  ] : system;
1149
1158
  const tools = options.tools?.length ? toAnthropicTools(options.tools, {
1150
1159
  cacheControl,
1151
- enableFineGrainedToolStreaming: true
1160
+ // Keep the serialized tool bytes identical to runStream so the
1161
+ // prewarmed prompt cache actually hits — both are gated by the flag.
1162
+ enableFineGrainedToolStreaming: fineGrainedToolStreamingEnabled()
1152
1163
  }) : void 0;
1153
1164
  await client.messages.create(
1154
1165
  {
@@ -1228,7 +1239,7 @@ async function* runStream(options) {
1228
1239
  options.tools.filter((t) => !reservedServerNames.has(t.name)),
1229
1240
  {
1230
1241
  ...supportsFirstPartyToolExtras && cacheControl ? { cacheControl } : {},
1231
- ...supportsFirstPartyToolExtras ? { enableFineGrainedToolStreaming: true } : {}
1242
+ ...supportsFirstPartyToolExtras && fineGrainedToolStreamingEnabled() ? { enableFineGrainedToolStreaming: true } : {}
1232
1243
  }
1233
1244
  ) : [];
1234
1245
  return {
@@ -1254,7 +1265,10 @@ async function* runStream(options) {
1254
1265
  ...isOAuth ? ["claude-code-20250219", "oauth-2025-04-20"] : [],
1255
1266
  ...options.compaction ? ["compact-2026-01-12"] : [],
1256
1267
  ...options.clearToolUses ? ["context-management-2025-06-27"] : [],
1257
- "fine-grained-tool-streaming-2025-05-14",
1268
+ // Eager tool-input streaming beta — opt-in only (see
1269
+ // fineGrainedToolStreamingEnabled). Off by default: the un-buffered stream
1270
+ // truncates large tool payloads into malformed JSON → phantom empty calls.
1271
+ ...fineGrainedToolStreamingEnabled() ? ["fine-grained-tool-streaming-2025-05-14"] : [],
1258
1272
  ...!hasAdaptiveThinking ? ["interleaved-thinking-2025-05-14"] : [],
1259
1273
  // The 1-h cache TTL (cacheRetention "long") is gated behind this beta. Without
1260
1274
  // it Anthropic silently ignores ttl:"1h" and falls back to the 5-min default,
@@ -1387,7 +1401,14 @@ async function* runStream(options) {
1387
1401
  try {
1388
1402
  const parsed = JSON.parse(accum.argsJson);
1389
1403
  args = isJsonObject(parsed) ? parsed : {};
1390
- } catch {
1404
+ } catch (parseErr) {
1405
+ const rawPartial = accum.argsJson;
1406
+ const snippet = rawPartial.length > 200 ? `${rawPartial.slice(0, 200)}\u2026` : rawPartial;
1407
+ throw new ProviderError(
1408
+ "anthropic",
1409
+ `Tool "${accum.toolName}" input JSON was truncated in the stream (${rawPartial.length} bytes): ${snippet}; ${parseErr.message}`,
1410
+ { cause: parseErr }
1411
+ );
1391
1412
  }
1392
1413
  }
1393
1414
  const tc = {
@@ -1608,6 +1629,7 @@ function readUnifiedRateLimit(headers) {
1608
1629
  return { rejected: status === "rejected", ...resetsAt ? { resetsAt } : {} };
1609
1630
  }
1610
1631
  function toError(err) {
1632
+ if (err instanceof ProviderError) return err;
1611
1633
  if (err instanceof import_sdk.default.APIError) {
1612
1634
  const errorBody = err.error;
1613
1635
  const nestedError = errorBody?.error;
@@ -2238,10 +2260,10 @@ async function* runStream3(options) {
2238
2260
  if (options.model === "gpt-5.5-pro") {
2239
2261
  hint = "Use gpt-5.5 instead. OpenAI's Codex model catalog does not list gpt-5.5-pro.";
2240
2262
  } else {
2241
- hint = "This model is not available through Codex for the authenticated account. Run /model and choose a model listed for OpenAI Codex, or check your Codex model picker/usage limits.";
2263
+ hint = "This model is not available through Codex for the authenticated account. Switch to a model listed for OpenAI Codex via the model selector, or check your Codex usage limits.";
2242
2264
  }
2243
2265
  } else if (response.status === 404 && text.includes("does not exist")) {
2244
- hint = "This model is not in the current OpenAI Codex catalog for this account. Try gpt-5.5, gpt-5.4, gpt-5.4-mini, or gpt-5.3-codex.";
2266
+ hint = "This model is not in the current OpenAI Codex catalog for this account. Switch to gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, or gpt-5.5 via the model selector.";
2245
2267
  }
2246
2268
  throw new ProviderError("openai", message, {
2247
2269
  statusCode: response.status,
@@ -2665,10 +2687,11 @@ var CODE_ASSIST_SUPPORTED_MODELS = /* @__PURE__ */ new Set([
2665
2687
  "gemini-3.1-pro-preview",
2666
2688
  "gemini-3.1-pro-preview-customtools",
2667
2689
  "gemini-3-flash-preview",
2668
- "gemini-3.1-flash-lite-preview",
2690
+ "gemini-3.5-flash",
2691
+ "gemini-3-flash",
2692
+ "gemini-3.1-flash-lite",
2669
2693
  "gemini-2.5-pro",
2670
2694
  "gemini-2.5-flash",
2671
- "gemini-2.5-flash-lite",
2672
2695
  "gemma-4-31b-it",
2673
2696
  "gemma-4-26b-a4b-it"
2674
2697
  ]);
@@ -2685,6 +2708,18 @@ function getCodeAssistEndpoint(method) {
2685
2708
  function formatUnsupportedModelMessage(model) {
2686
2709
  return `Gemini OAuth is configured to use the Gemini Code Assist subscription endpoint only. That endpoint does not currently expose model "${model}".`;
2687
2710
  }
2711
+ var ACCOUNT_GATED_MODELS = /* @__PURE__ */ new Set([
2712
+ "gemini-3-flash",
2713
+ "gemini-3.5-flash",
2714
+ "gemini-3.1-pro-preview",
2715
+ "gemini-3.1-pro-preview-customtools"
2716
+ ]);
2717
+ function accountGatedMessage(model) {
2718
+ return `Your Google account isn't entitled to "${model}" over Gemini Code Assist OAuth, so the API reports it as not found. This is an account-access limit, not a ezcoder bug.`;
2719
+ }
2720
+ function accountGatedHint() {
2721
+ return `Newer Gemini models (3.5 Flash, 3.1 Pro Preview) are available only to Code Assist Standard/Enterprise accounts with preview/GA access enabled by a cloud admin \u2014 free/personal accounts usually can't call them. Switch to Gemini 3.1 Flash Lite (it works on this account) with /model, or sign in with a Code Assist Standard/Enterprise account that has preview access.`;
2722
+ }
2688
2723
  function formatErrorMessage(status, body, model) {
2689
2724
  if (status === 404 && !CODE_ASSIST_SUPPORTED_MODELS.has(model)) {
2690
2725
  return `Gemini API error (404): ${body}
@@ -2995,7 +3030,8 @@ async function fetchCodeAssist(plan, options) {
2995
3030
  if (!response.ok) {
2996
3031
  const text = await response.text().catch(() => "");
2997
3032
  const quota = parseGeminiQuota(response.status, text);
2998
- let message = formatErrorMessage(response.status, text, options.model);
3033
+ const accountGated = response.status === 404 && ACCOUNT_GATED_MODELS.has(options.model);
3034
+ let message = accountGated ? accountGatedMessage(options.model) : formatErrorMessage(response.status, text, options.model);
2999
3035
  let resetsAt;
3000
3036
  if (quota?.exhausted) {
3001
3037
  message = `Gemini quota exhausted \u2014 usage limit reached. ${message}`;
@@ -3004,7 +3040,8 @@ async function fetchCodeAssist(plan, options) {
3004
3040
  }
3005
3041
  throw new ProviderError("gemini", message, {
3006
3042
  statusCode: response.status,
3007
- ...resetsAt !== void 0 ? { resetsAt } : {}
3043
+ ...resetsAt !== void 0 ? { resetsAt } : {},
3044
+ ...accountGated ? { hint: accountGatedHint() } : {}
3008
3045
  });
3009
3046
  }
3010
3047
  return response;