@fungi.computer/mule 0.2.1 → 0.2.2

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/README.md CHANGED
@@ -12,10 +12,10 @@ npm install @fungi.computer/mule
12
12
  ```
13
13
 
14
14
  The package ships ESM only and depends on `effect` and Pi
15
- (`@earendil-works/pi-ai`) at runtime, plus `@fungi.computer/cairn` for IDs. Mule
16
- does not require or install the MCP SDK. Consumers that type-check dependency
17
- declarations (`skipLibCheck: false`) must install Pi’s Google GenAI optional
18
- declaration dependency themselves:
15
+ (`@earendil-works/pi-ai`) at runtime, plus TypeBox and `@fungi.computer/cairn`
16
+ for IDs. Mule does not require or install the MCP SDK. Consumers that type-check
17
+ dependency declarations (`skipLibCheck: false`) must install Pi’s Google GenAI
18
+ optional declaration dependency themselves:
19
19
 
20
20
  ```sh
21
21
  npm install --save-dev @modelcontextprotocol/sdk
@@ -11,6 +11,12 @@ const decodeFailedEvent = Schema.decodeUnknownOption(Schema.Struct({
11
11
  response: providerError,
12
12
  }));
13
13
  const decodeErrorReply = Schema.decodeUnknownOption(Schema.fromJsonString(providerError));
14
+ const decodeErrorEvent = Schema.decodeUnknownOption(Schema.Struct({
15
+ type: Schema.Literal("error"),
16
+ status: Schema.optional(Schema.Number.check(Schema.isInt(), Schema.isBetween({ minimum: 100, maximum: 599 }))),
17
+ code: Schema.optional(Schema.String),
18
+ error: Schema.optional(providerError.fields.error),
19
+ }));
14
20
  const decodeBodyChunk = Schema.decodeUnknownSync(Schema.instanceOf(Uint8Array));
15
21
  const errorBodyBytes = 16 * 1024;
16
22
  const decodeSeconds = Schema.decodeUnknownOption(Schema.NumberFromString.check(Schema.isBetween({ minimum: 0, maximum: 60 })));
@@ -24,7 +30,9 @@ const decodeLimit = Schema.decodeUnknownOption(Schema.Literals([
24
30
  const decodeRejected = Schema.decodeUnknownOption(Schema.Literal("rejected"));
25
31
  const decodeExhausted = Schema.decodeUnknownOption(Schema.Literal("0"));
26
32
  const decodeDate = Schema.decodeUnknownOption(Schema.DateTimeUtcFromString);
27
- const decodeOverloaded = Schema.decodeUnknownOption(Schema.Struct({
33
+ const decodeOverloaded = Schema.decodeUnknownOption(
34
+ // https://docs.anthropic.com/en/api/errors#http-errors
35
+ Schema.Struct({
28
36
  type: Schema.Literal("error"),
29
37
  error: Schema.Struct({ type: Schema.Literal("overloaded_error") }),
30
38
  }));
@@ -171,6 +179,22 @@ export function observeProviderStatus(options) {
171
179
  if (Option.isSome(failed) &&
172
180
  failed.value.response.error.code === usageLimitCode)
173
181
  rejection = { code: "usage-limit-reached" };
182
+ // OpenAI's Responses error code, not an inference from overload prose:
183
+ // https://platform.openai.com/docs/api-reference/responses/object#responses/object-error
184
+ if (Option.isSome(failed) &&
185
+ failed.value.response.error.code === "server_error")
186
+ rejection = { code: "provider_unavailable" };
187
+ // WebSocket API errors retain HTTP status in the parsed event:
188
+ // https://developers.openai.com/api/docs/guides/websocket-mode/#handling-errors
189
+ const error = decodeErrorEvent(data);
190
+ if (Option.isSome(error)) {
191
+ const status = error.value.status;
192
+ if (status !== undefined && status >= 500)
193
+ rejection = { code: "provider_unavailable", status };
194
+ else if (status === undefined &&
195
+ (error.value.code ?? error.value.error?.code) === "server_error")
196
+ rejection = { code: "provider_unavailable" };
197
+ }
174
198
  if (Option.isSome(decodeOverloaded(data)))
175
199
  rejection = { code: "overloaded" };
176
200
  await options?.onProviderStreamEvent?.(data, model);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fungi.computer/mule",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "author": "Levi <levi@technomancy.dev>",
5
5
  "description": "Effect-native Pi model and tool loop",
6
6
  "type": "module",