@qoniai/qoni 0.4.0 → 0.4.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/dist/index.js CHANGED
@@ -768,11 +768,11 @@ var RunHandle = class {
768
768
  }
769
769
  /** Drive the run to a terminal state and return the settled result. */
770
770
  async wait(opts = {}) {
771
- const { signal, timedOut } = withTimeout(opts.signal, opts.timeoutMs);
771
+ const { signal, timedOut, dispose } = withTimeout(opts.signal, opts.timeoutMs);
772
772
  let lastEventId;
773
773
  let eventIdAtLastClose;
774
774
  let sawCleanClose = false;
775
- let terminalPayload;
775
+ let terminalDetail;
776
776
  let terminalDoneReason;
777
777
  let screenshotIndex = 0;
778
778
  try {
@@ -780,24 +780,28 @@ var RunHandle = class {
780
780
  for await (const event of this.events({
781
781
  signal,
782
782
  lastEventId,
783
- onWireEvent: opts.onWireEvent,
783
+ onWireEvent: (wire) => waitWithSignal(() => {
784
+ if (wire.id !== void 0) lastEventId = wire.id;
785
+ return opts.onWireEvent?.(wire);
786
+ }, signal),
784
787
  onReconnect: opts.onReconnect
785
788
  })) {
786
- if (event.raw.id) lastEventId = event.raw.id;
787
- await opts.onEvent?.(event);
789
+ await waitWithSignal(() => opts.onEvent?.(event), signal);
788
790
  if (event.type === "screenshot") {
789
- await opts.onScreenshot?.(event.image, screenshotIndex++);
791
+ await waitWithSignal(() => opts.onScreenshot?.(event.image, screenshotIndex++), signal);
790
792
  } else if (event.type === "interaction") {
791
- await opts.onInteraction?.(this.interactionHandle(event.data), event);
793
+ await waitWithSignal(() => opts.onInteraction?.(this.interactionHandle(event.data), event), signal);
792
794
  }
793
795
  if (event.isTerminal) {
794
- terminalPayload = isJsonObject(event.raw.data) ? event.raw.data : void 0;
795
796
  if (event.type === "done") terminalDoneReason = event.data.terminalReason || void 0;
796
797
  break settled;
797
798
  }
798
799
  }
799
- const detail2 = await this.ops.getDetail();
800
- if (isTerminalRunStatus(detail2.status)) break;
800
+ const detail2 = await waitWithSignal(() => this.ops.getDetail(signal), signal);
801
+ if (isTerminalRunStatus(normalizeRunStatus(this.id, detail2).status)) {
802
+ terminalDetail = detail2;
803
+ break;
804
+ }
801
805
  if (sawCleanClose && lastEventId === eventIdAtLastClose) {
802
806
  throw new QoniError(
803
807
  `run event stream ended before a terminal event while the run is still "${String(detail2.status)}" \u2014 re-attach or poll status()`,
@@ -807,6 +811,11 @@ var RunHandle = class {
807
811
  sawCleanClose = true;
808
812
  eventIdAtLastClose = lastEventId;
809
813
  }
814
+ const detail = terminalDetail ?? await waitWithSignal(() => this.ops.getDetail(signal), signal);
815
+ this.#adoptSessionRef(detail);
816
+ const result = settleRunResult(this.id, detail, [], terminalDoneReason);
817
+ result.artifacts = this.ops.listArtifacts ? await waitWithSignal(() => this.ops.listArtifacts(signal), signal) : [];
818
+ return result;
810
819
  } catch (err) {
811
820
  if (timedOut() && !opts.signal?.aborted) {
812
821
  throw new QoniTimeoutError(
@@ -815,17 +824,9 @@ var RunHandle = class {
815
824
  );
816
825
  }
817
826
  throw err;
827
+ } finally {
828
+ dispose();
818
829
  }
819
- let detail;
820
- try {
821
- detail = await this.ops.getDetail();
822
- } catch (err) {
823
- if (!terminalPayload) throw err;
824
- detail = terminalPayload;
825
- }
826
- this.#adoptSessionRef(detail);
827
- const artifacts = this.ops.listArtifacts ? await this.ops.listArtifacts() : [];
828
- return settleRunResult(this.id, detail, artifacts, terminalDoneReason);
829
830
  }
830
831
  /**
831
832
  * Wrap an {@link Interaction} (from `event.data` of an `interaction` event)
@@ -878,15 +879,12 @@ function normalizeRunStatus(id, detail) {
878
879
  function settleRunResult(runId, detail, artifacts, fallbackTerminalReason) {
879
880
  const terminalReason = (typeof detail.terminal_reason === "string" ? detail.terminal_reason : void 0) ?? fallbackTerminalReason;
880
881
  const isTaskSuccessful = typeof detail.is_task_successful === "boolean" ? detail.is_task_successful : void 0;
881
- let status;
882
- if (isTerminalRunStatus(detail.status)) {
883
- status = detail.status;
884
- } else if (terminalReason === "canceled") {
885
- status = "canceled";
886
- } else if (terminalReason === "failed" || terminalReason === "expired" || isTaskSuccessful === false) {
887
- status = "failed";
888
- } else {
889
- status = "succeeded";
882
+ const status = normalizeRunStatus(runId, detail).status;
883
+ if (!isTerminalRunStatus(status)) {
884
+ throw new QoniError(
885
+ "run detail did not confirm a terminal state \u2014 re-attach or poll status()",
886
+ { code: "upstream.failed", retryable: true, body: detail }
887
+ );
890
888
  }
891
889
  return {
892
890
  runId,
@@ -913,19 +911,40 @@ function isVideoFrame(wire) {
913
911
  return type === "browser_video_frame" || type === "run.browser_video_frame";
914
912
  }
915
913
  function withTimeout(signal, timeoutMs) {
916
- if (!timeoutMs) return { signal, timedOut: () => false };
914
+ if (!timeoutMs) return { signal, timedOut: () => false, dispose: () => {
915
+ } };
917
916
  const controller = new AbortController();
918
917
  let fired = false;
919
918
  const timer = setTimeout(() => {
920
919
  fired = true;
921
920
  controller.abort();
922
921
  }, timeoutMs);
923
- controller.signal.addEventListener("abort", () => clearTimeout(timer), { once: true });
922
+ const onAbort = () => controller.abort(signal?.reason);
923
+ const dispose = () => {
924
+ clearTimeout(timer);
925
+ signal?.removeEventListener("abort", onAbort);
926
+ };
927
+ controller.signal.addEventListener("abort", dispose, { once: true });
924
928
  if (signal) {
925
- if (signal.aborted) controller.abort();
926
- else signal.addEventListener("abort", () => controller.abort(), { once: true });
929
+ if (signal.aborted) onAbort();
930
+ else signal.addEventListener("abort", onAbort, { once: true });
927
931
  }
928
- return { signal: controller.signal, timedOut: () => fired };
932
+ return { signal: controller.signal, timedOut: () => fired, dispose };
933
+ }
934
+ function waitWithSignal(operation, signal) {
935
+ if (!signal) return Promise.resolve().then(operation);
936
+ return new Promise((resolve, reject) => {
937
+ const onAbort = () => reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
938
+ if (signal.aborted) {
939
+ onAbort();
940
+ return;
941
+ }
942
+ signal.addEventListener("abort", onAbort, { once: true });
943
+ Promise.resolve().then(() => {
944
+ signal.throwIfAborted();
945
+ return operation();
946
+ }).then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
947
+ });
929
948
  }
930
949
 
931
950
  // src/deep-research.ts
@@ -940,6 +959,7 @@ function createDeepResearchNamespace(transport) {
940
959
  `/deep_research/runs/${encodeURIComponent(input.runId)}`,
941
960
  input.token,
942
961
  {
962
+ signal: input.signal,
943
963
  requiredScopes: ["webagent.deep_research:read"]
944
964
  }
945
965
  ),
@@ -985,6 +1005,7 @@ function createDeepResearchNamespace(transport) {
985
1005
  `/deep_research/runs/${encodeURIComponent(input.runId)}/artifacts`,
986
1006
  input.token,
987
1007
  {
1008
+ signal: input.signal,
988
1009
  requiredScopes: ["webagent.deep_research:read"]
989
1010
  }
990
1011
  ),
@@ -999,7 +1020,7 @@ function createDeepResearchNamespace(transport) {
999
1020
  };
1000
1021
  function buildOps(token, runId) {
1001
1022
  return {
1002
- getDetail: async () => asRecord((await api.get({ token, runId })).data),
1023
+ getDetail: async (signal) => asRecord((await api.get({ token, runId, signal })).data),
1003
1024
  streamEvents: (opts) => api.events({
1004
1025
  token,
1005
1026
  runId,
@@ -1019,8 +1040,8 @@ function createDeepResearchNamespace(transport) {
1019
1040
  );
1020
1041
  },
1021
1042
  cancel: async () => asRecord((await api.cancel({ token, runId })).data),
1022
- listArtifacts: async () => {
1023
- const res = await api.listArtifacts({ token, runId });
1043
+ listArtifacts: async (signal) => {
1044
+ const res = await api.listArtifacts({ token, runId, signal });
1024
1045
  const items = Array.isArray(res.data?.items) ? res.data.items : [];
1025
1046
  return items.filter(isJsonObject).map((item) => toArtifact(item, token, runId));
1026
1047
  }
@@ -1140,6 +1161,7 @@ function createDoAnythingNamespace(transport) {
1140
1161
  `/do_anything/runs/${encodeURIComponent(input.runId)}`,
1141
1162
  input.token,
1142
1163
  {
1164
+ signal: input.signal,
1143
1165
  requiredScopes: ["webagent.do_anything:read"]
1144
1166
  }
1145
1167
  ),
@@ -1197,7 +1219,7 @@ function createDoAnythingNamespace(transport) {
1197
1219
  };
1198
1220
  function buildOps(token, runId, capture) {
1199
1221
  return {
1200
- getDetail: async () => asRecord2((await api.getRun({ token, runId })).data),
1222
+ getDetail: async (signal) => asRecord2((await api.getRun({ token, runId, signal })).data),
1201
1223
  streamEvents: (opts) => api.events({
1202
1224
  token,
1203
1225
  runId,
@@ -1791,6 +1813,7 @@ function createWebSearchNamespace(transport) {
1791
1813
  `/web_search/runs/${encodeURIComponent(input.runId)}`,
1792
1814
  input.token,
1793
1815
  {
1816
+ signal: input.signal,
1794
1817
  requiredScopes: ["webagent.web_search:read"]
1795
1818
  }
1796
1819
  ),
@@ -1816,7 +1839,7 @@ function createWebSearchNamespace(transport) {
1816
1839
  };
1817
1840
  function buildOps(token, runId) {
1818
1841
  return {
1819
- getDetail: async () => asRecord4((await api.get({ token, runId })).data),
1842
+ getDetail: async (signal) => asRecord4((await api.get({ token, runId, signal })).data),
1820
1843
  streamEvents: (opts) => api.events({
1821
1844
  token,
1822
1845
  runId,
@@ -1909,8 +1932,8 @@ function renameKeys5(value, mapping) {
1909
1932
  }
1910
1933
 
1911
1934
  // src/client.ts
1912
- var DEFAULT_QONI_HOST = "https://anima.eazo.ai/dashboard";
1913
- var QoniAgentKit = class {
1935
+ var DEFAULT_QONI_HOST = "https://dashboard.qoni.ai";
1936
+ var Qoni = class {
1914
1937
  constructor(options) {
1915
1938
  this.options = options;
1916
1939
  const accessKey = options.accessKey ?? options.accessKeyId;
@@ -2089,7 +2112,9 @@ var QoniAgentKit = class {
2089
2112
  }
2090
2113
  }
2091
2114
  async webAgentJson(method, path, token, payload = {}) {
2115
+ payload.signal?.throwIfAborted();
2092
2116
  const runtimeToken = await this.productTokenFor("webagent", token, payload.requiredScopes);
2117
+ payload.signal?.throwIfAborted();
2093
2118
  const baseUrl = await this.baseUrlFor("webagent");
2094
2119
  return this.jsonRequest(
2095
2120
  baseUrl,
@@ -2100,9 +2125,11 @@ var QoniAgentKit = class {
2100
2125
  // Binary GET against the WebAgent API — artifact content downloads. JSON
2101
2126
  // error payloads still map to typed QoniErrors.
2102
2127
  async webAgentBytes(path, token, payload = {}) {
2128
+ payload.signal?.throwIfAborted();
2103
2129
  const runtimeToken = await this.productTokenFor("webagent", token, payload.requiredScopes);
2130
+ payload.signal?.throwIfAborted();
2104
2131
  const baseUrl = await this.baseUrlFor("webagent");
2105
- const response = await this.fetchWithTimeout(
2132
+ return this.fetchWithTimeout(
2106
2133
  urlWithBasePath(baseUrl, this.webAgentPath(runtimeToken, path), payload.query),
2107
2134
  {
2108
2135
  method: "GET",
@@ -2111,20 +2138,22 @@ var QoniAgentKit = class {
2111
2138
  authorization: `Bearer ${runtimeToken}`,
2112
2139
  ...payload.headers || {}
2113
2140
  }
2114
- }
2141
+ },
2142
+ async (response, signal) => {
2143
+ if (!response.ok) {
2144
+ throw errorFromPayload(
2145
+ response.status,
2146
+ await readJson(response, signal),
2147
+ `Qoni request failed with HTTP ${response.status}`
2148
+ );
2149
+ }
2150
+ return {
2151
+ bytes: await readBody(response, signal),
2152
+ mime: response.headers.get("content-type") || "application/octet-stream"
2153
+ };
2154
+ },
2155
+ payload.signal
2115
2156
  );
2116
- if (!response.ok) {
2117
- throw errorFromPayload(
2118
- response.status,
2119
- await readJson(response),
2120
- `Qoni request failed with HTTP ${response.status}`
2121
- );
2122
- }
2123
- const buffer = await response.arrayBuffer();
2124
- return {
2125
- bytes: new Uint8Array(buffer),
2126
- mime: response.headers.get("content-type") || "application/octet-stream"
2127
- };
2128
2157
  }
2129
2158
  async *webAgentSSE(path, token, payload = {}) {
2130
2159
  const runtimeToken = await this.productTokenFor("webagent", token, payload.requiredScopes);
@@ -2164,15 +2193,16 @@ var QoniAgentKit = class {
2164
2193
  });
2165
2194
  }
2166
2195
  async jsonRequest(baseUrl, pathname, options) {
2167
- const response = await this.fetchWithTimeout(
2196
+ const { response, payload } = await this.fetchWithTimeout(
2168
2197
  urlWithBasePath(baseUrl, pathname, options.query),
2169
2198
  {
2170
2199
  method: options.method,
2171
2200
  headers: requestHeaders(options),
2172
2201
  body: requestBody(options.body)
2173
- }
2202
+ },
2203
+ async (response2, signal) => ({ response: response2, payload: await readJson(response2, signal) }),
2204
+ options.signal
2174
2205
  );
2175
- const payload = await readJson(response);
2176
2206
  if (!response.ok) {
2177
2207
  throw errorFromPayload(
2178
2208
  response.status,
@@ -2222,45 +2252,55 @@ var QoniAgentKit = class {
2222
2252
  }
2223
2253
  }
2224
2254
  async *sseConnectOnce(baseUrl, pathname, options) {
2225
- const response = await this.fetchWithTimeout(
2226
- urlWithBasePath(baseUrl, pathname, options.query),
2227
- {
2228
- method: "GET",
2229
- headers: {
2230
- accept: "text/event-stream",
2231
- authorization: `Bearer ${options.token}`,
2232
- ...options.headers || {},
2233
- ...options.lastEventId ? { "last-event-id": options.lastEventId } : {}
2234
- }
2235
- },
2236
- options.signal,
2237
- { streamBody: true }
2238
- );
2239
- if (!response.ok) {
2240
- throw errorFromPayload(
2241
- response.status,
2242
- await readJson(response),
2243
- `Qoni stream failed with HTTP ${response.status}`
2244
- );
2245
- }
2246
- if (!response.body) {
2247
- throw errorFromPayload(502, void 0, "Qoni stream response has no body");
2248
- }
2249
- const reader = response.body.getReader();
2255
+ let cleanup;
2256
+ let reader;
2257
+ const onAbort = () => {
2258
+ void reader?.cancel(options.signal?.reason).catch(() => void 0);
2259
+ };
2250
2260
  const decoder = new TextDecoder();
2251
2261
  let buffer = "";
2252
2262
  try {
2263
+ const response = await this.fetchWithTimeout(
2264
+ urlWithBasePath(baseUrl, pathname, options.query),
2265
+ {
2266
+ method: "GET",
2267
+ headers: {
2268
+ accept: "text/event-stream",
2269
+ authorization: `Bearer ${options.token}`,
2270
+ ...options.headers || {},
2271
+ ...options.lastEventId ? { "last-event-id": options.lastEventId } : {}
2272
+ }
2273
+ },
2274
+ async (response2, signal) => {
2275
+ if (!response2.ok) {
2276
+ throw errorFromPayload(
2277
+ response2.status,
2278
+ await readJson(response2, signal),
2279
+ `Qoni stream failed with HTTP ${response2.status}`
2280
+ );
2281
+ }
2282
+ return response2;
2283
+ },
2284
+ options.signal,
2285
+ { streamCleanup: (dispose) => {
2286
+ cleanup = dispose;
2287
+ } }
2288
+ );
2289
+ if (!response.body) {
2290
+ throw errorFromPayload(502, void 0, "Qoni stream response has no body");
2291
+ }
2292
+ reader = response.body.getReader();
2293
+ options.signal?.addEventListener("abort", onAbort, { once: true });
2253
2294
  while (true) {
2254
- if (options.signal?.aborted) {
2255
- await reader.cancel().catch(() => void 0);
2256
- throw options.signal.reason || new DOMException("Aborted", "AbortError");
2257
- }
2295
+ options.signal?.throwIfAborted();
2258
2296
  const { done, value } = await reader.read();
2297
+ options.signal?.throwIfAborted();
2259
2298
  if (done) break;
2260
2299
  buffer += decoder.decode(value, { stream: true });
2261
2300
  const chunks = buffer.split(/\r?\n\r?\n/);
2262
2301
  buffer = chunks.pop() || "";
2263
2302
  for (const chunk of chunks) {
2303
+ options.signal?.throwIfAborted();
2264
2304
  const event = parseSSEEvent(chunk);
2265
2305
  if (event) yield event;
2266
2306
  }
@@ -2268,10 +2308,16 @@ var QoniAgentKit = class {
2268
2308
  const finalEvent = parseSSEEvent(buffer);
2269
2309
  if (finalEvent) yield finalEvent;
2270
2310
  } finally {
2271
- reader.releaseLock();
2311
+ cleanup?.();
2312
+ options.signal?.removeEventListener("abort", onAbort);
2313
+ void reader?.cancel().catch(() => void 0);
2314
+ try {
2315
+ reader?.releaseLock();
2316
+ } catch {
2317
+ }
2272
2318
  }
2273
2319
  }
2274
- async fetchWithTimeout(input, init, signal, opts) {
2320
+ async fetchWithTimeout(input, init, consume, signal, opts) {
2275
2321
  if (signal?.aborted) throw signal.reason || new DOMException("Aborted", "AbortError");
2276
2322
  const controller = new AbortController();
2277
2323
  const resolved = resolveLocalGenauthRequest(input);
@@ -2286,24 +2332,46 @@ var QoniAgentKit = class {
2286
2332
  didTimeout = true;
2287
2333
  controller.abort();
2288
2334
  }, this.timeoutMs);
2335
+ let response;
2289
2336
  try {
2290
- return await this.fetchImpl(resolved.url, { ...requestInit, signal: controller.signal });
2337
+ response = await new Promise((resolve, reject) => {
2338
+ const onAbort = () => reject(controller.signal.reason);
2339
+ controller.signal.addEventListener("abort", onAbort, { once: true });
2340
+ Promise.resolve().then(() => {
2341
+ controller.signal.throwIfAborted();
2342
+ return this.fetchImpl(resolved.url, { ...requestInit, signal: controller.signal });
2343
+ }).then((response2) => {
2344
+ if (controller.signal.aborted) {
2345
+ void response2.body?.cancel(controller.signal.reason).catch(() => void 0);
2346
+ reject(controller.signal.reason);
2347
+ } else {
2348
+ resolve(response2);
2349
+ }
2350
+ }, reject).finally(() => controller.signal.removeEventListener("abort", onAbort));
2351
+ });
2352
+ const result = await consume(response, controller.signal);
2353
+ controller.signal.throwIfAborted();
2354
+ return result;
2291
2355
  } catch (error) {
2292
- if (isAbortError(error) && didTimeout || isConnectTimeoutError(error)) {
2356
+ void response?.body?.cancel().catch(() => void 0);
2357
+ if (signal?.aborted) throw signal.reason;
2358
+ if (didTimeout || isConnectTimeoutError(error)) {
2293
2359
  throw timeoutError(error);
2294
2360
  }
2295
2361
  if (isFetchNetworkError(error)) throw networkError(error);
2296
2362
  throw error;
2297
2363
  } finally {
2298
2364
  clearTimeout(timeout);
2299
- if (!opts?.streamBody) signal?.removeEventListener("abort", abortFromSignal);
2365
+ const cleanup = () => signal?.removeEventListener("abort", abortFromSignal);
2366
+ if (opts?.streamCleanup) opts.streamCleanup(cleanup);
2367
+ else cleanup();
2300
2368
  }
2301
2369
  }
2302
2370
  async baseUrlFor(service) {
2303
2371
  const explicit = this.explicitBaseUrlFor(service);
2304
2372
  if (explicit) return explicit;
2305
- const runtime = await this.runtimeConfig();
2306
2373
  if (service === "qoni") return this.host;
2374
+ const runtime = await this.runtimeConfig();
2307
2375
  const hostOrigin = originBaseUrl(this.host);
2308
2376
  if (service === "genauth") return runtime.genauthBaseUrl ?? hostOrigin;
2309
2377
  if (service === "gumem") return runtime.gumemBaseUrl ?? hostOrigin;
@@ -2352,7 +2420,7 @@ var QoniAgentKit = class {
2352
2420
  pathname,
2353
2421
  {}
2354
2422
  );
2355
- const response = await this.fetchWithTimeout(
2423
+ const { response, payload } = await this.fetchWithTimeout(
2356
2424
  urlWithBasePath(this.host, pathname),
2357
2425
  {
2358
2426
  method: "GET",
@@ -2360,9 +2428,9 @@ var QoniAgentKit = class {
2360
2428
  accept: "application/json",
2361
2429
  ...headers
2362
2430
  }
2363
- }
2431
+ },
2432
+ async (response2, signal) => ({ response: response2, payload: await readJson(response2, signal) })
2364
2433
  );
2365
- const payload = await readJson(response);
2366
2434
  if (!response.ok) {
2367
2435
  throw errorFromPayload(
2368
2436
  response.status,
@@ -2456,18 +2524,52 @@ function requestBody(body) {
2456
2524
  function isBodyInit(value) {
2457
2525
  return typeof value === "string" || value instanceof ArrayBuffer || value instanceof Blob || value instanceof FormData || value instanceof URLSearchParams;
2458
2526
  }
2459
- async function readJson(response) {
2527
+ async function readBody(response, signal) {
2528
+ if (!response.body) {
2529
+ signal.throwIfAborted();
2530
+ return new Uint8Array();
2531
+ }
2532
+ const reader = response.body.getReader();
2533
+ const onAbort = () => {
2534
+ void reader.cancel(signal.reason).catch(() => void 0);
2535
+ };
2536
+ signal.addEventListener("abort", onAbort, { once: true });
2537
+ try {
2538
+ const chunks = [];
2539
+ let size = 0;
2540
+ for (; ; ) {
2541
+ signal.throwIfAborted();
2542
+ const { done, value } = await reader.read();
2543
+ signal.throwIfAborted();
2544
+ if (done) break;
2545
+ chunks.push(value);
2546
+ size += value.byteLength;
2547
+ }
2548
+ const bytes = new Uint8Array(size);
2549
+ let offset = 0;
2550
+ for (const chunk of chunks) {
2551
+ bytes.set(chunk, offset);
2552
+ offset += chunk.byteLength;
2553
+ }
2554
+ return bytes;
2555
+ } finally {
2556
+ signal.removeEventListener("abort", onAbort);
2557
+ void reader.cancel().catch(() => void 0);
2558
+ reader.releaseLock();
2559
+ }
2560
+ }
2561
+ async function readJson(response, signal) {
2460
2562
  const contentType = response.headers.get("content-type")?.toLowerCase() || "";
2461
- if (contentType.includes("ndjson") || contentType.includes("jsonl")) {
2462
- const body = await response.text();
2463
- if (!body.trim()) return [];
2464
- try {
2563
+ const body = new TextDecoder().decode(await readBody(response, signal));
2564
+ try {
2565
+ if (contentType.includes("ndjson") || contentType.includes("jsonl")) {
2566
+ if (!body.trim()) return [];
2465
2567
  return body.split(/\r?\n/).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
2466
- } catch {
2467
- return void 0;
2468
2568
  }
2569
+ return JSON.parse(body);
2570
+ } catch {
2571
+ return void 0;
2469
2572
  }
2470
- return response.json().catch(() => void 0);
2471
2573
  }
2472
2574
  function normalizeResponse(payload, _service) {
2473
2575
  if (isJsonObject(payload) && ("data" in payload || "meta" in payload)) {
@@ -2710,6 +2812,7 @@ function isRetryableStreamError(err) {
2710
2812
  if (err && typeof err === "object") {
2711
2813
  const e = err;
2712
2814
  if (e.name === "AbortError") return false;
2815
+ if (e.status === 408) return true;
2713
2816
  if (typeof e.retryable === "boolean") return e.retryable;
2714
2817
  if (typeof e.status === "number") {
2715
2818
  return e.status >= 500 || e.status === 408 || e.status === 429;
@@ -2816,9 +2919,6 @@ function normalizeDelegateAgentTokenResponse(response) {
2816
2919
  }
2817
2920
  };
2818
2921
  }
2819
- function isAbortError(error) {
2820
- return error instanceof DOMException && error.name === "AbortError";
2821
- }
2822
2922
  function isConnectTimeoutError(error) {
2823
2923
  const cause = errorCause(error);
2824
2924
  return errorCode(cause) === "UND_ERR_CONNECT_TIMEOUT" || errorName(cause) === "ConnectTimeoutError";
@@ -2843,8 +2943,7 @@ export {
2843
2943
  InteractionStatuses,
2844
2944
  InteractionTypes,
2845
2945
  MonitorHandle,
2846
- QoniAgentKit as Qoni,
2847
- QoniAgentKit,
2946
+ Qoni,
2848
2947
  QoniAuthError,
2849
2948
  QoniDelegationRequiredError,
2850
2949
  QoniError,