@cortexkit/anthropic-auth-core 1.4.1 → 1.6.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/relay.js CHANGED
@@ -241,6 +241,22 @@ function toBinaryChunk(data) {
241
241
  function parseRelayControlMessage(data) {
242
242
  return JSON.parse(data);
243
243
  }
244
+ function formatCloseEvent(event) {
245
+ const close = event;
246
+ const parts = [
247
+ `code=${close.code ?? 'unknown'}`,
248
+ `wasClean=${close.wasClean ?? 'unknown'}`,
249
+ ];
250
+ if (close.reason)
251
+ parts.push(`reason=${JSON.stringify(close.reason)}`);
252
+ return parts.join(' ');
253
+ }
254
+ function relayControlErrorMessage(message) {
255
+ const detail = message.message || 'relay websocket error';
256
+ return message.status
257
+ ? `relay websocket error ${message.status}: ${detail}`
258
+ : detail;
259
+ }
244
260
  class PersistentRelaySession {
245
261
  config;
246
262
  affinity;
@@ -358,7 +374,7 @@ class PersistentRelaySession {
358
374
  reject(error);
359
375
  this.failPending(error);
360
376
  });
361
- socket.addEventListener('close', () => {
377
+ socket.addEventListener('close', (event) => {
362
378
  clearTimeout(timeout);
363
379
  if (this.socket === socket) {
364
380
  this.socket = undefined;
@@ -368,9 +384,16 @@ class PersistentRelaySession {
368
384
  if (this.pending) {
369
385
  if (this.pending.retryingBeforeResponse)
370
386
  return;
371
- if (this.retryPendingBeforeResponse(this.pending, 'closed before response'))
387
+ const closedAfterResponseStart = this.pending.responseStartedAt != null;
388
+ const reason = closedAfterResponseStart
389
+ ? 'closed after response_start before stream bytes'
390
+ : 'closed before response';
391
+ if (this.retryPendingBeforeResponse(this.pending, reason, event))
372
392
  return;
373
- const error = new Error('relay websocket closed before response');
393
+ const error = new Error(closedAfterResponseStart
394
+ ? 'relay websocket closed during response stream'
395
+ : 'relay websocket closed before response');
396
+ relayLog(`websocket ${closedAfterResponseStart ? 'closed during response stream' : 'closed before response without retry'} session=${shortAffinity(this.affinity)} request=${this.pending.payload.id} chunks=${this.pending.streamChunkCount} bytes=${this.pending.streamByteCount} ${formatCloseEvent(event)}`);
374
397
  this.failPending(error);
375
398
  }
376
399
  });
@@ -404,6 +427,8 @@ class PersistentRelaySession {
404
427
  rejectDone,
405
428
  sentAt,
406
429
  optimisticResponse,
430
+ streamChunkCount: 0,
431
+ streamByteCount: 0,
407
432
  retryAttempts: 0,
408
433
  retryingBeforeResponse: false,
409
434
  };
@@ -430,8 +455,8 @@ class PersistentRelaySession {
430
455
  this.socket?.close();
431
456
  }, 45_000);
432
457
  }
433
- retryPendingBeforeResponse(pending, reason) {
434
- if (pending.responseStartedAt != null)
458
+ retryPendingBeforeResponse(pending, reason, closeEvent) {
459
+ if (pending.responseStartedAt != null && pending.streamByteCount > 0)
435
460
  return false;
436
461
  if (pending.streamDone)
437
462
  return false;
@@ -442,7 +467,7 @@ class PersistentRelaySession {
442
467
  clearTimeout(pending.timeout);
443
468
  const attempt = pending.retryAttempts;
444
469
  const originalId = pending.payload.id;
445
- relayLog(`websocket ${reason}; reconnecting and retrying full_sync session=${shortAffinity(this.affinity)} request=${originalId} retry=${attempt}`);
470
+ relayLog(`websocket ${reason}; reconnecting and retrying full_sync session=${shortAffinity(this.affinity)} request=${originalId} retry=${attempt} chunks=${pending.streamChunkCount} bytes=${pending.streamByteCount}${closeEvent ? ` ${formatCloseEvent(closeEvent)}` : ''}`);
446
471
  this.socket?.close();
447
472
  this.socket = undefined;
448
473
  this.serverState = undefined;
@@ -478,11 +503,16 @@ class PersistentRelaySession {
478
503
  })();
479
504
  return true;
480
505
  }
506
+ enqueueStreamChunk(pending, chunk) {
507
+ pending.streamChunkCount += 1;
508
+ pending.streamByteCount += chunk.byteLength;
509
+ pending.streamController?.enqueue(chunk);
510
+ }
481
511
  handleBinaryChunk(data) {
482
512
  const pending = this.pending;
483
513
  if (!pending?.responseStarted)
484
514
  return;
485
- pending.streamController?.enqueue(toBinaryChunk(data));
515
+ this.enqueueStreamChunk(pending, toBinaryChunk(data));
486
516
  }
487
517
  resolvePendingResponse(pending, status, statusText, headers) {
488
518
  if (pending.responseStarted)
@@ -536,7 +566,7 @@ class PersistentRelaySession {
536
566
  return;
537
567
  }
538
568
  if (message.type === 'chunk') {
539
- pending.streamController?.enqueue(decodeRelayChunk(message.base64));
569
+ this.enqueueStreamChunk(pending, decodeRelayChunk(message.base64));
540
570
  return;
541
571
  }
542
572
  if (message.type === 'done') {
@@ -549,7 +579,7 @@ class PersistentRelaySession {
549
579
  // would reject a settled promise and leave the stream hanging. Instead,
550
580
  // inject an SSE error event and close cleanly.
551
581
  if (pending.optimisticResponse && pending.responseStartedAt != null) {
552
- relayLog(`websocket relay error during optimistic response session=${shortAffinity(this.affinity)} request=${pending.payload.id} status=${message.status} message=${message.message || 'unknown'}`);
582
+ relayLog(`websocket relay error during optimistic response session=${shortAffinity(this.affinity)} request=${pending.payload.id} status=${message.status} message=${message.message || 'unknown'} chunks=${pending.streamChunkCount} bytes=${pending.streamByteCount}`);
553
583
  pending.streamController?.enqueue(new TextEncoder().encode(`event: error\ndata: ${JSON.stringify({ type: 'error', error: { type: 'relay_error', message: message.message || 'relay error' } })}\n\n`));
554
584
  this.finishPending();
555
585
  this.socket?.close();
@@ -561,7 +591,7 @@ class PersistentRelaySession {
561
591
  }
562
592
  const error = message.status === 409
563
593
  ? new RelayStateMismatchError(message.message || 'state mismatch')
564
- : new Error(message.message || 'relay websocket error');
594
+ : new Error(relayControlErrorMessage(message));
565
595
  this.failPending(error);
566
596
  }
567
597
  }
@@ -570,7 +600,7 @@ class PersistentRelaySession {
570
600
  if (!pending)
571
601
  return;
572
602
  const finishedAt = perfNowMs();
573
- relayLog(`perf websocket done session=${shortAffinity(this.affinity)} request=${pending.payload.id} sentMs=${formatMs(finishedAt - pending.sentAt)} streamMs=${pending.responseStartedAt == null ? 'unknown' : formatMs(finishedAt - pending.responseStartedAt)}`);
603
+ relayLog(`perf websocket done session=${shortAffinity(this.affinity)} request=${pending.payload.id} sentMs=${formatMs(finishedAt - pending.sentAt)} streamMs=${pending.responseStartedAt == null ? 'unknown' : formatMs(finishedAt - pending.responseStartedAt)} chunks=${pending.streamChunkCount} bytes=${pending.streamByteCount}`);
574
604
  clearTimeout(pending.timeout);
575
605
  if (!pending.streamDone) {
576
606
  pending.streamDone = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/anthropic-auth-core",
3
- "version": "1.4.1",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",