@prestyj/ai 5.29.1 → 5.30.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
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  classifyProviderError: () => classifyProviderError,
41
41
  dropInvalidToolCalls: () => dropInvalidToolCalls,
42
42
  environmentSecrets: () => environmentSecrets,
43
+ formatChatError: () => formatChatError,
43
44
  formatError: () => formatError,
44
45
  formatErrorForDisplay: () => formatErrorForDisplay,
45
46
  hasLoneSurrogate: () => hasLoneSurrogate,
@@ -1498,6 +1499,10 @@ function toLocalReasoningEffort(level) {
1498
1499
  function toGlmReasoningEffort(level) {
1499
1500
  return level === "ultra" ? "max" : level;
1500
1501
  }
1502
+ function toCodexReasoningEffort(level, model) {
1503
+ if (level !== "ultra") return level;
1504
+ return model === "gpt-6-astra" || model === "gpt-6.1-sol" ? "xhigh" : "max";
1505
+ }
1501
1506
  function toOpenAIReasoningEffort(level, model) {
1502
1507
  const effort = level === "max" || level === "ultra" ? "xhigh" : level;
1503
1508
  if (model.startsWith("fugu") && (effort === "low" || effort === "medium")) {
@@ -2763,7 +2768,7 @@ function toError2(err, provider = "openai") {
2763
2768
  const cleanMessage = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyMessage ? bodyMessage : isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
2764
2769
  let hint;
2765
2770
  if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
2766
- hint = "codex-mini-latest requires an OpenAI Pro or Max subscription. Your account currently has access to GPT-5.4 and GPT-5.4 Mini.";
2771
+ hint = "This request could not use codex-mini-latest. Check your account access or choose another available model.";
2767
2772
  }
2768
2773
  const requestId = err.request_id ?? (typeof body?.request_id === "string" ? body.request_id : void 0);
2769
2774
  const code = typeof err.code === "string" ? err.code : void 0;
@@ -2969,7 +2974,7 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
2969
2974
  // GPT-5.6/6 require at least low; older models still support thinking off.
2970
2975
  // Apply the floor here for every caller, including one-off prompt rewrites.
2971
2976
  // `ultra` is a client orchestration preset, not a Codex API effort.
2972
- effort: options.thinking === "ultra" ? "max" : options.thinking ?? (responsesLite ? "low" : "none"),
2977
+ effort: options.thinking ? toCodexReasoningEffort(options.thinking, options.model) : responsesLite ? "low" : "none",
2973
2978
  summary: "auto",
2974
2979
  ...liteShape ? { context: "all_turns" } : {}
2975
2980
  };
@@ -3030,9 +3035,9 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
3030
3035
  if (usageLimit) throw usageLimit;
3031
3036
  let hint;
3032
3037
  if (response.status === 400 && message === `The '${options.model}' model is not supported when using Codex with a ChatGPT account.`) {
3033
- hint = "This model is not available through your ChatGPT account. Switch to a model listed for OpenAI via the model selector, or check your ChatGPT usage limits.";
3038
+ hint = "This model is not available through your ChatGPT account. Choose another available model using the model selector.";
3034
3039
  } else if (response.status === 404 && text.includes("does not exist")) {
3035
- hint = "This model is not in OpenAI's current catalog for your ChatGPT account. Switch to GPT-6 Astra, GPT-6.1 Sol, or GPT-6 Luna via the model selector.";
3040
+ hint = "This model is not in OpenAI's current catalog for your ChatGPT account. Choose another available model using the model selector.";
3036
3041
  }
3037
3042
  throw new ProviderError("openai", message, {
3038
3043
  statusCode: response.status,
@@ -3505,6 +3510,7 @@ function codexUsageLimitError(errorObj, statusCode, requestId) {
3505
3510
  const isRateOr429 = CODEX_RATE_LIMIT_CODE.test(code) || statusCode === 429;
3506
3511
  if (!isHardUsage && !(isRateOr429 && resetsAt != null)) return null;
3507
3512
  return new ProviderError("openai", "ChatGPT usage limit reached", {
3513
+ cause: errorObj,
3508
3514
  statusCode: statusCode ?? 429,
3509
3515
  ...requestId ? { requestId } : {},
3510
3516
  ...resetsAt ? { resetsAt } : {}
@@ -4435,6 +4441,157 @@ function messagesContainVideo(messages) {
4435
4441
  return false;
4436
4442
  }
4437
4443
 
4444
+ // src/chat-error.ts
4445
+ function causeCode(error) {
4446
+ if (!(error instanceof Error) || !error.cause || typeof error.cause !== "object") return "";
4447
+ const cause = error.cause;
4448
+ if ("code" in cause && typeof cause.code === "string") return cause.code;
4449
+ if ("type" in cause && typeof cause.type === "string") return cause.type;
4450
+ return "";
4451
+ }
4452
+ function formatChatError(error) {
4453
+ const base = formatError(error);
4454
+ const raw = error instanceof Error ? error.message : "";
4455
+ const code = causeCode(error);
4456
+ const text = `${code} ${raw}`.toLowerCase();
4457
+ const provider = /chatgpt/i.test(raw) ? "ChatGPT" : providerLabel(base.provider);
4458
+ const present = (reason, headline, guidance) => ({
4459
+ ...base,
4460
+ ...raw ? { message: raw } : {},
4461
+ reason,
4462
+ headline,
4463
+ guidance
4464
+ });
4465
+ if (error instanceof VideoUnsupportedError) {
4466
+ return present(
4467
+ "capability",
4468
+ "This model can\u2019t read this video",
4469
+ "Choose a model that supports video."
4470
+ );
4471
+ }
4472
+ if (base.source === "capability") {
4473
+ return present(
4474
+ "unknown",
4475
+ "This request isn\u2019t supported",
4476
+ "Open details to check the request requirements."
4477
+ );
4478
+ }
4479
+ if (/requires a newer version of codex/.test(text)) {
4480
+ return present(
4481
+ "update",
4482
+ "EZ Coder needs an update",
4483
+ "Update the app, or choose another model."
4484
+ );
4485
+ }
4486
+ if (/insufficient.*(?:balance|credits?)|(?:balance|credits?).*(?:insufficient|exhausted|depleted)|credit balance is too low|payment_required/.test(
4487
+ text
4488
+ )) {
4489
+ return present(
4490
+ "billing",
4491
+ `${provider} credits are unavailable`,
4492
+ "Check your balance and billing, or use another provider."
4493
+ );
4494
+ }
4495
+ if (/usage_not_included|does not yet include access|not supported when using codex with a chatgpt account|(?:model[^\n]*(?:not found|not available|does not exist))|model_not_found/.test(
4496
+ text
4497
+ )) {
4498
+ return present(
4499
+ "model_access",
4500
+ "This model isn\u2019t available to this account",
4501
+ "Choose another model available to your account."
4502
+ );
4503
+ }
4504
+ if (/insufficient_quota|exceeded your current quota|billing.?limit|spend.?limit|quota.?exceeded/.test(
4505
+ text
4506
+ )) {
4507
+ return present(
4508
+ "quota",
4509
+ `${provider} quota is unavailable`,
4510
+ "Check your plan or billing, or use another provider."
4511
+ );
4512
+ }
4513
+ if (/^rate_limit_exceeded$/i.test(code)) {
4514
+ return present(
4515
+ "rate_limit",
4516
+ `${provider} is limiting requests`,
4517
+ "Wait a moment before trying again."
4518
+ );
4519
+ }
4520
+ if (/usage limit reached|usage_limit_reached/.test(text)) {
4521
+ return present(
4522
+ "usage_limit",
4523
+ `${provider} usage limit reached`,
4524
+ "Wait for the reset, or use another provider."
4525
+ );
4526
+ }
4527
+ if (base.source === "network") {
4528
+ return present(
4529
+ "network",
4530
+ "Couldn\u2019t reach the provider",
4531
+ "Check your connection before trying again."
4532
+ );
4533
+ }
4534
+ if (base.source === "auth" || base.statusCode === 401) {
4535
+ return present(
4536
+ "auth",
4537
+ `${provider} sign-in needs attention`,
4538
+ "Reconnect your account in provider settings."
4539
+ );
4540
+ }
4541
+ if (base.statusCode === 413 || /context[_ ](?:length|window)|maximum context|request_too_large|prompt is too long/.test(text)) {
4542
+ return present(
4543
+ "context",
4544
+ "This conversation is too large",
4545
+ "Compact the conversation or send a smaller request."
4546
+ );
4547
+ }
4548
+ if (base.statusCode === 429 || /rate_limit|rate limit|too many requests/.test(text)) {
4549
+ return present(
4550
+ "rate_limit",
4551
+ `${provider} is limiting requests`,
4552
+ "Wait a moment before trying again."
4553
+ );
4554
+ }
4555
+ if (base.statusCode === 403) {
4556
+ return present(
4557
+ "model_access",
4558
+ "This account can\u2019t use this request",
4559
+ "Check account access or choose another model."
4560
+ );
4561
+ }
4562
+ if (error instanceof ProviderError) {
4563
+ if (base.statusCode != null && base.statusCode >= 500) {
4564
+ return present(
4565
+ "provider",
4566
+ `${provider} couldn\u2019t complete the request`,
4567
+ "Try again later. Check details if it keeps happening."
4568
+ );
4569
+ }
4570
+ return present(
4571
+ "provider",
4572
+ `${provider} didn\u2019t accept the request`,
4573
+ "Check the details before trying again."
4574
+ );
4575
+ }
4576
+ return present("unknown", "Something went wrong", "Open details to see what was reported.");
4577
+ }
4578
+ function providerLabel(provider) {
4579
+ switch (provider) {
4580
+ case "openai":
4581
+ return "OpenAI";
4582
+ case "anthropic":
4583
+ return "Anthropic";
4584
+ case "gemini":
4585
+ return "Gemini";
4586
+ case "xai":
4587
+ return "xAI";
4588
+ case "local":
4589
+ return "The local server";
4590
+ default:
4591
+ return "The provider";
4592
+ }
4593
+ }
4594
+
4438
4595
  // src/error-classification.ts
4439
4596
  var CONTEXT_OVERFLOW_PATTERNS = [
4440
4597
  /context_length_exceeded/i,
@@ -4825,6 +4982,7 @@ function registerPalsuProvider(config) {
4825
4982
  classifyProviderError,
4826
4983
  dropInvalidToolCalls,
4827
4984
  environmentSecrets,
4985
+ formatChatError,
4828
4986
  formatError,
4829
4987
  formatErrorForDisplay,
4830
4988
  hasLoneSurrogate,