@athenaintel/react 0.59.0 → 0.60.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/README.md +52 -19
- package/dist/agent-runtime/src/composer-markdown.cjs +0 -16
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.js +1 -17
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/named-agents.js +1 -1
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
- package/dist/agent-runtime/src/offline-status.d.ts +27 -0
- package/dist/agent-runtime/src/offline-status.js.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +7 -0
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +7 -0
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/chat/AthenaChat.cjs +15 -5
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.js +16 -6
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat-ui/index.cjs +2 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +1 -0
- package/dist/chat-ui/index.js +2 -0
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +9 -3
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.js +9 -3
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs +18 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.d.ts +10 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js +19 -3
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +9 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +6 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js +9 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs +89 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs.map +1 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.d.ts +8 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js +89 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js.map +1 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs +140 -116
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.d.ts +46 -12
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js +141 -117
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +37 -6
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +39 -8
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs +12 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.d.ts +8 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.js +12 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.js.map +1 -0
- package/dist/collab/client.cjs +24 -1
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +16 -0
- package/dist/collab/client.js +24 -1
- package/dist/collab/client.js.map +1 -1
- package/dist/composer/attached-references.js +1 -1
- package/dist/composer/staged-message-metadata.cjs +12 -0
- package/dist/composer/staged-message-metadata.cjs.map +1 -0
- package/dist/composer/staged-message-metadata.d.ts +15 -0
- package/dist/composer/staged-message-metadata.js +12 -0
- package/dist/composer/staged-message-metadata.js.map +1 -0
- package/dist/data/athena-request.cjs +2 -0
- package/dist/data/athena-request.cjs.map +1 -1
- package/dist/data/athena-request.js +2 -0
- package/dist/data/athena-request.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +4 -3
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.js +4 -3
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/anchors/parse.cjs +11 -1
- package/dist/references/src/anchors/parse.cjs.map +1 -1
- package/dist/references/src/anchors/parse.js +11 -1
- package/dist/references/src/anchors/parse.js.map +1 -1
- package/dist/references/src/anchors/schemas.d.ts +1 -0
- package/dist/references/src/anchors/serialize.cjs +1 -0
- package/dist/references/src/anchors/serialize.cjs.map +1 -1
- package/dist/references/src/anchors/serialize.js +1 -0
- package/dist/references/src/anchors/serialize.js.map +1 -1
- package/dist/references/src/anchors/types.cjs.map +1 -1
- package/dist/references/src/anchors/types.d.ts +9 -0
- package/dist/references/src/anchors/types.js.map +1 -1
- package/dist/references/src/schemas.d.ts +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.cjs +6 -8
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.js +6 -8
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/threads/statewire-thread-list.cjs +14 -2
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.d.ts +11 -2
- package/dist/threads/statewire-thread-list.js +14 -2
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/tools/drive-tool-uis.cjs +8 -4
- package/dist/tools/drive-tool-uis.cjs.map +1 -1
- package/dist/tools/drive-tool-uis.d.ts +5 -4
- package/dist/tools/drive-tool-uis.js +9 -5
- package/dist/tools/drive-tool-uis.js.map +1 -1
- package/dist/version.cjs +4 -0
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.ts +9 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -1
- package/dist/workbench/live-desktop-api.cjs +2 -1
- package/dist/workbench/live-desktop-api.cjs.map +1 -1
- package/dist/workbench/live-desktop-api.js +2 -1
- package/dist/workbench/live-desktop-api.js.map +1 -1
- package/dist/workbench/session-workspace-api.cjs +7 -2
- package/dist/workbench/session-workspace-api.cjs.map +1 -1
- package/dist/workbench/session-workspace-api.d.ts +10 -0
- package/dist/workbench/session-workspace-api.js +7 -2
- package/dist/workbench/session-workspace-api.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getAthenaApiBaseUrl } from "../collab/mint.js";
|
|
2
2
|
import { sendWithCredentialRenewal } from "../runtime/credential-renewal.js";
|
|
3
3
|
import { graphQLErrorEntries, AthenaApiError, AthenaApiErrorKind, graphQLErrorCode, restErrorDetail, isAthenaApiError } from "./athena-api-error.js";
|
|
4
|
+
import { ATHENA_REACT_CLIENT, ATHENA_CLIENT_HEADER } from "../version.js";
|
|
4
5
|
const ATHENA_REQUEST_TIMEOUT_MS = 3e4;
|
|
5
6
|
const RATE_LIMIT_MAX_RETRIES = 2;
|
|
6
7
|
const RATE_LIMIT_MAX_WAIT_MS = 3e4;
|
|
@@ -65,6 +66,7 @@ function prepare(config, path, options) {
|
|
|
65
66
|
}
|
|
66
67
|
const headers = {
|
|
67
68
|
Accept: "application/json",
|
|
69
|
+
[ATHENA_CLIENT_HEADER]: ATHENA_REACT_CLIENT,
|
|
68
70
|
...options.json !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
69
71
|
...options.headers
|
|
70
72
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"athena-request.js","sources":["../../src/data/athena-request.ts"],"sourcesContent":["/**\n * The SDK's authenticated transport to agora, without React. Every request:\n *\n * - presents the provider's credential: the live token from `getToken`, renewed\n * once after a 401 (`sendWithCredentialRenewal`, the statewire transport's\n * `staleAuth` contract), else the API key;\n * - goes to the provider's `backendUrl`, and only there: a path must start\n * with `/`;\n * - waits out a 429 as agora's `Retry-After` asks, a bounded number of times;\n * - is abandoned after `timeoutMs`;\n * - fails as an `AthenaApiError`, except a request the caller cancelled, which\n * rejects with the abort's reason as `fetch` does.\n *\n * `useAthenaFetch` binds it to the provider, and the data hooks run on it.\n */\nimport { getAthenaApiBaseUrl } from '../collab/mint';\nimport { sendWithCredentialRenewal } from '../runtime/credential-renewal';\nimport type {\n AthenaStatewireTokenGetter,\n StatewireAuthSource,\n} from '../runtime/statewire-auth-headers';\nimport {\n AthenaApiError,\n AthenaApiErrorKind,\n graphQLErrorCode,\n graphQLErrorEntries,\n isAthenaApiError,\n restErrorDetail,\n} from './athena-api-error';\n\n/** Where a request goes and the credential it presents: the fields of `useAthenaConfig()` it reads. */\nexport interface AthenaRequestConfig {\n /** The Agora API base (`useAthenaConfig().backendUrl`). */\n backendUrl: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n}\n\nexport type AthenaQueryParamValue = string | number | boolean | null | undefined;\n\n/** Query-string parameters: `null` and `undefined` are left out, an array repeats its key. */\nexport type AthenaQueryParams = Readonly<\n Record<string, AthenaQueryParamValue | readonly (string | number | boolean)[]>\n>;\n\n/** A body the SDK can send again (a 401's renewal and a 429's retry resend it): never a stream. */\nexport type AthenaRequestBody = Exclude<BodyInit, ReadableStream>;\n\n/** How a 429 is waited out. */\nexport interface AthenaRateLimitRetry {\n /** How many times the request is sent again (default 2). */\n maxRetries?: number;\n /**\n * The longest the SDK waits before sending again, in ms (default 30 000).\n * When agora asks for longer, the request fails at once with the 429, whose\n * `retryAfterMs` says when to come back.\n */\n maxWaitMs?: number;\n}\n\nexport interface AthenaRequestOptions {\n /** Default `GET`, or `POST` when the request has a body. */\n method?: string;\n params?: AthenaQueryParams;\n /** A body sent as JSON (`Content-Type: application/json`). Not with `body`. */\n json?: unknown;\n /** A body sent as is (`FormData`, `Blob`, text…). Not with `json`. */\n body?: AthenaRequestBody;\n /**\n * Extra headers. A request presents the provider's credential and no other:\n * `Authorization`, `X-API-KEY`, `Cookie`, `Proxy-Authorization` and\n * `X-Athena-View-As` are refused, in any letter case.\n */\n headers?: Readonly<Record<string, string>>;\n /** Cancels the request (and a wait between its attempts); it then rejects with the abort's reason. */\n signal?: AbortSignal;\n /** How long one attempt may take, in ms (default 30 000); `0` waits as long as it takes. */\n timeoutMs?: number;\n /** How a 429 is waited out; `false` fails at once. */\n rateLimitRetry?: AthenaRateLimitRetry | false;\n}\n\nexport const ATHENA_REQUEST_TIMEOUT_MS = 30_000;\nconst RATE_LIMIT_MAX_RETRIES = 2;\nconst RATE_LIMIT_MAX_WAIT_MS = 30_000;\n/** The first wait for a 429 that says nothing of when to come back; it doubles for each retry. */\nconst RATE_LIMIT_FIRST_BACKOFF_MS = 1_000;\n/** What agora's per-user limiter answers, before it runs anything (`user_request_rate_limit.py`). */\nconst RATE_LIMITED_CODE = 'RATE_LIMITED';\nconst SAFE_METHODS: ReadonlySet<string> = new Set(['GET', 'HEAD', 'OPTIONS']);\n/**\n * Headers that say who a request acts as, or through whose eyes\n * (`X-Athena-View-As`, agora's view-as lens): only the provider sets those.\n */\nconst IDENTITY_HEADERS: ReadonlySet<string> = new Set([\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n 'x-athena-view-as',\n]);\n\n/** The request as sent: its method, its URL and its path for errors (no query string). */\ninterface PreparedRequest {\n method: string;\n url: string;\n path: string;\n headers: Record<string, string>;\n body: AthenaRequestBody | undefined;\n}\n\nfunction refuse(message: string, method: string, path: string): AthenaApiError {\n return new AthenaApiError({ kind: AthenaApiErrorKind.Request, message, method, path });\n}\n\nfunction prepare(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions,\n): PreparedRequest {\n const hasBody = options.json !== undefined || options.body !== undefined;\n const method = (options.method ?? (hasBody ? 'POST' : 'GET')).toUpperCase();\n const errorPath = path.split('?')[0] ?? path;\n // A path, never a URL: a request carries the person's credential, so it goes\n // to the provider's backend and nowhere else.\n if (!path.startsWith('/') || path.startsWith('//')) {\n throw refuse(\n `A request path must start with a single \"/\" (it goes to the provider's backendUrl): ${JSON.stringify(path)}`,\n method,\n errorPath,\n );\n }\n if (options.json !== undefined && options.body !== undefined) {\n throw refuse('A request takes `json` or `body`, not both', method, errorPath);\n }\n // Header names are case-insensitive: a lowercase `authorization` would be\n // sent beside the provider's and could act as someone else, whose answer the\n // data hooks would then cache under the provider's identity.\n for (const name of Object.keys(options.headers ?? {})) {\n if (IDENTITY_HEADERS.has(name.toLowerCase())) {\n throw refuse(\n `A request may not set ${name}: it presents the provider's credential and no other`,\n method,\n errorPath,\n );\n }\n }\n const base = getAthenaApiBaseUrl(config.backendUrl);\n let url: URL;\n let backendOrigin: string;\n try {\n backendOrigin = new URL(base).origin;\n url = new URL(`${base}${path}`);\n } catch (error) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.Request,\n message: `The provider's backendUrl is not a URL: ${JSON.stringify(config.backendUrl)}`,\n method,\n path: errorPath,\n cause: error,\n });\n }\n if (url.origin !== backendOrigin) {\n throw refuse(`A request path must stay on the provider's backendUrl: ${JSON.stringify(path)}`, method, errorPath);\n }\n for (const [name, value] of Object.entries(options.params ?? {})) {\n for (const item of Array.isArray(value) ? value : [value]) {\n if (item !== null && item !== undefined) url.searchParams.append(name, String(item));\n }\n }\n // TODO(#54756): name the app on every call (the provider's `appId`) once agora\n // records it and limits by it.\n const headers: Record<string, string> = {\n Accept: 'application/json',\n ...(options.json !== undefined ? { 'Content-Type': 'application/json' } : {}),\n ...options.headers,\n };\n return {\n method,\n url: url.toString(),\n path: errorPath,\n headers,\n body: options.json !== undefined ? JSON.stringify(options.json) : options.body,\n };\n}\n\n/** The provider's credential; a `getToken` that throws fails the request as `credential`. */\nfunction credentialSource(config: AthenaRequestConfig, request: PreparedRequest): StatewireAuthSource {\n const getToken = config.getToken;\n return {\n apiKey: config.apiKey,\n token: config.token,\n ...(getToken\n ? {\n getToken: async (options?: { force?: boolean }) => {\n try {\n return await getToken(options);\n } catch (error) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.Credential,\n message: 'The provider could not resolve a credential for the request',\n method: request.method,\n path: request.path,\n cause: error,\n });\n }\n },\n }\n : {}),\n };\n}\n\n/** One attempt's signal: the caller's cancel, and its own timeout. */\ninterface Attempt {\n signal: AbortSignal;\n timedOut: () => boolean;\n /**\n * Stops the timeout. `keepCancel` leaves the caller's signal able to cancel\n * the body the caller still reads.\n */\n settle: (options?: { keepCancel?: boolean }) => void;\n}\n\nfunction startAttempt(parent: AbortSignal | undefined, timeoutMs: number): Attempt {\n const controller = new AbortController();\n let timedOut = false;\n const forward = () => controller.abort(parent?.reason);\n if (parent?.aborted) controller.abort(parent.reason);\n else parent?.addEventListener('abort', forward, { once: true });\n const timer =\n timeoutMs > 0 && Number.isFinite(timeoutMs)\n ? setTimeout(() => {\n timedOut = true;\n controller.abort(new DOMException(`No answer within ${timeoutMs} ms`, 'TimeoutError'));\n }, timeoutMs)\n : undefined;\n return {\n signal: controller.signal,\n timedOut: () => timedOut,\n settle: ({ keepCancel = false } = {}) => {\n if (timer !== undefined) clearTimeout(timer);\n if (!keepCancel) parent?.removeEventListener('abort', forward);\n },\n };\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n return signal.reason ?? new DOMException('The request was cancelled', 'AbortError');\n}\n\n/** A fetch or a body read that threw: the caller's cancel as is, else a typed failure. */\nfunction failureOf({\n error,\n attempt,\n signal,\n request,\n timeoutMs,\n reading,\n}: {\n error: unknown;\n attempt: Attempt;\n signal: AbortSignal | undefined;\n request: PreparedRequest;\n timeoutMs: number;\n reading: boolean;\n}): unknown {\n if (signal?.aborted) return abortReason(signal);\n if (isAthenaApiError(error)) return error;\n if (attempt.timedOut()) {\n return new AthenaApiError({\n kind: AthenaApiErrorKind.Timeout,\n message: `Athena did not answer within ${timeoutMs} ms`,\n method: request.method,\n path: request.path,\n cause: error,\n });\n }\n return new AthenaApiError({\n kind: reading ? AthenaApiErrorKind.Response : AthenaApiErrorKind.Network,\n message: reading ? 'The answer was cut off before it was read' : 'Athena could not be reached',\n method: request.method,\n path: request.path,\n cause: error,\n });\n}\n\n/**\n * How long agora asked the caller to wait, in ms: the `Retry-After` header\n * (seconds or a date), else the `retryAfterSeconds` of a rate-limit refusal's\n * body. `null` when it said nothing it is possible to read.\n */\nexport function retryAfterMsOf(response: Response, body: unknown, now: number = Date.now()): number | null {\n const header = response.headers.get('retry-after')?.trim();\n if (header) {\n if (/^\\d+$/.test(header)) return Number(header) * 1000;\n const date = Date.parse(header);\n if (Number.isFinite(date)) return Math.max(0, date - now);\n }\n for (const entry of graphQLErrorEntries(body)) {\n const seconds = entry.extensions?.retryAfterSeconds;\n if (typeof seconds === 'number' && Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n }\n const seconds = restErrorDetail(body).retryAfterSeconds;\n return seconds !== null && seconds >= 0 ? seconds * 1000 : null;\n}\n\n/** JSON when it reads as JSON, the text otherwise; `undefined` for nothing. */\nfunction lenientBody(text: string): unknown {\n if (text.length === 0) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** How much of an error body that is not JSON (a proxy's error page) an error keeps. */\nconst TEXT_DETAIL_LIMIT = 1_000;\n\n/**\n * The `AthenaApiError` an error status answers, its body read for agora's code\n * and message. A body the attempt's timeout cut off is a timeout (a stalled\n * 5xx must not read as a 5xx, which a read retries), and the caller's cancel\n * stays a cancel; a body that fails otherwise is left out.\n */\nasync function httpError(\n response: Response,\n request: PreparedRequest,\n { signal, attempt, timeoutMs }: { signal: AbortSignal | undefined; attempt: Attempt; timeoutMs: number },\n): Promise<AthenaApiError> {\n let body: unknown;\n try {\n body = lenientBody(await response.text());\n } catch (error) {\n if (signal?.aborted || attempt.timedOut()) {\n throw failureOf({ error, attempt, signal, request, timeoutMs, reading: true });\n }\n body = undefined;\n }\n const statusLine = response.statusText\n ? `${response.status} ${response.statusText}`\n : `HTTP ${response.status}`;\n const common = {\n kind: AthenaApiErrorKind.Http,\n status: response.status,\n retryAfterMs: retryAfterMsOf(response, body),\n method: request.method,\n path: request.path,\n };\n // Not JSON: a gateway's or proxy's page, never agora's words.\n if (typeof body === 'string') {\n return new AthenaApiError({ ...common, message: statusLine, detail: body.slice(0, TEXT_DETAIL_LIMIT) });\n }\n const errors = graphQLErrorEntries(body);\n const rest = restErrorDetail(body);\n return new AthenaApiError({\n ...common,\n code: graphQLErrorCode(errors[0]) ?? rest.code,\n message: errors[0]?.message ?? rest.message ?? statusLine,\n errors,\n detail: errors.length > 0 ? undefined : rest.detail,\n });\n}\n\n/**\n * How long to wait before sending a refused request again, or `null` to fail\n * now. A write goes again only when agora's limiter refused it: that refusal\n * comes before anything runs, so the write cannot apply twice.\n */\nfunction rateLimitWaitMs({\n error,\n retry,\n method,\n policy,\n}: {\n error: AthenaApiError;\n retry: number;\n method: string;\n policy: AthenaRateLimitRetry | false | undefined;\n}): number | null {\n if (policy === false) return null;\n if (retry >= (policy?.maxRetries ?? RATE_LIMIT_MAX_RETRIES)) return null;\n if (!SAFE_METHODS.has(method) && error.code !== RATE_LIMITED_CODE) return null;\n const waitMs =\n error.retryAfterMs ?? RATE_LIMIT_FIRST_BACKOFF_MS * 2 ** retry * (0.8 + Math.random() * 0.4);\n return waitMs <= (policy?.maxWaitMs ?? RATE_LIMIT_MAX_WAIT_MS) ? waitMs : null;\n}\n\nfunction sleep(ms: number, signal: AbortSignal | undefined): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortReason(signal));\n return;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const onAbort = () => {\n clearTimeout(timer);\n if (signal) reject(abortReason(signal));\n };\n timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/**\n * Send until agora answers with something other than a 429 the SDK waits out.\n * Answers that response (any status) with the attempt that got it, whose\n * timeout still runs: the caller settles it once the body is read.\n */\nasync function exchange(\n config: AthenaRequestConfig,\n request: PreparedRequest,\n options: AthenaRequestOptions,\n): Promise<{ response: Response; attempt: Attempt; timeoutMs: number }> {\n const timeoutMs = options.timeoutMs ?? ATHENA_REQUEST_TIMEOUT_MS;\n const source = credentialSource(config, request);\n for (let retry = 0; ; retry += 1) {\n const attempt = startAttempt(options.signal, timeoutMs);\n let response: Response;\n try {\n response = await sendWithCredentialRenewal(source, (credentialHeaders) =>\n fetch(request.url, {\n method: request.method,\n headers: { ...request.headers, ...credentialHeaders },\n body: request.body ?? null,\n signal: attempt.signal,\n }),\n );\n } catch (error) {\n attempt.settle();\n throw failureOf({ error, attempt, signal: options.signal, request, timeoutMs, reading: false });\n }\n if (response.status !== 429) return { response, attempt, timeoutMs };\n let refusal: AthenaApiError;\n try {\n refusal = await httpError(response, request, { signal: options.signal, attempt, timeoutMs });\n } finally {\n attempt.settle();\n }\n const waitMs = rateLimitWaitMs({ error: refusal, retry, method: request.method, policy: options.rateLimitRetry });\n if (waitMs === null) throw refusal;\n await sleep(waitMs, options.signal);\n }\n}\n\n/**\n * Send a request and answer its response once agora answered 2xx, for a body\n * the caller reads itself (a file, a stream). An error status throws\n * `AthenaApiError`. The timeout covers the wait for the answer, not the body.\n */\nexport async function athenaFetchResponse(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions = {},\n): Promise<Response> {\n const request = prepare(config, path, options);\n const { response, attempt, timeoutMs } = await exchange(config, request, options);\n if (response.ok) {\n attempt.settle({ keepCancel: true });\n return response;\n }\n try {\n throw await httpError(response, request, { signal: options.signal, attempt, timeoutMs });\n } finally {\n attempt.settle();\n }\n}\n\n/** A 2xx answer's body: JSON when agora says it is JSON, text otherwise, `undefined` for none. */\nasync function athenaFetchBody(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions,\n): Promise<{ status: number; body: unknown; request: PreparedRequest }> {\n const request = prepare(config, path, options);\n const { response, attempt, timeoutMs } = await exchange(config, request, options);\n try {\n if (!response.ok) throw await httpError(response, request, { signal: options.signal, attempt, timeoutMs });\n let text: string;\n try {\n text = await response.text();\n } catch (error) {\n throw failureOf({ error, attempt, signal: options.signal, request, timeoutMs, reading: true });\n }\n if (text.length === 0) return { status: response.status, body: undefined, request };\n const contentType = response.headers.get('content-type') ?? '';\n if (!/[/+]json\\b/i.test(contentType)) {\n return { status: response.status, body: contentType ? text : lenientBody(text), request };\n }\n try {\n return { status: response.status, body: JSON.parse(text), request };\n } catch (error) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.Response,\n status: response.status,\n message: 'Agora answered with JSON that could not be read',\n method: request.method,\n path: request.path,\n cause: error,\n });\n }\n } finally {\n attempt.settle();\n }\n}\n\n/**\n * Send a request and answer its body: JSON when agora says it is JSON, text\n * otherwise, `undefined` for an empty answer. `T` is the caller's word for\n * what the route answers; nothing checks it.\n */\nexport async function athenaFetchJson<T = unknown>(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions = {},\n): Promise<T> {\n const { body } = await athenaFetchBody(config, path, options);\n return body as T;\n}\n\nexport type AthenaGraphQLVariables = Readonly<Record<string, unknown>>;\n\n/**\n * A GraphQL document whose result and variables types travel with it, as\n * graphql-codegen's `TypedDocumentString` (its client preset with\n * `documentMode: 'string'`) carries them.\n */\nexport interface AthenaTypedDocument<TData, TVariables> {\n toString(): string;\n __apiType?: (variables: TVariables) => TData;\n}\n\n/** A GraphQL document: its text, or a typed document that names its result and variables. */\nexport type AthenaGraphQLDocument<TData = unknown, TVariables = AthenaGraphQLVariables> =\n | string\n | AthenaTypedDocument<TData, TVariables>;\n\nexport interface AthenaGraphQLRequestOptions\n extends Pick<AthenaRequestOptions, 'headers' | 'signal' | 'timeoutMs' | 'rateLimitRetry'> {\n /** The operation to run when the document holds several. */\n operationName?: string;\n}\n\n/**\n * Run one GraphQL operation on agora's `/graphql` and answer its `data`. An\n * answer with errors throws `AthenaApiError` (`kind: 'graphql'`, `code` the\n * first error's `extensions.code`), as does one with no data.\n */\nexport async function athenaGraphQL<TData = unknown, TVariables extends object = AthenaGraphQLVariables>(\n config: AthenaRequestConfig,\n document: AthenaGraphQLDocument<TData, TVariables>,\n variables?: TVariables,\n options: AthenaGraphQLRequestOptions = {},\n): Promise<TData> {\n const { operationName, ...requestOptions } = options;\n // TODO(#54756): send a registered operation's id (`documentId`) instead of its\n // text once agora allowlists each app's operations.\n const { status, body, request } = await athenaFetchBody(config, '/graphql', {\n ...requestOptions,\n method: 'POST',\n json: {\n query: String(document),\n variables: variables ?? {},\n ...(operationName ? { operationName } : {}),\n },\n });\n const errors = graphQLErrorEntries(body);\n const first = errors[0];\n if (first) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.GraphQL,\n status,\n code: graphQLErrorCode(first),\n message: first.message,\n errors,\n method: request.method,\n path: request.path,\n });\n }\n const data: unknown =\n typeof body === 'object' && body !== null ? Reflect.get(body, 'data') : undefined;\n if (data === undefined || data === null) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.GraphQL,\n status,\n message: 'The GraphQL answer had no data',\n method: request.method,\n path: request.path,\n });\n }\n return data as TData;\n}\n\n/** One operation a GraphQL document defines. */\nexport interface AthenaGraphQLOperation {\n type: 'query' | 'mutation' | 'subscription';\n /** `null` for an anonymous operation. */\n name: string | null;\n}\n\nconst GRAPHQL_IGNORED = /(?:[\\s,]+|#[^\\n\\r]*)+/y;\nconst GRAPHQL_NAME = /[_A-Za-z][_0-9A-Za-z]*/y;\n\n/**\n * The operations a GraphQL document defines, in order, fragments left out. A\n * lexical read that skips strings, comments, variable definitions (default\n * values included), directives and selection sets; it never validates the\n * document, which agora does.\n */\nexport function graphQLOperationsOf(document: string): AthenaGraphQLOperation[] {\n const operations: AthenaGraphQLOperation[] = [];\n let at = 0;\n const skipIgnored = () => {\n GRAPHQL_IGNORED.lastIndex = at;\n if (GRAPHQL_IGNORED.exec(document)) at = GRAPHQL_IGNORED.lastIndex;\n };\n const readName = (): string | null => {\n GRAPHQL_NAME.lastIndex = at;\n const name = GRAPHQL_NAME.exec(document)?.[0] ?? null;\n if (name !== null) at = GRAPHQL_NAME.lastIndex;\n return name;\n };\n /** Past the balanced `(…)` or `{…}` that opens at `at`, strings and comments included. */\n const skipGroup = () => {\n const open = document[at];\n const close = open === '(' ? ')' : '}';\n let depth = 0;\n while (at < document.length) {\n if (document.startsWith('\"\"\"', at)) {\n const end = document.indexOf('\"\"\"', at + 3);\n at = end === -1 ? document.length : end + 3;\n continue;\n }\n const char = document[at];\n if (char === '\"') {\n at += 1;\n while (at < document.length && document[at] !== '\"' && document[at] !== '\\n') {\n at += document[at] === '\\\\' ? 2 : 1;\n }\n at += 1;\n continue;\n }\n if (char === '#') {\n while (at < document.length && document[at] !== '\\n') at += 1;\n continue;\n }\n at += 1;\n if (char === open) depth += 1;\n else if (char === close) {\n depth -= 1;\n if (depth === 0) return;\n }\n }\n };\n /** Past a definition's header (variables, type condition, directives) and its selection set. */\n const skipDefinition = () => {\n while (at < document.length) {\n skipIgnored();\n const char = document[at];\n if (char === '{') {\n skipGroup();\n return;\n }\n if (char === '(') skipGroup();\n else at += 1;\n }\n };\n for (;;) {\n skipIgnored();\n if (at >= document.length) return operations;\n if (document[at] === '{') {\n operations.push({ type: 'query', name: null });\n skipGroup();\n continue;\n }\n const word = readName();\n if (word === 'query' || word === 'mutation' || word === 'subscription') {\n skipIgnored();\n operations.push({ type: word, name: readName() });\n }\n skipDefinition();\n }\n}\n\n/**\n * The operation a request runs: the one `operationName` names, else the\n * document's only one. `null` when neither picks one (agora refuses those).\n */\nexport function selectedGraphQLOperation(\n document: string,\n operationName?: string | null,\n): AthenaGraphQLOperation | null {\n const operations = graphQLOperationsOf(document);\n if (operationName) return operations.find((operation) => operation.name === operationName) ?? null;\n return operations.length === 1 ? (operations[0] ?? null) : null;\n}\n\n/**\n * An authenticated fetch bound to one configuration (see `useAthenaFetch`).\n * Called, it answers the route's body; `raw` answers the response itself and\n * `graphql` runs one GraphQL operation.\n */\nexport interface AthenaFetch {\n <T = unknown>(path: string, options?: AthenaRequestOptions): Promise<T>;\n raw(path: string, options?: AthenaRequestOptions): Promise<Response>;\n graphql<TData = unknown, TVariables extends object = AthenaGraphQLVariables>(\n document: AthenaGraphQLDocument<TData, TVariables>,\n variables?: TVariables,\n options?: AthenaGraphQLRequestOptions,\n ): Promise<TData>;\n}\n\n/**\n * `useAthenaFetch` without React: the transport bound to `config`, read once.\n * Hosts outside a component can pass `useAthenaConfig()`'s value along.\n */\nexport function createAthenaFetch(config: AthenaRequestConfig): AthenaFetch {\n const bound: AthenaRequestConfig = {\n backendUrl: config.backendUrl,\n apiKey: config.apiKey,\n token: config.token,\n getToken: config.getToken,\n };\n return Object.assign(\n <T = unknown>(path: string, options?: AthenaRequestOptions) =>\n athenaFetchJson<T>(bound, path, options),\n {\n raw: (path: string, options?: AthenaRequestOptions) => athenaFetchResponse(bound, path, options),\n graphql: <TData = unknown, TVariables extends object = AthenaGraphQLVariables>(\n document: AthenaGraphQLDocument<TData, TVariables>,\n variables?: TVariables,\n options?: AthenaGraphQLRequestOptions,\n ) => athenaGraphQL<TData, TVariables>(bound, document, variables, options),\n },\n );\n}\n"],"names":["seconds"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"athena-request.js","sources":["../../src/data/athena-request.ts"],"sourcesContent":["/**\n * The SDK's authenticated transport to agora, without React. Every request:\n *\n * - presents the provider's credential: the live token from `getToken`, renewed\n * once after a 401 (`sendWithCredentialRenewal`, the statewire transport's\n * `staleAuth` contract), else the API key;\n * - goes to the provider's `backendUrl`, and only there: a path must start\n * with `/`;\n * - waits out a 429 as agora's `Retry-After` asks, a bounded number of times;\n * - is abandoned after `timeoutMs`;\n * - fails as an `AthenaApiError`, except a request the caller cancelled, which\n * rejects with the abort's reason as `fetch` does.\n *\n * `useAthenaFetch` binds it to the provider, and the data hooks run on it.\n */\nimport { getAthenaApiBaseUrl } from '../collab/mint';\nimport { sendWithCredentialRenewal } from '../runtime/credential-renewal';\nimport type {\n AthenaStatewireTokenGetter,\n StatewireAuthSource,\n} from '../runtime/statewire-auth-headers';\nimport {\n AthenaApiError,\n AthenaApiErrorKind,\n graphQLErrorCode,\n graphQLErrorEntries,\n isAthenaApiError,\n restErrorDetail,\n} from './athena-api-error';\nimport { ATHENA_CLIENT_HEADER, ATHENA_REACT_CLIENT } from '../version';\n\n/** Where a request goes and the credential it presents: the fields of `useAthenaConfig()` it reads. */\nexport interface AthenaRequestConfig {\n /** The Agora API base (`useAthenaConfig().backendUrl`). */\n backendUrl: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n}\n\nexport type AthenaQueryParamValue = string | number | boolean | null | undefined;\n\n/** Query-string parameters: `null` and `undefined` are left out, an array repeats its key. */\nexport type AthenaQueryParams = Readonly<\n Record<string, AthenaQueryParamValue | readonly (string | number | boolean)[]>\n>;\n\n/** A body the SDK can send again (a 401's renewal and a 429's retry resend it): never a stream. */\nexport type AthenaRequestBody = Exclude<BodyInit, ReadableStream>;\n\n/** How a 429 is waited out. */\nexport interface AthenaRateLimitRetry {\n /** How many times the request is sent again (default 2). */\n maxRetries?: number;\n /**\n * The longest the SDK waits before sending again, in ms (default 30 000).\n * When agora asks for longer, the request fails at once with the 429, whose\n * `retryAfterMs` says when to come back.\n */\n maxWaitMs?: number;\n}\n\nexport interface AthenaRequestOptions {\n /** Default `GET`, or `POST` when the request has a body. */\n method?: string;\n params?: AthenaQueryParams;\n /** A body sent as JSON (`Content-Type: application/json`). Not with `body`. */\n json?: unknown;\n /** A body sent as is (`FormData`, `Blob`, text…). Not with `json`. */\n body?: AthenaRequestBody;\n /**\n * Extra headers. A request presents the provider's credential and no other:\n * `Authorization`, `X-API-KEY`, `Cookie`, `Proxy-Authorization` and\n * `X-Athena-View-As` are refused, in any letter case.\n */\n headers?: Readonly<Record<string, string>>;\n /** Cancels the request (and a wait between its attempts); it then rejects with the abort's reason. */\n signal?: AbortSignal;\n /** How long one attempt may take, in ms (default 30 000); `0` waits as long as it takes. */\n timeoutMs?: number;\n /** How a 429 is waited out; `false` fails at once. */\n rateLimitRetry?: AthenaRateLimitRetry | false;\n}\n\nexport const ATHENA_REQUEST_TIMEOUT_MS = 30_000;\nconst RATE_LIMIT_MAX_RETRIES = 2;\nconst RATE_LIMIT_MAX_WAIT_MS = 30_000;\n/** The first wait for a 429 that says nothing of when to come back; it doubles for each retry. */\nconst RATE_LIMIT_FIRST_BACKOFF_MS = 1_000;\n/** What agora's per-user limiter answers, before it runs anything (`user_request_rate_limit.py`). */\nconst RATE_LIMITED_CODE = 'RATE_LIMITED';\nconst SAFE_METHODS: ReadonlySet<string> = new Set(['GET', 'HEAD', 'OPTIONS']);\n/**\n * Headers that say who a request acts as, or through whose eyes\n * (`X-Athena-View-As`, agora's view-as lens): only the provider sets those.\n */\nconst IDENTITY_HEADERS: ReadonlySet<string> = new Set([\n 'authorization',\n 'proxy-authorization',\n 'cookie',\n 'x-api-key',\n 'x-athena-view-as',\n]);\n\n/** The request as sent: its method, its URL and its path for errors (no query string). */\ninterface PreparedRequest {\n method: string;\n url: string;\n path: string;\n headers: Record<string, string>;\n body: AthenaRequestBody | undefined;\n}\n\nfunction refuse(message: string, method: string, path: string): AthenaApiError {\n return new AthenaApiError({ kind: AthenaApiErrorKind.Request, message, method, path });\n}\n\nfunction prepare(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions,\n): PreparedRequest {\n const hasBody = options.json !== undefined || options.body !== undefined;\n const method = (options.method ?? (hasBody ? 'POST' : 'GET')).toUpperCase();\n const errorPath = path.split('?')[0] ?? path;\n // A path, never a URL: a request carries the person's credential, so it goes\n // to the provider's backend and nowhere else.\n if (!path.startsWith('/') || path.startsWith('//')) {\n throw refuse(\n `A request path must start with a single \"/\" (it goes to the provider's backendUrl): ${JSON.stringify(path)}`,\n method,\n errorPath,\n );\n }\n if (options.json !== undefined && options.body !== undefined) {\n throw refuse('A request takes `json` or `body`, not both', method, errorPath);\n }\n // Header names are case-insensitive: a lowercase `authorization` would be\n // sent beside the provider's and could act as someone else, whose answer the\n // data hooks would then cache under the provider's identity.\n for (const name of Object.keys(options.headers ?? {})) {\n if (IDENTITY_HEADERS.has(name.toLowerCase())) {\n throw refuse(\n `A request may not set ${name}: it presents the provider's credential and no other`,\n method,\n errorPath,\n );\n }\n }\n const base = getAthenaApiBaseUrl(config.backendUrl);\n let url: URL;\n let backendOrigin: string;\n try {\n backendOrigin = new URL(base).origin;\n url = new URL(`${base}${path}`);\n } catch (error) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.Request,\n message: `The provider's backendUrl is not a URL: ${JSON.stringify(config.backendUrl)}`,\n method,\n path: errorPath,\n cause: error,\n });\n }\n if (url.origin !== backendOrigin) {\n throw refuse(`A request path must stay on the provider's backendUrl: ${JSON.stringify(path)}`, method, errorPath);\n }\n for (const [name, value] of Object.entries(options.params ?? {})) {\n for (const item of Array.isArray(value) ? value : [value]) {\n if (item !== null && item !== undefined) url.searchParams.append(name, String(item));\n }\n }\n // TODO(#54756): name the app on every call (the provider's `appId`) once agora\n // records it and limits by it.\n const headers: Record<string, string> = {\n Accept: 'application/json',\n [ATHENA_CLIENT_HEADER]: ATHENA_REACT_CLIENT,\n ...(options.json !== undefined ? { 'Content-Type': 'application/json' } : {}),\n ...options.headers,\n };\n return {\n method,\n url: url.toString(),\n path: errorPath,\n headers,\n body: options.json !== undefined ? JSON.stringify(options.json) : options.body,\n };\n}\n\n/** The provider's credential; a `getToken` that throws fails the request as `credential`. */\nfunction credentialSource(config: AthenaRequestConfig, request: PreparedRequest): StatewireAuthSource {\n const getToken = config.getToken;\n return {\n apiKey: config.apiKey,\n token: config.token,\n ...(getToken\n ? {\n getToken: async (options?: { force?: boolean }) => {\n try {\n return await getToken(options);\n } catch (error) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.Credential,\n message: 'The provider could not resolve a credential for the request',\n method: request.method,\n path: request.path,\n cause: error,\n });\n }\n },\n }\n : {}),\n };\n}\n\n/** One attempt's signal: the caller's cancel, and its own timeout. */\ninterface Attempt {\n signal: AbortSignal;\n timedOut: () => boolean;\n /**\n * Stops the timeout. `keepCancel` leaves the caller's signal able to cancel\n * the body the caller still reads.\n */\n settle: (options?: { keepCancel?: boolean }) => void;\n}\n\nfunction startAttempt(parent: AbortSignal | undefined, timeoutMs: number): Attempt {\n const controller = new AbortController();\n let timedOut = false;\n const forward = () => controller.abort(parent?.reason);\n if (parent?.aborted) controller.abort(parent.reason);\n else parent?.addEventListener('abort', forward, { once: true });\n const timer =\n timeoutMs > 0 && Number.isFinite(timeoutMs)\n ? setTimeout(() => {\n timedOut = true;\n controller.abort(new DOMException(`No answer within ${timeoutMs} ms`, 'TimeoutError'));\n }, timeoutMs)\n : undefined;\n return {\n signal: controller.signal,\n timedOut: () => timedOut,\n settle: ({ keepCancel = false } = {}) => {\n if (timer !== undefined) clearTimeout(timer);\n if (!keepCancel) parent?.removeEventListener('abort', forward);\n },\n };\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n return signal.reason ?? new DOMException('The request was cancelled', 'AbortError');\n}\n\n/** A fetch or a body read that threw: the caller's cancel as is, else a typed failure. */\nfunction failureOf({\n error,\n attempt,\n signal,\n request,\n timeoutMs,\n reading,\n}: {\n error: unknown;\n attempt: Attempt;\n signal: AbortSignal | undefined;\n request: PreparedRequest;\n timeoutMs: number;\n reading: boolean;\n}): unknown {\n if (signal?.aborted) return abortReason(signal);\n if (isAthenaApiError(error)) return error;\n if (attempt.timedOut()) {\n return new AthenaApiError({\n kind: AthenaApiErrorKind.Timeout,\n message: `Athena did not answer within ${timeoutMs} ms`,\n method: request.method,\n path: request.path,\n cause: error,\n });\n }\n return new AthenaApiError({\n kind: reading ? AthenaApiErrorKind.Response : AthenaApiErrorKind.Network,\n message: reading ? 'The answer was cut off before it was read' : 'Athena could not be reached',\n method: request.method,\n path: request.path,\n cause: error,\n });\n}\n\n/**\n * How long agora asked the caller to wait, in ms: the `Retry-After` header\n * (seconds or a date), else the `retryAfterSeconds` of a rate-limit refusal's\n * body. `null` when it said nothing it is possible to read.\n */\nexport function retryAfterMsOf(response: Response, body: unknown, now: number = Date.now()): number | null {\n const header = response.headers.get('retry-after')?.trim();\n if (header) {\n if (/^\\d+$/.test(header)) return Number(header) * 1000;\n const date = Date.parse(header);\n if (Number.isFinite(date)) return Math.max(0, date - now);\n }\n for (const entry of graphQLErrorEntries(body)) {\n const seconds = entry.extensions?.retryAfterSeconds;\n if (typeof seconds === 'number' && Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n }\n const seconds = restErrorDetail(body).retryAfterSeconds;\n return seconds !== null && seconds >= 0 ? seconds * 1000 : null;\n}\n\n/** JSON when it reads as JSON, the text otherwise; `undefined` for nothing. */\nfunction lenientBody(text: string): unknown {\n if (text.length === 0) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** How much of an error body that is not JSON (a proxy's error page) an error keeps. */\nconst TEXT_DETAIL_LIMIT = 1_000;\n\n/**\n * The `AthenaApiError` an error status answers, its body read for agora's code\n * and message. A body the attempt's timeout cut off is a timeout (a stalled\n * 5xx must not read as a 5xx, which a read retries), and the caller's cancel\n * stays a cancel; a body that fails otherwise is left out.\n */\nasync function httpError(\n response: Response,\n request: PreparedRequest,\n { signal, attempt, timeoutMs }: { signal: AbortSignal | undefined; attempt: Attempt; timeoutMs: number },\n): Promise<AthenaApiError> {\n let body: unknown;\n try {\n body = lenientBody(await response.text());\n } catch (error) {\n if (signal?.aborted || attempt.timedOut()) {\n throw failureOf({ error, attempt, signal, request, timeoutMs, reading: true });\n }\n body = undefined;\n }\n const statusLine = response.statusText\n ? `${response.status} ${response.statusText}`\n : `HTTP ${response.status}`;\n const common = {\n kind: AthenaApiErrorKind.Http,\n status: response.status,\n retryAfterMs: retryAfterMsOf(response, body),\n method: request.method,\n path: request.path,\n };\n // Not JSON: a gateway's or proxy's page, never agora's words.\n if (typeof body === 'string') {\n return new AthenaApiError({ ...common, message: statusLine, detail: body.slice(0, TEXT_DETAIL_LIMIT) });\n }\n const errors = graphQLErrorEntries(body);\n const rest = restErrorDetail(body);\n return new AthenaApiError({\n ...common,\n code: graphQLErrorCode(errors[0]) ?? rest.code,\n message: errors[0]?.message ?? rest.message ?? statusLine,\n errors,\n detail: errors.length > 0 ? undefined : rest.detail,\n });\n}\n\n/**\n * How long to wait before sending a refused request again, or `null` to fail\n * now. A write goes again only when agora's limiter refused it: that refusal\n * comes before anything runs, so the write cannot apply twice.\n */\nfunction rateLimitWaitMs({\n error,\n retry,\n method,\n policy,\n}: {\n error: AthenaApiError;\n retry: number;\n method: string;\n policy: AthenaRateLimitRetry | false | undefined;\n}): number | null {\n if (policy === false) return null;\n if (retry >= (policy?.maxRetries ?? RATE_LIMIT_MAX_RETRIES)) return null;\n if (!SAFE_METHODS.has(method) && error.code !== RATE_LIMITED_CODE) return null;\n const waitMs =\n error.retryAfterMs ?? RATE_LIMIT_FIRST_BACKOFF_MS * 2 ** retry * (0.8 + Math.random() * 0.4);\n return waitMs <= (policy?.maxWaitMs ?? RATE_LIMIT_MAX_WAIT_MS) ? waitMs : null;\n}\n\nfunction sleep(ms: number, signal: AbortSignal | undefined): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortReason(signal));\n return;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const onAbort = () => {\n clearTimeout(timer);\n if (signal) reject(abortReason(signal));\n };\n timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/**\n * Send until agora answers with something other than a 429 the SDK waits out.\n * Answers that response (any status) with the attempt that got it, whose\n * timeout still runs: the caller settles it once the body is read.\n */\nasync function exchange(\n config: AthenaRequestConfig,\n request: PreparedRequest,\n options: AthenaRequestOptions,\n): Promise<{ response: Response; attempt: Attempt; timeoutMs: number }> {\n const timeoutMs = options.timeoutMs ?? ATHENA_REQUEST_TIMEOUT_MS;\n const source = credentialSource(config, request);\n for (let retry = 0; ; retry += 1) {\n const attempt = startAttempt(options.signal, timeoutMs);\n let response: Response;\n try {\n response = await sendWithCredentialRenewal(source, (credentialHeaders) =>\n fetch(request.url, {\n method: request.method,\n headers: { ...request.headers, ...credentialHeaders },\n body: request.body ?? null,\n signal: attempt.signal,\n }),\n );\n } catch (error) {\n attempt.settle();\n throw failureOf({ error, attempt, signal: options.signal, request, timeoutMs, reading: false });\n }\n if (response.status !== 429) return { response, attempt, timeoutMs };\n let refusal: AthenaApiError;\n try {\n refusal = await httpError(response, request, { signal: options.signal, attempt, timeoutMs });\n } finally {\n attempt.settle();\n }\n const waitMs = rateLimitWaitMs({ error: refusal, retry, method: request.method, policy: options.rateLimitRetry });\n if (waitMs === null) throw refusal;\n await sleep(waitMs, options.signal);\n }\n}\n\n/**\n * Send a request and answer its response once agora answered 2xx, for a body\n * the caller reads itself (a file, a stream). An error status throws\n * `AthenaApiError`. The timeout covers the wait for the answer, not the body.\n */\nexport async function athenaFetchResponse(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions = {},\n): Promise<Response> {\n const request = prepare(config, path, options);\n const { response, attempt, timeoutMs } = await exchange(config, request, options);\n if (response.ok) {\n attempt.settle({ keepCancel: true });\n return response;\n }\n try {\n throw await httpError(response, request, { signal: options.signal, attempt, timeoutMs });\n } finally {\n attempt.settle();\n }\n}\n\n/** A 2xx answer's body: JSON when agora says it is JSON, text otherwise, `undefined` for none. */\nasync function athenaFetchBody(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions,\n): Promise<{ status: number; body: unknown; request: PreparedRequest }> {\n const request = prepare(config, path, options);\n const { response, attempt, timeoutMs } = await exchange(config, request, options);\n try {\n if (!response.ok) throw await httpError(response, request, { signal: options.signal, attempt, timeoutMs });\n let text: string;\n try {\n text = await response.text();\n } catch (error) {\n throw failureOf({ error, attempt, signal: options.signal, request, timeoutMs, reading: true });\n }\n if (text.length === 0) return { status: response.status, body: undefined, request };\n const contentType = response.headers.get('content-type') ?? '';\n if (!/[/+]json\\b/i.test(contentType)) {\n return { status: response.status, body: contentType ? text : lenientBody(text), request };\n }\n try {\n return { status: response.status, body: JSON.parse(text), request };\n } catch (error) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.Response,\n status: response.status,\n message: 'Agora answered with JSON that could not be read',\n method: request.method,\n path: request.path,\n cause: error,\n });\n }\n } finally {\n attempt.settle();\n }\n}\n\n/**\n * Send a request and answer its body: JSON when agora says it is JSON, text\n * otherwise, `undefined` for an empty answer. `T` is the caller's word for\n * what the route answers; nothing checks it.\n */\nexport async function athenaFetchJson<T = unknown>(\n config: AthenaRequestConfig,\n path: string,\n options: AthenaRequestOptions = {},\n): Promise<T> {\n const { body } = await athenaFetchBody(config, path, options);\n return body as T;\n}\n\nexport type AthenaGraphQLVariables = Readonly<Record<string, unknown>>;\n\n/**\n * A GraphQL document whose result and variables types travel with it, as\n * graphql-codegen's `TypedDocumentString` (its client preset with\n * `documentMode: 'string'`) carries them.\n */\nexport interface AthenaTypedDocument<TData, TVariables> {\n toString(): string;\n __apiType?: (variables: TVariables) => TData;\n}\n\n/** A GraphQL document: its text, or a typed document that names its result and variables. */\nexport type AthenaGraphQLDocument<TData = unknown, TVariables = AthenaGraphQLVariables> =\n | string\n | AthenaTypedDocument<TData, TVariables>;\n\nexport interface AthenaGraphQLRequestOptions\n extends Pick<AthenaRequestOptions, 'headers' | 'signal' | 'timeoutMs' | 'rateLimitRetry'> {\n /** The operation to run when the document holds several. */\n operationName?: string;\n}\n\n/**\n * Run one GraphQL operation on agora's `/graphql` and answer its `data`. An\n * answer with errors throws `AthenaApiError` (`kind: 'graphql'`, `code` the\n * first error's `extensions.code`), as does one with no data.\n */\nexport async function athenaGraphQL<TData = unknown, TVariables extends object = AthenaGraphQLVariables>(\n config: AthenaRequestConfig,\n document: AthenaGraphQLDocument<TData, TVariables>,\n variables?: TVariables,\n options: AthenaGraphQLRequestOptions = {},\n): Promise<TData> {\n const { operationName, ...requestOptions } = options;\n // TODO(#54756): send a registered operation's id (`documentId`) instead of its\n // text once agora allowlists each app's operations.\n const { status, body, request } = await athenaFetchBody(config, '/graphql', {\n ...requestOptions,\n method: 'POST',\n json: {\n query: String(document),\n variables: variables ?? {},\n ...(operationName ? { operationName } : {}),\n },\n });\n const errors = graphQLErrorEntries(body);\n const first = errors[0];\n if (first) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.GraphQL,\n status,\n code: graphQLErrorCode(first),\n message: first.message,\n errors,\n method: request.method,\n path: request.path,\n });\n }\n const data: unknown =\n typeof body === 'object' && body !== null ? Reflect.get(body, 'data') : undefined;\n if (data === undefined || data === null) {\n throw new AthenaApiError({\n kind: AthenaApiErrorKind.GraphQL,\n status,\n message: 'The GraphQL answer had no data',\n method: request.method,\n path: request.path,\n });\n }\n return data as TData;\n}\n\n/** One operation a GraphQL document defines. */\nexport interface AthenaGraphQLOperation {\n type: 'query' | 'mutation' | 'subscription';\n /** `null` for an anonymous operation. */\n name: string | null;\n}\n\nconst GRAPHQL_IGNORED = /(?:[\\s,]+|#[^\\n\\r]*)+/y;\nconst GRAPHQL_NAME = /[_A-Za-z][_0-9A-Za-z]*/y;\n\n/**\n * The operations a GraphQL document defines, in order, fragments left out. A\n * lexical read that skips strings, comments, variable definitions (default\n * values included), directives and selection sets; it never validates the\n * document, which agora does.\n */\nexport function graphQLOperationsOf(document: string): AthenaGraphQLOperation[] {\n const operations: AthenaGraphQLOperation[] = [];\n let at = 0;\n const skipIgnored = () => {\n GRAPHQL_IGNORED.lastIndex = at;\n if (GRAPHQL_IGNORED.exec(document)) at = GRAPHQL_IGNORED.lastIndex;\n };\n const readName = (): string | null => {\n GRAPHQL_NAME.lastIndex = at;\n const name = GRAPHQL_NAME.exec(document)?.[0] ?? null;\n if (name !== null) at = GRAPHQL_NAME.lastIndex;\n return name;\n };\n /** Past the balanced `(…)` or `{…}` that opens at `at`, strings and comments included. */\n const skipGroup = () => {\n const open = document[at];\n const close = open === '(' ? ')' : '}';\n let depth = 0;\n while (at < document.length) {\n if (document.startsWith('\"\"\"', at)) {\n const end = document.indexOf('\"\"\"', at + 3);\n at = end === -1 ? document.length : end + 3;\n continue;\n }\n const char = document[at];\n if (char === '\"') {\n at += 1;\n while (at < document.length && document[at] !== '\"' && document[at] !== '\\n') {\n at += document[at] === '\\\\' ? 2 : 1;\n }\n at += 1;\n continue;\n }\n if (char === '#') {\n while (at < document.length && document[at] !== '\\n') at += 1;\n continue;\n }\n at += 1;\n if (char === open) depth += 1;\n else if (char === close) {\n depth -= 1;\n if (depth === 0) return;\n }\n }\n };\n /** Past a definition's header (variables, type condition, directives) and its selection set. */\n const skipDefinition = () => {\n while (at < document.length) {\n skipIgnored();\n const char = document[at];\n if (char === '{') {\n skipGroup();\n return;\n }\n if (char === '(') skipGroup();\n else at += 1;\n }\n };\n for (;;) {\n skipIgnored();\n if (at >= document.length) return operations;\n if (document[at] === '{') {\n operations.push({ type: 'query', name: null });\n skipGroup();\n continue;\n }\n const word = readName();\n if (word === 'query' || word === 'mutation' || word === 'subscription') {\n skipIgnored();\n operations.push({ type: word, name: readName() });\n }\n skipDefinition();\n }\n}\n\n/**\n * The operation a request runs: the one `operationName` names, else the\n * document's only one. `null` when neither picks one (agora refuses those).\n */\nexport function selectedGraphQLOperation(\n document: string,\n operationName?: string | null,\n): AthenaGraphQLOperation | null {\n const operations = graphQLOperationsOf(document);\n if (operationName) return operations.find((operation) => operation.name === operationName) ?? null;\n return operations.length === 1 ? (operations[0] ?? null) : null;\n}\n\n/**\n * An authenticated fetch bound to one configuration (see `useAthenaFetch`).\n * Called, it answers the route's body; `raw` answers the response itself and\n * `graphql` runs one GraphQL operation.\n */\nexport interface AthenaFetch {\n <T = unknown>(path: string, options?: AthenaRequestOptions): Promise<T>;\n raw(path: string, options?: AthenaRequestOptions): Promise<Response>;\n graphql<TData = unknown, TVariables extends object = AthenaGraphQLVariables>(\n document: AthenaGraphQLDocument<TData, TVariables>,\n variables?: TVariables,\n options?: AthenaGraphQLRequestOptions,\n ): Promise<TData>;\n}\n\n/**\n * `useAthenaFetch` without React: the transport bound to `config`, read once.\n * Hosts outside a component can pass `useAthenaConfig()`'s value along.\n */\nexport function createAthenaFetch(config: AthenaRequestConfig): AthenaFetch {\n const bound: AthenaRequestConfig = {\n backendUrl: config.backendUrl,\n apiKey: config.apiKey,\n token: config.token,\n getToken: config.getToken,\n };\n return Object.assign(\n <T = unknown>(path: string, options?: AthenaRequestOptions) =>\n athenaFetchJson<T>(bound, path, options),\n {\n raw: (path: string, options?: AthenaRequestOptions) => athenaFetchResponse(bound, path, options),\n graphql: <TData = unknown, TVariables extends object = AthenaGraphQLVariables>(\n document: AthenaGraphQLDocument<TData, TVariables>,\n variables?: TVariables,\n options?: AthenaGraphQLRequestOptions,\n ) => athenaGraphQL<TData, TVariables>(bound, document, variables, options),\n },\n );\n}\n"],"names":["seconds"],"mappings":"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"}
|
|
@@ -593,9 +593,10 @@ function AthenaStatewireActiveThreadHost({
|
|
|
593
593
|
...standaloneProps,
|
|
594
594
|
children: [
|
|
595
595
|
/* @__PURE__ */ jsxRuntime.jsx(statewireThreadList.StatewireThreadTitlePoller, {}),
|
|
596
|
-
/* @__PURE__ */ jsxRuntime.
|
|
597
|
-
|
|
598
|
-
|
|
596
|
+
/* @__PURE__ */ jsxRuntime.jsxs(statewireThreadList.StatewireThreadListSendSync, { startChannel, children: [
|
|
597
|
+
/* @__PURE__ */ jsxRuntime.jsx(AssetPanelThreadSync, {}),
|
|
598
|
+
children
|
|
599
|
+
] })
|
|
599
600
|
]
|
|
600
601
|
}
|
|
601
602
|
);
|