@opengeni/xai-subscription 0.1.0 → 0.1.2-canary.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/index.js CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  XAI_REFRESH_FALLBACK_MS,
14
14
  XAI_REFRESH_WINDOW_MS,
15
15
  XAI_RESPONSE_SDK_OUTER_TIMEOUT_MS,
16
+ XAI_RESPONSE_STREAM_IDLE_TIMEOUT_MS,
16
17
  XAI_SUBSCRIPTION_AUTO_COMPACTION_PERCENT,
17
18
  XAI_SUBSCRIPTION_EFFECTIVE_CONTEXT_PERCENT,
18
19
  XAI_SUBSCRIPTION_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
@@ -31,7 +32,7 @@ import {
31
32
  XAI_VIDEO_POLL_INTERVAL_MS,
32
33
  XAI_VIDEO_POLL_REQUEST_TIMEOUT_MS,
33
34
  XAI_VIDEO_START_TIMEOUT_MS
34
- } from "./chunk-JEFGIUGN.js";
35
+ } from "./chunk-QSLO7YEK.js";
35
36
 
36
37
  // src/errors.ts
37
38
  var XaiSubscriptionError = class extends Error {
@@ -54,6 +55,113 @@ var XaiSubscriptionTransientError = class extends XaiSubscriptionError {
54
55
  this.name = "XaiSubscriptionTransientError";
55
56
  }
56
57
  };
58
+ var XaiSubscriptionHostedToolContinuationError = class extends XaiSubscriptionError {
59
+ code = "xai_hosted_tool_continuation_stalled";
60
+ constructor() {
61
+ super(
62
+ "timeout",
63
+ "SuperGrok stopped responding after completing a hosted search. The partial response was preserved and was not replayed automatically."
64
+ );
65
+ this.name = "XaiSubscriptionHostedToolContinuationError";
66
+ }
67
+ };
68
+ var XaiSubscriptionStreamingTerminalError = class extends XaiSubscriptionError {
69
+ code;
70
+ eventType;
71
+ requestId;
72
+ diagnosticTruncated;
73
+ headers;
74
+ constructor(input) {
75
+ super("provider_rejected", input.message, input.status);
76
+ this.name = "XaiSubscriptionStreamingTerminalError";
77
+ this.code = input.code;
78
+ this.eventType = input.eventType;
79
+ this.requestId = input.requestId ?? null;
80
+ this.diagnosticTruncated = input.diagnosticTruncated === true;
81
+ this.headers = input.headers ?? new Headers();
82
+ }
83
+ };
84
+ var XAI_SUBSCRIPTION_RATE_LIMIT_CODES = /* @__PURE__ */ new Set([
85
+ "rate_limit_exceeded",
86
+ "too_many_requests",
87
+ "overloaded_error",
88
+ "server_overloaded",
89
+ "capacity_exceeded",
90
+ "resource_exhausted"
91
+ ]);
92
+ var XAI_SUBSCRIPTION_RATE_LIMIT_MESSAGE = /the model is currently at capacity due to high demand/i;
93
+ function isXaiSubscriptionRateLimitDiagnostic(input) {
94
+ if (input.status === 429) return true;
95
+ const code = (input.code ?? "").trim().toLowerCase();
96
+ if (XAI_SUBSCRIPTION_RATE_LIMIT_CODES.has(code)) return true;
97
+ return XAI_SUBSCRIPTION_RATE_LIMIT_MESSAGE.test(input.message ?? "");
98
+ }
99
+ function classifyXaiSubscriptionStreamingTerminalError(error) {
100
+ let current = error;
101
+ for (let depth = 0; depth < 8 && current && typeof current === "object"; depth += 1) {
102
+ const value = current;
103
+ if (current instanceof XaiSubscriptionStreamingTerminalError || value.name === "XaiSubscriptionStreamingTerminalError") {
104
+ const code = typeof value.code === "string" && value.code.length > 0 ? value.code : null;
105
+ const eventType = typeof value.eventType === "string" && value.eventType.length > 0 ? value.eventType : null;
106
+ const message = typeof value.message === "string" ? value.message : "";
107
+ if (!code || !eventType || message.length === 0) return null;
108
+ const status = Number(value.status);
109
+ return {
110
+ message,
111
+ code,
112
+ eventType,
113
+ requestId: typeof value.requestId === "string" ? value.requestId : null,
114
+ ...Number.isInteger(status) && status >= 100 && status <= 599 ? { status } : {},
115
+ diagnosticTruncated: value.diagnosticTruncated === true
116
+ };
117
+ }
118
+ current = value.cause;
119
+ }
120
+ return null;
121
+ }
122
+ var XaiSubscriptionStreamIdleTimeoutError = class extends XaiSubscriptionError {
123
+ constructor(requestId, responseObserved, eventCount, lastEventType, silenceDurationMs) {
124
+ super(
125
+ "timeout",
126
+ "SuperGrok stopped sending valid response events. The partial response was preserved and was not replayed automatically."
127
+ );
128
+ this.requestId = requestId;
129
+ this.responseObserved = responseObserved;
130
+ this.eventCount = eventCount;
131
+ this.lastEventType = lastEventType;
132
+ this.silenceDurationMs = silenceDurationMs;
133
+ this.name = "XaiSubscriptionStreamIdleTimeoutError";
134
+ }
135
+ code = "xai_response_stream_idle_timeout";
136
+ };
137
+ function classifyXaiSubscriptionStreamIdleTimeoutError(error) {
138
+ let current = error;
139
+ for (let depth = 0; depth < 8 && current && typeof current === "object"; depth += 1) {
140
+ const value = current;
141
+ if (current instanceof XaiSubscriptionStreamIdleTimeoutError || value.code === "xai_response_stream_idle_timeout") {
142
+ return {
143
+ requestId: typeof value.requestId === "string" ? value.requestId : null,
144
+ responseObserved: value.responseObserved === true,
145
+ eventCount: typeof value.eventCount === "number" && Number.isSafeInteger(value.eventCount) ? value.eventCount : 0,
146
+ lastEventType: typeof value.lastEventType === "string" ? value.lastEventType : null,
147
+ silenceDurationMs: typeof value.silenceDurationMs === "number" && Number.isFinite(value.silenceDurationMs) ? Math.max(0, value.silenceDurationMs) : 0
148
+ };
149
+ }
150
+ current = value.cause;
151
+ }
152
+ return null;
153
+ }
154
+ function isXaiSubscriptionHostedToolContinuationError(error) {
155
+ let current = error;
156
+ for (let depth = 0; depth < 6 && current && typeof current === "object"; depth += 1) {
157
+ if (current instanceof XaiSubscriptionHostedToolContinuationError) return true;
158
+ if (current.code === "xai_hosted_tool_continuation_stalled") {
159
+ return true;
160
+ }
161
+ current = current.cause;
162
+ }
163
+ return false;
164
+ }
57
165
 
58
166
  // src/bounded-operation.ts
59
167
  async function runBoundedXaiOperation(operation, timeoutMs) {
@@ -303,6 +411,27 @@ async function fetchXaiVerifiedIdentity(accessToken, options = {}) {
303
411
  name: nullableString(body.name)
304
412
  };
305
413
  }
414
+ function xaiIdentityFromDeviceTokens(tokens) {
415
+ const accessClaims = decodeXaiJwtPayload(tokens.accessToken);
416
+ const idClaims = tokens.idToken ? decodeXaiJwtPayload(tokens.idToken) : null;
417
+ const subject = nullableString(accessClaims?.principal_id) ?? nullableString(accessClaims?.principalId) ?? nullableString(idClaims?.sub) ?? nullableString(accessClaims?.sub);
418
+ if (!subject) {
419
+ throw new XaiSubscriptionError(
420
+ "invalid_response",
421
+ "xAI OAuth token response is missing account identity"
422
+ );
423
+ }
424
+ const givenName = nullableString(idClaims?.given_name) ?? nullableString(accessClaims?.given_name);
425
+ const familyName = nullableString(idClaims?.family_name) ?? nullableString(accessClaims?.family_name);
426
+ const combinedName = [givenName, familyName].filter(Boolean).join(" ") || null;
427
+ const emailVerifiedClaim = idClaims?.email_verified ?? accessClaims?.email_verified;
428
+ return {
429
+ subject,
430
+ email: nullableString(idClaims?.email) ?? nullableString(accessClaims?.email),
431
+ emailVerified: typeof emailVerifiedClaim === "boolean" ? emailVerifiedClaim : null,
432
+ name: nullableString(idClaims?.name) ?? nullableString(accessClaims?.name) ?? combinedName
433
+ };
434
+ }
306
435
  function decodeXaiJwtPayload(jwt) {
307
436
  const payload = jwt.split(".")[1];
308
437
  if (!payload) return null;
@@ -425,6 +554,17 @@ var XAI_SUBSCRIPTION_REQUEST_BODY_NORMALIZED_HEADER = "x-opengeni-xai-subscripti
425
554
  var XAI_SUBSCRIPTION_REQUEST_MODEL_HEADER = "x-opengeni-xai-subscription-model";
426
555
  var XAI_SUBSCRIPTION_REQUEST_ID_HEADER = "x-opengeni-xai-subscription-request-id";
427
556
  var MAX_ERROR_BODY_BYTES = 64 * 1024;
557
+ var MAX_STREAM_IDLE_TIMEOUT_MS = 24 * 60 * 6e4;
558
+ var MAX_TERMINAL_ERROR_FIELD_BYTES = 256;
559
+ var MAX_TERMINAL_ERROR_MESSAGE_BYTES = 4 * 1024;
560
+ var TERMINAL_ERROR_TRUNCATION_MARKER = "\u2026 [truncated]";
561
+ var NON_RETRYABLE_SSE_ERROR_CODES = /* @__PURE__ */ new Set([
562
+ "context_length_exceeded",
563
+ "invalid_prompt",
564
+ "invalid_request",
565
+ "insufficient_quota",
566
+ "usage_limit_reached"
567
+ ]);
428
568
  function xaiSubscriptionFetch(base) {
429
569
  return async (input, init) => {
430
570
  const context = xaiSubscriptionRequestStorage.getStore();
@@ -439,7 +579,7 @@ function xaiSubscriptionFetch(base) {
439
579
  new Headers(init.headers).forEach((value, key) => originalHeaders.set(key, value));
440
580
  }
441
581
  const normalized = originalHeaders.get(XAI_SUBSCRIPTION_REQUEST_BODY_NORMALIZED_HEADER) === "1";
442
- const requestId = originalHeaders.get(XAI_SUBSCRIPTION_REQUEST_ID_HEADER) ?? randomUUID();
582
+ const requestId = originalHeaders.get(XAI_SUBSCRIPTION_REQUEST_ID_HEADER) ?? context.nextRequestId?.() ?? randomUUID();
443
583
  const handedOffModel = originalHeaders.get(XAI_SUBSCRIPTION_REQUEST_MODEL_HEADER);
444
584
  originalHeaders.delete(XAI_SUBSCRIPTION_REQUEST_BODY_NORMALIZED_HEADER);
445
585
  originalHeaders.delete(XAI_SUBSCRIPTION_REQUEST_ID_HEADER);
@@ -449,7 +589,10 @@ function xaiSubscriptionFetch(base) {
449
589
  const parsed = body ? JSON.parse(body) : {};
450
590
  const normalizedBody = normalized ? parsed : normalizeXaiSubscriptionRequestBody(parsed, context.resolveModel, context.hostedSearch);
451
591
  const model = handedOffModel ?? (typeof normalizedBody.model === "string" ? normalizedBody.model : "grok-4.6");
452
- const send = async (refresh) => {
592
+ const streamIdleTimeoutMs = boundedStreamIdleTimeout(
593
+ context.streamIdleTimeoutMs ?? context.hostedToolContinuationTimeoutMs
594
+ );
595
+ const send = async (refresh, transportAttempt) => {
453
596
  const token = refresh ? await context.refresh() : await context.getToken();
454
597
  const headers = new Headers(originalHeaders);
455
598
  headers.set("authorization", `Bearer ${token.accessToken}`);
@@ -468,19 +611,64 @@ function xaiSubscriptionFetch(base) {
468
611
  headers.set("x-grok-req-id", requestId);
469
612
  headers.set("x-grok-agent-id", context.turnId);
470
613
  headers.set("x-grok-model-override", model);
471
- return await base(url, {
472
- ...init,
473
- method: init?.method ?? (input instanceof Request ? input.method : "POST"),
474
- headers,
475
- body: JSON.stringify(normalizedBody)
476
- });
614
+ const audit = {
615
+ ctx: context,
616
+ requestId,
617
+ transportAttempt,
618
+ model,
619
+ startedAt: performance.now(),
620
+ streamIdleTimeoutMs,
621
+ eventCount: 0,
622
+ lastEventType: null,
623
+ lastProgressAt: null,
624
+ terminal: false,
625
+ terminalEventEmitted: false
626
+ };
627
+ let response;
628
+ try {
629
+ await emitRequestEvent(audit, {
630
+ phase: "started",
631
+ responseObserved: false
632
+ });
633
+ response = await base(url, {
634
+ ...init,
635
+ method: init?.method ?? (input instanceof Request ? input.method : "POST"),
636
+ headers,
637
+ body: JSON.stringify(normalizedBody)
638
+ });
639
+ await emitRequestEvent(audit, {
640
+ phase: "headers",
641
+ responseObserved: true,
642
+ status: response.status,
643
+ ...providerRequestIdFields(response.headers)
644
+ });
645
+ return { response, audit };
646
+ } catch (error) {
647
+ await response?.body?.cancel(error).catch(() => void 0);
648
+ await emitRequestEvent(audit, {
649
+ phase: "failed",
650
+ responseObserved: response !== void 0,
651
+ ...response ? {
652
+ status: response.status,
653
+ ...providerRequestIdFields(response.headers)
654
+ } : {}
655
+ }).catch(() => void 0);
656
+ throw error;
657
+ }
477
658
  };
478
- let response = await send(false);
479
- if (response.status === 401) {
480
- await response.body?.cancel().catch(() => void 0);
481
- response = await send(true);
659
+ let sent = await send(false, 1);
660
+ if (sent.response.status === 401) {
661
+ await sent.response.body?.cancel().catch(() => void 0);
662
+ await emitRequestEvent(sent.audit, {
663
+ phase: "failed",
664
+ responseObserved: true,
665
+ status: sent.response.status,
666
+ willRetry: true,
667
+ ...providerRequestIdFields(sent.response.headers)
668
+ });
669
+ sent = await send(true, 2);
482
670
  }
483
- return await normalizeResponse(response, context.onFinalContextUsage);
671
+ return await normalizeResponse(sent.response, sent.audit, context.onFinalContextUsage);
484
672
  };
485
673
  }
486
674
  async function requestBodyText(input, init, replayableBodyFactory) {
@@ -490,19 +678,33 @@ async function requestBodyText(input, init, replayableBodyFactory) {
490
678
  if (init?.body === void 0 || init.body === null) return "";
491
679
  throw new Error("SuperGrok subscription request body must be replayable JSON text");
492
680
  }
493
- async function normalizeResponse(response, onFinalContextUsage) {
681
+ async function normalizeResponse(response, audit, onFinalContextUsage) {
494
682
  if (!response.ok) {
495
683
  const bytes = new Uint8Array(await response.arrayBuffer());
496
684
  const bounded = bytes.byteLength > MAX_ERROR_BODY_BYTES ? bytes.slice(0, MAX_ERROR_BODY_BYTES) : bytes;
497
685
  const headers = new Headers(response.headers);
498
686
  headers.set(XAI_SUBSCRIPTION_TRANSPORT_ERROR_HEADER, "1");
687
+ await emitRequestEvent(audit, {
688
+ phase: "failed",
689
+ responseObserved: true,
690
+ status: response.status,
691
+ ...providerRequestIdFields(response.headers)
692
+ });
499
693
  return new Response(bounded, {
500
694
  status: response.status,
501
695
  statusText: response.statusText,
502
696
  headers
503
697
  });
504
698
  }
505
- if (!response.body) return response;
699
+ if (!response.body) {
700
+ await emitRequestEvent(audit, {
701
+ phase: "completed",
702
+ responseObserved: true,
703
+ status: response.status,
704
+ ...providerRequestIdFields(response.headers)
705
+ });
706
+ return response;
707
+ }
506
708
  const contentType = response.headers.get("content-type") ?? "";
507
709
  if (!contentType.includes("text/event-stream")) {
508
710
  const value = await response.json();
@@ -512,6 +714,12 @@ async function normalizeResponse(response, onFinalContextUsage) {
512
714
  });
513
715
  emitContextUsage(normalized.value, normalized.finalContextTokens, onFinalContextUsage);
514
716
  const responseValue = normalized.value && typeof normalized.value === "object" && !Array.isArray(normalized.value) ? normalized.value.response : value;
717
+ await emitRequestEvent(audit, {
718
+ phase: "completed",
719
+ responseObserved: true,
720
+ status: response.status,
721
+ ...providerRequestIdFields(response.headers)
722
+ });
515
723
  return Response.json(responseValue, {
516
724
  status: response.status,
517
725
  statusText: response.statusText,
@@ -522,24 +730,185 @@ async function normalizeResponse(response, onFinalContextUsage) {
522
730
  const decoder = new TextDecoder();
523
731
  const encoder = new TextEncoder();
524
732
  let pending = "";
733
+ let idleTimer = null;
734
+ let controllerRef = null;
735
+ let silenceStartedAt = performance.now();
736
+ let streamSettled = false;
737
+ const errorStream = (error) => {
738
+ if (streamSettled || !controllerRef) return;
739
+ streamSettled = true;
740
+ controllerRef.error(error);
741
+ };
742
+ const closeStream = () => {
743
+ if (streamSettled || !controllerRef) return;
744
+ streamSettled = true;
745
+ controllerRef.close();
746
+ };
747
+ const clearIdleTimer = () => {
748
+ if (idleTimer !== null) clearTimeout(idleTimer);
749
+ idleTimer = null;
750
+ };
751
+ const armIdleTimer = () => {
752
+ clearIdleTimer();
753
+ idleTimer = setTimeout(() => {
754
+ if (audit.terminal || !controllerRef) return;
755
+ audit.terminal = true;
756
+ clearIdleTimer();
757
+ const now = performance.now();
758
+ const silenceDurationMs = Math.max(0, now - silenceStartedAt);
759
+ const error = new XaiSubscriptionStreamIdleTimeoutError(
760
+ audit.requestId,
761
+ audit.eventCount > 0,
762
+ audit.eventCount,
763
+ audit.lastEventType,
764
+ silenceDurationMs
765
+ );
766
+ void reader.cancel(error).catch(() => void 0);
767
+ void emitRequestEvent(audit, {
768
+ phase: "timed_out",
769
+ responseObserved: audit.eventCount > 0,
770
+ status: response.status,
771
+ silenceDurationMs,
772
+ ...providerRequestIdFields(response.headers)
773
+ }).then(
774
+ () => errorStream(error),
775
+ () => errorStream(error)
776
+ );
777
+ }, audit.streamIdleTimeoutMs);
778
+ idleTimer.unref?.();
779
+ };
525
780
  const body = new ReadableStream({
781
+ start(controller) {
782
+ controllerRef = controller;
783
+ silenceStartedAt = performance.now();
784
+ armIdleTimer();
785
+ },
526
786
  async pull(controller) {
527
- const chunk = await reader.read();
528
- pending += decoder.decode(chunk.value, { stream: !chunk.done });
529
- const parts = pending.split("\n\n");
530
- pending = parts.pop() ?? "";
531
- for (const part of parts)
532
- controller.enqueue(encoder.encode(`${normalizeSseEvent(part, onFinalContextUsage)}
787
+ if (audit.terminal) return;
788
+ try {
789
+ while (!audit.terminal) {
790
+ const chunk = await reader.read();
791
+ if (audit.terminal) return;
792
+ pending += decoder.decode(chunk.value, { stream: !chunk.done });
793
+ const parts = pending.split(/\r?\n\r?\n/);
794
+ pending = parts.pop() ?? "";
795
+ if (chunk.done && pending) {
796
+ parts.push(pending);
797
+ pending = "";
798
+ }
799
+ let enqueued = false;
800
+ for (const part of parts) {
801
+ const progress = sseProgress(part);
802
+ if (!progress.valid) {
803
+ controller.enqueue(
804
+ encoder.encode(`${normalizeSseEvent(part, onFinalContextUsage)}
805
+
806
+ `)
807
+ );
808
+ enqueued = true;
809
+ continue;
810
+ }
811
+ clearIdleTimer();
812
+ const now = performance.now();
813
+ const interEventGapMs = Math.max(0, now - (audit.lastProgressAt ?? audit.startedAt));
814
+ audit.eventCount = Math.min(Number.MAX_SAFE_INTEGER, audit.eventCount + 1);
815
+ audit.lastEventType = progress.eventType;
816
+ audit.lastProgressAt = now;
817
+ silenceStartedAt = now;
818
+ if (audit.eventCount === 1) {
819
+ await emitRequestEvent(audit, {
820
+ phase: "first_event",
821
+ responseObserved: true,
822
+ status: response.status,
823
+ ...providerRequestIdFields(response.headers)
824
+ });
825
+ } else {
826
+ emitDiagnosticEvent(audit, {
827
+ phase: "progress",
828
+ responseObserved: true,
829
+ status: response.status,
830
+ interEventGapMs,
831
+ ...providerRequestIdFields(response.headers)
832
+ });
833
+ }
834
+ if (progress.terminal === "failed") {
835
+ audit.terminal = true;
836
+ clearIdleTimer();
837
+ await reader.cancel().catch(() => void 0);
838
+ await emitRequestEvent(audit, {
839
+ phase: "failed",
840
+ responseObserved: true,
841
+ status: response.status,
842
+ ...providerRequestIdFields(response.headers)
843
+ });
844
+ errorStream(xaiSseTerminalError(response, audit, progress));
845
+ return;
846
+ }
847
+ controller.enqueue(
848
+ encoder.encode(`${normalizeSseEvent(part, onFinalContextUsage)}
533
849
 
534
- `));
535
- if (chunk.done) {
536
- if (pending)
537
- controller.enqueue(encoder.encode(normalizeSseEvent(pending, onFinalContextUsage)));
538
- controller.close();
850
+ `)
851
+ );
852
+ enqueued = true;
853
+ if (progress.terminal === "completed") {
854
+ audit.terminal = true;
855
+ clearIdleTimer();
856
+ await reader.cancel().catch(() => void 0);
857
+ await emitRequestEvent(audit, {
858
+ phase: "completed",
859
+ responseObserved: true,
860
+ status: response.status,
861
+ ...providerRequestIdFields(response.headers)
862
+ });
863
+ closeStream();
864
+ return;
865
+ }
866
+ armIdleTimer();
867
+ }
868
+ if (chunk.done) {
869
+ audit.terminal = true;
870
+ clearIdleTimer();
871
+ await emitRequestEvent(audit, {
872
+ phase: "failed",
873
+ responseObserved: true,
874
+ status: response.status,
875
+ ...providerRequestIdFields(response.headers)
876
+ });
877
+ closeStream();
878
+ return;
879
+ }
880
+ if (enqueued) return;
881
+ }
882
+ } catch (error) {
883
+ if (audit.terminal) {
884
+ errorStream(error);
885
+ return;
886
+ }
887
+ audit.terminal = true;
888
+ clearIdleTimer();
889
+ await reader.cancel(error).catch(() => void 0);
890
+ await emitRequestEvent(audit, {
891
+ phase: "failed",
892
+ responseObserved: true,
893
+ status: response.status,
894
+ ...providerRequestIdFields(response.headers)
895
+ }).catch(() => void 0);
896
+ errorStream(error);
539
897
  }
540
898
  },
541
- cancel(reason) {
542
- return reader.cancel(reason);
899
+ async cancel(reason) {
900
+ streamSettled = true;
901
+ if (!audit.terminal) {
902
+ audit.terminal = true;
903
+ clearIdleTimer();
904
+ await emitRequestEvent(audit, {
905
+ phase: "failed",
906
+ responseObserved: true,
907
+ status: response.status,
908
+ ...providerRequestIdFields(response.headers)
909
+ }).catch(() => void 0);
910
+ }
911
+ await reader.cancel(reason).catch(() => void 0);
543
912
  }
544
913
  });
545
914
  return new Response(body, {
@@ -548,11 +917,155 @@ async function normalizeResponse(response, onFinalContextUsage) {
548
917
  headers: response.headers
549
918
  });
550
919
  }
920
+ function sseProgress(block) {
921
+ for (const line of block.split("\n")) {
922
+ if (!line.startsWith("data:")) continue;
923
+ const data = line.slice(5).trim();
924
+ if (!data) continue;
925
+ if (data === "[DONE]") {
926
+ return { valid: true, eventType: "done", terminal: "completed", payload: null };
927
+ }
928
+ try {
929
+ const parsed = JSON.parse(data);
930
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
931
+ return { valid: false, eventType: null, terminal: null, payload: null };
932
+ }
933
+ const payload = parsed;
934
+ const rawType = payload.type;
935
+ if (typeof rawType !== "string" || !/^[a-z0-9_.-]{1,96}$/i.test(rawType)) {
936
+ return { valid: false, eventType: null, terminal: null, payload: null };
937
+ }
938
+ const type = rawType;
939
+ if (type === "response.completed") {
940
+ return { valid: true, eventType: type, terminal: "completed", payload };
941
+ }
942
+ if (type === "error" || type === "response.incomplete" || type === "response.failed" || type === "response.error") {
943
+ return { valid: true, eventType: type, terminal: "failed", payload };
944
+ }
945
+ return { valid: true, eventType: type, terminal: null, payload };
946
+ } catch {
947
+ return { valid: false, eventType: null, terminal: null, payload: null };
948
+ }
949
+ }
950
+ return { valid: false, eventType: null, terminal: null, payload: null };
951
+ }
952
+ function boundedTerminalErrorField(value, maxBytes) {
953
+ if (typeof value !== "string") return { truncated: false };
954
+ const encoder = new TextEncoder();
955
+ const encoded = encoder.encode(value);
956
+ if (encoded.byteLength <= maxBytes) return { value, truncated: false };
957
+ const markerBytes = encoder.encode(TERMINAL_ERROR_TRUNCATION_MARKER).byteLength;
958
+ let prefixEnd = Math.max(0, maxBytes - markerBytes);
959
+ while (prefixEnd > 0 && (encoded[prefixEnd] & 192) === 128) {
960
+ prefixEnd -= 1;
961
+ }
962
+ return {
963
+ value: `${new TextDecoder().decode(encoded.subarray(0, prefixEnd))}${TERMINAL_ERROR_TRUNCATION_MARKER}`,
964
+ truncated: true
965
+ };
966
+ }
967
+ function terminalErrorSource(payload, eventType) {
968
+ if (!payload) return null;
969
+ if (eventType === "error" || eventType === "response.error") {
970
+ return payload.error ?? payload;
971
+ }
972
+ const response = payload.response;
973
+ if (response && typeof response === "object" && !Array.isArray(response)) {
974
+ const nested = response.error;
975
+ if (nested !== void 0 && nested !== null) return nested;
976
+ }
977
+ return payload.error ?? payload;
978
+ }
979
+ function xaiSseTerminalError(source, audit, progress) {
980
+ const rawError = terminalErrorSource(progress.payload, progress.eventType);
981
+ const record2 = rawError && typeof rawError === "object" && !Array.isArray(rawError) ? rawError : {};
982
+ const eventTypeField = boundedTerminalErrorField(
983
+ progress.eventType,
984
+ MAX_TERMINAL_ERROR_FIELD_BYTES
985
+ );
986
+ const rawCode = record2.code ?? (typeof record2.type === "string" && record2.type !== eventTypeField.value && record2.type !== "error" ? record2.type : void 0);
987
+ const codeField = boundedTerminalErrorField(rawCode, MAX_TERMINAL_ERROR_FIELD_BYTES);
988
+ const messageField = boundedTerminalErrorField(
989
+ record2.message ?? (typeof rawError === "string" ? rawError : void 0),
990
+ MAX_TERMINAL_ERROR_MESSAGE_BYTES
991
+ );
992
+ const eventType = eventTypeField.value ?? "error";
993
+ const fallbackCode = eventType === "response.failed" ? "response_failed" : eventType === "response.incomplete" ? "response_incomplete" : "response_error";
994
+ const fallbackMessage = eventType === "response.incomplete" ? "The SuperGrok response was incomplete" : eventType === "response.failed" ? "The SuperGrok response failed" : "The SuperGrok response stream reported an error";
995
+ const message = messageField.value?.length ? messageField.value : fallbackMessage;
996
+ let code = codeField.value?.length ? codeField.value : fallbackCode;
997
+ const rateLimited = !NON_RETRYABLE_SSE_ERROR_CODES.has(code) && isXaiSubscriptionRateLimitDiagnostic({ code, message });
998
+ if (rateLimited && (code === fallbackCode || code === "response_error")) {
999
+ code = "rate_limit_exceeded";
1000
+ }
1001
+ const status = rateLimited ? 429 : NON_RETRYABLE_SSE_ERROR_CODES.has(code) ? 400 : 502;
1002
+ const headers = new Headers(source.headers);
1003
+ headers.set("content-type", "application/json");
1004
+ headers.set(XAI_SUBSCRIPTION_TRANSPORT_ERROR_HEADER, "1");
1005
+ headers.set("x-should-retry", "false");
1006
+ headers.delete("content-length");
1007
+ headers.delete("content-encoding");
1008
+ return new XaiSubscriptionStreamingTerminalError({
1009
+ message,
1010
+ code,
1011
+ eventType,
1012
+ requestId: audit.requestId,
1013
+ status,
1014
+ diagnosticTruncated: eventTypeField.truncated || codeField.truncated || messageField.truncated,
1015
+ headers
1016
+ });
1017
+ }
1018
+ function boundedStreamIdleTimeout(value) {
1019
+ const resolved = value ?? XAI_RESPONSE_STREAM_IDLE_TIMEOUT_MS;
1020
+ if (!Number.isSafeInteger(resolved) || resolved < 1 || resolved > MAX_STREAM_IDLE_TIMEOUT_MS) {
1021
+ throw new RangeError("SuperGrok response stream idle timeout is invalid");
1022
+ }
1023
+ return resolved;
1024
+ }
1025
+ function providerRequestId(headers) {
1026
+ return headers.get("x-request-id") ?? headers.get("request-id") ?? void 0;
1027
+ }
1028
+ function providerRequestIdFields(headers) {
1029
+ const value = providerRequestId(headers);
1030
+ return value ? { providerRequestId: value } : {};
1031
+ }
1032
+ function requestEventFor(audit, event) {
1033
+ const now = performance.now();
1034
+ return {
1035
+ requestId: audit.requestId,
1036
+ transportAttempt: audit.transportAttempt,
1037
+ model: audit.model,
1038
+ durationMs: Math.max(0, now - audit.startedAt),
1039
+ streamIdleTimeoutMs: audit.streamIdleTimeoutMs,
1040
+ eventCount: audit.eventCount,
1041
+ ...audit.lastEventType ? { lastEventType: audit.lastEventType } : {},
1042
+ ...audit.lastProgressAt !== null ? {
1043
+ lastProgressDurationMs: Math.max(0, audit.lastProgressAt - audit.startedAt)
1044
+ } : {},
1045
+ ...event
1046
+ };
1047
+ }
1048
+ function emitDiagnosticEvent(audit, event) {
1049
+ const observed = requestEventFor(audit, event);
1050
+ try {
1051
+ audit.ctx.onModelRequestDiagnostic?.(observed);
1052
+ } catch {
1053
+ }
1054
+ return observed;
1055
+ }
1056
+ async function emitRequestEvent(audit, event) {
1057
+ if (event.phase === "completed" || event.phase === "failed" || event.phase === "timed_out") {
1058
+ if (audit.terminalEventEmitted) return;
1059
+ audit.terminalEventEmitted = true;
1060
+ }
1061
+ const observed = emitDiagnosticEvent(audit, event);
1062
+ await audit.ctx.onModelRequestEvent?.(observed);
1063
+ }
551
1064
  function normalizeSseEvent(block, onFinalContextUsage) {
552
1065
  const lines = block.split("\n");
553
1066
  return lines.map((line) => {
554
1067
  if (!line.startsWith("data:")) return line;
555
- const data = line.slice(5).trimStart();
1068
+ const data = line.slice(5).trim();
556
1069
  if (!data || data === "[DONE]") return line;
557
1070
  try {
558
1071
  const normalized = normalizeXaiResponseEventJson(JSON.parse(data));
@@ -580,6 +1093,7 @@ function emitContextUsage(value, finalContextTokens, sink) {
580
1093
  function isXaiSubscriptionTransportError(error) {
581
1094
  let current = error;
582
1095
  for (let depth = 0; depth < 6 && current && typeof current === "object"; depth += 1) {
1096
+ if (current instanceof XaiSubscriptionStreamingTerminalError) return true;
583
1097
  const value = current;
584
1098
  const headers = value.headers;
585
1099
  if (headers && typeof headers === "object" && typeof headers.get === "function" && headers.get(XAI_SUBSCRIPTION_TRANSPORT_ERROR_HEADER) === "1") {
@@ -1195,6 +1709,7 @@ export {
1195
1709
  XAI_REFRESH_FALLBACK_MS,
1196
1710
  XAI_REFRESH_WINDOW_MS,
1197
1711
  XAI_RESPONSE_SDK_OUTER_TIMEOUT_MS,
1712
+ XAI_RESPONSE_STREAM_IDLE_TIMEOUT_MS,
1198
1713
  XAI_SUBSCRIPTION_AUTO_COMPACTION_PERCENT,
1199
1714
  XAI_SUBSCRIPTION_EFFECTIVE_CONTEXT_PERCENT,
1200
1715
  XAI_SUBSCRIPTION_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
@@ -1218,8 +1733,13 @@ export {
1218
1733
  XAI_VIDEO_POLL_REQUEST_TIMEOUT_MS,
1219
1734
  XAI_VIDEO_START_TIMEOUT_MS,
1220
1735
  XaiSubscriptionError,
1736
+ XaiSubscriptionHostedToolContinuationError,
1221
1737
  XaiSubscriptionReloginRequired,
1738
+ XaiSubscriptionStreamIdleTimeoutError,
1739
+ XaiSubscriptionStreamingTerminalError,
1222
1740
  XaiSubscriptionTransientError,
1741
+ classifyXaiSubscriptionStreamIdleTimeoutError,
1742
+ classifyXaiSubscriptionStreamingTerminalError,
1223
1743
  decodeXaiJwtPayload,
1224
1744
  fetchXaiProxyJson,
1225
1745
  fetchXaiSubscriptionModels,
@@ -1228,6 +1748,8 @@ export {
1228
1748
  generateXaiSubscriptionImage,
1229
1749
  generateXaiSubscriptionVideo,
1230
1750
  getXaiSubscriptionVideoStatus,
1751
+ isXaiSubscriptionHostedToolContinuationError,
1752
+ isXaiSubscriptionRateLimitDiagnostic,
1231
1753
  isXaiSubscriptionTransportError,
1232
1754
  normalizeXaiResponseEventJson,
1233
1755
  normalizeXaiSubscriptionRequestBody,
@@ -1238,6 +1760,7 @@ export {
1238
1760
  runBoundedXaiOperation,
1239
1761
  startXaiSubscriptionVideoWithBody,
1240
1762
  xaiAccessTokenExpiry,
1763
+ xaiIdentityFromDeviceTokens,
1241
1764
  xaiSubscriptionFetch,
1242
1765
  xaiSubscriptionProxyHeaders,
1243
1766
  xaiSubscriptionRequestStorage