@athenaintel/react 0.12.1 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/collab.js ADDED
@@ -0,0 +1,334 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { WebsocketProvider } from "@y/websocket";
5
+ import * as Y from "@y/y";
6
+ import { useState, useRef, useEffect, useMemo, useSyncExternalStore } from "react";
7
+ import { u as useAthenaConfig } from "./AthenaContext-MOslgOmE.js";
8
+ const WS_CLOSE_AUTH_REVOKED = 4401;
9
+ const WS_CLOSE_DOC_DELETED = 4404;
10
+ function classifyClose(code) {
11
+ if (code === void 0) return "retry";
12
+ if (code === WS_CLOSE_AUTH_REVOKED) return "remint";
13
+ if (code >= 4400 && code < 4500) return "stop";
14
+ return "retry";
15
+ }
16
+ class CollabTokenError extends Error {
17
+ constructor(status, message) {
18
+ super(message);
19
+ __publicField(this, "status");
20
+ this.name = "CollabTokenError";
21
+ this.status = status;
22
+ }
23
+ }
24
+ function getAuthHeaders(auth) {
25
+ if (auth.token) {
26
+ return { Authorization: `Bearer ${auth.token}` };
27
+ }
28
+ if (auth.apiKey) {
29
+ return { "X-API-KEY": auth.apiKey };
30
+ }
31
+ return {};
32
+ }
33
+ function getAthenaApiBaseUrl(backendUrl) {
34
+ const stripped = backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
35
+ return stripped.replace(/\/$/, "");
36
+ }
37
+ async function mintCollabToken(args) {
38
+ const base = getAthenaApiBaseUrl(args.auth.backendUrl);
39
+ const response = await fetch(
40
+ `${base}/api/v0/assets/${encodeURIComponent(args.assetId)}/collab-token`,
41
+ {
42
+ method: "POST",
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ ...getAuthHeaders(args.auth)
46
+ },
47
+ body: JSON.stringify({ access: args.access }),
48
+ signal: args.signal
49
+ }
50
+ );
51
+ if (!response.ok) {
52
+ let detail = "";
53
+ try {
54
+ const body = await response.json();
55
+ if (body && typeof body === "object" && "detail" in body) {
56
+ detail = String(body.detail);
57
+ }
58
+ } catch {
59
+ }
60
+ throw new CollabTokenError(
61
+ response.status,
62
+ detail || `Collab token mint failed with status ${response.status}`
63
+ );
64
+ }
65
+ return await response.json();
66
+ }
67
+ const REFRESH_HEADROOM_MS = 5 * 60 * 1e3;
68
+ const MIN_REFRESH_DELAY_MS = 30 * 1e3;
69
+ const MAX_CONSECUTIVE_REMINTS = 2;
70
+ function connectGenericDoc(args) {
71
+ const access = args.access ?? "view";
72
+ const doc = new Y.Doc();
73
+ const listeners = /* @__PURE__ */ new Set();
74
+ let provider = null;
75
+ let refreshTimer = null;
76
+ let destroyed = false;
77
+ let status = "connecting";
78
+ let accessType = null;
79
+ let error = null;
80
+ let lastPresence = null;
81
+ let version = 0;
82
+ let consecutiveRemints = 0;
83
+ const notify = () => {
84
+ version += 1;
85
+ for (const listener of listeners) listener();
86
+ };
87
+ const setStatus = (next, err = null) => {
88
+ if (destroyed && next !== "closed") return;
89
+ status = next;
90
+ error = err;
91
+ notify();
92
+ };
93
+ const clearRefreshTimer = () => {
94
+ if (refreshTimer !== null) {
95
+ clearTimeout(refreshTimer);
96
+ refreshTimer = null;
97
+ }
98
+ };
99
+ const teardownProvider = () => {
100
+ clearRefreshTimer();
101
+ if (provider) {
102
+ provider.destroy();
103
+ provider = null;
104
+ }
105
+ };
106
+ const scheduleRefresh = (grant) => {
107
+ clearRefreshTimer();
108
+ const delay = Math.max(
109
+ grant.expires_at_ms - Date.now() - REFRESH_HEADROOM_MS,
110
+ MIN_REFRESH_DELAY_MS
111
+ );
112
+ refreshTimer = setTimeout(() => {
113
+ void connect({ scheduledRefresh: true });
114
+ }, delay);
115
+ };
116
+ const connect = async (opts) => {
117
+ if (destroyed) return;
118
+ const scheduledRefresh = (opts == null ? void 0 : opts.scheduledRefresh) === true;
119
+ if (!scheduledRefresh) {
120
+ teardownProvider();
121
+ } else {
122
+ clearRefreshTimer();
123
+ }
124
+ let grant;
125
+ try {
126
+ grant = await mintCollabToken({ auth: args.auth, assetId: args.assetId, access });
127
+ } catch (err) {
128
+ if (scheduledRefresh && !destroyed) {
129
+ refreshTimer = setTimeout(() => {
130
+ void connect({ scheduledRefresh: true });
131
+ }, MIN_REFRESH_DELAY_MS);
132
+ return;
133
+ }
134
+ setStatus("error", err instanceof Error ? err : new Error(String(err)));
135
+ return;
136
+ }
137
+ if (destroyed) return;
138
+ if (scheduledRefresh) {
139
+ teardownProvider();
140
+ }
141
+ accessType = grant.access_type;
142
+ const nextProvider = new WebsocketProvider(grant.ws_url, `${grant.org}/${grant.doc_id}`, doc, {
143
+ params: {
144
+ yauth: grant.token,
145
+ branch: grant.branch,
146
+ gc: "true"
147
+ }
148
+ });
149
+ provider = nextProvider;
150
+ nextProvider.on("status", (event) => {
151
+ if (provider !== nextProvider) return;
152
+ if (event.status === "connected") {
153
+ consecutiveRemints = 0;
154
+ }
155
+ setStatus(event.status);
156
+ if (event.status === "connected" && lastPresence !== null) {
157
+ nextProvider.awareness.setLocalState(lastPresence);
158
+ }
159
+ });
160
+ nextProvider.on("connection-close", (event) => {
161
+ if (provider !== nextProvider) return;
162
+ const action = classifyClose(event == null ? void 0 : event.code);
163
+ if (action === "remint") {
164
+ consecutiveRemints += 1;
165
+ teardownProvider();
166
+ if (consecutiveRemints > MAX_CONSECUTIVE_REMINTS) {
167
+ setStatus(
168
+ "closed",
169
+ new Error("Access repeatedly revoked mid-session (4401); giving up.")
170
+ );
171
+ return;
172
+ }
173
+ void connect();
174
+ } else if (action === "stop") {
175
+ teardownProvider();
176
+ setStatus(
177
+ "closed",
178
+ new Error(`Connection closed permanently (code ${(event == null ? void 0 : event.code) ?? "unknown"})`)
179
+ );
180
+ }
181
+ });
182
+ nextProvider.awareness.on("change", () => {
183
+ if (provider !== nextProvider) return;
184
+ notify();
185
+ });
186
+ scheduleRefresh(grant);
187
+ };
188
+ void connect();
189
+ return {
190
+ doc,
191
+ get status() {
192
+ return status;
193
+ },
194
+ get accessType() {
195
+ return accessType;
196
+ },
197
+ get error() {
198
+ return error;
199
+ },
200
+ get version() {
201
+ return version;
202
+ },
203
+ getPresence: () => {
204
+ if (!provider) return [];
205
+ const entries = [];
206
+ provider.awareness.getStates().forEach((state, clientId) => {
207
+ entries.push({ clientId, state });
208
+ });
209
+ return entries;
210
+ },
211
+ setPresence: (state) => {
212
+ lastPresence = state;
213
+ provider == null ? void 0 : provider.awareness.setLocalState(state);
214
+ },
215
+ refreshNow: () => connect({ scheduledRefresh: true }),
216
+ onChange: (listener) => {
217
+ listeners.add(listener);
218
+ return () => {
219
+ listeners.delete(listener);
220
+ };
221
+ },
222
+ destroy: () => {
223
+ if (destroyed) return;
224
+ destroyed = true;
225
+ teardownProvider();
226
+ listeners.clear();
227
+ doc.destroy();
228
+ status = "closed";
229
+ }
230
+ };
231
+ }
232
+ function useGenericDoc(assetId, options) {
233
+ const config = useAthenaConfig();
234
+ const access = (options == null ? void 0 : options.access) ?? "view";
235
+ const [handle, setHandle] = useState(null);
236
+ const handleRef = useRef(null);
237
+ useEffect(() => {
238
+ const next = connectGenericDoc({
239
+ assetId,
240
+ access,
241
+ auth: {
242
+ backendUrl: config.backendUrl,
243
+ apiKey: config.apiKey,
244
+ token: config.token
245
+ }
246
+ });
247
+ handleRef.current = next;
248
+ setHandle(next);
249
+ return () => {
250
+ handleRef.current = null;
251
+ next.destroy();
252
+ };
253
+ }, [assetId, access, config.backendUrl, config.apiKey, config.token]);
254
+ const subscribe = useMemo(() => {
255
+ return (onStoreChange) => {
256
+ if (!handle) return () => {
257
+ };
258
+ return handle.onChange(onStoreChange);
259
+ };
260
+ }, [handle]);
261
+ useSyncExternalStore(
262
+ subscribe,
263
+ () => {
264
+ if (!handle) return EMPTY_SNAPSHOT;
265
+ return `${handle.status}|${handle.accessType ?? ""}|${handle.version}`;
266
+ },
267
+ () => EMPTY_SNAPSHOT
268
+ );
269
+ return {
270
+ doc: (handle == null ? void 0 : handle.doc) ?? null,
271
+ status: (handle == null ? void 0 : handle.status) ?? "connecting",
272
+ accessType: (handle == null ? void 0 : handle.accessType) ?? null,
273
+ error: (handle == null ? void 0 : handle.error) ?? null,
274
+ presence: (handle == null ? void 0 : handle.getPresence()) ?? [],
275
+ setPresence: (state) => {
276
+ var _a;
277
+ return (_a = handleRef.current) == null ? void 0 : _a.setPresence(state);
278
+ }
279
+ };
280
+ }
281
+ const EMPTY_SNAPSHOT = "init||0";
282
+ function defineDocShape(shape) {
283
+ const keys = Object.keys(shape);
284
+ return {
285
+ shape,
286
+ bind(doc) {
287
+ const toJSON = () => {
288
+ const out = {};
289
+ for (const key of keys) {
290
+ out[key] = doc.get(key).toJSON();
291
+ }
292
+ return out;
293
+ };
294
+ return {
295
+ get: (key) => doc.get(key),
296
+ toJSON,
297
+ subscribe: (listener) => {
298
+ let scheduled = false;
299
+ const emit = () => {
300
+ scheduled = false;
301
+ listener(toJSON());
302
+ };
303
+ const onDeepChange = () => {
304
+ if (scheduled) return;
305
+ scheduled = true;
306
+ queueMicrotask(emit);
307
+ };
308
+ const roots = keys.map((key) => doc.get(key));
309
+ for (const root of roots) {
310
+ root.observeDeep(onDeepChange);
311
+ }
312
+ listener(toJSON());
313
+ return () => {
314
+ for (const root of roots) {
315
+ root.unobserveDeep(onDeepChange);
316
+ }
317
+ };
318
+ }
319
+ };
320
+ }
321
+ };
322
+ }
323
+ export {
324
+ CollabTokenError,
325
+ WS_CLOSE_AUTH_REVOKED,
326
+ WS_CLOSE_DOC_DELETED,
327
+ classifyClose,
328
+ connectGenericDoc,
329
+ defineDocShape,
330
+ getAthenaApiBaseUrl,
331
+ mintCollabToken,
332
+ useGenericDoc
333
+ };
334
+ //# sourceMappingURL=collab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collab.js","sources":["../src/collab/close-policy.ts","../src/collab/mint.ts","../src/collab/client.ts","../src/collab/react.ts","../src/collab/shape.ts"],"sourcesContent":["/**\n * Keryx WebSocket close-code policy.\n *\n * Keryx (@y/hub) encodes retry semantics in close codes: 4400–4499 are\n * permanent application errors — the client must stop reconnecting until the\n * app acts — while everything else is transient and left to the provider's\n * exponential backoff. Two permanent codes carry specific meaning:\n *\n * - 4401 \"permission revoked\": the token was rejected mid-session (access\n * revoked, permissions changed, or the token aged out server-side). The\n * right response is one fresh mint — which re-runs the server-side\n * permission check — and a reconnect only if the mint succeeds.\n * - 4404 \"document deleted\": permanent; the document is not coming back.\n */\n\nexport const WS_CLOSE_AUTH_REVOKED = 4401;\nexport const WS_CLOSE_DOC_DELETED = 4404;\n\nexport type CloseAction = 'remint' | 'stop' | 'retry';\n\nexport function classifyClose(code: number | undefined): CloseAction {\n if (code === undefined) return 'retry';\n if (code === WS_CLOSE_AUTH_REVOKED) return 'remint';\n if (code >= 4400 && code < 4500) return 'stop';\n return 'retry';\n}\n","/**\n * Collab-token mint client for Generic Doc assets.\n *\n * Calls `POST /api/v0/assets/{assetId}/collab-token` — the only public surface\n * that issues Keryx capability tokens, allowlisted server-side to the\n * `generic_doc` asset type and admin-only during the initial rollout. Tokens\n * are room-bound and short-lived; `connectGenericDoc` re-mints automatically\n * before expiry.\n */\n\nexport interface CollabAuth {\n /** Athena API base or any Athena backend URL (e.g. the AthenaProvider `backendUrl`). */\n backendUrl: string;\n /** Personal or sandbox API key. Used when no bearer token is provided. */\n apiKey?: string;\n /** Per-viewer bearer token. Takes precedence over the API key. */\n token?: string | null;\n}\n\nexport interface CollabTokenResponse {\n token: string;\n access_type: 'r' | 'rw';\n expires_at_ms: number;\n ws_url: string;\n rest_url: string;\n org: string;\n doc_id: string;\n branch: string;\n}\n\nexport class CollabTokenError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = 'CollabTokenError';\n this.status = status;\n }\n}\n\nfunction getAuthHeaders(auth: CollabAuth): Record<string, string> {\n if (auth.token) {\n return { Authorization: `Bearer ${auth.token}` };\n }\n if (auth.apiKey) {\n return { 'X-API-KEY': auth.apiKey };\n }\n return {};\n}\n\n/** Trim a nested Athena endpoint (e.g. `/api/assistant-ui`) back to the API origin. */\nexport function getAthenaApiBaseUrl(backendUrl: string): string {\n const stripped = backendUrl.replace(/\\/api\\/assistant-ui\\/?$/, '');\n return stripped.replace(/\\/$/, '');\n}\n\nexport async function mintCollabToken(args: {\n auth: CollabAuth;\n assetId: string;\n access: 'view' | 'edit';\n signal?: AbortSignal;\n}): Promise<CollabTokenResponse> {\n const base = getAthenaApiBaseUrl(args.auth.backendUrl);\n const response = await fetch(\n `${base}/api/v0/assets/${encodeURIComponent(args.assetId)}/collab-token`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...getAuthHeaders(args.auth),\n },\n body: JSON.stringify({ access: args.access }),\n signal: args.signal,\n }\n );\n if (!response.ok) {\n let detail = '';\n try {\n const body: unknown = await response.json();\n if (body && typeof body === 'object' && 'detail' in body) {\n detail = String((body as { detail: unknown }).detail);\n }\n } catch {\n // non-JSON error body; status alone tells the story\n }\n throw new CollabTokenError(\n response.status,\n detail || `Collab token mint failed with status ${response.status}`\n );\n }\n return (await response.json()) as CollabTokenResponse;\n}\n","/**\n * Vanilla (framework-agnostic) live client for Generic Doc assets.\n *\n * `connectGenericDoc` owns the full connection lifecycle: mint a room-bound\n * token via the public API, open the Keryx WebSocket with the v14 provider\n * (`@y/websocket` + `@y/y`), re-mint before expiry, apply the close-code\n * policy (4401 → one fresh mint, other 44xx → permanent stop, everything\n * else → provider backoff), and expose presence from awareness. React apps\n * use `useGenericDoc` from `@athenaintel/react/collab` instead of calling\n * this directly.\n */\n\nimport { WebsocketProvider } from '@y/websocket';\nimport * as Y from '@y/y';\nimport { classifyClose } from './close-policy';\nimport {\n type CollabAuth,\n type CollabTokenResponse,\n CollabTokenError,\n mintCollabToken,\n} from './mint';\n\nexport type GenericDocStatus =\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'closed'\n | 'error';\n\nexport interface PresenceEntry {\n clientId: number;\n state: Record<string, unknown>;\n}\n\nexport interface GenericDocHandle {\n /** The live shared document. Owned by the handle; destroyed with it. */\n readonly doc: Y.Doc;\n readonly status: GenericDocStatus;\n /** Granted access from the last successful mint. */\n readonly accessType: 'r' | 'rw' | null;\n /** Terminal error, when status is 'error' or 'closed'. */\n readonly error: Error | null;\n /** Monotonic change counter — bumps on every status/presence notification. */\n readonly version: number;\n getPresence: () => PresenceEntry[];\n /** Broadcast this client's presence state (requires a live connection). */\n setPresence: (state: Record<string, unknown> | null) => void;\n /**\n * Force an early token refresh. Session-preserving: the live connection\n * stays up until the fresh token is minted; a failed mint retries on a\n * short timer instead of dropping the session.\n */\n refreshNow: () => Promise<void>;\n onChange: (listener: () => void) => () => void;\n destroy: () => void;\n}\n\n/** Re-mint this long before token expiry (clamped to a floor for short TTLs). */\nconst REFRESH_HEADROOM_MS = 5 * 60 * 1000;\nconst MIN_REFRESH_DELAY_MS = 30 * 1000;\n\n/** Consecutive 4401→mint cycles allowed without a successful connect between. */\nconst MAX_CONSECUTIVE_REMINTS = 2;\n\nexport function connectGenericDoc(args: {\n assetId: string;\n auth: CollabAuth;\n access?: 'view' | 'edit';\n}): GenericDocHandle {\n const access = args.access ?? 'view';\n const doc = new Y.Doc();\n const listeners = new Set<() => void>();\n\n let provider: WebsocketProvider | null = null;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n let destroyed = false;\n let status: GenericDocStatus = 'connecting';\n let accessType: 'r' | 'rw' | null = null;\n let error: Error | null = null;\n let lastPresence: Record<string, unknown> | null = null;\n let version = 0;\n let consecutiveRemints = 0;\n\n const notify = () => {\n version += 1;\n for (const listener of listeners) listener();\n };\n\n const setStatus = (next: GenericDocStatus, err: Error | null = null) => {\n if (destroyed && next !== 'closed') return;\n status = next;\n error = err;\n notify();\n };\n\n const clearRefreshTimer = () => {\n if (refreshTimer !== null) {\n clearTimeout(refreshTimer);\n refreshTimer = null;\n }\n };\n\n const teardownProvider = () => {\n clearRefreshTimer();\n if (provider) {\n provider.destroy();\n provider = null;\n }\n };\n\n const scheduleRefresh = (grant: CollabTokenResponse) => {\n clearRefreshTimer();\n const delay = Math.max(\n grant.expires_at_ms - Date.now() - REFRESH_HEADROOM_MS,\n MIN_REFRESH_DELAY_MS\n );\n refreshTimer = setTimeout(() => {\n void connect({ scheduledRefresh: true });\n }, delay);\n };\n\n const connect = async (opts?: { scheduledRefresh?: boolean }): Promise<void> => {\n if (destroyed) return;\n const scheduledRefresh = opts?.scheduledRefresh === true;\n // A scheduled refresh mints FIRST and keeps the live session up: the old\n // token has ~5 minutes of headroom, so a transient mint failure retries\n // on a short timer instead of dropping a healthy connection.\n if (!scheduledRefresh) {\n teardownProvider();\n } else {\n clearRefreshTimer();\n }\n let grant: CollabTokenResponse;\n try {\n grant = await mintCollabToken({ auth: args.auth, assetId: args.assetId, access });\n } catch (err) {\n if (scheduledRefresh && !destroyed) {\n refreshTimer = setTimeout(() => {\n void connect({ scheduledRefresh: true });\n }, MIN_REFRESH_DELAY_MS);\n return;\n }\n // A denied mint is authoritative (revoked / not shared / not eligible);\n // anything else (network) is worth telling the caller about too — the\n // handle stays usable via a later explicit reconnect-by-recreate.\n setStatus('error', err instanceof Error ? err : new Error(String(err)));\n return;\n }\n if (destroyed) return;\n if (scheduledRefresh) {\n teardownProvider();\n }\n accessType = grant.access_type;\n\n const nextProvider = new WebsocketProvider(grant.ws_url, `${grant.org}/${grant.doc_id}`, doc, {\n params: {\n yauth: grant.token,\n branch: grant.branch,\n gc: 'true',\n },\n });\n provider = nextProvider;\n\n nextProvider.on('status', (event: { status: 'connecting' | 'connected' | 'disconnected' }) => {\n if (provider !== nextProvider) return;\n if (event.status === 'connected') {\n consecutiveRemints = 0;\n }\n setStatus(event.status);\n if (event.status === 'connected' && lastPresence !== null) {\n nextProvider.awareness.setLocalState(lastPresence);\n }\n });\n\n nextProvider.on('connection-close', (event: CloseEvent | null) => {\n if (provider !== nextProvider) return;\n const action = classifyClose(event?.code);\n if (action === 'remint') {\n // Revoked mid-session: a fresh mint re-runs the server-side permission\n // check. If access is truly gone the mint 403s and we land in 'error'.\n // Bounded: repeated 4401s without an intervening successful connect\n // mean the server keeps rejecting freshly minted tokens — stop rather\n // than loop mint→connect→kick.\n consecutiveRemints += 1;\n teardownProvider();\n if (consecutiveRemints > MAX_CONSECUTIVE_REMINTS) {\n setStatus(\n 'closed',\n new Error('Access repeatedly revoked mid-session (4401); giving up.')\n );\n return;\n }\n void connect();\n } else if (action === 'stop') {\n teardownProvider();\n setStatus(\n 'closed',\n new Error(`Connection closed permanently (code ${event?.code ?? 'unknown'})`)\n );\n }\n // 'retry': the provider's exponential backoff handles it.\n });\n\n nextProvider.awareness.on('change', () => {\n if (provider !== nextProvider) return;\n notify();\n });\n\n scheduleRefresh(grant);\n };\n\n void connect();\n\n return {\n doc,\n get status() {\n return status;\n },\n get accessType() {\n return accessType;\n },\n get error() {\n return error;\n },\n get version() {\n return version;\n },\n getPresence: () => {\n if (!provider) return [];\n const entries: PresenceEntry[] = [];\n provider.awareness.getStates().forEach((state, clientId) => {\n entries.push({ clientId, state: state as Record<string, unknown> });\n });\n return entries;\n },\n setPresence: (state) => {\n lastPresence = state;\n provider?.awareness.setLocalState(state);\n },\n refreshNow: () => connect({ scheduledRefresh: true }),\n onChange: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n destroy: () => {\n if (destroyed) return;\n destroyed = true;\n teardownProvider();\n listeners.clear();\n doc.destroy();\n status = 'closed';\n },\n };\n}\n\nexport { CollabTokenError };\nexport type { CollabAuth, CollabTokenResponse };\n","/**\n * React bindings for Generic Doc live collaboration.\n *\n * `useGenericDoc(assetId)` opens (and owns) a `connectGenericDoc` handle,\n * resolving auth from the surrounding `AthenaProvider` (per-viewer bearer when\n * present, API key otherwise) and re-rendering on status/presence changes via\n * `useSyncExternalStore`.\n */\n\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport { useAthenaConfig } from '../provider/AthenaContext';\nimport {\n type GenericDocHandle,\n type GenericDocStatus,\n type PresenceEntry,\n connectGenericDoc,\n} from './client';\nimport type * as Y from '@y/y';\n\nexport interface UseGenericDocResult {\n /** Null until the handle is created (first render effect). */\n doc: Y.Doc | null;\n status: GenericDocStatus;\n accessType: 'r' | 'rw' | null;\n error: Error | null;\n presence: PresenceEntry[];\n setPresence: (state: Record<string, unknown> | null) => void;\n}\n\nexport function useGenericDoc(\n assetId: string,\n options?: { access?: 'view' | 'edit' }\n): UseGenericDocResult {\n const config = useAthenaConfig();\n const access = options?.access ?? 'view';\n const [handle, setHandle] = useState<GenericDocHandle | null>(null);\n const handleRef = useRef<GenericDocHandle | null>(null);\n\n useEffect(() => {\n const next = connectGenericDoc({\n assetId,\n access,\n auth: {\n backendUrl: config.backendUrl,\n apiKey: config.apiKey,\n token: config.token,\n },\n });\n handleRef.current = next;\n setHandle(next);\n return () => {\n handleRef.current = null;\n next.destroy();\n };\n // Recreate when the target or credentials change; the handle re-mints on\n // its own schedule otherwise.\n }, [assetId, access, config.backendUrl, config.apiKey, config.token]);\n\n const subscribe = useMemo(() => {\n return (onStoreChange: () => void) => {\n if (!handle) return () => {};\n return handle.onChange(onStoreChange);\n };\n }, [handle]);\n\n const snapshot = useSyncExternalStore(\n subscribe,\n () => {\n if (!handle) return EMPTY_SNAPSHOT;\n return `${handle.status}|${handle.accessType ?? ''}|${handle.version}`;\n },\n () => EMPTY_SNAPSHOT\n );\n void snapshot;\n\n return {\n doc: handle?.doc ?? null,\n status: handle?.status ?? 'connecting',\n accessType: handle?.accessType ?? null,\n error: handle?.error ?? null,\n presence: handle?.getPresence() ?? [],\n setPresence: (state) => handleRef.current?.setPresence(state),\n };\n}\n\nconst EMPTY_SNAPSHOT = 'init||0';\n","/**\n * `defineDocShape` — a typed lens over a Generic Doc's root types.\n *\n * A shape is documentation + ergonomics, not a migration system: it names the\n * root keys an app expects and gives JSON-level reads (`toJSON`, `subscribe`)\n * that hide CRDT mechanics for the common case. The raw `Y.Doc` (yjs v14 /\n * `@y/y`) stays available on the handle for full delta-level power.\n */\n\nimport type * as Y from '@y/y';\n\nexport type DocShapeKind = 'map' | 'array' | 'text' | 'xml';\n\nexport interface BoundDocShape<S extends Record<string, DocShapeKind>> {\n /** The live root type for a declared key (v14 unified `YType`). */\n get: <K extends keyof S & string>(key: K) => ReturnType<Y.Doc['get']>;\n /** JSON snapshot of every declared root (v14 node shape: attributes + `children`). */\n toJSON: () => Record<keyof S & string, unknown>;\n /**\n * Subscribe to JSON snapshots. Fires once immediately, then after every\n * change to any declared root (batched per transaction flush).\n */\n subscribe: (listener: (json: Record<keyof S & string, unknown>) => void) => () => void;\n}\n\nexport function defineDocShape<S extends Record<string, DocShapeKind>>(shape: S) {\n const keys = Object.keys(shape) as Array<keyof S & string>;\n return {\n shape,\n bind(doc: Y.Doc): BoundDocShape<S> {\n const toJSON = () => {\n const out: Record<string, unknown> = {};\n for (const key of keys) {\n out[key] = doc.get(key).toJSON();\n }\n return out as Record<keyof S & string, unknown>;\n };\n return {\n get: (key) => doc.get(key),\n toJSON,\n subscribe: (listener) => {\n let scheduled = false;\n const emit = () => {\n scheduled = false;\n listener(toJSON());\n };\n const onDeepChange = () => {\n if (scheduled) return;\n scheduled = true;\n queueMicrotask(emit);\n };\n const roots = keys.map((key) => doc.get(key));\n for (const root of roots) {\n root.observeDeep(onDeepChange);\n }\n listener(toJSON());\n return () => {\n for (const root of roots) {\n root.unobserveDeep(onDeepChange);\n }\n };\n },\n };\n },\n };\n}\n"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -54,6 +54,7 @@ const reactLanggraph = require("@assistant-ui/react-langgraph");
54
54
  const reactStatewire = require("@assistant-ui/react-statewire");
55
55
  const store = require("@assistant-ui/store");
56
56
  const ReactDOM = require("react-dom");
57
+ const AthenaContext = require("./AthenaContext-B1QMhIP-.cjs");
57
58
  function _interopNamespaceDefault(e) {
58
59
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
59
60
  if (e) {
@@ -72,7 +73,7 @@ function _interopNamespaceDefault(e) {
72
73
  }
73
74
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
74
75
  const ReactDOM__namespace = /* @__PURE__ */ _interopNamespaceDefault(ReactDOM);
75
- const version$1 = "0.12.1";
76
+ const version$1 = "0.12.2";
76
77
  const packageJson = {
77
78
  version: version$1
78
79
  };
@@ -17057,14 +17058,6 @@ const DEFAULT_AUTO_OPEN_TOOLS = {
17057
17058
  CreateParagraph: openOnResult("document"),
17058
17059
  OpenDocument: openOnResult("document")
17059
17060
  };
17060
- const AthenaContext = React.createContext(null);
17061
- function useAthenaConfig() {
17062
- const ctx = React.useContext(AthenaContext);
17063
- if (!ctx) {
17064
- throw new Error("[AthenaSDK] useAthenaConfig must be used within <AthenaProvider>");
17065
- }
17066
- return ctx;
17067
- }
17068
17061
  const MAX_FALLBACK_TITLE_LENGTH = 50;
17069
17062
  const CONTENT_PART_TYPES = /* @__PURE__ */ new Set(["text", "image_url", "image"]);
17070
17063
  function isRecord(value) {
@@ -20498,7 +20491,7 @@ function AthenaStandalone({
20498
20491
  linkClicks,
20499
20492
  citationLinks
20500
20493
  });
20501
- return /* @__PURE__ */ jsxRuntime.jsx(react$1.AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children }) }) });
20494
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children }) }) });
20502
20495
  }
20503
20496
  const initialStatewireLifecycle = {
20504
20497
  connection: null,
@@ -20626,7 +20619,7 @@ function AthenaStatewireStandalone({
20626
20619
  linkClicks,
20627
20620
  citationLinks
20628
20621
  });
20629
- return /* @__PURE__ */ jsxRuntime.jsx(react$1.AuiProvider, { value: aui, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaStatewireLifecycleContext.Provider, { value: lifecycleValue, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipProvider, { children: [
20622
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.AuiProvider, { value: aui, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaStatewireLifecycleContext.Provider, { value: lifecycleValue, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipProvider, { children: [
20630
20623
  /* @__PURE__ */ jsxRuntime.jsx(StatewireClientToolBridge, { tools: clientTools, threadId }),
20631
20624
  children
20632
20625
  ] }) }) }) });
@@ -20803,7 +20796,7 @@ function AthenaWithThreadList({
20803
20796
  linkClicks,
20804
20797
  citationLinks
20805
20798
  });
20806
- return /* @__PURE__ */ jsxRuntime.jsx(react$1.AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(ThreadListRefreshContext.Provider, { value: handleRefresh, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipProvider, { children: [
20799
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(ThreadListRefreshContext.Provider, { value: handleRefresh, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipProvider, { children: [
20807
20800
  /* @__PURE__ */ jsxRuntime.jsx(
20808
20801
  ActiveThreadStateHydrator,
20809
20802
  {
@@ -53188,7 +53181,7 @@ const resolveAthenaLink = ({
53188
53181
  const useAthenaLinkClickHandler = () => {
53189
53182
  const openAsset = useAssetPanelStore((state) => state.openAsset);
53190
53183
  const isAssetPanelAvailable = useAssetPanelStore((state) => state.assetPanelHostCount > 0);
53191
- const athenaConfig = React.useContext(AthenaContext);
53184
+ const athenaConfig = React.useContext(AthenaContext.AthenaContext);
53192
53185
  const appUrl = athenaConfig == null ? void 0 : athenaConfig.appUrl;
53193
53186
  return React.useCallback(
53194
53187
  ({ href, linkText, target, nativeEvent }) => {
@@ -53261,7 +53254,7 @@ const useAthenaLinkClickHandler = () => {
53261
53254
  );
53262
53255
  };
53263
53256
  const useAthenaCitationLinkHandler = () => {
53264
- const athenaConfig = React.useContext(AthenaContext);
53257
+ const athenaConfig = React.useContext(AthenaContext.AthenaContext);
53265
53258
  const appUrl = athenaConfig == null ? void 0 : athenaConfig.appUrl;
53266
53259
  const handleLinkClick = useAthenaLinkClickHandler();
53267
53260
  return React.useCallback(
@@ -55913,7 +55906,7 @@ function ensurePastedImageFileName({
55913
55906
  }
55914
55907
  const MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024;
55915
55908
  function useFileUpload() {
55916
- const config2 = useAthenaConfig();
55909
+ const config2 = AthenaContext.useAthenaConfig();
55917
55910
  const configRef = React.useRef(config2);
55918
55911
  configRef.current = config2;
55919
55912
  const { backendUrl, apiKey } = config2;
@@ -56043,7 +56036,7 @@ const TiptapComposer = ({ tools = [], rootCategories }) => {
56043
56036
  } = useAttachments();
56044
56037
  const { upload } = useFileUpload();
56045
56038
  const { quote, clearQuote } = useQuote();
56046
- const { appUrl, transport } = useAthenaConfig();
56039
+ const { appUrl, transport } = AthenaContext.useAthenaConfig();
56047
56040
  const attachmentsRef = React.useRef(attachments);
56048
56041
  attachmentsRef.current = attachments;
56049
56042
  const quoteRef = React.useRef(quote);
@@ -60694,7 +60687,7 @@ function useFreshPresignedUrl({
60694
60687
  fallbackUrl
60695
60688
  }) {
60696
60689
  const [freshUrl, setFreshUrl] = React.useState(null);
60697
- const config2 = useAthenaConfig();
60690
+ const config2 = AthenaContext.useAthenaConfig();
60698
60691
  const configRef = React.useRef(config2);
60699
60692
  configRef.current = config2;
60700
60693
  React.useEffect(() => {
@@ -62138,7 +62131,7 @@ const AthenaChat = ({
62138
62131
  groupToolCalls = false
62139
62132
  }) => {
62140
62133
  var _a3, _b2, _c2;
62141
- const athenaConfig = useAthenaConfig();
62134
+ const athenaConfig = AthenaContext.useAthenaConfig();
62142
62135
  const providerMentionTools = React.useMemo(() => {
62143
62136
  const uniqueToolkitIds = Array.from(new Set(athenaConfig.enabledToolkits));
62144
62137
  return uniqueToolkitIds.map((id) => {
@@ -62299,7 +62292,7 @@ const ThreadScrollToBottom = () => /* @__PURE__ */ jsxRuntime.jsx(react$1.Thread
62299
62292
  }
62300
62293
  ) });
62301
62294
  const ComposerAction = () => {
62302
- const { transport } = useAthenaConfig();
62295
+ const { transport } = AthenaContext.useAthenaConfig();
62303
62296
  const queuesWhileRunning = allowsMidRunSend(transport);
62304
62297
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between", children: [
62305
62298
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsx(FileUploadButton, {}) }),
@@ -62321,7 +62314,7 @@ const ComposerAction = () => {
62321
62314
  };
62322
62315
  const ComposerSendWithQuote = () => {
62323
62316
  const aui = react$1.useAui();
62324
- const { appUrl, transport } = useAthenaConfig();
62317
+ const { appUrl, transport } = AthenaContext.useAthenaConfig();
62325
62318
  const { quote, clearQuote } = useQuote();
62326
62319
  const { attachments, clearAttachments, isUploading } = useAttachments();
62327
62320
  const editorRef = useComposerEditorRef();
@@ -62584,7 +62577,7 @@ const AthenaAssistantMessage = ({
62584
62577
  };
62585
62578
  const AthenaAssistantActionBar = ({ className }) => {
62586
62579
  const threadId = useAthenaThreadId();
62587
- const { appUrl } = useAthenaConfig();
62580
+ const { appUrl } = AthenaContext.useAthenaConfig();
62588
62581
  return /* @__PURE__ */ jsxRuntime.jsxs(
62589
62582
  react$1.ActionBarPrimitive.Root,
62590
62583
  {
@@ -63018,7 +63011,7 @@ const AthenaAssetEmbed = ({
63018
63011
  ...iframeProps
63019
63012
  }) => {
63020
63013
  const iframeRef = React.useRef(null);
63021
- const athenaConfig = useAthenaConfig();
63014
+ const athenaConfig = AthenaContext.useAthenaConfig();
63022
63015
  const { backendUrl, appUrl, apiKey } = athenaConfig;
63023
63016
  const { embedUrl, isLoading, error: error2 } = useAssetEmbed(assetId, {
63024
63017
  backendUrl,
@@ -63176,7 +63169,7 @@ const ASSET_TYPE_CONFIG = {
63176
63169
  const AssetIframe = React.memo(
63177
63170
  ({ tab }) => {
63178
63171
  const iframeRef = React.useRef(null);
63179
- const { backendUrl, appUrl, apiKey, token } = useAthenaConfig();
63172
+ const { backendUrl, appUrl, apiKey, token } = AthenaContext.useAthenaConfig();
63180
63173
  const { embedUrl, isLoading, error: error2 } = useAssetEmbed(tab.id, {
63181
63174
  backendUrl,
63182
63175
  appUrl,
@@ -63616,6 +63609,7 @@ function useComposerAttachment() {
63616
63609
  }, [aui]);
63617
63610
  return { addFile, addContent, clear };
63618
63611
  }
63612
+ exports.useAthenaConfig = AthenaContext.useAthenaConfig;
63619
63613
  exports.ATHENA_REACT_SDK_VERSION = ATHENA_REACT_SDK_VERSION;
63620
63614
  exports.ATHENA_SDK_ERROR_CODES = ATHENA_SDK_ERROR_CODES;
63621
63615
  exports.ATHENA_TRANSPORTS = ATHENA_TRANSPORTS;
@@ -63744,7 +63738,6 @@ exports.useAppendToComposer = useAppendToComposer;
63744
63738
  exports.useAssetEmbed = useAssetEmbed;
63745
63739
  exports.useAssetPanelStore = useAssetPanelStore;
63746
63740
  exports.useAthenaCitationLinkHandler = useAthenaCitationLinkHandler;
63747
- exports.useAthenaConfig = useAthenaConfig;
63748
63741
  exports.useAthenaDiagnostics = useAthenaDiagnostics;
63749
63742
  exports.useAthenaLinkClickHandler = useAthenaLinkClickHandler;
63750
63743
  exports.useAthenaRuntime = useAthenaRuntime;