@jxsuite/ai 0.36.5 → 0.37.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxsuite/ai",
3
- "version": "0.36.5",
3
+ "version": "0.37.0",
4
4
  "description": "AI infrastructure for Jx Suite — streaming LLM client abstraction, tool registry, and reactive chat state",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,10 +28,10 @@
28
28
  "upgrade": "bun update --latest && bun install"
29
29
  },
30
30
  "dependencies": {
31
- "@jxsuite/protocol": "^2.1.0",
32
- "@vue/reactivity": "3.5.41"
31
+ "@jxsuite/protocol": "^2.2.0",
32
+ "@vue/reactivity": "3.5.42"
33
33
  },
34
34
  "devDependencies": {
35
- "@happy-dom/global-registrator": "^20.11.8"
35
+ "@happy-dom/global-registrator": "^20.12.0"
36
36
  }
37
37
  }
@@ -113,6 +113,14 @@ interface OpenAIStreamChunk {
113
113
  /** Error response body — the proxy's flat `{ error: "..." }` or OpenAI's `{ error: { message } }`. */
114
114
  interface ErrorResponseBody {
115
115
  error?: string | { message?: string; code?: string; type?: string };
116
+ /**
117
+ * The proxy's machine code, alongside its human `error` — `cf_reconnect_required` and friends.
118
+ *
119
+ * A backend that knows WHY it refused says so here, and a client can only act on the reason it is
120
+ * given: the whole point of the code is that the Reconnect affordance appears without the user
121
+ * reading a sentence and deciding what it meant.
122
+ */
123
+ code?: string;
116
124
  }
117
125
 
118
126
  // ─── Type definitions ────────────────────────────────────────────────────────
@@ -508,6 +516,11 @@ export function createProxyStreamingClient({
508
516
  // Try to extract a clean message from JSON error bodies (e.g. the proxy's
509
517
  // { error: "..." } shape or OpenAI's { error: { message: "..." } }).
510
518
  let cleanMessage = errorBody || response.statusText;
519
+ /* The body's machine code beats the status. `code` was `String(response.status)`
520
+ unconditionally, so a proxy answering 401 `{ code: "cf_reconnect_required" }` reached the
521
+ client as `"401"` — indistinguishable from a bad BYOK key, and the one reading that would
522
+ have put a Reconnect button on screen was thrown away at the only place it arrived. */
523
+ let machineCode = "";
511
524
  try {
512
525
  const parsed = JSON.parse(errorBody) as ErrorResponseBody;
513
526
  if (typeof parsed.error === "string") {
@@ -515,13 +528,16 @@ export function createProxyStreamingClient({
515
528
  } else if (parsed.error?.message) {
516
529
  cleanMessage = parsed.error.message;
517
530
  }
531
+ if (typeof parsed.code === "string" && parsed.code) {
532
+ machineCode = parsed.code;
533
+ }
518
534
  } catch {
519
535
  /* Not JSON — use the raw body. */
520
536
  }
521
537
  yield {
522
538
  type: "error",
523
539
  message: cleanMessage,
524
- code: String(response.status),
540
+ code: machineCode || String(response.status),
525
541
  };
526
542
  return;
527
543
  }