@ekodb/ekodb-client 0.24.0 → 0.26.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/src/index.ts CHANGED
@@ -7,7 +7,13 @@ export {
7
7
  RateLimitError,
8
8
  SchemaCache,
9
9
  extractRecordId,
10
+ HealthStatus,
11
+ parseHealthStatus,
12
+ HealthOK,
13
+ HealthDegraded,
14
+ HealthUnknown,
10
15
  } from "./client";
16
+ export type { HealthState } from "./client";
11
17
  export { QueryBuilder, SortOrder } from "./query-builder";
12
18
  export { SearchQueryBuilder } from "./search";
13
19
  export {
@@ -82,6 +88,8 @@ export type {
82
88
  UpdateSessionRequest,
83
89
  MergeSessionsRequest,
84
90
  ChatModels,
91
+ ChatProviderState,
92
+ ChatProviderStatus,
85
93
  CompactChatRequest,
86
94
  CompactChatResponse,
87
95
  EmbedRequest,
@@ -432,6 +432,96 @@ describe("WebSocketClient", () => {
432
432
  client.close();
433
433
  });
434
434
 
435
+ // The WebSocket route carries the provider-failure classification like
436
+ // the SSE route does, in the event's camelCase shape.
437
+ it("carries the provider failure classification on a chat stream error", async () => {
438
+ const client = new WebSocketClient(
439
+ `ws://localhost:${port}/api/ws`,
440
+ "test-token",
441
+ );
442
+
443
+ const streamPromise = client.chatSend("chat-4", "test");
444
+
445
+ await new Promise((r) => wss.once("connection", r));
446
+ const ws = getLastConnection();
447
+ await waitForMessage(ws);
448
+
449
+ const stream = await streamPromise;
450
+ const events: any[] = [];
451
+ stream.on("event", (e) => events.push(e));
452
+
453
+ ws.send(
454
+ JSON.stringify({
455
+ type: "ChatStreamError",
456
+ payload: {
457
+ chat_id: "chat-4",
458
+ error: "OpenAI API error 429 Too Many Requests",
459
+ error_kind: "provider_rate_limited",
460
+ provider: "openai",
461
+ provider_status: 429,
462
+ retry_after_secs: 7,
463
+ },
464
+ }),
465
+ );
466
+
467
+ await new Promise((r) => stream.on("close", r));
468
+ expect(events).toEqual([
469
+ {
470
+ type: "error",
471
+ error: "OpenAI API error 429 Too Many Requests",
472
+ errorKind: "provider_rate_limited",
473
+ provider: "openai",
474
+ providerStatus: 429,
475
+ retryAfterSecs: 7,
476
+ },
477
+ ]);
478
+
479
+ client.close();
480
+ });
481
+
482
+ // A structured `error` value is still an error, with string text — the
483
+ // WebSocket route guards the shape exactly as the SSE route does.
484
+ it("keeps the error text a string when the payload's error is an object", async () => {
485
+ const client = new WebSocketClient(
486
+ `ws://localhost:${port}/api/ws`,
487
+ "test-token",
488
+ );
489
+
490
+ const streamPromise = client.chatSend("chat-5", "test");
491
+
492
+ await new Promise((r) => wss.once("connection", r));
493
+ const ws = getLastConnection();
494
+ await waitForMessage(ws);
495
+
496
+ const stream = await streamPromise;
497
+ const events: any[] = [];
498
+ stream.on("event", (e) => events.push(e));
499
+
500
+ ws.send(
501
+ JSON.stringify({
502
+ type: "ChatStreamError",
503
+ payload: {
504
+ chat_id: "chat-5",
505
+ error: { code: "upstream_down", status: 503 },
506
+ error_kind: "provider_unavailable",
507
+ provider: "gemini",
508
+ },
509
+ }),
510
+ );
511
+
512
+ await new Promise((r) => stream.on("close", r));
513
+ expect(events).toEqual([
514
+ {
515
+ type: "error",
516
+ error: "Unknown error",
517
+ errorKind: "provider_unavailable",
518
+ provider: "gemini",
519
+ },
520
+ ]);
521
+
522
+ client.close();
523
+ });
524
+
435
525
  it("sends options with ChatSend", async () => {
436
526
  const client = new WebSocketClient(
437
527
  `ws://localhost:${port}/api/ws`,
package/tsconfig.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2020",
4
- "module": "commonjs",
4
+ "module": "nodenext",
5
5
  "lib": ["ES2020"],
6
6
  "declaration": true,
7
7
  "outDir": "./dist",
@@ -10,7 +10,7 @@
10
10
  "esModuleInterop": true,
11
11
  "skipLibCheck": true,
12
12
  "forceConsistentCasingInFileNames": true,
13
- "moduleResolution": "node",
13
+ "moduleResolution": "nodenext",
14
14
  "resolveJsonModule": true,
15
15
  "noUnusedLocals": true,
16
16
  "noUnusedParameters": true