@opencode/ai 2.0.5 → 2.0.6

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.
@@ -571,12 +571,17 @@ export declare const WebSocketErrorEvent: Schema.StructWithRest<Schema.Struct<{
571
571
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
572
572
  readonly message: Schema.optional<Schema.String>;
573
573
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
574
- readonly error: Schema.optional<Schema.NullOr<Schema.Struct<{
574
+ readonly error: Schema.optional<Schema.NullOr<Schema.decodeTo<Schema.Struct<{
575
575
  readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
576
576
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
577
577
  readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
578
578
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
579
- }>>>;
579
+ }>, Schema.Union<readonly [Schema.String, Schema.Struct<{
580
+ readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
581
+ readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
582
+ readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
583
+ readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
584
+ }>]>, never, never>>>;
580
585
  readonly headers: Schema.optional<Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>>>;
581
586
  }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>;
582
587
  export declare const decodeKnownErrorEvent: (event: Event) => Effect.Effect<{
@@ -641,22 +646,32 @@ export declare const Event: Schema.decodeTo<Schema.toType<Schema.StructWithRest<
641
646
  }>>>;
642
647
  readonly total_tokens: Schema.optional<Schema.Number>;
643
648
  }>>>;
644
- readonly error: Schema.optional<Schema.NullOr<Schema.Struct<{
649
+ readonly error: Schema.optional<Schema.NullOr<Schema.decodeTo<Schema.Struct<{
645
650
  readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
646
651
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
647
652
  readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
648
653
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
649
- }>>>;
654
+ }>, Schema.Union<readonly [Schema.String, Schema.Struct<{
655
+ readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
656
+ readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
657
+ readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
658
+ readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
659
+ }>]>, never, never>>>;
650
660
  }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>;
651
661
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
652
662
  readonly message: Schema.optional<Schema.String>;
653
663
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
654
- readonly error: Schema.optional<Schema.NullOr<Schema.Struct<{
664
+ readonly error: Schema.optional<Schema.NullOr<Schema.decodeTo<Schema.Struct<{
655
665
  readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
656
666
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
657
667
  readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
658
668
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
659
- }>>>;
669
+ }>, Schema.Union<readonly [Schema.String, Schema.Struct<{
670
+ readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
671
+ readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
672
+ readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
673
+ readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
674
+ }>]>, never, never>>>;
660
675
  readonly status: Schema.optional<Schema.Unknown>;
661
676
  readonly status_code: Schema.optional<Schema.Unknown>;
662
677
  readonly headers: Schema.optional<Schema.Unknown>;
@@ -704,22 +719,32 @@ export declare const Event: Schema.decodeTo<Schema.toType<Schema.StructWithRest<
704
719
  }>>>;
705
720
  readonly total_tokens: Schema.optional<Schema.Number>;
706
721
  }>>>;
707
- readonly error: Schema.optional<Schema.NullOr<Schema.Struct<{
722
+ readonly error: Schema.optional<Schema.NullOr<Schema.decodeTo<Schema.Struct<{
708
723
  readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
709
724
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
710
725
  readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
711
726
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
712
- }>>>;
727
+ }>, Schema.Union<readonly [Schema.String, Schema.Struct<{
728
+ readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
729
+ readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
730
+ readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
731
+ readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
732
+ }>]>, never, never>>>;
713
733
  }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>;
714
734
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
715
735
  readonly message: Schema.optional<Schema.String>;
716
736
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
717
- readonly error: Schema.optional<Schema.NullOr<Schema.Struct<{
737
+ readonly error: Schema.optional<Schema.NullOr<Schema.decodeTo<Schema.Struct<{
718
738
  readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
719
739
  readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
720
740
  readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
721
741
  readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
722
- }>>>;
742
+ }>, Schema.Union<readonly [Schema.String, Schema.Struct<{
743
+ readonly type: Schema.optional<Schema.NullOr<Schema.String>>;
744
+ readonly code: Schema.optional<Schema.NullOr<Schema.String>>;
745
+ readonly message: Schema.optional<Schema.NullOr<Schema.String>>;
746
+ readonly param: Schema.optional<Schema.NullOr<Schema.String>>;
747
+ }>]>, never, never>>>;
723
748
  readonly status: Schema.optional<Schema.Unknown>;
724
749
  readonly status_code: Schema.optional<Schema.Unknown>;
725
750
  readonly headers: Schema.optional<Schema.Unknown>;
@@ -240,12 +240,16 @@ export const StreamItem = Schema.StructWithRest(Schema.Struct({
240
240
  // Responses-compatible providers put streaming error details at the top level or
241
241
  // under `error`, and response failures under `response.error`. Accept all three shapes.
242
242
  // https://www.openresponses.org/specification
243
- const OpenResponsesErrorPayload = Schema.Struct({
243
+ const OpenResponsesErrorObject = Schema.Struct({
244
244
  type: optionalNull(Schema.String),
245
245
  code: optionalNull(Schema.String),
246
246
  message: optionalNull(Schema.String),
247
247
  param: optionalNull(Schema.String),
248
248
  });
249
+ const OpenResponsesErrorPayload = Schema.Union([Schema.String, OpenResponsesErrorObject]).pipe(Schema.decodeTo(OpenResponsesErrorObject, {
250
+ decode: SchemaGetter.transform((error) => (typeof error === "string" ? { message: error } : error)),
251
+ encode: SchemaGetter.passthrough(),
252
+ }));
249
253
  const WebSocketErrorHeader = Schema.Union([Schema.String, Schema.Number, Schema.Boolean]);
250
254
  export const WebSocketErrorEvent = Schema.StructWithRest(Schema.Struct({
251
255
  type: Schema.tag("error"),
@@ -309,7 +313,9 @@ const decodeFrame = Schema.decodeUnknownEffect(ProviderShared.Json);
309
313
  * Decodes one WebSocket frame. xAI answers a rejected `response.create` with `{ "error": { "message", "type" } }` and no
310
314
  * event type; that envelope reads as an error event so the failure classifies instead of failing decoding.
311
315
  */
312
- export const decodeChannelEvent = (frame) => decodeFrame(frame).pipe(Effect.flatMap((value) => decodeEventValue(ProviderShared.isRecord(value) && value.type === undefined && ProviderShared.isRecord(value.error)
316
+ export const decodeChannelEvent = (frame) => decodeFrame(frame).pipe(Effect.flatMap((value) => decodeEventValue(ProviderShared.isRecord(value) &&
317
+ value.type === undefined &&
318
+ (typeof value.error === "string" || ProviderShared.isRecord(value.error))
313
319
  ? { ...value, type: "error" }
314
320
  : value)));
315
321
  const BASE_ADAPTER = { id: ADAPTER, name: NAME };
@@ -38,7 +38,15 @@ export const isContextOverflowFailure = (failure) => failure instanceof AIError
38
38
  ? failure.reason._tag === "InvalidRequest" && failure.reason.classification === "context-overflow"
39
39
  : Schema.is(ProviderErrorEvent)(failure) && failure.classification === "context-overflow";
40
40
  const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown));
41
- const QUOTA_CODES = new Set(["insufficient_quota", "usage_not_included", "billing_error"]);
41
+ // OpenCode Zen reports account caps as typed 429/402 errors that are not throttles.
42
+ const QUOTA_CODES = new Set([
43
+ "insufficient_quota",
44
+ "usage_not_included",
45
+ "billing_error",
46
+ "gousagelimiterror",
47
+ "freeusagelimiterror",
48
+ "creditlimitexceeded",
49
+ ]);
42
50
  const AUTH_CODES = new Set(["authentication_error", "permission_error"]);
43
51
  const SERVER_CODES = new Set([
44
52
  "api_error",
@@ -66,7 +74,8 @@ const CONTENT_POLICY_CODES = new Set([
66
74
  // as a `[code]` label at the start of the rewritten message.
67
75
  const GATEWAY_CODE_LABEL = /^[^:\n]+: \[([A-Za-z0-9_.-]+)\]/;
68
76
  const RATE_LIMIT_TEXT = /rate increased too quickly|rate[-_\s]?limit|too[_\s]?many[_\s]?requests/i;
69
- const QUOTA_TEXT = /insufficient[-_\s]?quota|quota[-_\s]?exceeded/i;
77
+ // Only consulted on 429, where throttles and account caps share a status.
78
+ const QUOTA_TEXT = /insufficient[-_\s]?quota|quota[-_\s]?exceeded|budget exceeded|usage limit/i;
70
79
  // Policy rejections without a dedicated code, matched against the provider's own
71
80
  // explanation only. OpenAI reuses `invalid_prompt` for usage-policy rejections while
72
81
  // Bedrock Mantle reuses it for schema validation; Anthropic reports blocked output
@@ -102,7 +111,9 @@ export function classifyProviderFailure(input) {
102
111
  return new InvalidRequestError({ ...details, classification: "payload-too-large" });
103
112
  if (codes.some((code) => CONTENT_POLICY_CODES.has(code)) || (clientScoped && CONTENT_POLICY_TEXT.test(input.message)))
104
113
  return new ContentPolicyError(details);
105
- if (codes.some((code) => QUOTA_CODES.has(code)) || (input.status === 429 && QUOTA_TEXT.test(text)))
114
+ if (input.status === 402 ||
115
+ codes.some((code) => QUOTA_CODES.has(code)) ||
116
+ (input.status === 429 && QUOTA_TEXT.test(text)))
106
117
  return new QuotaExceededError(details);
107
118
  if (input.status === 401 || input.status === 403 || codes.some((code) => AUTH_CODES.has(code)))
108
119
  return new AuthenticationError(details);
@@ -117,10 +128,12 @@ export function classifyProviderFailure(input) {
117
128
  if (input.status === 408 ||
118
129
  input.status === 409 ||
119
130
  (input.status !== undefined && input.status >= 500) ||
131
+ // Server codes and phrasing only decide when no HTTP status contradicts them:
132
+ // gateways such as OpenCode Zen substitute `server_error` for codes they do
133
+ // not forward, so a 4xx with a server code is still a rejected request.
120
134
  ((input.status === undefined || input.status < 400) &&
121
- !codes.some((code) => INVALID_REQUEST_CODES.has(code)) &&
122
- SERVER_ERROR_TEXT.test(text)) ||
123
- codes.some((code) => SERVER_CODES.has(code) || code.includes("exhausted") || code.includes("unavailable")))
135
+ ((!codes.some((code) => INVALID_REQUEST_CODES.has(code)) && SERVER_ERROR_TEXT.test(text)) ||
136
+ codes.some((code) => SERVER_CODES.has(code) || code.includes("exhausted") || code.includes("unavailable")))))
124
137
  return new ProviderInternalError({
125
138
  ...details,
126
139
  retryAfterMs: input.retryAfterMs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "name": "@opencode/ai",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@clack/prompts": "1.0.0-alpha.1",
32
32
  "@effect/platform-node": "4.0.0-rc.112",
33
- "@opencode/http-recorder": "2.0.5",
33
+ "@opencode/http-recorder": "2.0.6",
34
34
  "@tsconfig/bun": "1.0.9",
35
35
  "@types/bun": "1.4.0",
36
36
  "@typescript/native-preview": "7.0.0-dev.20251207.1",
@@ -40,7 +40,7 @@
40
40
  "@aws-sdk/credential-providers": "3.1057.0",
41
41
  "@smithy/eventstream-codec": "4.2.14",
42
42
  "@smithy/util-utf8": "4.2.2",
43
- "@opencode/schema": "2.0.5",
43
+ "@opencode/schema": "2.0.6",
44
44
  "aws4fetch": "1.0.20",
45
45
  "effect": "4.0.0-rc.112",
46
46
  "google-auth-library": "10.5.0"