@athenaintel/react 0.59.0 → 0.60.1

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.
Files changed (157) hide show
  1. package/README.md +124 -20
  2. package/dist/agent-runtime/src/client-tool-bridge.cjs +20 -2
  3. package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
  4. package/dist/agent-runtime/src/client-tool-bridge.d.ts +9 -4
  5. package/dist/agent-runtime/src/client-tool-bridge.js +20 -2
  6. package/dist/agent-runtime/src/client-tool-bridge.js.map +1 -1
  7. package/dist/agent-runtime/src/client-tools.cjs.map +1 -1
  8. package/dist/agent-runtime/src/client-tools.d.ts +9 -0
  9. package/dist/agent-runtime/src/client-tools.js.map +1 -1
  10. package/dist/agent-runtime/src/composer-markdown.cjs +0 -16
  11. package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
  12. package/dist/agent-runtime/src/composer-markdown.js +1 -17
  13. package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
  14. package/dist/agent-runtime/src/named-agents.js +1 -1
  15. package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
  16. package/dist/agent-runtime/src/offline-status.d.ts +27 -0
  17. package/dist/agent-runtime/src/offline-status.js.map +1 -1
  18. package/dist/agent-runtime/src/tool-metadata.cjs +7 -0
  19. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  20. package/dist/agent-runtime/src/tool-metadata.js +7 -0
  21. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  22. package/dist/chat/AthenaChat.cjs +17 -5
  23. package/dist/chat/AthenaChat.cjs.map +1 -1
  24. package/dist/chat/AthenaChat.js +18 -6
  25. package/dist/chat/AthenaChat.js.map +1 -1
  26. package/dist/chat/StatewireClientToolBridge.cjs +69 -1
  27. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  28. package/dist/chat/StatewireClientToolBridge.d.ts +14 -1
  29. package/dist/chat/StatewireClientToolBridge.js +70 -2
  30. package/dist/chat/StatewireClientToolBridge.js.map +1 -1
  31. package/dist/chat/StatewireClientToolConsentCard.cjs +65 -0
  32. package/dist/chat/StatewireClientToolConsentCard.cjs.map +1 -0
  33. package/dist/chat/StatewireClientToolConsentCard.d.ts +24 -0
  34. package/dist/chat/StatewireClientToolConsentCard.js +65 -0
  35. package/dist/chat/StatewireClientToolConsentCard.js.map +1 -0
  36. package/dist/chat/client-tool-write-consent.cjs +111 -0
  37. package/dist/chat/client-tool-write-consent.cjs.map +1 -0
  38. package/dist/chat/client-tool-write-consent.d.ts +71 -0
  39. package/dist/chat/client-tool-write-consent.js +111 -0
  40. package/dist/chat/client-tool-write-consent.js.map +1 -0
  41. package/dist/chat/statewire-client-tools.cjs +30 -5
  42. package/dist/chat/statewire-client-tools.cjs.map +1 -1
  43. package/dist/chat/statewire-client-tools.d.ts +34 -2
  44. package/dist/chat/statewire-client-tools.js +30 -5
  45. package/dist/chat/statewire-client-tools.js.map +1 -1
  46. package/dist/chat-ui/index.cjs +2 -0
  47. package/dist/chat-ui/index.cjs.map +1 -1
  48. package/dist/chat-ui/index.d.ts +1 -0
  49. package/dist/chat-ui/index.js +2 -0
  50. package/dist/chat-ui/index.js.map +1 -1
  51. package/dist/chat-ui/mentions/mention-chip.cjs +9 -3
  52. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  53. package/dist/chat-ui/mentions/mention-chip.js +9 -3
  54. package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
  55. package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs +18 -2
  56. package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs.map +1 -1
  57. package/dist/chat-ui/mentions/suggestions/components/mention-icon.d.ts +10 -1
  58. package/dist/chat-ui/mentions/suggestions/components/mention-icon.js +19 -3
  59. package/dist/chat-ui/mentions/suggestions/components/mention-icon.js.map +1 -1
  60. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +9 -0
  61. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  62. package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +6 -0
  63. package/dist/chat-ui/mentions/suggestions/data/api-client.js +9 -0
  64. package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
  65. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs +89 -0
  66. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs.map +1 -0
  67. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.d.ts +8 -0
  68. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js +89 -0
  69. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js.map +1 -0
  70. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs +153 -116
  71. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs.map +1 -1
  72. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.d.ts +58 -12
  73. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js +154 -117
  74. package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js.map +1 -1
  75. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +38 -6
  76. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
  77. package/dist/chat-ui/mentions/suggestions/data/sources/index.js +40 -8
  78. package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
  79. package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs +13 -0
  80. package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs.map +1 -0
  81. package/dist/chat-ui/mentions/use-asset-icon-app-url.d.ts +9 -0
  82. package/dist/chat-ui/mentions/use-asset-icon-app-url.js +13 -0
  83. package/dist/chat-ui/mentions/use-asset-icon-app-url.js.map +1 -0
  84. package/dist/chat-ui/statewire.cjs +4 -0
  85. package/dist/chat-ui/statewire.cjs.map +1 -1
  86. package/dist/chat-ui/statewire.d.ts +2 -0
  87. package/dist/chat-ui/statewire.js +4 -0
  88. package/dist/chat-ui/statewire.js.map +1 -1
  89. package/dist/collab/client.cjs +24 -1
  90. package/dist/collab/client.cjs.map +1 -1
  91. package/dist/collab/client.d.ts +16 -0
  92. package/dist/collab/client.js +24 -1
  93. package/dist/collab/client.js.map +1 -1
  94. package/dist/composer/attached-references.js +1 -1
  95. package/dist/composer/staged-message-metadata.cjs +12 -0
  96. package/dist/composer/staged-message-metadata.cjs.map +1 -0
  97. package/dist/composer/staged-message-metadata.d.ts +15 -0
  98. package/dist/composer/staged-message-metadata.js +12 -0
  99. package/dist/composer/staged-message-metadata.js.map +1 -0
  100. package/dist/data/athena-request.cjs +2 -0
  101. package/dist/data/athena-request.cjs.map +1 -1
  102. package/dist/data/athena-request.js +2 -0
  103. package/dist/data/athena-request.js.map +1 -1
  104. package/dist/index.cjs +5 -0
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.d.ts +6 -2
  107. package/dist/index.js +6 -1
  108. package/dist/index.js.map +1 -1
  109. package/dist/provider/AthenaProvider.cjs +26 -6
  110. package/dist/provider/AthenaProvider.cjs.map +1 -1
  111. package/dist/provider/AthenaProvider.d.ts +8 -1
  112. package/dist/provider/AthenaProvider.js +27 -7
  113. package/dist/provider/AthenaProvider.js.map +1 -1
  114. package/dist/react/package.json.cjs +1 -1
  115. package/dist/react/package.json.js +1 -1
  116. package/dist/references/src/anchors/parse.cjs +11 -1
  117. package/dist/references/src/anchors/parse.cjs.map +1 -1
  118. package/dist/references/src/anchors/parse.js +11 -1
  119. package/dist/references/src/anchors/parse.js.map +1 -1
  120. package/dist/references/src/anchors/schemas.d.ts +1 -0
  121. package/dist/references/src/anchors/serialize.cjs +1 -0
  122. package/dist/references/src/anchors/serialize.cjs.map +1 -1
  123. package/dist/references/src/anchors/serialize.js +1 -0
  124. package/dist/references/src/anchors/serialize.js.map +1 -1
  125. package/dist/references/src/anchors/types.cjs.map +1 -1
  126. package/dist/references/src/anchors/types.d.ts +9 -0
  127. package/dist/references/src/anchors/types.js.map +1 -1
  128. package/dist/references/src/schemas.d.ts +2 -0
  129. package/dist/runtime/useAthenaStatewireRuntime.cjs +6 -8
  130. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  131. package/dist/runtime/useAthenaStatewireRuntime.js +6 -8
  132. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  133. package/dist/threads/statewire-thread-list.cjs +14 -2
  134. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  135. package/dist/threads/statewire-thread-list.d.ts +11 -2
  136. package/dist/threads/statewire-thread-list.js +14 -2
  137. package/dist/threads/statewire-thread-list.js.map +1 -1
  138. package/dist/tools/drive-tool-uis.cjs +8 -4
  139. package/dist/tools/drive-tool-uis.cjs.map +1 -1
  140. package/dist/tools/drive-tool-uis.d.ts +5 -4
  141. package/dist/tools/drive-tool-uis.js +9 -5
  142. package/dist/tools/drive-tool-uis.js.map +1 -1
  143. package/dist/version.cjs +4 -0
  144. package/dist/version.cjs.map +1 -1
  145. package/dist/version.d.ts +9 -0
  146. package/dist/version.js +4 -0
  147. package/dist/version.js.map +1 -1
  148. package/dist/workbench/live-desktop-api.cjs +2 -1
  149. package/dist/workbench/live-desktop-api.cjs.map +1 -1
  150. package/dist/workbench/live-desktop-api.js +2 -1
  151. package/dist/workbench/live-desktop-api.js.map +1 -1
  152. package/dist/workbench/session-workspace-api.cjs +7 -2
  153. package/dist/workbench/session-workspace-api.cjs.map +1 -1
  154. package/dist/workbench/session-workspace-api.d.ts +10 -0
  155. package/dist/workbench/session-workspace-api.js +7 -2
  156. package/dist/workbench/session-workspace-api.js.map +1 -1
  157. 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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"}
package/dist/index.cjs CHANGED
@@ -49,6 +49,8 @@ const statewireBanners = require("./chat/statewire-banners.cjs");
49
49
  const StatewireRunRefusalNotice = require("./chat/StatewireRunRefusalNotice.cjs");
50
50
  const StatewireClientToolBridge = require("./chat/StatewireClientToolBridge.cjs");
51
51
  const statewireClientTools = require("./chat/statewire-client-tools.cjs");
52
+ const StatewireClientToolConsentCard = require("./chat/StatewireClientToolConsentCard.cjs");
53
+ const clientToolWriteConsent = require("./chat/client-tool-write-consent.cjs");
52
54
  const statewireLifecycleContext = require("./provider/statewire-lifecycle-context.cjs");
53
55
  const statewireLifecycle = require("./runtime/statewire-lifecycle.cjs");
54
56
  const statewireThreadList = require("./threads/statewire-thread-list.cjs");
@@ -319,7 +321,10 @@ exports.RUN_START_REFUSAL_FALLBACK_MESSAGE = StatewireRunRefusalNotice.RUN_START
319
321
  exports.StatewireRunRefusalNotice = StatewireRunRefusalNotice.StatewireRunRefusalNotice;
320
322
  exports.StatewireClientToolBridge = StatewireClientToolBridge.StatewireClientToolBridge;
321
323
  exports.collectStatewireClientTools = statewireClientTools.collectStatewireClientTools;
324
+ exports.requiresWriteConsent = statewireClientTools.requiresWriteConsent;
322
325
  exports.statewireClientToolWireEntries = statewireClientTools.statewireClientToolWireEntries;
326
+ exports.StatewireClientToolConsentCard = StatewireClientToolConsentCard.StatewireClientToolConsentCard;
327
+ exports.useClientToolWriteConsent = clientToolWriteConsent.useClientToolWriteConsent;
323
328
  exports.useAthenaStatewireLifecycle = statewireLifecycleContext.useAthenaStatewireLifecycle;
324
329
  exports.athenaStatewireErrorNotice = statewireLifecycle.athenaStatewireErrorNotice;
325
330
  exports.threadSummaryFromConversation = statewireThreadList.threadSummaryFromConversation;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.d.ts CHANGED
@@ -69,8 +69,12 @@ export type { StatewireRunRefusalNoticeProps } from './chat/StatewireRunRefusalN
69
69
  export { COLLAB_AGENT_CHANNEL_SESSION_MISMATCH, readRunStartRefusal, } from './agent-runtime/src/index';
70
70
  export type { RunStartRefusal } from './agent-runtime/src/index';
71
71
  export { StatewireClientToolBridge } from './chat/StatewireClientToolBridge';
72
- export { collectStatewireClientTools, statewireClientToolWireEntries, } from './chat/statewire-client-tools';
73
- export type { StatewireClientTool } from './chat/statewire-client-tools';
72
+ export { collectStatewireClientTools, requiresWriteConsent, statewireClientToolWireEntries, } from './chat/statewire-client-tools';
73
+ export type { ClientToolWriteConsentOptions, StatewireClientTool, } from './chat/statewire-client-tools';
74
+ export { StatewireClientToolConsentCard } from './chat/StatewireClientToolConsentCard';
75
+ export type { StatewireClientToolConsentCardProps } from './chat/StatewireClientToolConsentCard';
76
+ export { useClientToolWriteConsent } from './chat/client-tool-write-consent';
77
+ export type { ClientToolWriteConfirmer, ClientToolWriteConsent, ClientToolWriteConsentRequest, ClientToolWriteConsentTool, } from './chat/client-tool-write-consent';
74
78
  export { useAthenaStatewireLifecycle } from './provider/statewire-lifecycle-context';
75
79
  export { athenaStatewireErrorNotice } from './runtime/statewire-lifecycle';
76
80
  export type { AthenaStatewireErrorNotice, AthenaStatewireLifecycleState, } from './runtime/statewire-lifecycle';
package/dist/index.js CHANGED
@@ -46,7 +46,9 @@ import { StatewireQueuedMessages } from "./chat/StatewireQueuedMessages.js";
46
46
  import { StatewireConnectionBanner, StatewireErrorBanner } from "./chat/statewire-banners.js";
47
47
  import { RUN_START_REFUSAL_FALLBACK_MESSAGE, StatewireRunRefusalNotice } from "./chat/StatewireRunRefusalNotice.js";
48
48
  import { StatewireClientToolBridge } from "./chat/StatewireClientToolBridge.js";
49
- import { collectStatewireClientTools, statewireClientToolWireEntries } from "./chat/statewire-client-tools.js";
49
+ import { collectStatewireClientTools, requiresWriteConsent, statewireClientToolWireEntries } from "./chat/statewire-client-tools.js";
50
+ import { StatewireClientToolConsentCard } from "./chat/StatewireClientToolConsentCard.js";
51
+ import { useClientToolWriteConsent } from "./chat/client-tool-write-consent.js";
50
52
  import { useAthenaStatewireLifecycle } from "./provider/statewire-lifecycle-context.js";
51
53
  import { athenaStatewireErrorNotice } from "./runtime/statewire-lifecycle.js";
52
54
  import { threadSummaryFromConversation, useAthenaStatewireThreadList, useRefreshThreadList } from "./threads/statewire-thread-list.js";
@@ -367,6 +369,7 @@ export {
367
369
  SetSlideNotesToolUI,
368
370
  StatewireApprovalCard,
369
371
  StatewireClientToolBridge,
372
+ StatewireClientToolConsentCard,
370
373
  StatewireConnectionBanner,
371
374
  StatewireErrorBanner,
372
375
  StatewireHistoryEdge,
@@ -587,6 +590,7 @@ export {
587
590
  readTurnTiming,
588
591
  renameThread,
589
592
  repoSearchRequestBody,
593
+ requiresWriteConsent,
590
594
  resetAssetAutoOpen,
591
595
  resetRememberedExpansionsForTests,
592
596
  resolveActivityPhase,
@@ -689,6 +693,7 @@ export {
689
693
  useAttachments,
690
694
  useBrowserDecisionConfirmer,
691
695
  useChatVoiceEnabled,
696
+ useClientToolWriteConsent,
692
697
  useComposerAttachment,
693
698
  useComposerReady,
694
699
  useDeepAgentLaneFollowRegistry,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -38,6 +38,7 @@ const statewireServerLaneContext = require("../runtime/statewire-server-lane-con
38
38
  const athenaDiagnostics = require("../diagnostics/athena-diagnostics.cjs");
39
39
  const errors = require("../diagnostics/errors.cjs");
40
40
  const statewireClientTools = require("../chat/statewire-client-tools.cjs");
41
+ const clientToolWriteConsent = require("../chat/client-tool-write-consent.cjs");
41
42
  const tooltip = require("../ui/tooltip.cjs");
42
43
  const autoOpenTools = require("../tools/auto-open-tools.cjs");
43
44
  const AthenaContext = require("./AthenaContext.cjs");
@@ -391,6 +392,7 @@ function AthenaStatewireStandalone({
391
392
  linkClicks,
392
393
  citationLinks,
393
394
  modes,
395
+ confirmClientToolWrites,
394
396
  ...runtimeProps
395
397
  }) {
396
398
  const generatedIdRef = require$$0.useRef(null);
@@ -424,6 +426,13 @@ function AthenaStatewireStandalone({
424
426
  };
425
427
  const threadMode = hostModes.length > 0 ? listedPick(threadId) ?? sessionChannels[`${modeScope}\0${threadId}`] : void 0;
426
428
  const clientTools = useAthenaStatewireRuntime.useStatewireClientTools(runtimeProps.frontendTools);
429
+ const writeConsentStore = clientToolWriteConsent.useClientToolWriteConsentStore(
430
+ `${principal ?? "signing-in"}\0${runtimeProps.syncUrl}`
431
+ );
432
+ const writeConsentSummaries = require$$0.useMemo(
433
+ () => statewireClientTools.clientToolWriteConsentSummaries(runtimeProps.frontendTools),
434
+ [runtimeProps.frontendTools]
435
+ );
427
436
  const clientToolNamesKey = clientTools.map((tool) => tool.definition.name).join(",");
428
437
  const clientToolAppId = runtimeProps.appId;
429
438
  require$$0.useEffect(() => {
@@ -463,8 +472,16 @@ function AthenaStatewireStandalone({
463
472
  // eslint-disable-next-line react-hooks/exhaustive-deps
464
473
  [modeKey, modeScope, modePicks, sessionChannels, published, setModePick, setSessionChannel]
465
474
  );
466
- const scope = published && /* @__PURE__ */ jsxRuntime.jsx(react.AuiProvider, { value: published.client, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(threadIdContext.AthenaStatewireThreadIdContext.Provider, { value: published.threadId, children: /* @__PURE__ */ jsxRuntime.jsx(statewireLifecycleContext.AthenaStatewireLifecycleContext.Provider, { value: published.lifecycle, children: /* @__PURE__ */ jsxRuntime.jsx(threadStatus.DeepAgentConnectionContext.Provider, { value: published.lifecycle.connection, children: /* @__PURE__ */ jsxRuntime.jsx(statewireServerLaneContext.AthenaStatewireServerLaneContext.Provider, { value: published.serverLane, children: /* @__PURE__ */ jsxRuntime.jsx(statewireWindowContext.StatewireToolOutputsContext.Provider, { value: runtimeProps.toolOutputs, children: /* @__PURE__ */ jsxRuntime.jsx(useTurnSteps.TurnStepsControlContext.Provider, { value: earlierStepsButton.EarlierStepsButton, children: /* @__PURE__ */ jsxRuntime.jsx(statewireHistoryContext.StatewireHistoryContext.Provider, { value: runtimeProps.historyStore, children: /* @__PURE__ */ jsxRuntime.jsxs(tooltip.TooltipProvider, { children: [
467
- /* @__PURE__ */ jsxRuntime.jsx(StatewireClientToolBridge.StatewireClientToolBridge, { tools: clientTools, threadId: published.threadId }),
475
+ const scope = published && /* @__PURE__ */ jsxRuntime.jsx(react.AuiProvider, { value: published.client, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(threadIdContext.AthenaStatewireThreadIdContext.Provider, { value: published.threadId, children: /* @__PURE__ */ jsxRuntime.jsx(statewireLifecycleContext.AthenaStatewireLifecycleContext.Provider, { value: published.lifecycle, children: /* @__PURE__ */ jsxRuntime.jsx(threadStatus.DeepAgentConnectionContext.Provider, { value: published.lifecycle.connection, children: /* @__PURE__ */ jsxRuntime.jsx(statewireServerLaneContext.AthenaStatewireServerLaneContext.Provider, { value: published.serverLane, children: /* @__PURE__ */ jsxRuntime.jsx(statewireWindowContext.StatewireToolOutputsContext.Provider, { value: runtimeProps.toolOutputs, children: /* @__PURE__ */ jsxRuntime.jsx(useTurnSteps.TurnStepsControlContext.Provider, { value: earlierStepsButton.EarlierStepsButton, children: /* @__PURE__ */ jsxRuntime.jsx(statewireHistoryContext.StatewireHistoryContext.Provider, { value: runtimeProps.historyStore, children: /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(clientToolWriteConsent.ClientToolWriteConsentContext.Provider, { value: writeConsentStore, children: [
476
+ /* @__PURE__ */ jsxRuntime.jsx(
477
+ StatewireClientToolBridge.StatewireClientToolBridge,
478
+ {
479
+ tools: clientTools,
480
+ threadId: published.threadId,
481
+ writeConsentSummaries,
482
+ confirmWrites: confirmClientToolWrites
483
+ }
484
+ ),
468
485
  /* @__PURE__ */ jsxRuntime.jsx(
469
486
  StatewireThreadConfigLaneSync.StatewireThreadConfigLaneSync,
470
487
  {
@@ -494,7 +511,7 @@ function AthenaStatewireStandalone({
494
511
  children
495
512
  }
496
513
  ) }) })
497
- ] }) }) }) }) }) }) }) }) }) });
514
+ ] }) }) }) }) }) }) }) }) }) }) });
498
515
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
499
516
  /* @__PURE__ */ jsxRuntime.jsx(
500
517
  AthenaStatewireRuntimeMount,
@@ -593,9 +610,10 @@ function AthenaStatewireActiveThreadHost({
593
610
  ...standaloneProps,
594
611
  children: [
595
612
  /* @__PURE__ */ jsxRuntime.jsx(statewireThreadList.StatewireThreadTitlePoller, {}),
596
- /* @__PURE__ */ jsxRuntime.jsx(statewireThreadList.StatewireThreadListSendSync, { startChannel }),
597
- /* @__PURE__ */ jsxRuntime.jsx(AssetPanelThreadSync, {}),
598
- children
613
+ /* @__PURE__ */ jsxRuntime.jsxs(statewireThreadList.StatewireThreadListSendSync, { startChannel, children: [
614
+ /* @__PURE__ */ jsxRuntime.jsx(AssetPanelThreadSync, {}),
615
+ children
616
+ ] })
599
617
  ]
600
618
  }
601
619
  );
@@ -619,6 +637,7 @@ function AthenaProvider({
619
637
  model,
620
638
  tools = [],
621
639
  frontendTools = {},
640
+ confirmClientToolWrites,
622
641
  disableAutoOpen = false,
623
642
  apiUrl,
624
643
  backendUrl,
@@ -920,6 +939,7 @@ function AthenaProvider({
920
939
  tools,
921
940
  frontendToolIds: frontendToolNames,
922
941
  frontendTools: effectiveFrontendTools,
942
+ confirmClientToolWrites,
923
943
  workbench,
924
944
  knowledgeBase,
925
945
  systemPrompt,