@athenaintel/react 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -39
- package/dist/AthenaContext-B1QMhIP-.cjs.map +1 -1
- package/dist/AthenaContext-MOslgOmE.js.map +1 -1
- package/dist/chat/statewire-banners.d.ts +5 -9
- package/dist/chat-ui/index.d.ts +3 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +24 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +5 -0
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +1 -1
- package/dist/chat-ui/messages/continue-pill.d.ts +13 -0
- package/dist/chat-ui/messages/message-components.d.ts +7 -2
- package/dist/chat-ui/messages/runtime-message.d.ts +22 -0
- package/dist/chat-ui/messages/statewire-continue-run.d.ts +41 -0
- package/dist/chat-ui/thread/chat-composer-dock.d.ts +1 -1
- package/dist/chat-ui.cjs +279 -56
- package/dist/chat-ui.cjs.map +1 -1
- package/dist/chat-ui.js +312 -89
- package/dist/chat-ui.js.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +1 -1
- package/dist/diagnostics/errors.d.ts +0 -4
- package/dist/index.cjs +18834 -21869
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.js +18849 -21884
- package/dist/index.js.map +1 -1
- package/dist/lib/athena-urls.d.ts +0 -2
- package/dist/lib/posthog/wrap-posthog-client.d.ts +3 -1
- package/dist/provider/AthenaContext.d.ts +0 -7
- package/dist/provider/AthenaProvider.d.ts +25 -51
- package/dist/provider/config.d.ts +11 -14
- package/dist/provider/statewire-lifecycle-context.d.ts +3 -4
- package/dist/provider/types.d.ts +0 -1
- package/dist/runtime/statewire-lifecycle.d.ts +0 -1
- package/dist/runtime/statewire-run-config.d.ts +18 -5
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +6 -11
- package/dist/styles.css +1 -1
- package/dist/threads/ThreadList.d.ts +6 -1
- package/dist/threads/statewire-thread-list.d.ts +6 -5
- package/dist/threads/thread-id-context.d.ts +9 -0
- package/dist/threads/use-statewire-conversation-history.d.ts +2 -0
- package/dist/threads/useAthenaThreadManager.d.ts +24 -12
- package/dist/{use-rest-conversation-history-DpEswBqQ.js → use-rest-conversation-history-Bs5qn5G3.js} +7500 -6959
- package/dist/use-rest-conversation-history-Bs5qn5G3.js.map +1 -0
- package/dist/{use-rest-conversation-history-BdnG8jEP.cjs → use-rest-conversation-history-Dm0rdQgT.cjs} +7311 -6770
- package/dist/use-rest-conversation-history-Dm0rdQgT.cjs.map +1 -0
- package/package.json +3 -3
- package/dist/runtime/converter.d.ts +0 -5
- package/dist/runtime/external-message-converter.d.ts +0 -21
- package/dist/runtime/schemas.d.ts +0 -24
- package/dist/runtime/transport.d.ts +0 -39
- package/dist/runtime/useAthenaRuntime.d.ts +0 -47
- package/dist/threads/adapter.d.ts +0 -42
- package/dist/threads/useActiveThreadStateHydration.d.ts +0 -12
- package/dist/threads/useThreadTitlePolling.d.ts +0 -14
- package/dist/use-rest-conversation-history-BdnG8jEP.cjs.map +0 -1
- package/dist/use-rest-conversation-history-DpEswBqQ.js.map +0 -1
package/dist/chat-ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-ui.js","sources":["../../agent-runtime/src/asset-attachment.ts","../../../node_modules/lucide-react/dist/esm/icons/bot.js","../../../node_modules/lucide-react/dist/esm/icons/building-2.js","../../../node_modules/lucide-react/dist/esm/icons/cloud.js","../../../node_modules/lucide-react/dist/esm/icons/eye.js","../../../node_modules/lucide-react/dist/esm/icons/file-code.js","../../../node_modules/lucide-react/dist/esm/icons/headphones.js","../../../node_modules/lucide-react/dist/esm/icons/key.js","../../../node_modules/lucide-react/dist/esm/icons/keyboard.js","../../../node_modules/lucide-react/dist/esm/icons/layout-dashboard.js","../../../node_modules/lucide-react/dist/esm/icons/library.js","../../../node_modules/lucide-react/dist/esm/icons/mic.js","../../../node_modules/lucide-react/dist/esm/icons/palette.js","../../../node_modules/lucide-react/dist/esm/icons/panels-top-left.js","../../../node_modules/lucide-react/dist/esm/icons/pen-tool.js","../../../node_modules/lucide-react/dist/esm/icons/phone.js","../../../node_modules/lucide-react/dist/esm/icons/smartphone.js","../../../node_modules/lucide-react/dist/esm/icons/sparkles.js","../../../node_modules/lucide-react/dist/esm/icons/square-check-big.js","../../../node_modules/lucide-react/dist/esm/icons/star.js","../../../node_modules/lucide-react/dist/esm/icons/user.js","../../../node_modules/lucide-react/dist/esm/icons/video.js","../../../node_modules/lucide-react/dist/esm/icons/zap.js","../src/chat-ui/header/chat-header.tsx","../src/chat-ui/header/conversation-history-panel.tsx","../src/chat-ui/mentions/mention-extension.ts","../src/chat-ui/mentions/suggestions/mention-suggestions.extension.ts","../src/chat-ui/mentions/suggestions/components/mention-suggestion-popup.tsx","../src/chat-ui/mentions/suggestions/data/orchestrator.ts","../src/chat-ui/mentions/suggestions/data/use-menu-items.ts","../src/chat-ui/mentions/suggestions/components/get-scope-name.ts","../src/chat-ui/mentions/suggestions/data/types.ts","../src/chat-ui/mentions/suggestions/components/mention-icon.tsx","../src/chat-ui/mentions/suggestions/components/menu-item.tsx","../src/chat-ui/mentions/suggestions/components/menu-skeleton.tsx","../src/chat-ui/mentions/suggestions/components/menu-list.tsx","../src/chat-ui/mentions/suggestions/components/menu-breadcrumbs.tsx","../src/chat-ui/mentions/suggestions/components/menu-summary.tsx","../src/chat-ui/mentions/suggestions/components/use-keyboard-navigation.ts","../src/chat-ui/mentions/suggestions/components/use-menu-navigation.ts","../src/chat-ui/mentions/suggestions/components/utils.ts","../src/chat-ui/mentions/suggestions/components/mention-suggestion-list.tsx","../src/chat-ui/mentions/suggestions/data/sources/index.ts","../src/chat-ui/mentions/suggestions/data/use-mention-suggestions.ts","../src/chat-ui/composer/pending-attachment-uploads.ts","../src/chat-ui/composer/tiptap-composer.tsx","../src/chat-ui/auth/sign-in-card.tsx"],"sourcesContent":["import type {\n Attachment,\n AttachmentAdapter,\n CompleteAttachment,\n PendingAttachment,\n} from '@assistant-ui/core';\n\n/**\n * Shared Athena asset-attachment choreography (issue #29088): upload the file\n * as a normal Athena asset, insert its final mention into the host composer,\n * and yield no assistant-ui attachment tile — the deep-agent backend resolves\n * the mention (documents via read_asset, images inlined server-side), so no\n * duplicate base64 part ever enters statewire. No preparation state rides the\n * wire: readiness is local to the composer doing the attaching.\n */\n\nexport interface UploadedChatAsset {\n id: string;\n title: string;\n assetType: string;\n}\n\n/** Composer mention-insertion hook. The return value is awaited when it is a\n * promise and otherwise ignored, so ordinary event-handler arrows fit. */\nexport type ChatAssetMentionHandler = (asset: UploadedChatAsset) => unknown;\n\nconst mentionHandlersByThread = new Map<string, ChatAssetMentionHandler>();\n\n/**\n * Register the composer's mention-insertion hook for one thread. The hook is\n * the per-client seam — TipTap on web, the native editor bridge on mobile —\n * and the identity-checked unregister keeps a stale composer from clobbering\n * a newer registration.\n */\nexport function registerChatAssetMentionHandler(\n threadId: string,\n handler: ChatAssetMentionHandler\n): () => void {\n mentionHandlersByThread.set(threadId, handler);\n return () => {\n if (mentionHandlersByThread.get(threadId) === handler) {\n mentionHandlersByThread.delete(threadId);\n }\n };\n}\n\nexport function getChatAssetMentionHandler(\n threadId: string\n): ChatAssetMentionHandler | undefined {\n return mentionHandlersByThread.get(threadId);\n}\n\nexport interface ChatAssetUploadResponse {\n success?: Array<{\n id?: unknown;\n title?: unknown;\n file_name?: unknown;\n athena_original_type?: unknown;\n }>;\n}\n\n/**\n * Map agora's `/api/upload/` response to the mention payload. Title falls\n * back `title → file_name → local file name`; the asset type falls back to\n * the caller's sniffed default when the row carries none.\n */\nexport function uploadedChatAsset(args: {\n body: ChatAssetUploadResponse;\n fallbackTitle: string;\n fallbackAssetType: string;\n}): UploadedChatAsset {\n const row = args.body.success?.[0];\n if (!row || typeof row.id !== 'string') {\n throw new Error('The upload finished without creating an asset.');\n }\n const title =\n typeof row.title === 'string' && row.title.trim()\n ? row.title\n : typeof row.file_name === 'string' && row.file_name.trim()\n ? row.file_name\n : args.fallbackTitle;\n return {\n id: row.id,\n title,\n assetType:\n typeof row.athena_original_type === 'string' && row.athena_original_type.length > 0\n ? row.athena_original_type\n : args.fallbackAssetType,\n };\n}\n\n/** The local default when the upload response carries no asset type. */\nexport function sniffAssetTypeForFile(file: { type: string }): string {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type === 'application/pdf') return 'pdf';\n return 'file';\n}\n\nexport interface UploadChatAssetOptions {\n /** Agora base URL (trailing slashes tolerated). */\n baseUrl: string;\n file: File;\n /** Auth headers for the upload request. */\n headers: () => Promise<Record<string, string>> | Record<string, string>;\n /**\n * Fresh headers for exactly one retry after a 401 (e.g. a force-renewed\n * token). Omitted, a 401 fails like any other error status.\n */\n retryHeadersOn401?: () => Promise<Record<string, string>> | Record<string, string>;\n /** Upload timeout; the request aborts (and the add() rejects) past it. */\n timeoutMs?: number;\n}\n\nconst DEFAULT_UPLOAD_TIMEOUT_MS = 60_000;\n\nasync function uploadOnce(\n options: UploadChatAssetOptions,\n headers: Record<string, string>\n): Promise<Response> {\n const form = new FormData();\n form.append('files', options.file, options.file.name);\n return fetch(`${options.baseUrl.replace(/\\/+$/, '')}/api/upload/`, {\n method: 'POST',\n headers,\n body: form,\n signal: AbortSignal.timeout(options.timeoutMs ?? DEFAULT_UPLOAD_TIMEOUT_MS),\n });\n}\n\n/**\n * Upload one file as an Athena asset through agora's `/api/upload/`.\n * Cancellation and the timeout live inside the adapter path by construction:\n * the abort signal rejects the `add()` generator, so the composer's send\n * (which awaits adapter completion) can never race a hung upload.\n */\nexport async function uploadChatAsset(\n options: UploadChatAssetOptions\n): Promise<UploadedChatAsset> {\n let response = await uploadOnce(options, await options.headers());\n if (response.status === 401 && options.retryHeadersOn401) {\n response = await uploadOnce(options, await options.retryHeadersOn401());\n }\n if (!response.ok) {\n const detail = await response.text().catch(() => '');\n throw new Error(\n `Attachment upload failed (${response.status})${\n detail ? `: ${detail.slice(0, 200)}` : ''\n }`\n );\n }\n return uploadedChatAsset({\n body: (await response.json()) as ChatAssetUploadResponse,\n fallbackTitle: options.file.name,\n fallbackAssetType: sniffAssetTypeForFile(options.file),\n });\n}\n\nexport interface AthenaAssetAttachmentAdapterOptions {\n threadId: string;\n /** File-picker filter; defaults to images (the deep-agent mention path). */\n accept?: string;\n /** Platform upload transport; most hosts wrap {@link uploadChatAsset}. */\n upload: (file: File) => Promise<UploadedChatAsset>;\n}\n\n/**\n * The shared mention-backed attachment adapter: `add()` requires the thread's\n * registered composer hook up front (no upload cost when the composer is\n * gone), uploads, then inserts the mention into the thread's CURRENT hook —\n * a same-thread composer remount mid-upload still receives the mention, and\n * the thread-keyed registry makes cross-thread insertion impossible by\n * construction. A thread whose hook is gone after the upload rejects with a\n * visible error (the conversation closed; the user must re-attach).\n * `send()` throws by contract: mention-backed attachments are never message\n * parts.\n */\nexport class AthenaAssetAttachmentAdapter implements AttachmentAdapter {\n readonly accept: string;\n\n constructor(private readonly options: AthenaAssetAttachmentAdapterOptions) {\n this.accept = options.accept ?? 'image/*';\n }\n\n // eslint-disable-next-line require-yield -- mention-backed uploads deliberately create no attachment tile\n async *add(args: { file: File }): AsyncGenerator<PendingAttachment, void> {\n const handler = getChatAssetMentionHandler(this.options.threadId);\n if (handler === undefined) {\n throw new Error('The original conversation is no longer open.');\n }\n const uploaded = await this.options.upload(args.file);\n const current = getChatAssetMentionHandler(this.options.threadId);\n if (current === undefined) {\n throw new Error('The original conversation is no longer open.');\n }\n await current(uploaded);\n }\n\n async remove(_attachment: Attachment): Promise<void> {}\n\n async send(_attachment: PendingAttachment): Promise<CompleteAttachment> {\n throw new Error('Mention-backed attachments are not sent as message parts.');\n }\n}\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 8V4H8\", key: \"hb8ula\" }],\n [\"rect\", { width: \"16\", height: \"12\", x: \"4\", y: \"8\", rx: \"2\", key: \"enze0r\" }],\n [\"path\", { d: \"M2 14h2\", key: \"vft8re\" }],\n [\"path\", { d: \"M20 14h2\", key: \"4cs60a\" }],\n [\"path\", { d: \"M15 13v2\", key: \"1xurst\" }],\n [\"path\", { d: \"M9 13v2\", key: \"rq6x2g\" }]\n];\nconst Bot = createLucideIcon(\"bot\", __iconNode);\n\nexport { __iconNode, Bot as default };\n//# sourceMappingURL=bot.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 12h4\", key: \"a56b0p\" }],\n [\"path\", { d: \"M10 8h4\", key: \"1sr2af\" }],\n [\"path\", { d: \"M14 21v-3a2 2 0 0 0-4 0v3\", key: \"1rgiei\" }],\n [\n \"path\",\n {\n d: \"M6 10H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-2\",\n key: \"secmi2\"\n }\n ],\n [\"path\", { d: \"M6 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16\", key: \"16ra0t\" }]\n];\nconst Building2 = createLucideIcon(\"building-2\", __iconNode);\n\nexport { __iconNode, Building2 as default };\n//# sourceMappingURL=building-2.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z\", key: \"p7xjir\" }]\n];\nconst Cloud = createLucideIcon(\"cloud\", __iconNode);\n\nexport { __iconNode, Cloud as default };\n//# sourceMappingURL=cloud.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n];\nconst Eye = createLucideIcon(\"eye\", __iconNode);\n\nexport { __iconNode, Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"path\", { d: \"M10 12.5 8 15l2 2.5\", key: \"1tg20x\" }],\n [\"path\", { d: \"m14 12.5 2 2.5-2 2.5\", key: \"yinavb\" }]\n];\nconst FileCode = createLucideIcon(\"file-code\", __iconNode);\n\nexport { __iconNode, FileCode as default };\n//# sourceMappingURL=file-code.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3\",\n key: \"1xhozi\"\n }\n ]\n];\nconst Headphones = createLucideIcon(\"headphones\", __iconNode);\n\nexport { __iconNode, Headphones as default };\n//# sourceMappingURL=headphones.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n];\nconst Key = createLucideIcon(\"key\", __iconNode);\n\nexport { __iconNode, Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 8h.01\", key: \"1r9ogq\" }],\n [\"path\", { d: \"M12 12h.01\", key: \"1mp3jc\" }],\n [\"path\", { d: \"M14 8h.01\", key: \"1primd\" }],\n [\"path\", { d: \"M16 12h.01\", key: \"1l6xoz\" }],\n [\"path\", { d: \"M18 8h.01\", key: \"emo2bl\" }],\n [\"path\", { d: \"M6 8h.01\", key: \"x9i8wu\" }],\n [\"path\", { d: \"M7 16h10\", key: \"wp8him\" }],\n [\"path\", { d: \"M8 12h.01\", key: \"czm47f\" }],\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }]\n];\nconst Keyboard = createLucideIcon(\"keyboard\", __iconNode);\n\nexport { __iconNode, Keyboard as default };\n//# sourceMappingURL=keyboard.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"9\", x: \"3\", y: \"3\", rx: \"1\", key: \"10lvy0\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"14\", y: \"3\", rx: \"1\", key: \"16une8\" }],\n [\"rect\", { width: \"7\", height: \"9\", x: \"14\", y: \"12\", rx: \"1\", key: \"1hutg5\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"ldoo1y\" }]\n];\nconst LayoutDashboard = createLucideIcon(\"layout-dashboard\", __iconNode);\n\nexport { __iconNode, LayoutDashboard as default };\n//# sourceMappingURL=layout-dashboard.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m16 6 4 14\", key: \"ji33uf\" }],\n [\"path\", { d: \"M12 6v14\", key: \"1n7gus\" }],\n [\"path\", { d: \"M8 8v12\", key: \"1gg7y9\" }],\n [\"path\", { d: \"M4 4v16\", key: \"6qkkli\" }]\n];\nconst Library = createLucideIcon(\"library\", __iconNode);\n\nexport { __iconNode, Library as default };\n//# sourceMappingURL=library.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 19v3\", key: \"npa21l\" }],\n [\"path\", { d: \"M19 10v2a7 7 0 0 1-14 0v-2\", key: \"1vc78b\" }],\n [\"rect\", { x: \"9\", y: \"2\", width: \"6\", height: \"13\", rx: \"3\", key: \"s6n7sd\" }]\n];\nconst Mic = createLucideIcon(\"mic\", __iconNode);\n\nexport { __iconNode, Mic as default };\n//# sourceMappingURL=mic.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\",\n key: \"e79jfc\"\n }\n ],\n [\"circle\", { cx: \"13.5\", cy: \"6.5\", r: \".5\", fill: \"currentColor\", key: \"1okk4w\" }],\n [\"circle\", { cx: \"17.5\", cy: \"10.5\", r: \".5\", fill: \"currentColor\", key: \"f64h9f\" }],\n [\"circle\", { cx: \"6.5\", cy: \"12.5\", r: \".5\", fill: \"currentColor\", key: \"qy21gx\" }],\n [\"circle\", { cx: \"8.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"fotxhn\" }]\n];\nconst Palette = createLucideIcon(\"palette\", __iconNode);\n\nexport { __iconNode, Palette as default };\n//# sourceMappingURL=palette.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M9 21V9\", key: \"1oto5p\" }]\n];\nconst PanelsTopLeft = createLucideIcon(\"panels-top-left\", __iconNode);\n\nexport { __iconNode, PanelsTopLeft as default };\n//# sourceMappingURL=panels-top-left.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\",\n key: \"nt11vn\"\n }\n ],\n [\n \"path\",\n {\n d: \"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18\",\n key: \"15qc1e\"\n }\n ],\n [\"path\", { d: \"m2.3 2.3 7.286 7.286\", key: \"1wuzzi\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"2\", key: \"xmgehs\" }]\n];\nconst PenTool = createLucideIcon(\"pen-tool\", __iconNode);\n\nexport { __iconNode, PenTool as default };\n//# sourceMappingURL=pen-tool.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384\",\n key: \"9njp5v\"\n }\n ]\n];\nconst Phone = createLucideIcon(\"phone\", __iconNode);\n\nexport { __iconNode, Phone as default };\n//# sourceMappingURL=phone.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"14\", height: \"20\", x: \"5\", y: \"2\", rx: \"2\", ry: \"2\", key: \"1yt0o3\" }],\n [\"path\", { d: \"M12 18h.01\", key: \"mhygvu\" }]\n];\nconst Smartphone = createLucideIcon(\"smartphone\", __iconNode);\n\nexport { __iconNode, Smartphone as default };\n//# sourceMappingURL=smartphone.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\",\n key: \"1s2grr\"\n }\n ],\n [\"path\", { d: \"M20 2v4\", key: \"1rf3ol\" }],\n [\"path\", { d: \"M22 4h-4\", key: \"gwowj6\" }],\n [\"circle\", { cx: \"4\", cy: \"20\", r: \"2\", key: \"6kqj1y\" }]\n];\nconst Sparkles = createLucideIcon(\"sparkles\", __iconNode);\n\nexport { __iconNode, Sparkles as default };\n//# sourceMappingURL=sparkles.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M21 10.656V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h12.344\", key: \"2acyp4\" }\n ],\n [\"path\", { d: \"m9 11 3 3L22 4\", key: \"1pflzl\" }]\n];\nconst SquareCheckBig = createLucideIcon(\"square-check-big\", __iconNode);\n\nexport { __iconNode, SquareCheckBig as default };\n//# sourceMappingURL=square-check-big.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\",\n key: \"r04s7s\"\n }\n ]\n];\nconst Star = createLucideIcon(\"star\", __iconNode);\n\nexport { __iconNode, Star as default };\n//# sourceMappingURL=star.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\", key: \"975kel\" }],\n [\"circle\", { cx: \"12\", cy: \"7\", r: \"4\", key: \"17ys0d\" }]\n];\nconst User = createLucideIcon(\"user\", __iconNode);\n\nexport { __iconNode, User as default };\n//# sourceMappingURL=user.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\",\n key: \"ftymec\"\n }\n ],\n [\"rect\", { x: \"2\", y: \"6\", width: \"14\", height: \"12\", rx: \"2\", key: \"158x01\" }]\n];\nconst Video = createLucideIcon(\"video\", __iconNode);\n\nexport { __iconNode, Video as default };\n//# sourceMappingURL=video.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\",\n key: \"1xq2db\"\n }\n ]\n];\nconst Zap = createLucideIcon(\"zap\", __iconNode);\n\nexport { __iconNode, Zap as default };\n//# sourceMappingURL=zap.js.map\n","import type { ReactNode } from 'react';\nimport { cn } from '../../lib/utils';\nimport {\n THREAD_HEADER_ACTIONS_CLASS,\n THREAD_HEADER_CLASS,\n THREAD_HEADER_PILL_CLASS,\n} from '../messages/message-components';\n\nexport function ChatHeaderRoot({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return <div className={cn(THREAD_HEADER_CLASS, className)}>{children}</div>;\n}\n\nexport function ChatHeaderIdentity({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return <div className={cn(THREAD_HEADER_PILL_CLASS, className)}>{children}</div>;\n}\n\nexport function ChatHeaderActions({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return <div className={cn(THREAD_HEADER_ACTIONS_CLASS, className)}>{children}</div>;\n}\n\n/** Composition API keeps each host's exact action order visible at call sites. */\nexport const ChatHeader = {\n Root: ChatHeaderRoot,\n Identity: ChatHeaderIdentity,\n Actions: ChatHeaderActions,\n};\n","import type { ConversationSummary } from \"@athenaintel/agent-runtime\";\nimport {\n ArchiveIcon,\n BotIcon,\n LoaderCircleIcon,\n MessageSquareIcon,\n PlusIcon,\n RefreshCwIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport { useMemo, type ChangeEvent } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { conversationDisplayTitle } from \"../../threads/use-rest-conversation-history\";\nimport { assetTypeToThumb } from \"../mentions/suggestions/data/sources/asset-type-icons\";\n\nexport type ConversationActivityFilter = \"all\" | \"chat\" | \"automated\";\nexport type ConversationTimeGroup =\n | \"Today\"\n | \"Yesterday\"\n | \"This Week\"\n | \"This Month\"\n | \"Older\";\n\nconst TIME_GROUPS: readonly ConversationTimeGroup[] = [\n \"Today\",\n \"Yesterday\",\n \"This Week\",\n \"This Month\",\n \"Older\",\n];\n\nconst AUTOMATED_SOURCE_CHANNELS = new Set([\n \"api\",\n \"email\",\n \"orchestration\",\n \"slack\",\n \"sms\",\n \"task\",\n \"teams\",\n]);\n\n/** Mirrors Agora's persisted background-run classification for list metadata. */\nexport function isAutomatedConversation(\n conversation: Pick<ConversationSummary, \"sourceChannel\" | \"triggerType\">,\n): boolean {\n const sourceChannel = conversation.sourceChannel?.trim().toLowerCase();\n if (sourceChannel && AUTOMATED_SOURCE_CHANNELS.has(sourceChannel))\n return true;\n const triggerType = conversation.triggerType?.trim().toLowerCase();\n return Boolean(triggerType && triggerType !== \"manual\");\n}\n\nexport function conversationTimeGroup(\n value: string,\n now: Date = new Date(),\n): ConversationTimeGroup {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return \"Older\";\n const startOfToday = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n );\n const startOfYesterday = new Date(startOfToday.getTime() - 86_400_000);\n const startOfWeek = new Date(\n startOfToday.getTime() - startOfToday.getDay() * 86_400_000,\n );\n const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);\n if (date >= startOfToday) return \"Today\";\n if (date >= startOfYesterday) return \"Yesterday\";\n if (date >= startOfWeek) return \"This Week\";\n if (date >= startOfMonth) return \"This Month\";\n return \"Older\";\n}\n\nexport interface ConversationHistoryPanelProps {\n conversations: readonly ConversationSummary[];\n activeThreadId: string;\n search: string;\n onSearchChange: (search: string) => void;\n activityFilter: ConversationActivityFilter;\n onActivityFilterChange: (filter: ConversationActivityFilter) => void;\n originFilter: string;\n onOriginFilterChange: (origin: string) => void;\n onSelect: (threadId: string) => void;\n onNewChat: () => void;\n onRefresh: () => void;\n onArchive: (threadId: string) => void;\n onSetReadState: (threadId: string, isUnread: boolean) => void;\n isLoading?: boolean;\n isRefreshing?: boolean;\n hasNextPage?: boolean;\n isFetchingNextPage?: boolean;\n onLoadMore?: () => void;\n}\n\nfunction originKey(conversation: ConversationSummary): string {\n return conversation.appId ?? conversation.sourceChannel ?? \"unknown\";\n}\n\nfunction originLabel(value: string): string {\n const normalized = value.toLowerCase();\n if (normalized.includes(\"chrome\")) return \"Chrome\";\n if (normalized.includes(\"powerpoint\")) return \"PowerPoint\";\n if (normalized.includes(\"word\")) return \"Word\";\n if (normalized.includes(\"excel\")) return \"Excel\";\n if (normalized.includes(\"office\")) return \"Office\";\n if (normalized === \"web\" || normalized.includes(\"olympus\")) return \"Athena\";\n if (normalized.includes(\"mobile\")) return \"Mobile\";\n if (value === \"unknown\") return \"Legacy\";\n return value.replace(/^athena[-_]/, \"\").replaceAll(\"_\", \" \");\n}\n\nfunction relativeTime(value: string): string {\n const timestamp = Date.parse(value);\n if (!Number.isFinite(timestamp)) return \"\";\n const elapsed = Math.max(0, Date.now() - timestamp);\n const minutes = Math.floor(elapsed / 60_000);\n if (minutes < 1) return \"<1m ago\";\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ${minutes % 60}m ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : new Date(timestamp).toLocaleDateString();\n}\n\nfunction ConversationTypeIcon({\n conversation,\n automated,\n}: {\n conversation: ConversationSummary;\n automated: boolean;\n}) {\n if (conversation.state === \"running\") {\n return (\n <LoaderCircleIcon\n aria-label=\"Conversation running\"\n className=\"mt-0.5 size-4 shrink-0 animate-spin text-primary\"\n />\n );\n }\n const thumbnail = assetTypeToThumb(conversation.assetType ?? \"session\");\n if (thumbnail) {\n return <img src={thumbnail} alt=\"\" className=\"mt-0.5 size-4 shrink-0\" />;\n }\n return automated ? (\n <BotIcon className=\"mt-0.5 size-4 shrink-0 text-primary\" />\n ) : (\n <MessageSquareIcon className=\"mt-0.5 size-4 shrink-0 text-emerald-500\" />\n );\n}\n\nexport function ConversationHistoryPanel({\n conversations,\n activeThreadId,\n search,\n onSearchChange,\n activityFilter,\n onActivityFilterChange,\n originFilter,\n onOriginFilterChange,\n onSelect,\n onNewChat,\n onRefresh,\n onArchive,\n onSetReadState,\n isLoading = false,\n isRefreshing = false,\n hasNextPage = false,\n isFetchingNextPage = false,\n onLoadMore,\n}: ConversationHistoryPanelProps) {\n const origins = useMemo(\n () => [...new Set(conversations.map(originKey))].sort(),\n [conversations],\n );\n const grouped = useMemo(() => {\n const visible = conversations.filter((conversation) => {\n const automated = isAutomatedConversation(conversation);\n if (activityFilter === \"chat\" && automated) return false;\n if (activityFilter === \"automated\" && !automated) return false;\n return originFilter === \"all\" || originKey(conversation) === originFilter;\n });\n const byGroup = new Map<ConversationTimeGroup, ConversationSummary[]>();\n for (const conversation of visible) {\n const group = conversationTimeGroup(conversation.updatedAt);\n const items = byGroup.get(group) ?? [];\n items.push(conversation);\n byGroup.set(group, items);\n }\n return TIME_GROUPS.flatMap((group) => {\n const items = byGroup.get(group);\n return items ? [{ group, items }] : [];\n });\n }, [activityFilter, conversations, originFilter]);\n const visibleCount = grouped.reduce(\n (count, group) => count + group.items.length,\n 0,\n );\n const handleSearch = (event: ChangeEvent<HTMLInputElement>) =>\n onSearchChange(event.target.value);\n\n return (\n <section\n aria-label=\"Conversation history\"\n className=\"border-b border-border bg-background px-2 pb-2\"\n data-testid=\"conversation-history-panel\"\n >\n <div className=\"flex h-10 items-center gap-1.5 px-1\">\n <h2 className=\"text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground\">\n Sessions\n </h2>\n <button\n type=\"button\"\n aria-label=\"Refresh sessions\"\n title=\"Refresh sessions\"\n disabled={isRefreshing}\n onClick={onRefresh}\n className=\"ml-auto rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50\"\n >\n <RefreshCwIcon\n className={cn(\"size-3.5\", isRefreshing && \"animate-spin\")}\n />\n </button>\n <button\n type=\"button\"\n onClick={onNewChat}\n className=\"flex h-7 shrink-0 items-center gap-1 rounded-md bg-primary px-2 text-[11px] font-medium text-primary-foreground\"\n >\n <PlusIcon className=\"size-3\" /> New\n </button>\n </div>\n <label className=\"relative block min-w-0 px-1 pb-2\">\n <SearchIcon className=\"pointer-events-none absolute left-3 top-1/2 size-3.5 -translate-y-[calc(50%+0.25rem)] text-muted-foreground\" />\n <span className=\"sr-only\">Search sessions</span>\n <input\n value={search}\n onChange={handleSearch}\n placeholder=\"Search sessions...\"\n className=\"h-8 w-full rounded-md border border-border bg-muted/40 pl-7 pr-2 text-xs outline-none focus:border-primary focus:bg-background\"\n />\n </label>\n <div className=\"flex gap-1 overflow-x-auto px-1 pb-2 text-[11px]\">\n {([\"all\", \"chat\", \"automated\"] as const).map((filter) => (\n <button\n key={filter}\n type=\"button\"\n onClick={() => onActivityFilterChange(filter)}\n className={cn(\n \"rounded-full border px-2 py-1 capitalize\",\n activityFilter === filter\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground\",\n )}\n >\n {filter === \"chat\"\n ? \"Chats\"\n : filter === \"automated\"\n ? \"Automations\"\n : \"All\"}\n </button>\n ))}\n <select\n aria-label=\"Filter by origin\"\n value={originFilter}\n onChange={(event) => onOriginFilterChange(event.target.value)}\n className=\"ml-auto rounded-full border border-border bg-background px-2 text-[11px] text-muted-foreground\"\n >\n <option value=\"all\">All origins</option>\n {origins.map((origin) => (\n <option key={origin} value={origin}>\n {originLabel(origin)}\n </option>\n ))}\n </select>\n </div>\n <div className=\"max-h-[min(60vh,28rem)] overflow-y-auto px-0.5\">\n {isLoading ? (\n <div className=\"flex items-center gap-2 px-2 py-4 text-xs text-muted-foreground\">\n <LoaderCircleIcon className=\"size-3.5 animate-spin\" /> Loading\n sessions…\n </div>\n ) : visibleCount === 0 ? (\n <p className=\"px-2 py-4 text-xs text-muted-foreground\">\n No matching sessions.\n </p>\n ) : (\n grouped.map(({ group, items }) => (\n <div key={group}>\n <h3 className=\"px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground/75\">\n {group}\n </h3>\n {items.map((conversation) => {\n const automated = isAutomatedConversation(conversation);\n return (\n <div\n key={conversation.threadId}\n className={cn(\n \"group flex items-start gap-2 rounded-md px-2 py-2 hover:bg-accent\",\n conversation.threadId === activeThreadId &&\n \"bg-primary/10 text-primary\",\n )}\n >\n <button\n type=\"button\"\n onClick={() => {\n onSelect(conversation.threadId);\n if (conversation.isUnread) {\n onSetReadState(conversation.threadId, false);\n }\n }}\n className=\"flex min-w-0 flex-1 items-start gap-2 text-left\"\n >\n <ConversationTypeIcon\n conversation={conversation}\n automated={automated}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-start gap-1\">\n <span className=\"line-clamp-2 flex-1 text-xs font-medium leading-snug\">\n {conversationDisplayTitle(conversation)}\n </span>\n {conversation.isUnread ? (\n <span\n aria-label=\"Unread\"\n className=\"mt-1 size-1.5 shrink-0 rounded-full bg-primary\"\n />\n ) : null}\n </span>\n <span className=\"mt-0.5 flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n <span>{relativeTime(conversation.updatedAt)}</span>\n <span aria-hidden=\"true\">·</span>\n <span className=\"truncate\">\n {originLabel(originKey(conversation))}\n </span>\n </span>\n </span>\n </button>\n <button\n type=\"button\"\n aria-label={`Archive ${conversationDisplayTitle(conversation)}`}\n title=\"Archive conversation\"\n onClick={() => onArchive(conversation.threadId)}\n className=\"invisible rounded p-1 text-muted-foreground hover:bg-background hover:text-foreground group-hover:visible focus:visible\"\n >\n <ArchiveIcon className=\"size-3.5\" />\n </button>\n </div>\n );\n })}\n </div>\n ))\n )}\n {hasNextPage ? (\n <button\n type=\"button\"\n disabled={isFetchingNextPage}\n onClick={onLoadMore}\n className=\"mt-1 w-full rounded-lg py-2 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50\"\n >\n {isFetchingNextPage ? \"Loading…\" : \"Load older sessions\"}\n </button>\n ) : visibleCount > 0 ? (\n <p className=\"py-2 text-center text-[10px] text-muted-foreground/70\">\n No more sessions\n </p>\n ) : null}\n </div>\n </section>\n );\n}\n","/**\n * Tiptap Mention Node Extension\n *\n * Defines the mention node type used in the editor. When a mention is\n * inserted, it creates a non-editable inline node with metadata.\n *\n * Renders as a chip with: [icon] Name\n */\n\nimport { mergeAttributes, Node } from \"@tiptap/core\";\n\nexport function makeMentionUrl(attrs: { id: string; type: string; name: string; title?: string; url?: string; description?: string; thumbnailUrl?: string; assetType?: string }): string {\n if (attrs.type === \"tool\") {\n return `mention://tool?name=${encodeURIComponent(attrs.id)}&description=${encodeURIComponent(attrs.description ?? \"\")}`;\n }\n if (attrs.type === \"asset\") {\n const params = new URLSearchParams({ asset_ids: attrs.id });\n if (attrs.assetType) params.set(\"assetType\", attrs.assetType);\n return `/dashboard/spaces?${params.toString()}`;\n }\n if (attrs.type === \"tab\") {\n const params = new URLSearchParams({\n tab_id: attrs.id,\n url: attrs.url ?? \"\",\n title: attrs.title ?? attrs.name,\n });\n return `mention://webpage?${params.toString()}`;\n }\n // Include athenaOriginalType and thumbnailUrl so the chip can be reconstructed\n const params = new URLSearchParams();\n params.set(\"id\", attrs.id);\n if (attrs.assetType) params.set(\"assetType\", attrs.assetType);\n if (attrs.thumbnailUrl) params.set(\"thumb\", attrs.thumbnailUrl);\n return `mention://${encodeURIComponent(attrs.type)}?${params.toString()}`;\n}\n\nexport interface MentionNodeAttrs {\n type: string;\n name: string;\n id: string;\n title?: string;\n url?: string;\n description?: string;\n thumbnailUrl?: string;\n fallbackIcon?: string;\n assetType?: string;\n}\n\nexport function parseMentionAnchorAttributes({\n href,\n textContent,\n}: {\n href: string;\n textContent: string | null;\n}): MentionNodeAttrs {\n const url = new URL(href);\n const isWebpage = url.hostname === \"webpage\";\n return {\n type: isWebpage ? \"tab\" : url.hostname || \"tool\",\n name: textContent?.replace(/^@/, \"\") || \"\",\n id: isWebpage\n ? url.searchParams.get(\"tab_id\") || \"\"\n : url.searchParams.get(\"name\") || url.searchParams.get(\"id\") || \"\",\n title: url.searchParams.get(\"title\") || \"\",\n url: url.searchParams.get(\"url\") || \"\",\n description: url.searchParams.get(\"description\") || \"\",\n thumbnailUrl: url.searchParams.get(\"thumb\") || \"\",\n fallbackIcon: \"\",\n assetType: url.searchParams.get(\"assetType\") || \"\",\n };\n}\n\nexport const MentionExtension = Node.create({\n name: \"mention\",\n group: \"inline\",\n inline: true,\n selectable: false,\n atom: true,\n\n addAttributes() {\n return {\n type: { default: \"tool\" },\n name: { default: \"\" },\n id: { default: \"\" },\n title: { default: \"\" },\n url: { default: \"\" },\n description: { default: \"\" },\n thumbnailUrl: { default: \"\" },\n fallbackIcon: { default: \"\" },\n assetType: { default: \"\" },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-mention]\",\n getAttrs: (dom) => {\n const el = dom as HTMLElement;\n return {\n type: el.getAttribute(\"data-type\") || \"tool\",\n name: el.getAttribute(\"data-name\") || el.textContent?.replace(/^@/, \"\") || \"\",\n id: el.getAttribute(\"data-id\") || \"\",\n title: el.getAttribute(\"data-title\") || \"\",\n url: el.getAttribute(\"data-url\") || \"\",\n description: el.getAttribute(\"data-description\") || \"\",\n thumbnailUrl: el.getAttribute(\"data-thumbnail-url\") || \"\",\n fallbackIcon: el.getAttribute(\"data-fallback-icon\") || \"\",\n assetType: el.getAttribute(\"data-asset-type\") || \"\",\n };\n },\n },\n {\n tag: \"a[href^='mention://']\",\n getAttrs: (dom) => {\n const el = dom as HTMLAnchorElement;\n return parseMentionAnchorAttributes({\n href: el.href,\n textContent: el.textContent,\n });\n },\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const thumbnailUrl = node.attrs.thumbnailUrl;\n\n // Build child elements: [icon] name\n const children: any[] = [];\n\n if (thumbnailUrl) {\n // Render SVG thumbnail as an img element inside the chip\n children.push([\n \"img\",\n {\n src: thumbnailUrl,\n alt: \"\",\n class: \"mention-chip-icon\",\n draggable: \"false\",\n },\n ]);\n }\n\n children.push([\"span\", { class: \"mention-chip-text\" }, node.attrs.name]);\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n \"data-type\": node.attrs.type,\n \"data-name\": node.attrs.name,\n \"data-id\": node.attrs.id,\n \"data-title\": node.attrs.title || \"\",\n \"data-url\": node.attrs.url || \"\",\n \"data-thumbnail-url\": node.attrs.thumbnailUrl || \"\",\n \"data-asset-type\": node.attrs.assetType || \"\",\n class: \"mention-chip\",\n }),\n ...children,\n ];\n },\n\n renderText({ node }) {\n const url = makeMentionUrl({\n id: node.attrs.id,\n type: node.attrs.type,\n name: node.attrs.name,\n title: node.attrs.title,\n url: node.attrs.url,\n description: node.attrs.description,\n thumbnailUrl: node.attrs.thumbnailUrl,\n assetType: node.attrs.assetType,\n });\n return `[@${node.attrs.name}](${url})`;\n },\n});\n","/**\n * Tiptap Mention Suggestions Extension\n *\n * Integrates the mention popup with Tiptap's suggestion plugin.\n * Ported from Olympus — same lifecycle management.\n */\n\nimport { Extension } from \"@tiptap/core\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport type { MentionSuggestionsStore } from \"./data/use-mention-suggestions\";\nimport type { MenuItem } from \"./data/types\";\n\nexport interface MentionSuggestionRenderProps {\n query: string;\n command: (item: MenuItem) => void;\n clientRect: (() => DOMRect | null) | null;\n editor: any;\n}\n\nexport type MentionSuggestionCallbacks = {\n onStart: (props: MentionSuggestionRenderProps) => void;\n onUpdate: (props: MentionSuggestionRenderProps) => void;\n onKeyDown: (event: KeyboardEvent) => boolean;\n onExit: () => void;\n};\n\nexport const MentionSuggestionsExtension = Extension.create<{\n store: MentionSuggestionsStore | null;\n callbacks: MentionSuggestionCallbacks | null;\n}>({\n name: \"mentionSuggestions\",\n\n addOptions() {\n return {\n store: null,\n callbacks: null,\n };\n },\n\n addProseMirrorPlugins() {\n const callbacks = this.options.callbacks;\n\n return [\n Suggestion({\n editor: this.editor,\n char: \"@\",\n allowSpaces: false,\n startOfLine: false,\n allowedPrefixes: [\" \", \"\\t\", \"\\n\", \"\\r\", \"(\", \"[\", \"{\", '\"', \"'\", \"\\u00A0\"],\n\n items: () => [],\n\n command: ({ editor, range, props }) => {\n const item = props as unknown as MenuItem;\n // Skip items that can't be mentioned (navigation is handled by the\n // list component)\n if (item.navigatesToScope || item.isNavigationOnly) return;\n\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({\n type: \"mention\",\n attrs: {\n type: item.type,\n name: item.name,\n id:\n item.type === \"tab\" && typeof item.extra?.tabId === \"number\"\n ? String(item.extra.tabId)\n : item.id,\n title:\n item.type === \"tab\" && typeof item.extra?.title === \"string\"\n ? item.extra.title\n : item.name,\n url: item.url ?? \"\",\n description: item.description ?? \"\",\n thumbnailUrl: item.thumbnailUrl ?? \"\",\n fallbackIcon: item.fallbackIcon ?? \"\",\n assetType:\n typeof item.extra?.athenaOriginalType === \"string\"\n ? item.extra.athenaOriginalType\n : \"\",\n },\n })\n .insertContent(\" \")\n .run();\n },\n\n render: () => ({\n onStart: (props) => {\n callbacks?.onStart({\n query: props.query,\n command: (item) => props.command(item as never),\n clientRect: props.clientRect ?? null,\n editor: props.editor,\n });\n },\n onUpdate: (props) => {\n callbacks?.onUpdate({\n query: props.query,\n command: (item) => props.command(item as never),\n clientRect: props.clientRect ?? null,\n editor: props.editor,\n });\n },\n onKeyDown: ({ event }) => {\n return callbacks?.onKeyDown(event) ?? false;\n },\n onExit: () => {\n callbacks?.onExit();\n },\n }),\n }),\n ];\n },\n});\n","/**\n * Floating popup wrapper for the mention suggestion menu.\n * Uses Floating UI for positioning near the cursor.\n */\n\nimport { type FC, type ReactNode, useEffect } from \"react\";\nimport {\n useFloating,\n offset,\n flip,\n shift,\n autoUpdate,\n FloatingPortal,\n} from \"@floating-ui/react\";\n\nexport const MentionSuggestionPopup: FC<{\n clientRect: (() => DOMRect | null) | null;\n children: ReactNode;\n}> = ({ clientRect, children }) => {\n const { refs, floatingStyles } = useFloating({\n placement: \"bottom-start\",\n middleware: [offset(10), flip(), shift({ padding: 8 })],\n whileElementsMounted: autoUpdate,\n });\n\n // Use setPositionReference for virtual elements (cursor position)\n // instead of elements.reference which requires a real DOM element\n useEffect(() => {\n if (clientRect) {\n refs.setPositionReference({\n getBoundingClientRect: () => clientRect() ?? new DOMRect(),\n });\n }\n }, [clientRect, refs]);\n\n return (\n <FloatingPortal>\n <div\n ref={refs.setFloating}\n style={floatingStyles}\n className=\"z-[9999]\"\n onMouseDown={(e) => e.preventDefault()} // Prevent focus loss on click\n >\n {children}\n </div>\n </FloatingPortal>\n );\n};\n","/**\n * Mention Orchestrator — Async data fetching with registry + cache.\n *\n * selectItems (pure read) + triggerFetchIfNeeded (async fetch).\n */\n\nimport type { MenuItem, MenuScope, FetchMetadata, SourceToRegister } from \"./types\";\nimport type { MentionSuggestionsStore, MentionSuggestionsStoreState } from \"./use-mention-suggestions\";\nimport { getFilteredItems, addItems } from \"./item-cache\";\nimport {\n getEntry,\n getFetchState,\n updateFetchState,\n registerSource,\n bindScopes,\n} from \"./scope-registry\";\nimport { filterItems } from \"./utils/filter-items\";\n\n/** Consecutive fetch failures tolerated before a scope+query stops retrying. */\nconst MAX_ERROR_RETRIES = 3;\n\n/**\n * Select items for a given scope + query from the cache.\n * Pure, synchronous read — no side effects.\n */\nexport function selectItems(\n store: MentionSuggestionsStore,\n scope: MenuScope | { id: string },\n query: string,\n _targetCount?: number,\n parentScope?: MenuScope | { id: string },\n): { items: MenuItem[]; isFetching: boolean; hasMore: boolean } {\n const state = store.state;\n const scopeId = typeof scope === \"string\" ? scope : scope.id;\n const parentScopeId = parentScope\n ? typeof parentScope === \"string\" ? parentScope : parentScope.id\n : undefined;\n\n // Read from cache\n const items = getFilteredItems(state.cache, scopeId, query);\n\n // Read fetch state from registry\n let isFetching = false;\n let hasMore = true;\n\n try {\n const fetchState = getFetchState(state.registry, scopeId, query, parentScopeId);\n isFetching = fetchState.isFetching;\n hasMore = fetchState.hasNextPage;\n } catch {\n // Scope not registered — no more to fetch\n hasMore = false;\n }\n\n return { items, isFetching, hasMore };\n}\n\n/**\n * Trigger an async fetch if needed.\n * Called by useMenuItems when cache < target AND hasMore AND !fetching.\n */\nexport function triggerFetchIfNeeded(\n store: MentionSuggestionsStore,\n scope: MenuScope | { id: string },\n query: string,\n _targetCount?: number,\n parentScope?: MenuScope | { id: string },\n): void {\n const scopeId = typeof scope === \"string\" ? scope : scope.id;\n const parentScopeId = parentScope\n ? typeof parentScope === \"string\" ? parentScope : parentScope.id\n : undefined;\n\n const state = store.state;\n\n // Check if scope is registered\n let entry;\n try {\n entry = getEntry(state.registry, scopeId, parentScopeId);\n } catch {\n return; // Not registered, nothing to fetch\n }\n\n // Check fetch state\n const fetchState = getFetchState(state.registry, scopeId, query, parentScopeId);\n if (fetchState.isFetching || !fetchState.hasNextPage || fetchState.error) {\n return;\n }\n\n // Safety limit\n const meta = (fetchState.meta as FetchMetadata) || {};\n if ((meta.fetchAttempts || 0) >= 10) return;\n\n // Mark as fetching\n updateFetchState(state.registry, scopeId, query, { isFetching: true }, parentScopeId);\n store.setState((prev) => ({ ...prev }));\n\n // Async fetch\n const sourceFn = entry.sourceFn;\n const sourceConfig = entry.sourceConfig;\n\n sourceFn({\n scope: scopeId,\n query,\n fetchState,\n sourceConfig,\n })\n .then((result) => {\n const currentState = store.state;\n\n // Add items to cache with scope tagging\n addItems(currentState.cache, result.items, scopeId);\n\n // Register dynamically discovered sources\n if (result.sources) {\n for (const src of result.sources) {\n try {\n getEntry(currentState.registry, src.scope);\n } catch {\n // Not registered yet — register it\n registerSource(\n currentState.registry,\n src.scope,\n src.sourceFn,\n src.sourceConfig,\n src.isFlat,\n );\n }\n }\n }\n\n // Register dynamically discovered bindings\n if (result.bindings) {\n for (const binding of result.bindings) {\n bindScopes(currentState.registry, binding.browseScope, binding.searchScope);\n }\n }\n\n // Update fetch state\n const currentMeta = (fetchState.meta as FetchMetadata) || {};\n // Advance the server-side offset by the rows the source consumed, which\n // exceeds `items.length` whenever a source drops rows after fetching.\n const consumed = result.pagination?.consumedCount ?? result.items.length;\n const newValidated = (currentMeta.validatedCount || 0) + consumed;\n\n updateFetchState(\n currentState.registry,\n scopeId,\n query,\n {\n isFetching: false,\n hasNextPage: result.pagination?.hasMore ?? false,\n error: null,\n meta: {\n ...currentMeta,\n ...result.meta,\n validatedCount: newValidated,\n fetchAttempts: (currentMeta.fetchAttempts || 0) + 1,\n errorAttempts: 0,\n },\n },\n parentScopeId,\n );\n\n // Trigger re-render\n store.setState((prev) => ({ ...prev }));\n })\n .catch((error) => {\n console.error(`[orchestrator] Fetch error for scope ${scopeId}:`, error);\n\n const currentState = store.state;\n const currentMeta = (fetchState.meta as FetchMetadata) || {};\n const errorAttempts = ((currentMeta.errorAttempts as number) || 0) + 1;\n const retriable = errorAttempts < MAX_ERROR_RETRIES;\n\n updateFetchState(\n currentState.registry,\n scopeId,\n query,\n {\n isFetching: false,\n hasNextPage: retriable,\n error: retriable\n ? null\n : error instanceof Error\n ? error\n : new Error(String(error)),\n meta: { ...currentMeta, errorAttempts },\n },\n parentScopeId,\n );\n\n store.setState((prev) => ({ ...prev }));\n });\n}\n","import { useStore } from '@tanstack/react-store';\nimport { useEffect, useState } from 'react';\nimport { selectItems, triggerFetchIfNeeded } from './orchestrator';\nimport type { MenuItem, MenuScope } from './types';\nimport type { MentionSuggestionsStore } from './use-mention-suggestions';\n\n/**\n * useMenuItems - Like React Query, but for menu items\n *\n * Clean, automatic hook that:\n * - Reads items from store (reactive!)\n * - Auto-fetches if needed (in useEffect)\n * - Returns clean interface { items, isFetching, hasMore }\n *\n * Usage:\n * ```typescript\n * const { items, isFetching, hasMore } = useMenuItems(store, {\n * scope: 'athena_folders',\n * query: 'doc',\n * minItems: 10,\n * parentScope: 'root'\n * });\n * ```\n */\nexport interface UseMenuItemsOptions {\n scope: MenuScope;\n query?: string;\n minItems?: number;\n parentScope?: MenuScope;\n}\n\nexport interface UseMenuItemsResult {\n items: MenuItem[];\n isFetching: boolean;\n hasMore: boolean;\n loadMore: () => void; // Explicit load more (not automatic!)\n targetCount: number; // Current target for debugging\n}\n\nexport function useMenuItems(\n store: MentionSuggestionsStore,\n options: UseMenuItemsOptions\n): UseMenuItemsResult {\n const { scope, query = '', minItems = 50, parentScope } = options;\n\n // Target item count (increases when user clicks \"Load More\")\n const [targetCount, setTargetCount] = useState(minItems);\n\n // Reset target when scope/query changes\n // biome-ignore lint/correctness/useExhaustiveDependencies: We intentionally reset on scope/query change\n useEffect(() => {\n setTargetCount(minItems);\n }, [scope, query, minItems]);\n\n // Read from store (pure, reactive)\n const snapshot = useStore(store, () =>\n selectItems(store, scope, query, targetCount, parentScope)\n );\n\n // Auto-fetch when: cached < target AND hasMore AND !fetching\n useEffect(() => {\n if (snapshot.items.length < targetCount && snapshot.hasMore && !snapshot.isFetching) {\n triggerFetchIfNeeded(store, scope, query, targetCount, parentScope);\n }\n }, [\n store,\n scope,\n query,\n targetCount,\n parentScope,\n snapshot.items.length,\n snapshot.hasMore,\n snapshot.isFetching,\n ]);\n\n // Explicit load more: Increase target by 50\n const loadMore = () => {\n if (snapshot.hasMore && !snapshot.isFetching) {\n setTargetCount((prev) => prev + 50);\n }\n };\n\n return {\n items: snapshot.items,\n isFetching: snapshot.isFetching,\n hasMore: snapshot.hasMore,\n loadMore,\n targetCount, // Expose for debugging\n };\n}\n","import type { MenuScope } from '../data/types';\nimport type { MentionSuggestionsStore } from '../data/use-mention-suggestions';\n\n/**\n * Known category scope names\n *\n * These are the top-level menu categories that have stable IDs.\n */\nconst KNOWN_SCOPE_NAMES: Record<MenuScope, string> = {\n root: 'All',\n global_search: 'Search',\n // Legacy order: my_spaces, favorites, assets, folders, tools, toolkits, team, workspace, drives\n my_spaces: 'My Spaces',\n favorites: 'Favorites',\n athena_assets: 'Assets',\n athena_folders: 'Folders',\n tools: 'Tools',\n toolkits: 'Toolkits',\n team: 'Team',\n workspace: 'Workspace',\n drive_catalogs: 'Drives',\n athena_projects: 'Projects',\n athena_browse_profiles: 'Browse Profiles',\n // Additional scopes\n asset_search: 'Search',\n};\n\n/**\n * getScopeName - Get friendly display name for a scope\n *\n * Strategy:\n * 1. Check known category names (fast path)\n * 2. Look up dynamic item in cache (folders, assets, etc.)\n * 3. Fall back to scope ID itself\n *\n * @param scope - The scope ID to look up\n * @param store - The mention suggestions store (to access cache)\n * @returns Friendly display name\n */\nexport function getScopeName(scope: MenuScope, store: MentionSuggestionsStore): string {\n // Fast path: known category\n const knownName = KNOWN_SCOPE_NAMES[scope];\n if (knownName) {\n return knownName;\n }\n\n // Dynamic path: look up item in cache\n // This handles folders, assets, SharePoint sites, etc.\n const { cache } = store.state;\n const allItems = Object.values(cache.items);\n\n // Find item that navigates to this scope\n const item = allItems.find((item) => item.navigatesToScope === scope);\n if (item) {\n return item.name;\n }\n\n // Fallback: format scope ID\n // folder_123 → Folder 123\n // sharepoint_abc → Sharepoint Abc\n return scope\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n","/**\n * Core types for mention suggestions data layer\n */\n\n/**\n * MenuScope - A navigable container in the mention menu hierarchy\n *\n * Conceptual model:\n * - SCOPE = Container/Group you navigate INTO (e.g., \"athena_assets\", \"folder_123\")\n * - ITEM = Individual mentionable thing you SELECT (e.g., specific asset, tool)\n *\n * Scopes form a navigation hierarchy:\n * root → athena_assets → folder_123 → subfolder_456\n *\n * Items can be visible in multiple scopes simultaneously:\n * Asset \"Report.pdf\" is in both \"folder_123\" AND \"asset_search\" results\n */\nexport type MenuScope = string;\n\nexport const MentionMenuSection = {\n CURRENT_WEBPAGE: \"current-webpage\",\n OTHER_WEBPAGES: \"other-webpages\",\n LIBRARY: \"library\",\n} as const;\n\nexport type MentionMenuSection =\n (typeof MentionMenuSection)[keyof typeof MentionMenuSection];\n\nexport interface WebpageMention {\n tabId: number;\n title: string;\n url: string;\n isCurrent: boolean;\n}\n\nexport interface WebpageMentionScope {\n primaryTabId: number;\n tabGroupId: number | null;\n allowedTabIds: readonly number[];\n}\n\n/**\n * Selector result - provides current state + loading indicators\n * Used by the UI to get immediate access to data and loading state\n */\nexport interface MenuItemsSelector {\n items: MenuItem[];\n isFetching: boolean;\n hasMore: boolean;\n}\n\n/**\n * MenuItem - individual mentionable item\n * Icon fields match MentionIcon component props exactly - no transforms needed at render time!\n *\n * Multi-scope system: Items can belong to multiple scopes simultaneously\n * Example: An asset can be visible in 'athena_assets', 'folder_123', and 'my_spaces'\n */\nexport interface MenuItem {\n id: string;\n name: string;\n type:\n | 'menu'\n | 'asset'\n | 'folder'\n | 'tool'\n | 'toolkit'\n | 'drive'\n | 'user'\n | 'task'\n | 'tab'\n | 'workspace_item'\n | 'drive_catalog'\n | 'placeholder';\n\n // Icon fields (match MentionIcon component props)\n thumbnailUrl?: string; // For assets: URL/path to thumbnail (e.g., from AthenaTypeToThumb)\n fallbackIcon: string; // For menus/tools: Lucide icon name (e.g., 'Folder', 'Wrench') or emoji\n\n // Multi-scope membership: Which menu scopes this item is visible in\n // Items can belong to multiple scopes simultaneously\n visibleInScopes: Set<MenuScope>; // e.g., Set(['athena_assets', 'folder_123', 'my_spaces'])\n\n // Navigation capability: If present, this item can be navigated into\n // When user selects this item, navigate to this scope\n navigatesToScope?: MenuScope;\n\n // Navigation-only flag: If true, item CANNOT be inserted as mention (only navigate)\n // Use for root categories that are pure navigation containers\n isNavigationOnly?: boolean; // Default: false (most items are mentionable)\n\n // Type-specific metadata\n extra?: Record<string, any>;\n description?: string;\n url?: string;\n menuSection?: MentionMenuSection;\n updatedAt?: string;\n email?: string; // For user type\n version?: string; // For versioned assets\n\n // Legacy compatibility\n parentMenuId?: string;\n}\n\n/**\n * FetchState - fetch status and pagination state for a specific query\n * Managed by orchestrator, not returned by sources\n */\nexport interface FetchState {\n isFetching: boolean;\n hasNextPage: boolean;\n fetchNext: (() => void) | null;\n error: Error | null; // Track errors to prevent infinite retry loops\n\n // Source-specific pagination metadata (offset, cursor, page token, etc.)\n // Each source stores what IT needs between calls\n // Orchestrator doesn't care what's in here!\n meta: unknown;\n}\n\n/**\n * FetchMetadata - Common metadata fields used by orchestrator\n * Sources can extend this with their own fields (e.g., pageToken, cursor)\n */\nexport interface FetchMetadata {\n // Orchestrator fields\n validatedCount?: number; // Number of items fetched and validated so far\n fetchAttempts?: number; // Number of fetch attempts (for safety limits)\n // Source-specific fields can be added via extension or intersection\n [key: string]: unknown;\n}\n\n/**\n * New source to register dynamically\n * Returned by sources when they discover navigable items (folders, catalogs, etc.)\n */\nexport interface SourceToRegister {\n scope: MenuScope; // The scope ID to register\n sourceFn: SourceFn; // The source function to use for this scope\n sourceConfig?: any; // Configuration for the source\n isFlat?: boolean; // Whether this scope should be flat (no navigation arrows)\n}\n\n/**\n * Scope binding to register dynamically\n * Binds a browse scope to a search scope (hot scope swap on query)\n */\nexport interface ScopeBindingToRegister {\n browseScope: MenuScope; // The scope shown when browsing (no query)\n searchScope: MenuScope; // The scope shown when searching (has query)\n}\n\n/**\n * Source result - returned by all source functions\n *\n * Sources come in two flavors:\n * 1. TRANSFORMERS - Transform existing data (no API calls)\n * Examples: tools, toolkits, workspace members, opened spaces\n * Pattern: Read from store/ref → transform → return items\n *\n * 2. FETCHERS - Fetch from API (async operations)\n * Examples: internal assets, folders, SharePoint items\n * Pattern: Call GraphQL/REST → transform response → return items\n *\n * 3. HYBRID - Behavior depends on query\n * Example: Root menu (transformer when no query, fetcher with query)\n *\n * Original design: Sources can return new sources to register!\n * This allows discovered items (folders, catalogs) to be dynamically registered\n * without circular dependencies (orchestrator handles registration centrally)\n */\nexport interface SourceResult {\n // Items to add/update (source sets navigatesToScope on navigable items)\n // Orchestrator will tag these items with the current scope\n items: MenuItem[];\n\n // Pagination metadata (what we learned from this fetch)\n // All sources return this - orchestrator uses it\n pagination?: {\n hasMore: boolean;\n totalCount?: number;\n // Rows the source consumed from the server for this page. Defaults to\n // `items.length`; sources that drop rows after fetching must report the\n // pre-filter count so the next offset does not re-read the same rows.\n consumedCount?: number;\n };\n\n // Source-specific metadata (e.g., pageToken for SharePoint, cursor for pagination)\n // Orchestrator merges this into fetchState.meta for the next fetch\n meta?: Record<string, unknown>;\n\n // New sources to register (for discovered navigable items)\n // Orchestrator will register these in the registry\n sources?: SourceToRegister[];\n\n // New bindings to register (for hot scope swap on query)\n // Example: catalogId → catalogId_search\n bindings?: ScopeBindingToRegister[];\n}\n\n/**\n * Source function context\n *\n * Sources are pure functions - just fetch/transform and return items!\n * Orchestrator handles sync/deduplication via Cache.addItems() with scope tagging\n */\nexport interface SourceContext<TConfig = any> {\n scope: MenuScope; // Current scope we're fetching for\n query: string; // User's search query\n fetchState: FetchState; // Pagination state for this query (includes source-specific meta)\n sourceConfig: TConfig; // Source configuration (can include getters for reactive data!)\n}\n\n/**\n * Source function type\n *\n * Pure function that provides items for a scope + query combination.\n * Can be a transformer (reads from store) or fetcher (calls API).\n * State (pagination, sourceConfig) is stored externally in registry entry.\n */\nexport type SourceFn<TConfig = any> = (context: SourceContext<TConfig>) => Promise<SourceResult>;\n","/**\n * Mention icon component.\n * Maps string icon names to Lucide icon components.\n */\n\nimport type { FC } from \"react\";\nimport {\n BookOpenIcon,\n Building2Icon,\n CalendarIcon,\n CameraIcon,\n CheckSquareIcon,\n CloudIcon,\n CodeIcon,\n DatabaseIcon,\n EyeIcon,\n FileCodeIcon,\n FileIcon,\n FileTextIcon,\n FolderIcon,\n FolderKanbanIcon,\n GlobeIcon,\n HardDriveIcon,\n HeadphonesIcon,\n ImageIcon,\n KeyIcon,\n KeyboardIcon,\n LayoutDashboardIcon,\n LayoutGridIcon,\n LayoutIcon,\n LibraryIcon,\n MailIcon,\n MicIcon,\n MonitorIcon,\n PackageIcon,\n PaletteIcon,\n PenToolIcon,\n PhoneIcon,\n SearchIcon,\n SheetIcon,\n SmartphoneIcon,\n SparklesIcon,\n StarIcon,\n TableIcon,\n UserIcon,\n UsersIcon,\n VideoIcon,\n WrenchIcon,\n ZapIcon,\n WorkflowIcon,\n} from \"lucide-react\";\n\nconst ICON_MAP: Record<string, FC<{ className?: string }>> = {\n // General\n file: FileIcon,\n \"file-text\": FileTextIcon,\n \"file-code\": FileCodeIcon,\n folder: FolderIcon,\n \"folder-kanban\": FolderKanbanIcon,\n globe: GlobeIcon,\n search: SearchIcon,\n star: StarIcon,\n users: UsersIcon,\n user: UserIcon,\n wrench: WrenchIcon,\n package: PackageIcon,\n \"building-2\": Building2Icon,\n \"hard-drive\": HardDriveIcon,\n \"layout-grid\": LayoutGridIcon,\n zap: ZapIcon,\n eye: EyeIcon,\n\n // Chrome tools\n camera: CameraIcon,\n keyboard: KeyboardIcon,\n code: CodeIcon,\n monitor: MonitorIcon,\n\n // Asset types\n image: ImageIcon,\n video: VideoIcon,\n headphones: HeadphonesIcon,\n mic: MicIcon,\n mail: MailIcon,\n calendar: CalendarIcon,\n phone: PhoneIcon,\n database: DatabaseIcon,\n table: TableIcon,\n sheet: SheetIcon,\n palette: PaletteIcon,\n \"pen-tool\": PenToolIcon,\n layout: LayoutIcon,\n \"layout-dashboard\": LayoutDashboardIcon,\n library: LibraryIcon,\n \"book-open\": BookOpenIcon,\n sparkles: SparklesIcon,\n \"check-square\": CheckSquareIcon,\n key: KeyIcon,\n smartphone: SmartphoneIcon,\n cloud: CloudIcon,\n workflow: WorkflowIcon,\n presentation: FileTextIcon, // Fallback for presentation type\n};\n\nexport function MentionIcon({\n fallbackIcon,\n thumbnailUrl,\n alt,\n className = \"w-4 h-4 flex-shrink-0\",\n}: {\n fallbackIcon?: string;\n thumbnailUrl?: string;\n alt?: string;\n className?: string;\n}) {\n if (thumbnailUrl) {\n return <img src={thumbnailUrl} alt={alt ?? \"\"} className={className} />;\n }\n const Icon = fallbackIcon ? ICON_MAP[fallbackIcon] : undefined;\n if (Icon) return <Icon className={className} />;\n // Emoji or text fallback\n if (fallbackIcon) return <span className=\"text-sm flex-shrink-0\">{fallbackIcon}</span>;\n return <FileIcon className={className} />;\n}\n","/**\n * Individual menu item in the mention popup.\n * Supports: tools (with description), users (with email), assets, categories.\n */\n\nimport type { MenuItem } from \"../data/types\";\nimport { MentionMenuSection } from \"../data/types\";\nimport { MentionIcon } from \"./mention-icon\";\nimport { cn } from \"../../../../lib/utils\";\n\nexport function MenuItemRow({\n item,\n isSelected,\n onMouseEnter,\n onClick,\n showArrow,\n}: {\n item: MenuItem;\n isSelected: boolean;\n onMouseEnter: () => void;\n onClick: () => void;\n showArrow?: boolean;\n}) {\n const hasTwoLines =\n (item.type === \"tool\" && item.description) ||\n (item.type === \"user\" && item.email) ||\n (item.type === \"workspace_item\" && item.description) ||\n (item.type === \"tab\" && item.description);\n\n return (\n <div\n role=\"button\"\n tabIndex={-1}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n className={cn(\n \"mention-item flex items-center justify-between gap-2 px-2 py-1.5 rounded cursor-pointer transition-colors\",\n \"hover:bg-gray-100\",\n item.menuSection === MentionMenuSection.CURRENT_WEBPAGE &&\n !isSelected &&\n \"bg-sky-50/70\",\n isSelected && \"bg-gray-100 is-selected\",\n )}\n >\n {/* Icon */}\n <span className={`flex items-center flex-shrink-0 ${hasTwoLines ? \"self-start mt-0.5\" : \"\"}`}>\n <MentionIcon\n fallbackIcon={item.fallbackIcon}\n thumbnailUrl={item.thumbnailUrl}\n alt={item.name}\n />\n </span>\n\n {/* Content */}\n {hasTwoLines ? (\n <div className=\"flex-1 flex flex-col gap-0 min-w-0 -mt-0.5\">\n <span className=\"text-sm leading-tight flex items-center gap-1.5\">\n {item.name}\n {item.extra?.isAdminOnly && (\n <span className=\"w-1.5 h-1.5 rounded-full bg-purple-400 flex-shrink-0\" />\n )}\n </span>\n <span className=\"text-xs text-gray-500 leading-tight mt-0.5 truncate\">\n {item.type === \"user\" ? item.email : item.description}\n </span>\n </div>\n ) : (\n <span className=\"flex-1 text-sm truncate min-w-0 flex items-center gap-1.5\">\n {item.name}\n {item.extra?.isAdminOnly && (\n <span className=\"w-1.5 h-1.5 rounded-full bg-purple-400 flex-shrink-0\" />\n )}\n </span>\n )}\n\n {/* Navigation arrow */}\n {showArrow && (\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n <span className=\"text-gray-400 text-sm px-1 rounded transition-all cursor-pointer hover:text-gray-600 hover:bg-gray-200\">\n →\n </span>\n </div>\n )}\n </div>\n );\n}\n","/**\n * Loading skeleton for the mention menu.\n */\n\nexport function MenuSkeleton() {\n return (\n <div className=\"px-1 py-1\">\n {[1, 2, 3, 4].map((i) => (\n <div key={i} className=\"flex items-center gap-2 px-2 py-1.5 rounded animate-pulse\">\n <div className=\"w-4 h-4 bg-gray-200 rounded flex-shrink-0\" />\n <div className=\"h-3.5 bg-gray-200 rounded flex-1\" style={{ maxWidth: `${50 + i * 10}%` }} />\n </div>\n ))}\n </div>\n );\n}\n","/**\n * Scrollable list of menu items with loading and empty states.\n */\n\nimport { Fragment, useEffect, useRef } from \"react\";\nimport { MentionMenuSection, type MenuItem } from \"../data/types\";\nimport { MenuItemRow } from \"./menu-item\";\nimport { MenuSkeleton } from \"./menu-skeleton\";\n\nexport function MenuList({\n items,\n selectedIndex,\n isLoading,\n hasMore,\n onSelect,\n onMouseEnter,\n onLoadMore,\n}: {\n items: MenuItem[];\n selectedIndex: number;\n isLoading?: boolean;\n hasMore?: boolean;\n onSelect: (item: MenuItem) => void;\n onMouseEnter: (index: number) => void;\n onLoadMore?: () => void;\n}) {\n const selectedRef = useRef<HTMLDivElement>(null);\n\n // Auto-scroll selected item into view\n useEffect(() => {\n selectedRef.current?.scrollIntoView({ block: \"nearest\" });\n }, [selectedIndex]);\n\n if (isLoading && items.length === 0) return <MenuSkeleton />;\n\n if (items.length === 0) {\n return (\n <div className=\"px-1 py-1\">\n <div className=\"px-2 py-9 text-center text-sm text-gray-500\">\n <div className=\"mb-1\">No results found</div>\n <div className=\"text-xs text-gray-400\">Try a different search or go back</div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"px-1 py-1\">\n {items.map((item, index) => {\n const previousSection = items[index - 1]?.menuSection;\n const startsOtherWebpages =\n item.menuSection === MentionMenuSection.OTHER_WEBPAGES &&\n previousSection !== MentionMenuSection.OTHER_WEBPAGES;\n const startsLibrary =\n item.menuSection === MentionMenuSection.LIBRARY &&\n (previousSection === MentionMenuSection.CURRENT_WEBPAGE ||\n previousSection === MentionMenuSection.OTHER_WEBPAGES);\n\n return (\n <Fragment key={item.id}>\n {startsOtherWebpages && (\n <div className=\"px-2 pb-1 pt-2 text-[11px] font-medium uppercase tracking-wide text-gray-400\">\n Other webpages in this group\n </div>\n )}\n {startsLibrary && <div className=\"mx-2 my-1 border-t border-gray-100\" />}\n <div ref={index === selectedIndex ? selectedRef : undefined}>\n <MenuItemRow\n item={item}\n isSelected={index === selectedIndex}\n onMouseEnter={() => onMouseEnter(index)}\n onClick={() => onSelect(item)}\n showArrow={!!item.navigatesToScope}\n />\n </div>\n </Fragment>\n );\n })}\n\n {/* Loading more indicator */}\n {isLoading && items.length > 0 && (\n <div className=\"px-2 py-2 text-center\">\n <span className=\"text-xs text-gray-400\">Loading more...</span>\n </div>\n )}\n\n {/* Load more sentinel */}\n {hasMore && !isLoading && onLoadMore && (\n <button\n type=\"button\"\n onClick={onLoadMore}\n className=\"w-full px-2 py-1.5 text-xs text-gray-500 hover:text-gray-700 hover:bg-gray-50 rounded transition-colors text-center\"\n >\n ··· Load more\n </button>\n )}\n </div>\n );\n}\n","/**\n * Breadcrumb navigation for the mention menu.\n */\n\nexport function MenuBreadcrumbs({\n scopePath,\n onNavigate,\n}: {\n scopePath: { id: string; name: string }[];\n onNavigate: (scopeId: string) => void;\n}) {\n return (\n <div className=\"flex items-center gap-1 text-xs text-gray-600 min-w-0\">\n {scopePath.map((item, index) => {\n const isLast = index === scopePath.length - 1;\n const isClickable = !isLast;\n\n return (\n <span key={item.id} className=\"flex items-center gap-1 min-w-0\">\n {isClickable ? (\n <button\n type=\"button\"\n onClick={() => onNavigate(item.id)}\n className=\"truncate hover:underline cursor-pointer transition-all hover:text-gray-800\"\n title={`Go to ${item.name}`}\n >\n {item.name}\n </button>\n ) : (\n <span className=\"truncate font-medium text-gray-800\">\n {item.name}\n </span>\n )}\n {!isLast && <span className=\"text-gray-400 flex-shrink-0\">→</span>}\n </span>\n );\n })}\n </div>\n );\n}\n","/**\n * Summary bar at the bottom of the mention menu.\n * Shows breadcrumbs + back button + optional loading spinner.\n */\n\nimport { MenuBreadcrumbs } from \"./menu-breadcrumbs\";\n\nexport function MenuSummary({\n scopePath,\n onNavigate,\n onBackClick,\n isFetching,\n}: {\n scopePath: { id: string; name: string }[];\n onNavigate: (scopeId: string) => void;\n onBackClick?: () => void;\n isFetching?: boolean;\n}) {\n // Don't show summary at root scope (unless fetching)\n if (scopePath.length <= 1 && !isFetching) return null;\n\n return (\n <div className=\"border-t border-gray-200 px-2 py-2 bg-gray-50\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n {scopePath.length > 1 && (\n <MenuBreadcrumbs scopePath={scopePath} onNavigate={onNavigate} />\n )}\n {isFetching && (\n <span className=\"flex-shrink-0 inline-block w-3 h-3 border border-gray-400 border-t-transparent rounded-full animate-spin\" />\n )}\n </div>\n {onBackClick && (\n <button\n type=\"button\"\n onClick={onBackClick}\n className=\"text-xs text-gray-600 hover:text-gray-800 px-2 py-1 rounded hover:bg-gray-200 transition-colors flex items-center gap-1 flex-shrink-0\"\n title=\"Go back (or press ←)\"\n >\n <span>←</span>\n <span>Back</span>\n </button>\n )}\n </div>\n </div>\n );\n}\n","/**\n * Keyboard navigation for the mention menu.\n *\n * Exposes an imperative handle so MentionSuggestionList can forward keystrokes\n * from the editor into the menu.\n */\n\nimport type { ForwardedRef } from \"react\";\nimport { useImperativeHandle } from \"react\";\nimport type { MenuItem } from \"../data/types\";\n\nexport interface KeyboardNavigationHandle {\n onKeyDown: (event: KeyboardEvent) => boolean;\n}\n\nexport function useKeyboardNavigation(\n ref: ForwardedRef<KeyboardNavigationHandle>,\n opts: {\n items: MenuItem[];\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n onSelect: (item: MenuItem) => void;\n onBack?: () => void;\n onClose: () => void;\n },\n) {\n const { items, selectedIndex, setSelectedIndex, onSelect, onBack, onClose } = opts;\n\n useImperativeHandle(\n ref,\n () => ({\n onKeyDown: (event: KeyboardEvent): boolean => {\n if (items.length === 0 && event.key !== \"Escape\") return false;\n\n switch (event.key) {\n case \"ArrowDown\": {\n const next = (selectedIndex + 1) % items.length;\n setSelectedIndex(next);\n return true;\n }\n case \"ArrowUp\": {\n const prev = (selectedIndex - 1 + items.length) % items.length;\n setSelectedIndex(prev);\n return true;\n }\n case \"Enter\": {\n const item = items[selectedIndex];\n if (item) onSelect(item);\n return true;\n }\n case \"ArrowLeft\": {\n if (onBack) {\n onBack();\n return true;\n }\n return false;\n }\n case \"Backspace\": {\n // Never capture Backspace — let Tiptap handle it naturally.\n // The suggestion plugin closes the popup when you backspace past @.\n return false;\n }\n case \"ArrowRight\": {\n const item = items[selectedIndex];\n if (item?.navigatesToScope) {\n onSelect(item);\n return true;\n }\n return false;\n }\n case \"Escape\": {\n onClose();\n return true;\n }\n default:\n return false;\n }\n },\n }),\n [items, selectedIndex, setSelectedIndex, onSelect, onBack, onClose],\n );\n}\n","import { Store } from '@tanstack/store';\nimport { useState } from 'react';\nimport type { MenuScope } from '../data/types';\n\n/**\n * Stack entry with scope and selected item position\n *\n * When navigating forward, we save the current selectedIndex so we can restore\n * it when navigating back (like browser history).\n */\nexport interface ScopeStackEntry {\n scope: MenuScope;\n selectedIndex: number; // Position of selected item when we left this scope\n breadcrumbLabel?: string; // Display name for this scope, when it isn't a known category\n parentScope?: MenuScope; // Scope we navigated from\n}\n\n/**\n * Menu navigation state - tracks current navigation context\n *\n * This is the \"current UI state\" that changes as user navigates and types.\n * Cleared when menu opens/closes.\n *\n * Uses a navigation stack for proper back button behavior:\n * - Forward navigation: push to stack (with current selectedIndex)\n * - Back navigation: pop from stack (restore selectedIndex)\n * - Current scope: last item in stack\n * - Parent scope: second-to-last item in stack\n */\nexport interface MenuNavigationState {\n // Navigation stack (browser-like history)\n // Example: [{ scope: 'root', selectedIndex: 2 }, { scope: 'folder_123', selectedIndex: 0 }]\n // Current scope = scopeStack[scopeStack.length - 1].scope\n // Parent scope = scopeStack[scopeStack.length - 2].scope\n scopeStack: ScopeStackEntry[];\n\n // Current search query\n query: string;\n\n // Is menu currently active?\n isActive: boolean;\n}\n\n/**\n * Menu navigation store with helper methods\n */\nexport interface MenuNavigationStore extends Store<MenuNavigationState> {\n navigateTo: (\n scope: MenuScope,\n currentSelectedIndex: number,\n options?: { breadcrumbLabel?: string; parentScope?: MenuScope },\n ) => void;\n navigateBack: () => void;\n setQuery: (query: string) => void;\n open: () => void;\n close: () => void;\n}\n\n/**\n * Get current scope from state\n */\nexport function getCurrentScope(state: MenuNavigationState): MenuScope {\n const lastEntry = state.scopeStack[state.scopeStack.length - 1];\n return lastEntry?.scope ?? \"root\";\n}\n\n/**\n * Get parent scope from state (for source inheritance)\n */\nexport function getParentScope(state: MenuNavigationState): MenuScope | undefined {\n if (state.scopeStack.length <= 1) return undefined;\n const parentEntry = state.scopeStack[state.scopeStack.length - 2];\n return parentEntry?.scope;\n}\n\n/**\n * Get selected index from current scope stack entry\n */\nexport function getSelectedIndex(state: MenuNavigationState): number {\n const lastEntry = state.scopeStack[state.scopeStack.length - 1];\n return lastEntry?.selectedIndex ?? 0;\n}\n\n/**\n * useMenuNavigation - Creates per-editor navigation state\n *\n * This is a UI concern - each editor instance gets its own navigation state.\n *\n * Returns a TanStack Store with navigation helper methods.\n */\nexport function useMenuNavigation(): MenuNavigationStore {\n const [store] = useState(() => {\n const baseStore = new Store<MenuNavigationState>({\n scopeStack: [{ scope: 'root', selectedIndex: 0 }],\n query: '',\n isActive: false,\n });\n\n // Extend store with navigation methods\n const navigationStore = baseStore as MenuNavigationStore;\n\n navigationStore.navigateTo = (\n scope: MenuScope,\n currentSelectedIndex: number,\n options?: { breadcrumbLabel?: string; parentScope?: MenuScope },\n ) => {\n const state = baseStore.state;\n\n // Save current selectedIndex in the current entry before navigating forward\n const updatedStack = [...state.scopeStack];\n if (updatedStack.length > 0) {\n updatedStack[updatedStack.length - 1] = {\n ...updatedStack[updatedStack.length - 1],\n selectedIndex: currentSelectedIndex,\n };\n }\n\n // Push new scope with selectedIndex = 0 (start at top of new scope)\n const newStack = [\n ...updatedStack,\n {\n scope,\n selectedIndex: 0,\n breadcrumbLabel: options?.breadcrumbLabel,\n parentScope: options?.parentScope,\n },\n ];\n\n baseStore.setState((prev) => ({\n ...prev,\n scopeStack: newStack,\n query: '',\n }));\n };\n\n navigationStore.navigateBack = () => {\n const state = baseStore.state;\n\n if (state.scopeStack.length <= 1) {\n return;\n }\n\n const newStack = state.scopeStack.slice(0, -1);\n\n baseStore.setState((prev) => ({\n ...prev,\n scopeStack: newStack,\n query: '',\n }));\n };\n\n navigationStore.setQuery = (query: string) => {\n baseStore.setState((prev) => ({ ...prev, query }));\n };\n\n navigationStore.open = () => {\n baseStore.setState(() => ({\n scopeStack: [{ scope: 'root', selectedIndex: 0 }],\n query: '',\n isActive: true,\n }));\n };\n\n navigationStore.close = () => {\n baseStore.setState(() => ({\n scopeStack: [{ scope: 'root', selectedIndex: 0 }],\n query: '',\n isActive: false,\n }));\n };\n\n return navigationStore;\n });\n\n return store;\n}\n","import type { Editor } from '@tiptap/core';\n\n/**\n * Clear text after @ trigger\n *\n * When navigating in the menu, we want to clear the typed query\n * but keep the @ trigger symbol.\n */\nexport function clearTextAfterTrigger(editor: Editor): void {\n const { state } = editor;\n const { from: cursorPos } = state.selection;\n const backwardText = state.doc.textBetween(0, cursorPos, undefined, '\\ufffc');\n const triggerIndex = backwardText.lastIndexOf('@');\n\n if (triggerIndex === -1) return;\n\n const offset = backwardText.length - triggerIndex;\n const from = cursorPos - offset + 1; // +1 to keep the @ symbol\n const to = cursorPos;\n\n if (from < to) {\n // Delete text after @ but keep the @ symbol\n const tr = state.tr.deleteRange(from, to);\n editor.view.dispatch(tr);\n }\n}\n","/**\n * MentionSuggestionList — Main mention menu component.\n *\n * Composed of:\n * - Registry + cache backed data (async fetching)\n * - useMenuNavigation for scope stack management\n * - useKeyboardNavigation for keyboard handling\n * - MenuList for item rendering with loading states\n * - MenuSummary for breadcrumbs + back\n */\n\nimport { useStore } from \"@tanstack/react-store\";\nimport type { Editor } from \"@tiptap/core\";\nimport { forwardRef, useCallback, useEffect, useState } from \"react\";\nimport type { MenuItem } from \"../data/types\";\nimport type { MentionSuggestionsStore } from \"../data/use-mention-suggestions\";\nimport { useMenuItems } from \"../data/use-menu-items\";\nimport { getSearchScope } from \"../data/scope-registry\";\nimport { getScopeName } from \"./get-scope-name\";\nimport { MenuList } from \"./menu-list\";\nimport { MenuSummary } from \"./menu-summary\";\nimport { useKeyboardNavigation, type KeyboardNavigationHandle } from \"./use-keyboard-navigation\";\nimport {\n getCurrentScope,\n getSelectedIndex,\n useMenuNavigation,\n} from \"./use-menu-navigation\";\nimport { clearTextAfterTrigger } from \"./utils\";\n\nexport interface MentionSuggestionListProps {\n store: MentionSuggestionsStore;\n editor: Editor;\n query: string;\n command: (item: MenuItem) => void;\n closeMenu: (dismissedByUser?: boolean) => void;\n}\n\nexport const MentionSuggestionList = forwardRef<\n KeyboardNavigationHandle,\n MentionSuggestionListProps\n>(({ store, editor, query, command, closeMenu }, ref) => {\n const [selectedIndexOverride, setSelectedIndexOverride] = useState<number | null>(null);\n const navStore = useMenuNavigation();\n\n // Get current scope from navigation\n const currentScopeId = useStore(navStore, (s) => getCurrentScope(s));\n const navSelectedIndex = useStore(navStore, (s) => getSelectedIndex(s));\n const selectedIndex = selectedIndexOverride ?? navSelectedIndex;\n const scopeStack = useStore(navStore, (s) => s.scopeStack);\n\n let effectiveScopeId = currentScopeId;\n\n if (query) {\n try {\n const searchScope = getSearchScope(store.state.registry, currentScopeId);\n if (searchScope) {\n effectiveScopeId = searchScope;\n }\n } catch {\n // No search scope binding — use current\n }\n }\n\n // Get items from the data store (reactive, with async fetching)\n const { items, isFetching, hasMore, loadMore } = useMenuItems(store, {\n scope: effectiveScopeId,\n query,\n minItems: 50,\n parentScope: currentScopeId !== effectiveScopeId ? currentScopeId : undefined,\n });\n\n // Reset selection on query or scope change\n useEffect(() => {\n setSelectedIndexOverride(null);\n }, [query, effectiveScopeId]);\n\n // Build scope path for breadcrumbs from the navigation stack\n const scopePath = scopeStack.map((entry) => ({\n id: entry.scope,\n name: entry.breadcrumbLabel ?? getScopeName(entry.scope, store),\n }));\n\n // Handle item selection\n const handleSelect = useCallback(\n (item: MenuItem) => {\n if (item.navigatesToScope) {\n navStore.navigateTo(item.navigatesToScope, selectedIndex, {\n breadcrumbLabel: item.name,\n parentScope: currentScopeId,\n });\n clearTextAfterTrigger(editor);\n setSelectedIndexOverride(null);\n return;\n }\n // Insert mention\n command(item);\n },\n [command, editor, navStore, selectedIndex, currentScopeId],\n );\n\n // Handle back navigation\n const handleBack = useCallback(() => {\n navStore.navigateBack();\n clearTextAfterTrigger(editor);\n setSelectedIndexOverride(null);\n }, [editor, navStore]);\n\n // Handle breadcrumb navigation\n const handleBreadcrumbNavigate = useCallback(\n (targetScopeId: string) => {\n // Navigate to specific scope in the stack\n const targetIdx = scopeStack.findIndex((entry) => entry.scope === targetScopeId);\n\n if (targetIdx >= 0) {\n // Pop stack down to the target\n const popsNeeded = scopeStack.length - 1 - targetIdx;\n for (let i = 0; i < popsNeeded; i++) {\n navStore.navigateBack();\n }\n clearTextAfterTrigger(editor);\n setSelectedIndexOverride(null);\n }\n },\n [editor, navStore, scopeStack],\n );\n\n // Keyboard navigation\n useKeyboardNavigation(ref, {\n items,\n selectedIndex,\n onSelect: handleSelect,\n onBack: currentScopeId !== \"root\" ? handleBack : undefined,\n onClose: () => closeMenu(true),\n setSelectedIndex: (idx: number) => {\n setSelectedIndexOverride(idx);\n },\n });\n\n return (\n <div className=\"bg-white border border-gray-300 rounded shadow-lg min-w-[280px] max-w-[380px] max-h-[320px] flex flex-col\">\n {/* Scrollable items */}\n <div className=\"flex-1 overflow-y-auto\">\n <MenuList\n items={items}\n selectedIndex={selectedIndex}\n isLoading={isFetching}\n hasMore={hasMore}\n onSelect={handleSelect}\n onMouseEnter={(idx) => {\n setSelectedIndexOverride(idx);\n }}\n onLoadMore={loadMore}\n />\n </div>\n\n {/* Bottom summary with breadcrumbs + back */}\n <MenuSummary\n scopePath={scopePath}\n onNavigate={handleBreadcrumbNavigate}\n onBackClick={currentScopeId !== \"root\" ? handleBack : undefined}\n isFetching={isFetching}\n />\n </div>\n );\n});\n\nMentionSuggestionList.displayName = \"MentionSuggestionList\";\n","/**\n * Mention data sources shared by every chat host.\n *\n * Each source function implements the SourceFn interface:\n * (context: SourceContext) => Promise<SourceResult>\n *\n * Sources are either:\n * - FETCHERS: Call GraphQL API (assets, folders, team, etc.)\n * - TRANSFORMERS: Return static/local data (root categories, host-provided items)\n */\n\nimport type {\n MenuItem,\n SourceFn,\n SourceResult,\n SourceToRegister,\n FetchMetadata,\n WebpageMention,\n} from \"../types\";\nimport { MentionMenuSection } from \"../types\";\nimport {\n fetchGraphQL,\n SIMPLE_SEARCH_QUERY,\n PAGINATED_ASSETS_QUERY,\n WORKSPACE_MEMBERS_QUERY,\n type MentionAuthContext,\n type AssetResult,\n type WorkspaceMember,\n} from \"../api-client\";\nimport { assetTypeToThumb, assetTypeToIcon } from \"./asset-type-icons\";\n\n// ── Helpers ──\n\nfunction assetToMenuItem(asset: AssetResult): MenuItem {\n const isFolder = asset.athenaOriginalType === \"folder\";\n return {\n id: asset.id,\n name: asset.title || \"Untitled\",\n type: isFolder ? \"folder\" : \"asset\",\n thumbnailUrl: assetTypeToThumb(asset.athenaOriginalType),\n fallbackIcon: assetTypeToIcon(asset.athenaOriginalType),\n navigatesToScope: isFolder ? asset.id : undefined,\n visibleInScopes: new Set(),\n updatedAt: asset.updatedAt ?? undefined,\n extra: {\n athenaOriginalType: asset.athenaOriginalType,\n parentFolderId: asset.parentFolderId,\n },\n };\n}\n\nasync function querySimpleSearch(\n auth: MentionAuthContext,\n opts: {\n query?: string;\n limit: number;\n offset: number;\n includeTypes?: string[];\n excludeTypes?: string[];\n },\n): Promise<{ items: MenuItem[]; hasMore: boolean }> {\n const searchRequest: Record<string, any> = {\n query: opts.query?.trim() || \"\",\n type: opts.includeTypes || [],\n notType: opts.excludeTypes || [],\n limit: opts.limit,\n offset: opts.offset,\n };\n\n const input = {\n searchRequest,\n returnFullAsset: true,\n shouldCalculateTotal: false,\n sort: { field: \"UPDATED_AT\", direction: \"DESC\" },\n filterColumns: { isArchived: false, isHidden: false },\n };\n\n const data = await fetchGraphQL<{ simpleSearch: { assets: AssetResult[]; totalCount: number } }>(\n auth,\n SIMPLE_SEARCH_QUERY,\n { input },\n );\n\n const assets = data.simpleSearch?.assets || [];\n return {\n items: assets.map(assetToMenuItem),\n hasMore: assets.length === opts.limit,\n };\n}\n\n// ══════════════════════════════════════════════════════════════════════\n// ROOT CATEGORIES (Transformer)\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface RootCategoriesConfig {\n categories: string[];\n getWebpages: () => readonly WebpageMention[];\n}\n\nconst CATEGORY_DEFS: Record<string, { name: string; icon: string; scope: string }> = {\n favorites: { name: \"Favorites\", icon: \"star\", scope: \"favorites\" },\n assets: { name: \"Assets\", icon: \"file-text\", scope: \"athena_assets\" },\n projects: { name: \"Projects\", icon: \"folder-kanban\", scope: \"athena_projects\" },\n browse_profiles: { name: \"Browse Profiles\", icon: \"globe\", scope: \"athena_browse_profiles\" },\n folders: { name: \"Folders\", icon: \"folder\", scope: \"athena_folders\" },\n team: { name: \"Team\", icon: \"users\", scope: \"team\" },\n drives: { name: \"Drives\", icon: \"hard-drive\", scope: \"drive_catalogs\" },\n};\n\nfunction webpageDescription(webpage: WebpageMention): string {\n try {\n const hostname = new URL(webpage.url).hostname;\n return webpage.isCurrent ? `${webpage.title} · ${hostname}` : hostname;\n } catch {\n return webpage.title;\n }\n}\n\nfunction webpageToMenuItem(webpage: WebpageMention): MenuItem {\n return {\n id: `webpage-tab-${webpage.tabId}`,\n name: webpage.isCurrent ? \"This webpage\" : webpage.title,\n type: \"tab\",\n thumbnailUrl: assetTypeToThumb(\"web_page\"),\n fallbackIcon: \"globe\",\n visibleInScopes: new Set([\"root\"]),\n description: webpageDescription(webpage),\n url: webpage.url,\n menuSection: webpage.isCurrent\n ? MentionMenuSection.CURRENT_WEBPAGE\n : MentionMenuSection.OTHER_WEBPAGES,\n extra: {\n tabId: webpage.tabId,\n title: webpage.title,\n isCurrent: webpage.isCurrent,\n },\n };\n}\n\nexport function buildRootMenuItems({\n categories,\n webpages,\n}: {\n categories: readonly string[];\n webpages: readonly WebpageMention[];\n}): MenuItem[] {\n const webpageItems = webpages.map(webpageToMenuItem);\n const categoryItems = categories\n .filter((cat: string) => CATEGORY_DEFS[cat])\n .map((cat: string) => {\n const def = CATEGORY_DEFS[cat];\n return {\n id: cat,\n name: def.name,\n type: \"menu\" as const,\n fallbackIcon: def.icon,\n visibleInScopes: new Set([\"root\"]),\n navigatesToScope: def.scope,\n isNavigationOnly: true,\n menuSection: MentionMenuSection.LIBRARY,\n };\n });\n\n return [...webpageItems, ...categoryItems];\n}\n\nexport const transformRootCategories: SourceFn<RootCategoriesConfig> = async (context) => {\n const { sourceConfig } = context;\n const items = buildRootMenuItems({\n categories: sourceConfig.categories,\n webpages: sourceConfig.getWebpages(),\n });\n\n return { items, pagination: { hasMore: false } };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// ASSETS (Fetcher) — All non-folder assets via SimpleSearch\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface AssetsConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchAssets: SourceFn<AssetsConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit,\n offset,\n excludeTypes: [\"folder\", \"catalog\", \"spaces\", \"session\", \"table\", \"task_item\"],\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// FAVORITES (Fetcher) — Favorited assets\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface FavoritesConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchFavorites: SourceFn<FavoritesConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const data = await fetchGraphQL<{ getPaginatedAssetsForWorkspace: AssetResult[] }>(\n sourceConfig.auth,\n PAGINATED_ASSETS_QUERY,\n {\n limit,\n offset,\n parentFolderId: null,\n filterTypes: null,\n filterColumns: {\n isFavorited: true,\n isArchived: false,\n isHidden: false,\n },\n },\n );\n\n const assets = data.getPaginatedAssetsForWorkspace || [];\n const items = assets.map(assetToMenuItem);\n\n return {\n items,\n pagination: { hasMore: assets.length === limit },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// FOLDERS (Fetcher) — All folders as flat list\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface FoldersConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchFolders: SourceFn<FoldersConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit,\n offset,\n includeTypes: [\"folder\"],\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// FOLDER CONTENTS (Fetcher) — Contents of a specific folder\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface FolderContentsConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchFolderContents: SourceFn<FolderContentsConfig> = async (context) => {\n const { scope, query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n // Scope IS the folder ID (or 'internal_drive' for root)\n const parentFolderId = scope === \"internal_drive\" ? null : scope;\n\n const data = await fetchGraphQL<{ getPaginatedAssetsForWorkspace: AssetResult[] }>(\n sourceConfig.auth,\n PAGINATED_ASSETS_QUERY,\n {\n limit,\n offset,\n parentFolderId,\n filterTypes: null,\n filterColumns: {\n isArchived: false,\n isHidden: false,\n ...(query ? { title: [{ op: \"LIKE\", value: `%${query}%` }] } : {}),\n },\n },\n );\n\n const rawAssets = data.getPaginatedAssetsForWorkspace || [];\n // Exclude catalogs from folder contents\n const assets = rawAssets.filter(\n (a) => a.athenaConvertedType !== \"catalog\" && a.athenaOriginalType !== \"catalog\",\n );\n const items = assets.map(assetToMenuItem);\n\n return {\n items,\n pagination: {\n hasMore: rawAssets.length === limit,\n consumedCount: rawAssets.length,\n },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// PROJECTS (Fetcher) — Project assets\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface TypedAssetsConfig {\n auth: MentionAuthContext;\n includeOnlyTypes: string[];\n limit?: number;\n}\n\nexport const fetchTypedAssets: SourceFn<TypedAssetsConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit,\n offset,\n includeTypes: sourceConfig.includeOnlyTypes,\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// TEAM (Fetcher) — Workspace members\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface TeamConfig {\n auth: MentionAuthContext;\n}\n\nexport const fetchTeam: SourceFn<TeamConfig> = async (context) => {\n const { sourceConfig } = context;\n const { auth } = sourceConfig;\n\n if (!auth.workspaceId) {\n return { items: [], pagination: { hasMore: false } };\n }\n\n const data = await fetchGraphQL<{ getUsersInWorkspace: WorkspaceMember[] }>(\n auth,\n WORKSPACE_MEMBERS_QUERY,\n { workspaceId: auth.workspaceId },\n );\n\n const members = data.getUsersInWorkspace || [];\n const items: MenuItem[] = members.map((member) => {\n const displayName =\n [member.firstName, member.lastName].filter(Boolean).join(\" \").trim() ||\n member.email ||\n \"Unknown User\";\n\n return {\n id: member.email || member.id,\n name: displayName,\n type: \"user\" as const,\n fallbackIcon: \"user\",\n visibleInScopes: new Set<string>(),\n email: member.email ?? undefined,\n extra: { isAdmin: member.isAdmin },\n };\n });\n\n return { items, pagination: { hasMore: false } };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// DRIVES (Fetcher) — Drive catalog assets\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface DrivesConfig {\n auth: MentionAuthContext;\n}\n\nexport const fetchDrives: SourceFn<DrivesConfig> = async (context) => {\n const { fetchState, sourceConfig } = context;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n limit: 50,\n offset,\n includeTypes: [\"catalog\"],\n });\n\n // Drive catalogs are navigation-only (navigate into them to see contents)\n const items: MenuItem[] = result.items.map((item) => ({\n ...item,\n type: \"drive_catalog\" as const,\n fallbackIcon: \"hard-drive\",\n isNavigationOnly: true,\n navigatesToScope: item.id,\n }));\n\n // Register folder contents source for each catalog\n const sources: SourceToRegister[] = items.map((item) => ({\n scope: item.id,\n sourceFn: fetchFolderContents,\n sourceConfig: { auth: sourceConfig.auth, limit: 50 },\n }));\n\n return {\n items,\n pagination: { hasMore: result.hasMore },\n sources,\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// GLOBAL SEARCH (Fetcher) — Aggregated search across all sources\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface GlobalSearchConfig {\n auth: MentionAuthContext;\n}\n\nexport const fetchGlobalSearch: SourceFn<GlobalSearchConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n if (!query?.trim()) return { items: [], pagination: { hasMore: false } };\n\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit: 50,\n offset,\n excludeTypes: [\"table\", \"catalog\", \"spaces\", \"task_item\", \"session\"],\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n","/**\n * Chrome Extension Mention Suggestions Store\n *\n * Full Olympus-style mention store with all categories:\n * Favorites, Assets, Projects, Browse Profiles, Folders,\n * current/group webpages, Team, Workspace, Drives + Global Search.\n *\n * Uses registry + cache architecture from Olympus with\n * async data fetching via GraphQL.\n */\n\nimport { Store } from \"@tanstack/store\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport type { MentionAuthContext } from \"./api-client\";\nimport { useMentionAuth } from \"./api-client\";\nimport { createItemCache, type ItemCache } from \"./item-cache\";\nimport {\n createScopeRegistry,\n registerSource,\n bindScopes,\n type ScopeRegistry,\n} from \"./scope-registry\";\nimport {\n transformRootCategories,\n fetchAssets,\n fetchFavorites,\n fetchFolders,\n fetchFolderContents,\n fetchTypedAssets,\n fetchTeam,\n fetchDrives,\n fetchGlobalSearch,\n} from \"./sources\";\nimport type { WebpageMention } from \"./types\";\n\nexport function webpageMentionFingerprint(\n webpages: readonly WebpageMention[],\n): string {\n return JSON.stringify(\n webpages.map(({ tabId, title, url, isCurrent }) => [\n tabId,\n title,\n url,\n isCurrent,\n ]),\n );\n}\n\n// ── Store types ──\n\nexport interface MentionSuggestionsStoreState {\n registry: ScopeRegistry;\n cache: ItemCache;\n}\n\nexport type MentionSuggestionsStore = Store<MentionSuggestionsStoreState>;\n\n// ── Categories ──\n\n/**\n * All mention menu categories, in display order.\n */\nexport const ROOT_MENTION_CATEGORIES = [\n \"favorites\",\n \"assets\",\n \"projects\",\n \"browse_profiles\",\n \"folders\",\n \"team\",\n \"drives\",\n] as const;\n\nexport type MentionRootCategory = (typeof ROOT_MENTION_CATEGORIES)[number];\n\n// ── Store builder ──\n\nfunction buildStore({\n auth,\n getWebpages,\n rootCategories,\n}: {\n auth: MentionAuthContext;\n getWebpages: () => readonly WebpageMention[];\n rootCategories: readonly MentionRootCategory[];\n}): MentionSuggestionsStore {\n const registry = createScopeRegistry();\n const cache = createItemCache();\n\n // ── Root categories ──\n registerSource(registry, \"root\", transformRootCategories, {\n categories: [...rootCategories],\n getWebpages,\n });\n\n // ── Global search (aggregated) ──\n registerSource(registry, \"global_search\", fetchGlobalSearch, { auth });\n bindScopes(registry, \"root\", \"global_search\");\n\n // ── Assets ──\n registerSource(registry, \"athena_assets\", fetchAssets, { auth, limit: 50 });\n\n // ── Favorites ──\n registerSource(registry, \"favorites\", fetchFavorites, { auth, limit: 50 });\n\n // ── Folders (flat list) ──\n registerSource(registry, \"athena_folders\", fetchFolders, { auth, limit: 50 }, true /* isFlat */);\n\n // ── Internal drive (folder navigation root) ──\n registerSource(registry, \"internal_drive\", fetchFolderContents, { auth, limit: 50 });\n\n // ── Projects ──\n registerSource(registry, \"athena_projects\", fetchTypedAssets, {\n auth,\n includeOnlyTypes: [\"project\"],\n limit: 50,\n });\n\n // ── Browse Profiles ──\n registerSource(registry, \"athena_browse_profiles\", fetchTypedAssets, {\n auth,\n includeOnlyTypes: [\"browse_profile\"],\n limit: 50,\n });\n\n // ── Team ──\n registerSource(registry, \"team\", fetchTeam, { auth });\n\n // ── Drives (catalogs) ──\n registerSource(registry, \"drive_catalogs\", fetchDrives, { auth });\n\n return new Store<MentionSuggestionsStoreState>({ registry, cache });\n}\n\n// ── Hook ──\n\n/**\n * Creates a stable MentionSuggestionsStore.\n * Uses MentionAuthCtx for API credentials.\n */\nexport function useMentionSuggestions({\n webpages,\n rootCategories = ROOT_MENTION_CATEGORIES,\n}: {\n webpages: readonly WebpageMention[];\n /** Categories shown at the top level; hosts can narrow the default set. */\n rootCategories?: readonly MentionRootCategory[];\n}): {\n store: MentionSuggestionsStore;\n invalidate: (scope: string) => void;\n} {\n const auth = useMentionAuth();\n const webpagesRef = useRef(webpages);\n webpagesRef.current = webpages;\n\n // Depend on primitive values to avoid rebuilding store on object identity changes\n const store = useMemo(\n () =>\n buildStore({\n auth,\n getWebpages: () => webpagesRef.current,\n rootCategories,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n auth.backendUrl,\n auth.accessToken,\n auth.apiKey,\n auth.workspaceId,\n auth.userId,\n rootCategories.join(\",\"),\n ],\n );\n\n const invalidate = useMemo(\n () => (scope: string) => {\n const state = store.state;\n const { registry, cache } = state;\n\n // Clear scope from cache\n if (cache.items) {\n for (const item of Object.values(cache.items)) {\n item.visibleInScopes.delete(scope);\n }\n // Remove orphaned items\n for (const [id, item] of Object.entries(cache.items)) {\n if (item.visibleInScopes.size === 0) {\n delete cache.items[id];\n }\n }\n }\n\n // Reset fetch states\n if (registry.entries[scope]) {\n registry.entries[scope].fetchStates = {};\n }\n\n store.setState((prev) => ({ ...prev }));\n },\n [store],\n );\n\n const webpageFingerprint = webpageMentionFingerprint(webpages);\n const previousWebpageFingerprintRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (previousWebpageFingerprintRef.current === webpageFingerprint) return;\n previousWebpageFingerprintRef.current = webpageFingerprint;\n invalidate(\"root\");\n }, [invalidate, webpageFingerprint]);\n\n return { store, invalidate };\n}\n","export class PendingAttachmentUploads {\n\tprivate readonly pending = new Set<Promise<void>>();\n\n\ttrack(upload: Promise<void>): Promise<void> {\n\t\tthis.pending.add(upload);\n\t\tvoid upload.then(\n\t\t\t() => this.pending.delete(upload),\n\t\t\t() => this.pending.delete(upload),\n\t\t);\n\t\treturn upload;\n\t}\n\n\tasync waitForIdle(): Promise<void> {\n\t\twhile (this.pending.size > 0) {\n\t\t\tawait Promise.allSettled([...this.pending]);\n\t\t}\n\t}\n}\n","/**\n * Tiptap Composer — Full Olympus mention system integration\n *\n * Uses the ported Olympus infrastructure:\n * - MentionSuggestionList (with scope navigation, breadcrumbs, keyboard nav)\n * - MentionSuggestionPopup (Floating UI positioning)\n * - MentionSuggestionsExtension (Tiptap @ trigger)\n * - MentionExtension (inline mention chips)\n * - useMentionSuggestions (full Olympus categories + async data)\n *\n * Auth credentials for GraphQL are provided via MentionAuthCtx, and the host\n * app (Chrome side panel, Office task pane) supplies any host-only mention\n * items — browser tabs, for instance — through `webpages`.\n */\n\nimport { useRef, useState, useCallback, useEffect, forwardRef, useImperativeHandle } from \"react\";\nimport { useEditor, EditorContent } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Extension, type JSONContent } from \"@tiptap/core\";\nimport { unstable_useComposerInput, useAui } from \"@assistant-ui/react\";\nimport { MentionExtension } from \"../mentions/mention-extension\";\nimport {\n MentionSuggestionsExtension,\n type MentionSuggestionCallbacks,\n type MentionSuggestionRenderProps,\n} from \"../mentions/suggestions/mention-suggestions.extension\";\nimport { MentionSuggestionPopup } from \"../mentions/suggestions/components/mention-suggestion-popup\";\nimport {\n MentionSuggestionList,\n} from \"../mentions/suggestions/components/mention-suggestion-list\";\nimport {\n useMentionSuggestions,\n type MentionRootCategory,\n} from \"../mentions/suggestions/data/use-mention-suggestions\";\nimport type {\n MenuItem,\n WebpageMention,\n} from \"../mentions/suggestions/data/types\";\nimport type { KeyboardNavigationHandle } from \"../mentions/suggestions/components/use-keyboard-navigation\";\nimport {\n registerChatAssetMentionHandler,\n type UploadedChatAsset,\n} from \"@athenaintel/agent-runtime\";\nimport { PendingAttachmentUploads } from \"./pending-attachment-uploads\";\n\n// ── Submit keybind extension ──\n\nconst SubmitKeybind = Extension.create<{ onSubmit: () => void; isMentionOpen: () => boolean }>({\n name: \"submitKeybind\",\n priority: 1000,\n addOptions() {\n return { onSubmit: () => {}, isMentionOpen: () => false };\n },\n addKeyboardShortcuts() {\n return {\n Enter: () => {\n // Don't submit when the mention popup is open — let it handle Enter\n if (this.options.isMentionOpen()) return false;\n this.options.onSubmit();\n return true;\n },\n \"Shift-Enter\": () => {\n this.editor.commands.setHardBreak();\n return true;\n },\n };\n },\n});\n\n// ── CSS for mention chips + editor ──\n\nconst MENTION_STYLES = `\n .mention-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: rgba(148, 163, 184, 0.1);\n color: #475569;\n border: 1px solid #cbd5e1;\n border-radius: 6px;\n padding: 1px 6px;\n font-size: 0.85em;\n font-weight: 500;\n white-space: nowrap;\n user-select: all;\n vertical-align: middle;\n height: 20px;\n line-height: 1;\n }\n .mention-chip-icon {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n }\n .mention-chip-text {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 180px;\n }\n .ProseMirror {\n outline: none;\n min-height: 36px;\n max-height: 120px;\n overflow-y: auto;\n }\n .ProseMirror p {\n margin: 0;\n }\n .ProseMirror p.is-editor-empty:first-child::before {\n content: attr(data-placeholder);\n float: left;\n color: #9ca3af;\n pointer-events: none;\n height: 0;\n }\n`;\n\n/** Convert recovered runtime text without letting Tiptap parse it as HTML. */\nexport function plainTextToTiptapContent(text: string): JSONContent {\n return {\n type: \"doc\",\n content: text.split(\"\\n\").map((line) => ({\n type: \"paragraph\",\n ...(line.length > 0\n ? { content: [{ type: \"text\", text: line }] }\n : {}),\n })),\n };\n}\n\n// ── Main component ──\n\nexport interface TiptapComposerHandle {\n submit: () => Promise<void>;\n addAttachment: (file: File) => Promise<void>;\n insertAssetMention: (asset: UploadedChatAsset) => void;\n}\n\nexport interface TiptapComposerProps {\n placeholder?: string;\n threadId: string;\n disabled?: boolean;\n /** Host-provided browser-tab mentions; empty in hosts without tab access. */\n webpages?: readonly WebpageMention[];\n rootCategories?: readonly MentionRootCategory[];\n onDraftStateChange?: (hasDraft: boolean) => void;\n /**\n * Optional submit interception: called with the serialized draft before the\n * composer-runtime send. Return `true` when the host consumed the draft\n * through another lane (e.g. a live voice session) — the editor clears and\n * the normal send is skipped. Return `false` to fall through unchanged.\n */\n interceptSubmit?: (text: string) => boolean | Promise<boolean>;\n}\n\nconst NO_WEBPAGES: readonly WebpageMention[] = [];\n\nexport const TiptapComposer = forwardRef<\n TiptapComposerHandle,\n TiptapComposerProps\n>(({ placeholder = \"Message Athena... (type @ to mention)\", threadId, disabled = false, webpages = NO_WEBPAGES, rootCategories, onDraftStateChange, interceptSubmit }, outerRef) => {\n const aui = useAui();\n const composerInput = unstable_useComposerInput();\n const applyingRuntimeTextRef = useRef(false);\n const listRef = useRef<KeyboardNavigationHandle>(null);\n const pendingUploadsRef = useRef(new PendingAttachmentUploads());\n const submitInFlightRef = useRef(false);\n\n const { store } = useMentionSuggestions({ webpages, rootCategories });\n\n // Popup state\n const [popupOpen, setPopupOpen] = useState(false);\n const popupOpenRef = useRef(false);\n const [popupProps, setPopupProps] = useState<MentionSuggestionRenderProps | null>(null);\n\n // Suggestion callbacks — drive the popup lifecycle\n const callbacksRef = useRef<MentionSuggestionCallbacks>({\n onStart: (props) => {\n setPopupOpen(true);\n popupOpenRef.current = true;\n setPopupProps(props);\n },\n onUpdate: (props) => {\n setPopupProps(props);\n },\n onKeyDown: (event) => {\n // Route keyboard events to the MentionSuggestionList\n return listRef.current?.onKeyDown(event) ?? false;\n },\n onExit: () => {\n setPopupOpen(false);\n popupOpenRef.current = false;\n setPopupProps(null);\n },\n });\n\n // Editor ref — needed because handleSubmit is created before useEditor returns\n const editorRef = useRef<ReturnType<typeof useEditor>>(null);\n\n // Submit via composer runtime so attachments (screenshots, files) are included.\n // aui.composer.setText() + aui.composer.send() bundles text + pending attachments.\n //\n // Statewire turns a send during an active run into a queued command. Do not\n // cancel first: cancellation aborts the shared run for every connected\n // client and turns a normal queued follow-up into a destructive stop.\n const handleSubmit = useCallback(async () => {\n if (disabled) return;\n if (submitInFlightRef.current) return;\n submitInFlightRef.current = true;\n try {\n await pendingUploadsRef.current.waitForIdle();\n const ed = editorRef.current;\n if (!ed) return;\n const text = ed.getText({ blockSeparator: \"\\n\" }).trim();\n if (!text) return;\n if (!composerInput.canSend) return;\n\n // Interception carries TEXT only: a draft with pending attachments\n // (screenshots, files) must ride the composer-runtime send that\n // bundles them, or the attachments would silently vanish. Attachment\n // state is read only when a host actually intercepts.\n if (interceptSubmit) {\n const hasAttachments =\n (aui.composer.getState().attachments?.length ?? 0) > 0;\n if (!hasAttachments && (await interceptSubmit(text))) {\n ed.commands.clearContent();\n onDraftStateChange?.(false);\n return;\n }\n }\n\n composerInput.setText(text);\n composerInput.send({ steer: false });\n\n ed.commands.clearContent();\n onDraftStateChange?.(false);\n } finally {\n submitInFlightRef.current = false;\n }\n }, [composerInput, disabled, interceptSubmit, onDraftStateChange]);\n\n const handleSubmitRef = useRef(handleSubmit);\n handleSubmitRef.current = handleSubmit;\n\n const addAttachment = useCallback(\n (file: File) =>\n pendingUploadsRef.current.track(aui.composer.addAttachment(file)),\n [aui],\n );\n\n // Handle paste events — intercept images from clipboard and add as attachments\n const handlePaste = useCallback(\n (_view: unknown, event: ClipboardEvent) => {\n const items = event.clipboardData?.items;\n if (!items) return false;\n\n let handled = false;\n for (const item of items) {\n if (item.type.startsWith(\"image/\")) {\n event.preventDefault();\n const blob = item.getAsFile();\n if (blob) {\n const ext = item.type.split(\"/\")[1] || \"png\";\n const file = new File([blob], `pasted-image-${Date.now()}.${ext}`, { type: item.type });\n void addAttachment(file).catch((error: unknown) => {\n console.error(\"[attach] Pasted image upload failed:\", error);\n });\n }\n handled = true;\n }\n }\n return handled;\n },\n [addAttachment],\n );\n\n // Handle drop events — intercept dropped image files\n const handleDrop = useCallback(\n (_view: unknown, event: DragEvent) => {\n const files = event.dataTransfer?.files;\n if (!files?.length) return false;\n\n let handled = false;\n for (const file of files) {\n if (file.type.startsWith(\"image/\")) {\n event.preventDefault();\n void addAttachment(file).catch((error: unknown) => {\n console.error(\"[attach] Dropped image upload failed:\", error);\n });\n handled = true;\n }\n }\n return handled;\n },\n [addAttachment],\n );\n\n const editor = useEditor({\n editable: !disabled,\n extensions: [\n StarterKit.configure({\n heading: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({ placeholder }),\n MentionExtension,\n MentionSuggestionsExtension.configure({\n store,\n callbacks: callbacksRef.current,\n }),\n SubmitKeybind.configure({\n onSubmit: () => void handleSubmitRef.current(),\n isMentionOpen: () => popupOpenRef.current,\n }),\n ],\n editorProps: {\n attributes: {\n class:\n \"w-full resize-none bg-transparent px-1.5 py-2 text-sm leading-snug outline-none\",\n \"data-testid\": \"athena-chat-composer\",\n },\n handlePaste,\n handleDrop,\n },\n onUpdate: ({ editor: updatedEditor }) => {\n const nextText = updatedEditor.getText({ blockSeparator: \"\\n\" });\n if (!applyingRuntimeTextRef.current) {\n composerInput.setText(nextText);\n }\n onDraftStateChange?.(nextText.trim().length > 0);\n },\n immediatelyRender: false,\n });\n\n // Keep ref in sync so handleSubmit always has the editor\n editorRef.current = editor;\n\n useEffect(() => {\n editor?.setEditable(!disabled);\n }, [disabled, editor]);\n\n // This rich editor replaces ComposerPrimitive.Input, so it must mirror its\n // draft into assistant-ui's composer state. Statewire restores that state\n // when a send is rejected during reconnect; mirroring it back into Tiptap\n // preserves the user's message instead of leaving an empty composer.\n useEffect(() => {\n if (!editor) return;\n const editorText = editor.getText({ blockSeparator: \"\\n\" });\n if (editorText === composerInput.value) return;\n applyingRuntimeTextRef.current = true;\n editor.commands.setContent(plainTextToTiptapContent(composerInput.value));\n applyingRuntimeTextRef.current = false;\n onDraftStateChange?.(composerInput.value.trim().length > 0);\n }, [composerInput.value, editor, onDraftStateChange]);\n\n const insertAssetMention = useCallback((asset: UploadedChatAsset) => {\n const currentEditor = editorRef.current;\n if (!currentEditor) throw new Error(\"The chat composer is not ready.\");\n currentEditor\n .chain()\n .focus()\n .insertContent({\n type: \"mention\",\n attrs: {\n type: \"asset\",\n name: asset.title,\n id: asset.id,\n assetType: asset.assetType,\n },\n })\n .insertContent(\" \")\n .run();\n }, []);\n\n useEffect(\n () => registerChatAssetMentionHandler(threadId, insertAssetMention),\n [insertAssetMention, threadId],\n );\n\n useImperativeHandle(\n outerRef,\n () => ({ submit: handleSubmit, addAttachment, insertAssetMention }),\n [addAttachment, handleSubmit, insertAssetMention],\n );\n\n return (\n <>\n <style>{MENTION_STYLES}</style>\n <div\n className=\"flex-1 min-w-0\"\n aria-label=\"Message composer\"\n aria-disabled={disabled}\n >\n <EditorContent editor={editor} />\n </div>\n\n {/* Olympus-style mention popup */}\n {popupOpen && popupProps && editor && (\n <MentionSuggestionPopup clientRect={popupProps.clientRect}>\n <MentionSuggestionList\n ref={listRef}\n store={store}\n editor={editor}\n query={popupProps.query}\n command={(item: MenuItem) => popupProps.command(item)}\n closeMenu={() => {\n setPopupOpen(false);\n editor.commands.focus();\n }}\n />\n </MentionSuggestionPopup>\n )}\n </>\n );\n});\n\nTiptapComposer.displayName = \"TiptapComposer\";\n","import { useId } from \"react\";\nimport type { ChangeEvent, FC, ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nexport const SignInCard: FC<{\n /** e.g. \"Local build abcd1234\" — shown under the heading when set. */\n buildLabel?: string | null;\n subtitle?: ReactNode;\n /** Environment pickers, consent checkboxes, and other host controls. */\n children?: ReactNode;\n error?: string | null;\n /** Hint shown above the button (e.g. host cannot open a dialog). */\n notice?: ReactNode;\n primaryLabel: string;\n primaryPendingLabel: string;\n isPending: boolean;\n disabled?: boolean;\n onPrimary: () => void;\n /** Developer fallbacks and other secondary affordances. */\n footer?: ReactNode;\n}> = ({\n buildLabel,\n subtitle,\n children,\n error,\n notice,\n primaryLabel,\n primaryPendingLabel,\n isPending,\n disabled = false,\n onPrimary,\n footer,\n}) => (\n // `min-h-full` centers the card in hosts whose root is not a flex container.\n <div className=\"flex min-h-full flex-1 flex-col items-center justify-center bg-muted/20 p-5\">\n <div className=\"w-full max-w-sm space-y-5 rounded-2xl border bg-background/95 p-5 shadow-sm\">\n <div className=\"text-center\">\n <h2 className=\"text-base font-semibold tracking-tight text-foreground\">\n Sign in to Athena\n </h2>\n {buildLabel ? (\n <p className=\"mt-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {buildLabel}\n </p>\n ) : null}\n {subtitle ? (\n <p className=\"mt-1.5 text-xs leading-relaxed text-muted-foreground\">\n {subtitle}\n </p>\n ) : null}\n </div>\n\n {children ? <div className=\"space-y-3\">{children}</div> : null}\n\n {notice ? (\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{notice}</p>\n ) : null}\n <div role=\"status\" aria-live=\"polite\">\n {error ? <p className=\"text-xs text-destructive\">{error}</p> : null}\n </div>\n\n <button\n type=\"button\"\n className=\"h-10 w-full rounded-lg bg-primary px-4 text-sm font-semibold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-40\"\n onClick={onPrimary}\n disabled={isPending || disabled}\n >\n {isPending ? primaryPendingLabel : primaryLabel}\n </button>\n\n {footer}\n </div>\n </div>\n);\n\nexport const SignInSelect: FC<{\n id: string;\n label: string;\n value: string;\n options: ReadonlyArray<{ label: string; value: string }>;\n onChange: (value: string) => void;\n /** Resolved endpoint shown under the select. */\n hint?: string | null;\n}> = ({ id, label, value, options, onChange, hint }) => (\n <div className=\"space-y-1.5\">\n <label\n htmlFor={id}\n className=\"text-[10px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n {label}\n </label>\n <select\n id={id}\n className=\"h-10 w-full rounded-lg border bg-background px-3 text-sm outline-none transition-shadow focus:ring-2 focus:ring-ring/20\"\n value={value}\n onChange={(event: ChangeEvent<HTMLSelectElement>) =>\n onChange(event.target.value)\n }\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {hint ? (\n <p className=\"px-1 text-[10px] text-muted-foreground\">{hint}</p>\n ) : null}\n </div>\n);\n\nexport const SignInTextField: FC<{\n label: string;\n placeholder?: string;\n value: string;\n onChange: (value: string) => void;\n type?: \"url\" | \"password\" | \"text\";\n className?: string;\n}> = ({ label, placeholder, value, onChange, type = \"text\", className }) => (\n <label className=\"block space-y-1\">\n <span className=\"text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {label}\n </span>\n <input\n className={cn(\n \"h-9 w-full rounded-md border bg-background px-2.5 text-xs outline-none focus:ring-2 focus:ring-ring/20\",\n className,\n )}\n type={type}\n placeholder={placeholder}\n value={value}\n onChange={(event: ChangeEvent<HTMLInputElement>) =>\n onChange(event.target.value)\n }\n />\n </label>\n);\n\n/** Collapsible section under the primary button, for developer-only logins. */\nexport const SignInFallbackSection: FC<{\n isOpen: boolean;\n onToggle: () => void;\n label: string;\n children: ReactNode;\n}> = ({ isOpen, onToggle, label, children }) => {\n const contentId = useId();\n return (\n <div className=\"border-t pt-3\">\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={contentId}\n className=\"w-full text-left text-[11px] font-medium text-muted-foreground hover:text-foreground\"\n onClick={onToggle}\n >\n {isOpen ? \"Hide\" : \"Show\"} {label}\n </button>\n {isOpen ? (\n <div id={contentId} className=\"mt-3 space-y-2\">\n {children}\n </div>\n ) : null}\n </div>\n );\n};\n\n/** Secondary button matching the fallback section's weight. */\nexport const SignInSecondaryButton: FC<{\n onClick: () => void;\n disabled?: boolean;\n children: ReactNode;\n}> = ({ onClick, disabled = false, children }) => (\n <button\n type=\"button\"\n className=\"h-9 w-full rounded-lg border bg-background text-xs font-medium hover:bg-muted disabled:opacity-40\"\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </button>\n);\n\n/** Checkbox + explanatory copy, used for host data-use disclosures. */\nexport const SignInConsent: FC<{\n checked: boolean;\n onChange: (checked: boolean) => void;\n children: ReactNode;\n}> = ({ checked, onChange, children }) => (\n <label className=\"flex cursor-pointer items-start gap-2.5 rounded-lg border bg-muted/30 p-3 text-xs leading-relaxed text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"mt-0.5 h-4 w-4 shrink-0 accent-primary\"\n checked={checked}\n onChange={(event: ChangeEvent<HTMLInputElement>) =>\n onChange(event.target.checked)\n }\n />\n <span>{children}</span>\n </label>\n);\n"],"names":["__iconNode","LoaderCircleIcon","BotIcon","MessageSquareIcon","RefreshCwIcon","PlusIcon","SearchIcon","ArchiveIcon","params","item","FileIcon","FileTextIcon","FileCodeIcon","FolderIcon","FolderKanbanIcon","GlobeIcon","StarIcon","UsersIcon","UserIcon","WrenchIcon","PackageIcon","Building2Icon","HardDriveIcon","LayoutGridIcon","ZapIcon","EyeIcon","CameraIcon","KeyboardIcon","CodeIcon","MonitorIcon","ImageIcon","VideoIcon","HeadphonesIcon","MicIcon","MailIcon","CalendarIcon","PhoneIcon","DatabaseIcon","TableIcon","SheetIcon","PaletteIcon","PenToolIcon","LayoutIcon","LayoutDashboardIcon","LibraryIcon","BookOpenIcon","SparklesIcon","CheckSquareIcon","KeyIcon","SmartphoneIcon","CloudIcon","WorkflowIcon","offset","Fragment"],"mappings":"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","x_google_ignoreList":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]}
|
|
1
|
+
{"version":3,"file":"chat-ui.js","sources":["../../agent-runtime/src/asset-attachment.ts","../../../node_modules/lucide-react/dist/esm/icons/archive.js","../../../node_modules/lucide-react/dist/esm/icons/bot.js","../../../node_modules/lucide-react/dist/esm/icons/building-2.js","../../../node_modules/lucide-react/dist/esm/icons/cloud.js","../../../node_modules/lucide-react/dist/esm/icons/eye.js","../../../node_modules/lucide-react/dist/esm/icons/file-code.js","../../../node_modules/lucide-react/dist/esm/icons/headphones.js","../../../node_modules/lucide-react/dist/esm/icons/key.js","../../../node_modules/lucide-react/dist/esm/icons/keyboard.js","../../../node_modules/lucide-react/dist/esm/icons/layout-dashboard.js","../../../node_modules/lucide-react/dist/esm/icons/library.js","../../../node_modules/lucide-react/dist/esm/icons/mic.js","../../../node_modules/lucide-react/dist/esm/icons/palette.js","../../../node_modules/lucide-react/dist/esm/icons/panels-top-left.js","../../../node_modules/lucide-react/dist/esm/icons/pen-tool.js","../../../node_modules/lucide-react/dist/esm/icons/phone.js","../../../node_modules/lucide-react/dist/esm/icons/smartphone.js","../../../node_modules/lucide-react/dist/esm/icons/sparkles.js","../../../node_modules/lucide-react/dist/esm/icons/square-check-big.js","../../../node_modules/lucide-react/dist/esm/icons/star.js","../../../node_modules/lucide-react/dist/esm/icons/user.js","../../../node_modules/lucide-react/dist/esm/icons/video.js","../../../node_modules/lucide-react/dist/esm/icons/zap.js","../src/chat-ui/header/chat-header.tsx","../src/chat-ui/header/conversation-history-panel.tsx","../src/chat-ui/mentions/mention-extension.ts","../src/chat-ui/mentions/suggestions/mention-suggestions.extension.ts","../src/chat-ui/mentions/suggestions/components/mention-suggestion-popup.tsx","../src/chat-ui/mentions/suggestions/data/orchestrator.ts","../src/chat-ui/mentions/suggestions/data/use-menu-items.ts","../src/chat-ui/mentions/suggestions/components/get-scope-name.ts","../src/chat-ui/mentions/suggestions/data/types.ts","../src/chat-ui/mentions/suggestions/components/mention-icon.tsx","../src/chat-ui/mentions/suggestions/components/menu-item.tsx","../src/chat-ui/mentions/suggestions/components/menu-skeleton.tsx","../src/chat-ui/mentions/suggestions/components/menu-list.tsx","../src/chat-ui/mentions/suggestions/components/menu-breadcrumbs.tsx","../src/chat-ui/mentions/suggestions/components/menu-summary.tsx","../src/chat-ui/mentions/suggestions/components/use-keyboard-navigation.ts","../src/chat-ui/mentions/suggestions/components/use-menu-navigation.ts","../src/chat-ui/mentions/suggestions/components/utils.ts","../src/chat-ui/mentions/suggestions/components/mention-suggestion-list.tsx","../src/chat-ui/mentions/suggestions/data/sources/index.ts","../src/chat-ui/mentions/suggestions/data/use-mention-suggestions.ts","../src/chat-ui/composer/pending-attachment-uploads.ts","../src/chat-ui/composer/tiptap-composer.tsx","../src/chat-ui/auth/sign-in-card.tsx","../src/chat-ui/messages/continue-pill.tsx","../src/chat-ui/messages/statewire-continue-run.tsx"],"sourcesContent":["import type {\n Attachment,\n AttachmentAdapter,\n CompleteAttachment,\n PendingAttachment,\n} from '@assistant-ui/core';\n\n/**\n * Shared Athena asset-attachment choreography (issue #29088): upload the file\n * as a normal Athena asset, insert its final mention into the host composer,\n * and yield no assistant-ui attachment tile — the deep-agent backend resolves\n * the mention (documents via read_asset, images inlined server-side), so no\n * duplicate base64 part ever enters statewire. No preparation state rides the\n * wire: readiness is local to the composer doing the attaching.\n */\n\nexport interface UploadedChatAsset {\n id: string;\n title: string;\n assetType: string;\n}\n\n/** Composer mention-insertion hook. The return value is awaited when it is a\n * promise and otherwise ignored, so ordinary event-handler arrows fit. */\nexport type ChatAssetMentionHandler = (asset: UploadedChatAsset) => unknown;\n\nconst mentionHandlersByThread = new Map<string, ChatAssetMentionHandler>();\n\n/**\n * Register the composer's mention-insertion hook for one thread. The hook is\n * the per-client seam — TipTap on web, the native editor bridge on mobile —\n * and the identity-checked unregister keeps a stale composer from clobbering\n * a newer registration.\n */\nexport function registerChatAssetMentionHandler(\n threadId: string,\n handler: ChatAssetMentionHandler\n): () => void {\n mentionHandlersByThread.set(threadId, handler);\n return () => {\n if (mentionHandlersByThread.get(threadId) === handler) {\n mentionHandlersByThread.delete(threadId);\n }\n };\n}\n\nexport function getChatAssetMentionHandler(\n threadId: string\n): ChatAssetMentionHandler | undefined {\n return mentionHandlersByThread.get(threadId);\n}\n\nexport interface ChatAssetUploadResponse {\n success?: Array<{\n id?: unknown;\n title?: unknown;\n file_name?: unknown;\n athena_original_type?: unknown;\n }>;\n}\n\n/**\n * Map agora's `/api/upload/` response to the mention payload. Title falls\n * back `title → file_name → local file name`; the asset type falls back to\n * the caller's sniffed default when the row carries none.\n */\nexport function uploadedChatAsset(args: {\n body: ChatAssetUploadResponse;\n fallbackTitle: string;\n fallbackAssetType: string;\n}): UploadedChatAsset {\n const row = args.body.success?.[0];\n if (!row || typeof row.id !== 'string') {\n throw new Error('The upload finished without creating an asset.');\n }\n const title =\n typeof row.title === 'string' && row.title.trim()\n ? row.title\n : typeof row.file_name === 'string' && row.file_name.trim()\n ? row.file_name\n : args.fallbackTitle;\n return {\n id: row.id,\n title,\n assetType:\n typeof row.athena_original_type === 'string' && row.athena_original_type.length > 0\n ? row.athena_original_type\n : args.fallbackAssetType,\n };\n}\n\n/** The local default when the upload response carries no asset type. */\nexport function sniffAssetTypeForFile(file: { type: string }): string {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type === 'application/pdf') return 'pdf';\n return 'file';\n}\n\nexport interface UploadChatAssetOptions {\n /** Agora base URL (trailing slashes tolerated). */\n baseUrl: string;\n file: File;\n /** Auth headers for the upload request. */\n headers: () => Promise<Record<string, string>> | Record<string, string>;\n /**\n * Fresh headers for exactly one retry after a 401 (e.g. a force-renewed\n * token). Omitted, a 401 fails like any other error status.\n */\n retryHeadersOn401?: () => Promise<Record<string, string>> | Record<string, string>;\n /** Upload timeout; the request aborts (and the add() rejects) past it. */\n timeoutMs?: number;\n}\n\nconst DEFAULT_UPLOAD_TIMEOUT_MS = 60_000;\n\nasync function uploadOnce(\n options: UploadChatAssetOptions,\n headers: Record<string, string>\n): Promise<Response> {\n const form = new FormData();\n form.append('files', options.file, options.file.name);\n return fetch(`${options.baseUrl.replace(/\\/+$/, '')}/api/upload/`, {\n method: 'POST',\n headers,\n body: form,\n signal: AbortSignal.timeout(options.timeoutMs ?? DEFAULT_UPLOAD_TIMEOUT_MS),\n });\n}\n\n/**\n * Upload one file as an Athena asset through agora's `/api/upload/`.\n * Cancellation and the timeout live inside the adapter path by construction:\n * the abort signal rejects the `add()` generator, so the composer's send\n * (which awaits adapter completion) can never race a hung upload.\n */\nexport async function uploadChatAsset(\n options: UploadChatAssetOptions\n): Promise<UploadedChatAsset> {\n let response = await uploadOnce(options, await options.headers());\n if (response.status === 401 && options.retryHeadersOn401) {\n response = await uploadOnce(options, await options.retryHeadersOn401());\n }\n if (!response.ok) {\n const detail = await response.text().catch(() => '');\n throw new Error(\n `Attachment upload failed (${response.status})${\n detail ? `: ${detail.slice(0, 200)}` : ''\n }`\n );\n }\n return uploadedChatAsset({\n body: (await response.json()) as ChatAssetUploadResponse,\n fallbackTitle: options.file.name,\n fallbackAssetType: sniffAssetTypeForFile(options.file),\n });\n}\n\nexport interface AthenaAssetAttachmentAdapterOptions {\n threadId: string;\n /** File-picker filter; defaults to images (the deep-agent mention path). */\n accept?: string;\n /** Platform upload transport; most hosts wrap {@link uploadChatAsset}. */\n upload: (file: File) => Promise<UploadedChatAsset>;\n}\n\n/**\n * The shared mention-backed attachment adapter: `add()` requires the thread's\n * registered composer hook up front (no upload cost when the composer is\n * gone), uploads, then inserts the mention into the thread's CURRENT hook —\n * a same-thread composer remount mid-upload still receives the mention, and\n * the thread-keyed registry makes cross-thread insertion impossible by\n * construction. A thread whose hook is gone after the upload rejects with a\n * visible error (the conversation closed; the user must re-attach).\n * `send()` throws by contract: mention-backed attachments are never message\n * parts.\n */\nexport class AthenaAssetAttachmentAdapter implements AttachmentAdapter {\n readonly accept: string;\n\n constructor(private readonly options: AthenaAssetAttachmentAdapterOptions) {\n this.accept = options.accept ?? 'image/*';\n }\n\n // eslint-disable-next-line require-yield -- mention-backed uploads deliberately create no attachment tile\n async *add(args: { file: File }): AsyncGenerator<PendingAttachment, void> {\n const handler = getChatAssetMentionHandler(this.options.threadId);\n if (handler === undefined) {\n throw new Error('The original conversation is no longer open.');\n }\n const uploaded = await this.options.upload(args.file);\n const current = getChatAssetMentionHandler(this.options.threadId);\n if (current === undefined) {\n throw new Error('The original conversation is no longer open.');\n }\n await current(uploaded);\n }\n\n async remove(_attachment: Attachment): Promise<void> {}\n\n async send(_attachment: PendingAttachment): Promise<CompleteAttachment> {\n throw new Error('Mention-backed attachments are not sent as message parts.');\n }\n}\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"20\", height: \"5\", x: \"2\", y: \"3\", rx: \"1\", key: \"1wp1u1\" }],\n [\"path\", { d: \"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8\", key: \"1s80jp\" }],\n [\"path\", { d: \"M10 12h4\", key: \"a56b0p\" }]\n];\nconst Archive = createLucideIcon(\"archive\", __iconNode);\n\nexport { __iconNode, Archive as default };\n//# sourceMappingURL=archive.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 8V4H8\", key: \"hb8ula\" }],\n [\"rect\", { width: \"16\", height: \"12\", x: \"4\", y: \"8\", rx: \"2\", key: \"enze0r\" }],\n [\"path\", { d: \"M2 14h2\", key: \"vft8re\" }],\n [\"path\", { d: \"M20 14h2\", key: \"4cs60a\" }],\n [\"path\", { d: \"M15 13v2\", key: \"1xurst\" }],\n [\"path\", { d: \"M9 13v2\", key: \"rq6x2g\" }]\n];\nconst Bot = createLucideIcon(\"bot\", __iconNode);\n\nexport { __iconNode, Bot as default };\n//# sourceMappingURL=bot.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 12h4\", key: \"a56b0p\" }],\n [\"path\", { d: \"M10 8h4\", key: \"1sr2af\" }],\n [\"path\", { d: \"M14 21v-3a2 2 0 0 0-4 0v3\", key: \"1rgiei\" }],\n [\n \"path\",\n {\n d: \"M6 10H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-2\",\n key: \"secmi2\"\n }\n ],\n [\"path\", { d: \"M6 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16\", key: \"16ra0t\" }]\n];\nconst Building2 = createLucideIcon(\"building-2\", __iconNode);\n\nexport { __iconNode, Building2 as default };\n//# sourceMappingURL=building-2.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z\", key: \"p7xjir\" }]\n];\nconst Cloud = createLucideIcon(\"cloud\", __iconNode);\n\nexport { __iconNode, Cloud as default };\n//# sourceMappingURL=cloud.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n];\nconst Eye = createLucideIcon(\"eye\", __iconNode);\n\nexport { __iconNode, Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"path\", { d: \"M10 12.5 8 15l2 2.5\", key: \"1tg20x\" }],\n [\"path\", { d: \"m14 12.5 2 2.5-2 2.5\", key: \"yinavb\" }]\n];\nconst FileCode = createLucideIcon(\"file-code\", __iconNode);\n\nexport { __iconNode, FileCode as default };\n//# sourceMappingURL=file-code.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3\",\n key: \"1xhozi\"\n }\n ]\n];\nconst Headphones = createLucideIcon(\"headphones\", __iconNode);\n\nexport { __iconNode, Headphones as default };\n//# sourceMappingURL=headphones.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n];\nconst Key = createLucideIcon(\"key\", __iconNode);\n\nexport { __iconNode, Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 8h.01\", key: \"1r9ogq\" }],\n [\"path\", { d: \"M12 12h.01\", key: \"1mp3jc\" }],\n [\"path\", { d: \"M14 8h.01\", key: \"1primd\" }],\n [\"path\", { d: \"M16 12h.01\", key: \"1l6xoz\" }],\n [\"path\", { d: \"M18 8h.01\", key: \"emo2bl\" }],\n [\"path\", { d: \"M6 8h.01\", key: \"x9i8wu\" }],\n [\"path\", { d: \"M7 16h10\", key: \"wp8him\" }],\n [\"path\", { d: \"M8 12h.01\", key: \"czm47f\" }],\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\", key: \"18n3k1\" }]\n];\nconst Keyboard = createLucideIcon(\"keyboard\", __iconNode);\n\nexport { __iconNode, Keyboard as default };\n//# sourceMappingURL=keyboard.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"9\", x: \"3\", y: \"3\", rx: \"1\", key: \"10lvy0\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"14\", y: \"3\", rx: \"1\", key: \"16une8\" }],\n [\"rect\", { width: \"7\", height: \"9\", x: \"14\", y: \"12\", rx: \"1\", key: \"1hutg5\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"ldoo1y\" }]\n];\nconst LayoutDashboard = createLucideIcon(\"layout-dashboard\", __iconNode);\n\nexport { __iconNode, LayoutDashboard as default };\n//# sourceMappingURL=layout-dashboard.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m16 6 4 14\", key: \"ji33uf\" }],\n [\"path\", { d: \"M12 6v14\", key: \"1n7gus\" }],\n [\"path\", { d: \"M8 8v12\", key: \"1gg7y9\" }],\n [\"path\", { d: \"M4 4v16\", key: \"6qkkli\" }]\n];\nconst Library = createLucideIcon(\"library\", __iconNode);\n\nexport { __iconNode, Library as default };\n//# sourceMappingURL=library.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 19v3\", key: \"npa21l\" }],\n [\"path\", { d: \"M19 10v2a7 7 0 0 1-14 0v-2\", key: \"1vc78b\" }],\n [\"rect\", { x: \"9\", y: \"2\", width: \"6\", height: \"13\", rx: \"3\", key: \"s6n7sd\" }]\n];\nconst Mic = createLucideIcon(\"mic\", __iconNode);\n\nexport { __iconNode, Mic as default };\n//# sourceMappingURL=mic.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\",\n key: \"e79jfc\"\n }\n ],\n [\"circle\", { cx: \"13.5\", cy: \"6.5\", r: \".5\", fill: \"currentColor\", key: \"1okk4w\" }],\n [\"circle\", { cx: \"17.5\", cy: \"10.5\", r: \".5\", fill: \"currentColor\", key: \"f64h9f\" }],\n [\"circle\", { cx: \"6.5\", cy: \"12.5\", r: \".5\", fill: \"currentColor\", key: \"qy21gx\" }],\n [\"circle\", { cx: \"8.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"fotxhn\" }]\n];\nconst Palette = createLucideIcon(\"palette\", __iconNode);\n\nexport { __iconNode, Palette as default };\n//# sourceMappingURL=palette.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M9 21V9\", key: \"1oto5p\" }]\n];\nconst PanelsTopLeft = createLucideIcon(\"panels-top-left\", __iconNode);\n\nexport { __iconNode, PanelsTopLeft as default };\n//# sourceMappingURL=panels-top-left.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\",\n key: \"nt11vn\"\n }\n ],\n [\n \"path\",\n {\n d: \"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18\",\n key: \"15qc1e\"\n }\n ],\n [\"path\", { d: \"m2.3 2.3 7.286 7.286\", key: \"1wuzzi\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"2\", key: \"xmgehs\" }]\n];\nconst PenTool = createLucideIcon(\"pen-tool\", __iconNode);\n\nexport { __iconNode, PenTool as default };\n//# sourceMappingURL=pen-tool.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384\",\n key: \"9njp5v\"\n }\n ]\n];\nconst Phone = createLucideIcon(\"phone\", __iconNode);\n\nexport { __iconNode, Phone as default };\n//# sourceMappingURL=phone.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"14\", height: \"20\", x: \"5\", y: \"2\", rx: \"2\", ry: \"2\", key: \"1yt0o3\" }],\n [\"path\", { d: \"M12 18h.01\", key: \"mhygvu\" }]\n];\nconst Smartphone = createLucideIcon(\"smartphone\", __iconNode);\n\nexport { __iconNode, Smartphone as default };\n//# sourceMappingURL=smartphone.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\",\n key: \"1s2grr\"\n }\n ],\n [\"path\", { d: \"M20 2v4\", key: \"1rf3ol\" }],\n [\"path\", { d: \"M22 4h-4\", key: \"gwowj6\" }],\n [\"circle\", { cx: \"4\", cy: \"20\", r: \"2\", key: \"6kqj1y\" }]\n];\nconst Sparkles = createLucideIcon(\"sparkles\", __iconNode);\n\nexport { __iconNode, Sparkles as default };\n//# sourceMappingURL=sparkles.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M21 10.656V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h12.344\", key: \"2acyp4\" }\n ],\n [\"path\", { d: \"m9 11 3 3L22 4\", key: \"1pflzl\" }]\n];\nconst SquareCheckBig = createLucideIcon(\"square-check-big\", __iconNode);\n\nexport { __iconNode, SquareCheckBig as default };\n//# sourceMappingURL=square-check-big.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\",\n key: \"r04s7s\"\n }\n ]\n];\nconst Star = createLucideIcon(\"star\", __iconNode);\n\nexport { __iconNode, Star as default };\n//# sourceMappingURL=star.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\", key: \"975kel\" }],\n [\"circle\", { cx: \"12\", cy: \"7\", r: \"4\", key: \"17ys0d\" }]\n];\nconst User = createLucideIcon(\"user\", __iconNode);\n\nexport { __iconNode, User as default };\n//# sourceMappingURL=user.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\",\n key: \"ftymec\"\n }\n ],\n [\"rect\", { x: \"2\", y: \"6\", width: \"14\", height: \"12\", rx: \"2\", key: \"158x01\" }]\n];\nconst Video = createLucideIcon(\"video\", __iconNode);\n\nexport { __iconNode, Video as default };\n//# sourceMappingURL=video.js.map\n","/**\n * @license lucide-react v0.575.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\",\n key: \"1xq2db\"\n }\n ]\n];\nconst Zap = createLucideIcon(\"zap\", __iconNode);\n\nexport { __iconNode, Zap as default };\n//# sourceMappingURL=zap.js.map\n","import type { ReactNode } from 'react';\nimport { cn } from '../../lib/utils';\nimport {\n THREAD_HEADER_ACTIONS_CLASS,\n THREAD_HEADER_CLASS,\n THREAD_HEADER_PILL_CLASS,\n} from '../messages/message-components';\n\nexport function ChatHeaderRoot({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return <div className={cn(THREAD_HEADER_CLASS, className)}>{children}</div>;\n}\n\nexport function ChatHeaderIdentity({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return <div className={cn(THREAD_HEADER_PILL_CLASS, className)}>{children}</div>;\n}\n\nexport function ChatHeaderActions({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return <div className={cn(THREAD_HEADER_ACTIONS_CLASS, className)}>{children}</div>;\n}\n\n/** Composition API keeps each host's exact action order visible at call sites. */\nexport const ChatHeader = {\n Root: ChatHeaderRoot,\n Identity: ChatHeaderIdentity,\n Actions: ChatHeaderActions,\n};\n","import type { ConversationSummary } from \"@athenaintel/agent-runtime\";\nimport {\n ArchiveIcon,\n BotIcon,\n LoaderCircleIcon,\n MessageSquareIcon,\n PlusIcon,\n RefreshCwIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport { useMemo, type ChangeEvent } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { conversationDisplayTitle } from \"../../threads/use-rest-conversation-history\";\nimport { assetTypeToThumb } from \"../mentions/suggestions/data/sources/asset-type-icons\";\n\nexport type ConversationActivityFilter = \"all\" | \"chat\" | \"automated\";\nexport type ConversationTimeGroup =\n | \"Today\"\n | \"Yesterday\"\n | \"This Week\"\n | \"This Month\"\n | \"Older\";\n\nconst TIME_GROUPS: readonly ConversationTimeGroup[] = [\n \"Today\",\n \"Yesterday\",\n \"This Week\",\n \"This Month\",\n \"Older\",\n];\n\nconst AUTOMATED_SOURCE_CHANNELS = new Set([\n \"api\",\n \"email\",\n \"orchestration\",\n \"slack\",\n \"sms\",\n \"task\",\n \"teams\",\n]);\n\n/** Mirrors Agora's persisted background-run classification for list metadata. */\nexport function isAutomatedConversation(\n conversation: Pick<ConversationSummary, \"sourceChannel\" | \"triggerType\">,\n): boolean {\n const sourceChannel = conversation.sourceChannel?.trim().toLowerCase();\n if (sourceChannel && AUTOMATED_SOURCE_CHANNELS.has(sourceChannel))\n return true;\n const triggerType = conversation.triggerType?.trim().toLowerCase();\n return Boolean(triggerType && triggerType !== \"manual\");\n}\n\nexport function conversationTimeGroup(\n value: string,\n now: Date = new Date(),\n): ConversationTimeGroup {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return \"Older\";\n const startOfToday = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n );\n const startOfYesterday = new Date(startOfToday.getTime() - 86_400_000);\n const startOfWeek = new Date(\n startOfToday.getTime() - startOfToday.getDay() * 86_400_000,\n );\n const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);\n if (date >= startOfToday) return \"Today\";\n if (date >= startOfYesterday) return \"Yesterday\";\n if (date >= startOfWeek) return \"This Week\";\n if (date >= startOfMonth) return \"This Month\";\n return \"Older\";\n}\n\nexport interface ConversationHistoryPanelProps {\n conversations: readonly ConversationSummary[];\n activeThreadId: string;\n search: string;\n onSearchChange: (search: string) => void;\n activityFilter: ConversationActivityFilter;\n onActivityFilterChange: (filter: ConversationActivityFilter) => void;\n originFilter: string;\n onOriginFilterChange: (origin: string) => void;\n onSelect: (threadId: string) => void;\n onNewChat: () => void;\n onRefresh: () => void;\n onArchive: (threadId: string) => void;\n onSetReadState: (threadId: string, isUnread: boolean) => void;\n isLoading?: boolean;\n isRefreshing?: boolean;\n hasNextPage?: boolean;\n isFetchingNextPage?: boolean;\n onLoadMore?: () => void;\n}\n\nfunction originKey(conversation: ConversationSummary): string {\n return conversation.appId ?? conversation.sourceChannel ?? \"unknown\";\n}\n\nfunction originLabel(value: string): string {\n const normalized = value.toLowerCase();\n if (normalized.includes(\"chrome\")) return \"Chrome\";\n if (normalized.includes(\"powerpoint\")) return \"PowerPoint\";\n if (normalized.includes(\"word\")) return \"Word\";\n if (normalized.includes(\"excel\")) return \"Excel\";\n if (normalized.includes(\"office\")) return \"Office\";\n if (normalized === \"web\" || normalized.includes(\"olympus\")) return \"Athena\";\n if (normalized.includes(\"mobile\")) return \"Mobile\";\n if (value === \"unknown\") return \"Legacy\";\n return value.replace(/^athena[-_]/, \"\").replaceAll(\"_\", \" \");\n}\n\nfunction relativeTime(value: string): string {\n const timestamp = Date.parse(value);\n if (!Number.isFinite(timestamp)) return \"\";\n const elapsed = Math.max(0, Date.now() - timestamp);\n const minutes = Math.floor(elapsed / 60_000);\n if (minutes < 1) return \"<1m ago\";\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ${minutes % 60}m ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : new Date(timestamp).toLocaleDateString();\n}\n\nfunction ConversationTypeIcon({\n conversation,\n automated,\n}: {\n conversation: ConversationSummary;\n automated: boolean;\n}) {\n if (conversation.state === \"running\") {\n return (\n <LoaderCircleIcon\n aria-label=\"Conversation running\"\n className=\"mt-0.5 size-4 shrink-0 animate-spin text-primary\"\n />\n );\n }\n const thumbnail = assetTypeToThumb(conversation.assetType ?? \"session\");\n if (thumbnail) {\n return <img src={thumbnail} alt=\"\" className=\"mt-0.5 size-4 shrink-0\" />;\n }\n return automated ? (\n <BotIcon className=\"mt-0.5 size-4 shrink-0 text-primary\" />\n ) : (\n <MessageSquareIcon className=\"mt-0.5 size-4 shrink-0 text-emerald-500\" />\n );\n}\n\nexport function ConversationHistoryPanel({\n conversations,\n activeThreadId,\n search,\n onSearchChange,\n activityFilter,\n onActivityFilterChange,\n originFilter,\n onOriginFilterChange,\n onSelect,\n onNewChat,\n onRefresh,\n onArchive,\n onSetReadState,\n isLoading = false,\n isRefreshing = false,\n hasNextPage = false,\n isFetchingNextPage = false,\n onLoadMore,\n}: ConversationHistoryPanelProps) {\n const origins = useMemo(\n () => [...new Set(conversations.map(originKey))].sort(),\n [conversations],\n );\n const grouped = useMemo(() => {\n const visible = conversations.filter((conversation) => {\n const automated = isAutomatedConversation(conversation);\n if (activityFilter === \"chat\" && automated) return false;\n if (activityFilter === \"automated\" && !automated) return false;\n return originFilter === \"all\" || originKey(conversation) === originFilter;\n });\n const byGroup = new Map<ConversationTimeGroup, ConversationSummary[]>();\n for (const conversation of visible) {\n const group = conversationTimeGroup(conversation.updatedAt);\n const items = byGroup.get(group) ?? [];\n items.push(conversation);\n byGroup.set(group, items);\n }\n return TIME_GROUPS.flatMap((group) => {\n const items = byGroup.get(group);\n return items ? [{ group, items }] : [];\n });\n }, [activityFilter, conversations, originFilter]);\n const visibleCount = grouped.reduce(\n (count, group) => count + group.items.length,\n 0,\n );\n const handleSearch = (event: ChangeEvent<HTMLInputElement>) =>\n onSearchChange(event.target.value);\n\n return (\n <section\n aria-label=\"Conversation history\"\n className=\"border-b border-border bg-background px-2 pb-2\"\n data-testid=\"conversation-history-panel\"\n >\n <div className=\"flex h-10 items-center gap-1.5 px-1\">\n <h2 className=\"text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground\">\n Sessions\n </h2>\n <button\n type=\"button\"\n aria-label=\"Refresh sessions\"\n title=\"Refresh sessions\"\n disabled={isRefreshing}\n onClick={onRefresh}\n className=\"ml-auto rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50\"\n >\n <RefreshCwIcon\n className={cn(\"size-3.5\", isRefreshing && \"animate-spin\")}\n />\n </button>\n <button\n type=\"button\"\n onClick={onNewChat}\n className=\"flex h-7 shrink-0 items-center gap-1 rounded-md bg-primary px-2 text-[11px] font-medium text-primary-foreground\"\n >\n <PlusIcon className=\"size-3\" /> New\n </button>\n </div>\n <label className=\"relative block min-w-0 px-1 pb-2\">\n <SearchIcon className=\"pointer-events-none absolute left-3 top-1/2 size-3.5 -translate-y-[calc(50%+0.25rem)] text-muted-foreground\" />\n <span className=\"sr-only\">Search sessions</span>\n <input\n value={search}\n onChange={handleSearch}\n placeholder=\"Search sessions...\"\n className=\"h-8 w-full rounded-md border border-border bg-muted/40 pl-7 pr-2 text-xs outline-none focus:border-primary focus:bg-background\"\n />\n </label>\n <div className=\"flex gap-1 overflow-x-auto px-1 pb-2 text-[11px]\">\n {([\"all\", \"chat\", \"automated\"] as const).map((filter) => (\n <button\n key={filter}\n type=\"button\"\n onClick={() => onActivityFilterChange(filter)}\n className={cn(\n \"rounded-full border px-2 py-1 capitalize\",\n activityFilter === filter\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground\",\n )}\n >\n {filter === \"chat\"\n ? \"Chats\"\n : filter === \"automated\"\n ? \"Automations\"\n : \"All\"}\n </button>\n ))}\n <select\n aria-label=\"Filter by origin\"\n value={originFilter}\n onChange={(event) => onOriginFilterChange(event.target.value)}\n className=\"ml-auto rounded-full border border-border bg-background px-2 text-[11px] text-muted-foreground\"\n >\n <option value=\"all\">All origins</option>\n {origins.map((origin) => (\n <option key={origin} value={origin}>\n {originLabel(origin)}\n </option>\n ))}\n </select>\n </div>\n <div className=\"max-h-[min(60vh,28rem)] overflow-y-auto px-0.5\">\n {isLoading ? (\n <div className=\"flex items-center gap-2 px-2 py-4 text-xs text-muted-foreground\">\n <LoaderCircleIcon className=\"size-3.5 animate-spin\" /> Loading\n sessions…\n </div>\n ) : visibleCount === 0 ? (\n <p className=\"px-2 py-4 text-xs text-muted-foreground\">\n No matching sessions.\n </p>\n ) : (\n grouped.map(({ group, items }) => (\n <div key={group}>\n <h3 className=\"px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground/75\">\n {group}\n </h3>\n {items.map((conversation) => {\n const automated = isAutomatedConversation(conversation);\n return (\n <div\n key={conversation.threadId}\n className={cn(\n \"group flex items-start gap-2 rounded-md px-2 py-2 hover:bg-accent\",\n conversation.threadId === activeThreadId &&\n \"bg-primary/10 text-primary\",\n )}\n >\n <button\n type=\"button\"\n onClick={() => {\n onSelect(conversation.threadId);\n if (conversation.isUnread) {\n onSetReadState(conversation.threadId, false);\n }\n }}\n className=\"flex min-w-0 flex-1 items-start gap-2 text-left\"\n >\n <ConversationTypeIcon\n conversation={conversation}\n automated={automated}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-start gap-1\">\n <span className=\"line-clamp-2 flex-1 text-xs font-medium leading-snug\">\n {conversationDisplayTitle(conversation)}\n </span>\n {conversation.isUnread ? (\n <span\n aria-label=\"Unread\"\n className=\"mt-1 size-1.5 shrink-0 rounded-full bg-primary\"\n />\n ) : null}\n </span>\n <span className=\"mt-0.5 flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n <span>{relativeTime(conversation.updatedAt)}</span>\n <span aria-hidden=\"true\">·</span>\n <span className=\"truncate\">\n {originLabel(originKey(conversation))}\n </span>\n </span>\n </span>\n </button>\n <button\n type=\"button\"\n aria-label={`Archive ${conversationDisplayTitle(conversation)}`}\n title=\"Archive conversation\"\n onClick={() => onArchive(conversation.threadId)}\n className=\"invisible rounded p-1 text-muted-foreground hover:bg-background hover:text-foreground group-hover:visible focus:visible\"\n >\n <ArchiveIcon className=\"size-3.5\" />\n </button>\n </div>\n );\n })}\n </div>\n ))\n )}\n {hasNextPage ? (\n <button\n type=\"button\"\n disabled={isFetchingNextPage}\n onClick={onLoadMore}\n className=\"mt-1 w-full rounded-lg py-2 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50\"\n >\n {isFetchingNextPage ? \"Loading…\" : \"Load older sessions\"}\n </button>\n ) : visibleCount > 0 ? (\n <p className=\"py-2 text-center text-[10px] text-muted-foreground/70\">\n No more sessions\n </p>\n ) : null}\n </div>\n </section>\n );\n}\n","/**\n * Tiptap Mention Node Extension\n *\n * Defines the mention node type used in the editor. When a mention is\n * inserted, it creates a non-editable inline node with metadata.\n *\n * Renders as a chip with: [icon] Name\n */\n\nimport { mergeAttributes, Node } from \"@tiptap/core\";\n\nexport function makeMentionUrl(attrs: { id: string; type: string; name: string; title?: string; url?: string; description?: string; thumbnailUrl?: string; assetType?: string }): string {\n if (attrs.type === \"tool\" || attrs.type === \"toolkit\") {\n return `mention://${attrs.type}?name=${encodeURIComponent(attrs.id)}&description=${encodeURIComponent(attrs.description ?? \"\")}`;\n }\n if (attrs.type === \"asset\") {\n const params = new URLSearchParams({ asset_ids: attrs.id });\n if (attrs.assetType) params.set(\"assetType\", attrs.assetType);\n return `/dashboard/spaces?${params.toString()}`;\n }\n if (attrs.type === \"tab\") {\n const params = new URLSearchParams({\n tab_id: attrs.id,\n url: attrs.url ?? \"\",\n title: attrs.title ?? attrs.name,\n });\n return `mention://webpage?${params.toString()}`;\n }\n // Include athenaOriginalType and thumbnailUrl so the chip can be reconstructed\n const params = new URLSearchParams();\n params.set(\"id\", attrs.id);\n if (attrs.assetType) params.set(\"assetType\", attrs.assetType);\n if (attrs.thumbnailUrl) params.set(\"thumb\", attrs.thumbnailUrl);\n return `mention://${encodeURIComponent(attrs.type)}?${params.toString()}`;\n}\n\nexport interface MentionNodeAttrs {\n type: string;\n name: string;\n id: string;\n title?: string;\n url?: string;\n description?: string;\n thumbnailUrl?: string;\n fallbackIcon?: string;\n assetType?: string;\n}\n\nexport function parseMentionAnchorAttributes({\n href,\n textContent,\n}: {\n href: string;\n textContent: string | null;\n}): MentionNodeAttrs {\n const url = new URL(href);\n const isWebpage = url.hostname === \"webpage\";\n return {\n type: isWebpage ? \"tab\" : url.hostname || \"tool\",\n name: textContent?.replace(/^@/, \"\") || \"\",\n id: isWebpage\n ? url.searchParams.get(\"tab_id\") || \"\"\n : url.searchParams.get(\"name\") || url.searchParams.get(\"id\") || \"\",\n title: url.searchParams.get(\"title\") || \"\",\n url: url.searchParams.get(\"url\") || \"\",\n description: url.searchParams.get(\"description\") || \"\",\n thumbnailUrl: url.searchParams.get(\"thumb\") || \"\",\n fallbackIcon: \"\",\n assetType: url.searchParams.get(\"assetType\") || \"\",\n };\n}\n\nexport const MentionExtension = Node.create({\n name: \"mention\",\n group: \"inline\",\n inline: true,\n selectable: false,\n atom: true,\n\n addAttributes() {\n return {\n type: { default: \"tool\" },\n name: { default: \"\" },\n id: { default: \"\" },\n title: { default: \"\" },\n url: { default: \"\" },\n description: { default: \"\" },\n thumbnailUrl: { default: \"\" },\n fallbackIcon: { default: \"\" },\n assetType: { default: \"\" },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span[data-mention]\",\n getAttrs: (dom) => {\n const el = dom as HTMLElement;\n return {\n type: el.getAttribute(\"data-type\") || \"tool\",\n name: el.getAttribute(\"data-name\") || el.textContent?.replace(/^@/, \"\") || \"\",\n id: el.getAttribute(\"data-id\") || \"\",\n title: el.getAttribute(\"data-title\") || \"\",\n url: el.getAttribute(\"data-url\") || \"\",\n description: el.getAttribute(\"data-description\") || \"\",\n thumbnailUrl: el.getAttribute(\"data-thumbnail-url\") || \"\",\n fallbackIcon: el.getAttribute(\"data-fallback-icon\") || \"\",\n assetType: el.getAttribute(\"data-asset-type\") || \"\",\n };\n },\n },\n {\n tag: \"a[href^='mention://']\",\n getAttrs: (dom) => {\n const el = dom as HTMLAnchorElement;\n return parseMentionAnchorAttributes({\n href: el.href,\n textContent: el.textContent,\n });\n },\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const thumbnailUrl = node.attrs.thumbnailUrl;\n\n // Build child elements: [icon] name\n const children: any[] = [];\n\n if (thumbnailUrl) {\n // Render SVG thumbnail as an img element inside the chip\n children.push([\n \"img\",\n {\n src: thumbnailUrl,\n alt: \"\",\n class: \"mention-chip-icon\",\n draggable: \"false\",\n },\n ]);\n }\n\n children.push([\"span\", { class: \"mention-chip-text\" }, node.attrs.name]);\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n \"data-type\": node.attrs.type,\n \"data-name\": node.attrs.name,\n \"data-id\": node.attrs.id,\n \"data-title\": node.attrs.title || \"\",\n \"data-url\": node.attrs.url || \"\",\n \"data-thumbnail-url\": node.attrs.thumbnailUrl || \"\",\n \"data-asset-type\": node.attrs.assetType || \"\",\n class: \"mention-chip\",\n }),\n ...children,\n ];\n },\n\n renderText({ node }) {\n const url = makeMentionUrl({\n id: node.attrs.id,\n type: node.attrs.type,\n name: node.attrs.name,\n title: node.attrs.title,\n url: node.attrs.url,\n description: node.attrs.description,\n thumbnailUrl: node.attrs.thumbnailUrl,\n assetType: node.attrs.assetType,\n });\n return `[@${node.attrs.name}](${url})`;\n },\n});\n","/**\n * Tiptap Mention Suggestions Extension\n *\n * Integrates the mention popup with Tiptap's suggestion plugin.\n * Ported from Olympus — same lifecycle management.\n */\n\nimport { Extension } from \"@tiptap/core\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport type { MentionSuggestionsStore } from \"./data/use-mention-suggestions\";\nimport type { MenuItem } from \"./data/types\";\n\nexport interface MentionSuggestionRenderProps {\n query: string;\n command: (item: MenuItem) => void;\n clientRect: (() => DOMRect | null) | null;\n editor: any;\n}\n\nexport type MentionSuggestionCallbacks = {\n onStart: (props: MentionSuggestionRenderProps) => void;\n onUpdate: (props: MentionSuggestionRenderProps) => void;\n onKeyDown: (event: KeyboardEvent) => boolean;\n onExit: () => void;\n};\n\nexport const MentionSuggestionsExtension = Extension.create<{\n store: MentionSuggestionsStore | null;\n callbacks: MentionSuggestionCallbacks | null;\n}>({\n name: \"mentionSuggestions\",\n\n addOptions() {\n return {\n store: null,\n callbacks: null,\n };\n },\n\n addProseMirrorPlugins() {\n const callbacks = this.options.callbacks;\n\n return [\n Suggestion({\n editor: this.editor,\n char: \"@\",\n allowSpaces: false,\n startOfLine: false,\n allowedPrefixes: [\" \", \"\\t\", \"\\n\", \"\\r\", \"(\", \"[\", \"{\", '\"', \"'\", \"\\u00A0\"],\n\n items: () => [],\n\n command: ({ editor, range, props }) => {\n const item = props as unknown as MenuItem;\n // Skip items that can't be mentioned (navigation is handled by the\n // list component)\n if (item.navigatesToScope || item.isNavigationOnly) return;\n\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({\n type: \"mention\",\n attrs: {\n type: item.type,\n name: item.name,\n id:\n item.type === \"tab\" && typeof item.extra?.tabId === \"number\"\n ? String(item.extra.tabId)\n : item.id,\n title:\n item.type === \"tab\" && typeof item.extra?.title === \"string\"\n ? item.extra.title\n : item.name,\n url: item.url ?? \"\",\n description: item.description ?? \"\",\n thumbnailUrl: item.thumbnailUrl ?? \"\",\n fallbackIcon: item.fallbackIcon ?? \"\",\n assetType:\n typeof item.extra?.athenaOriginalType === \"string\"\n ? item.extra.athenaOriginalType\n : \"\",\n },\n })\n .insertContent(\" \")\n .run();\n },\n\n render: () => ({\n onStart: (props) => {\n callbacks?.onStart({\n query: props.query,\n command: (item) => props.command(item as never),\n clientRect: props.clientRect ?? null,\n editor: props.editor,\n });\n },\n onUpdate: (props) => {\n callbacks?.onUpdate({\n query: props.query,\n command: (item) => props.command(item as never),\n clientRect: props.clientRect ?? null,\n editor: props.editor,\n });\n },\n onKeyDown: ({ event }) => {\n return callbacks?.onKeyDown(event) ?? false;\n },\n onExit: () => {\n callbacks?.onExit();\n },\n }),\n }),\n ];\n },\n});\n","/**\n * Floating popup wrapper for the mention suggestion menu.\n * Uses Floating UI for positioning near the cursor.\n */\n\nimport { type FC, type ReactNode, useEffect } from \"react\";\nimport {\n useFloating,\n offset,\n flip,\n shift,\n autoUpdate,\n FloatingPortal,\n} from \"@floating-ui/react\";\n\nexport const MentionSuggestionPopup: FC<{\n clientRect: (() => DOMRect | null) | null;\n children: ReactNode;\n}> = ({ clientRect, children }) => {\n const { refs, floatingStyles } = useFloating({\n placement: \"bottom-start\",\n middleware: [offset(10), flip(), shift({ padding: 8 })],\n whileElementsMounted: autoUpdate,\n });\n\n // Use setPositionReference for virtual elements (cursor position)\n // instead of elements.reference which requires a real DOM element\n useEffect(() => {\n if (clientRect) {\n refs.setPositionReference({\n getBoundingClientRect: () => clientRect() ?? new DOMRect(),\n });\n }\n }, [clientRect, refs]);\n\n return (\n <FloatingPortal>\n <div\n ref={refs.setFloating}\n style={floatingStyles}\n className=\"z-[9999]\"\n onMouseDown={(e) => e.preventDefault()} // Prevent focus loss on click\n >\n {children}\n </div>\n </FloatingPortal>\n );\n};\n","/**\n * Mention Orchestrator — Async data fetching with registry + cache.\n *\n * selectItems (pure read) + triggerFetchIfNeeded (async fetch).\n */\n\nimport type { MenuItem, MenuScope, FetchMetadata, SourceToRegister } from \"./types\";\nimport type { MentionSuggestionsStore, MentionSuggestionsStoreState } from \"./use-mention-suggestions\";\nimport { getFilteredItems, addItems } from \"./item-cache\";\nimport {\n getEntry,\n getFetchState,\n updateFetchState,\n registerSource,\n bindScopes,\n} from \"./scope-registry\";\nimport { filterItems } from \"./utils/filter-items\";\n\n/** Consecutive fetch failures tolerated before a scope+query stops retrying. */\nconst MAX_ERROR_RETRIES = 3;\n\n/**\n * Select items for a given scope + query from the cache.\n * Pure, synchronous read — no side effects.\n */\nexport function selectItems(\n store: MentionSuggestionsStore,\n scope: MenuScope | { id: string },\n query: string,\n _targetCount?: number,\n parentScope?: MenuScope | { id: string },\n): { items: MenuItem[]; isFetching: boolean; hasMore: boolean } {\n const state = store.state;\n const scopeId = typeof scope === \"string\" ? scope : scope.id;\n const parentScopeId = parentScope\n ? typeof parentScope === \"string\" ? parentScope : parentScope.id\n : undefined;\n\n // Read from cache\n const items = getFilteredItems(state.cache, scopeId, query);\n\n // Read fetch state from registry\n let isFetching = false;\n let hasMore = true;\n\n try {\n const fetchState = getFetchState(state.registry, scopeId, query, parentScopeId);\n isFetching = fetchState.isFetching;\n hasMore = fetchState.hasNextPage;\n } catch {\n // Scope not registered — no more to fetch\n hasMore = false;\n }\n\n return { items, isFetching, hasMore };\n}\n\n/**\n * Trigger an async fetch if needed.\n * Called by useMenuItems when cache < target AND hasMore AND !fetching.\n */\nexport function triggerFetchIfNeeded(\n store: MentionSuggestionsStore,\n scope: MenuScope | { id: string },\n query: string,\n _targetCount?: number,\n parentScope?: MenuScope | { id: string },\n): void {\n const scopeId = typeof scope === \"string\" ? scope : scope.id;\n const parentScopeId = parentScope\n ? typeof parentScope === \"string\" ? parentScope : parentScope.id\n : undefined;\n\n const state = store.state;\n\n // Check if scope is registered\n let entry;\n try {\n entry = getEntry(state.registry, scopeId, parentScopeId);\n } catch {\n return; // Not registered, nothing to fetch\n }\n\n // Check fetch state\n const fetchState = getFetchState(state.registry, scopeId, query, parentScopeId);\n if (fetchState.isFetching || !fetchState.hasNextPage || fetchState.error) {\n return;\n }\n\n // Safety limit\n const meta = (fetchState.meta as FetchMetadata) || {};\n if ((meta.fetchAttempts || 0) >= 10) return;\n\n // Mark as fetching\n updateFetchState(state.registry, scopeId, query, { isFetching: true }, parentScopeId);\n store.setState((prev) => ({ ...prev }));\n\n // Async fetch\n const sourceFn = entry.sourceFn;\n const sourceConfig = entry.sourceConfig;\n\n sourceFn({\n scope: scopeId,\n query,\n fetchState,\n sourceConfig,\n })\n .then((result) => {\n const currentState = store.state;\n\n // Add items to cache with scope tagging\n addItems(currentState.cache, result.items, scopeId);\n\n // Register dynamically discovered sources\n if (result.sources) {\n for (const src of result.sources) {\n try {\n getEntry(currentState.registry, src.scope);\n } catch {\n // Not registered yet — register it\n registerSource(\n currentState.registry,\n src.scope,\n src.sourceFn,\n src.sourceConfig,\n src.isFlat,\n );\n }\n }\n }\n\n // Register dynamically discovered bindings\n if (result.bindings) {\n for (const binding of result.bindings) {\n bindScopes(currentState.registry, binding.browseScope, binding.searchScope);\n }\n }\n\n // Update fetch state\n const currentMeta = (fetchState.meta as FetchMetadata) || {};\n // Advance the server-side offset by the rows the source consumed, which\n // exceeds `items.length` whenever a source drops rows after fetching.\n const consumed = result.pagination?.consumedCount ?? result.items.length;\n const newValidated = (currentMeta.validatedCount || 0) + consumed;\n\n updateFetchState(\n currentState.registry,\n scopeId,\n query,\n {\n isFetching: false,\n hasNextPage: result.pagination?.hasMore ?? false,\n error: null,\n meta: {\n ...currentMeta,\n ...result.meta,\n validatedCount: newValidated,\n fetchAttempts: (currentMeta.fetchAttempts || 0) + 1,\n errorAttempts: 0,\n },\n },\n parentScopeId,\n );\n\n // Trigger re-render\n store.setState((prev) => ({ ...prev }));\n })\n .catch((error) => {\n console.error(`[orchestrator] Fetch error for scope ${scopeId}:`, error);\n\n const currentState = store.state;\n const currentMeta = (fetchState.meta as FetchMetadata) || {};\n const errorAttempts = ((currentMeta.errorAttempts as number) || 0) + 1;\n const retriable = errorAttempts < MAX_ERROR_RETRIES;\n\n updateFetchState(\n currentState.registry,\n scopeId,\n query,\n {\n isFetching: false,\n hasNextPage: retriable,\n error: retriable\n ? null\n : error instanceof Error\n ? error\n : new Error(String(error)),\n meta: { ...currentMeta, errorAttempts },\n },\n parentScopeId,\n );\n\n store.setState((prev) => ({ ...prev }));\n });\n}\n","import { useStore } from '@tanstack/react-store';\nimport { useEffect, useState } from 'react';\nimport { selectItems, triggerFetchIfNeeded } from './orchestrator';\nimport type { MenuItem, MenuScope } from './types';\nimport type { MentionSuggestionsStore } from './use-mention-suggestions';\n\n/**\n * useMenuItems - Like React Query, but for menu items\n *\n * Clean, automatic hook that:\n * - Reads items from store (reactive!)\n * - Auto-fetches if needed (in useEffect)\n * - Returns clean interface { items, isFetching, hasMore }\n *\n * Usage:\n * ```typescript\n * const { items, isFetching, hasMore } = useMenuItems(store, {\n * scope: 'athena_folders',\n * query: 'doc',\n * minItems: 10,\n * parentScope: 'root'\n * });\n * ```\n */\nexport interface UseMenuItemsOptions {\n scope: MenuScope;\n query?: string;\n minItems?: number;\n parentScope?: MenuScope;\n}\n\nexport interface UseMenuItemsResult {\n items: MenuItem[];\n isFetching: boolean;\n hasMore: boolean;\n loadMore: () => void; // Explicit load more (not automatic!)\n targetCount: number; // Current target for debugging\n}\n\nexport function useMenuItems(\n store: MentionSuggestionsStore,\n options: UseMenuItemsOptions\n): UseMenuItemsResult {\n const { scope, query = '', minItems = 50, parentScope } = options;\n\n // Target item count (increases when user clicks \"Load More\")\n const [targetCount, setTargetCount] = useState(minItems);\n\n // Reset target when scope/query changes\n // biome-ignore lint/correctness/useExhaustiveDependencies: We intentionally reset on scope/query change\n useEffect(() => {\n setTargetCount(minItems);\n }, [scope, query, minItems]);\n\n // Read from store (pure, reactive)\n const snapshot = useStore(store, () =>\n selectItems(store, scope, query, targetCount, parentScope)\n );\n\n // Auto-fetch when: cached < target AND hasMore AND !fetching\n useEffect(() => {\n if (snapshot.items.length < targetCount && snapshot.hasMore && !snapshot.isFetching) {\n triggerFetchIfNeeded(store, scope, query, targetCount, parentScope);\n }\n }, [\n store,\n scope,\n query,\n targetCount,\n parentScope,\n snapshot.items.length,\n snapshot.hasMore,\n snapshot.isFetching,\n ]);\n\n // Explicit load more: Increase target by 50\n const loadMore = () => {\n if (snapshot.hasMore && !snapshot.isFetching) {\n setTargetCount((prev) => prev + 50);\n }\n };\n\n return {\n items: snapshot.items,\n isFetching: snapshot.isFetching,\n hasMore: snapshot.hasMore,\n loadMore,\n targetCount, // Expose for debugging\n };\n}\n","import type { MenuScope } from '../data/types';\nimport type { MentionSuggestionsStore } from '../data/use-mention-suggestions';\n\n/**\n * Known category scope names\n *\n * These are the top-level menu categories that have stable IDs.\n */\nconst KNOWN_SCOPE_NAMES: Record<MenuScope, string> = {\n root: 'All',\n global_search: 'Search',\n // Legacy order: my_spaces, favorites, assets, folders, tools, toolkits, team, workspace, drives\n my_spaces: 'My Spaces',\n favorites: 'Favorites',\n athena_assets: 'Assets',\n athena_folders: 'Folders',\n tools: 'Tools',\n toolkits: 'Toolkits',\n team: 'Team',\n workspace: 'Workspace',\n drive_catalogs: 'Drives',\n athena_projects: 'Projects',\n athena_browse_profiles: 'Browse Profiles',\n // Additional scopes\n asset_search: 'Search',\n};\n\n/**\n * getScopeName - Get friendly display name for a scope\n *\n * Strategy:\n * 1. Check known category names (fast path)\n * 2. Look up dynamic item in cache (folders, assets, etc.)\n * 3. Fall back to scope ID itself\n *\n * @param scope - The scope ID to look up\n * @param store - The mention suggestions store (to access cache)\n * @returns Friendly display name\n */\nexport function getScopeName(scope: MenuScope, store: MentionSuggestionsStore): string {\n // Fast path: known category\n const knownName = KNOWN_SCOPE_NAMES[scope];\n if (knownName) {\n return knownName;\n }\n\n // Dynamic path: look up item in cache\n // This handles folders, assets, SharePoint sites, etc.\n const { cache } = store.state;\n const allItems = Object.values(cache.items);\n\n // Find item that navigates to this scope\n const item = allItems.find((item) => item.navigatesToScope === scope);\n if (item) {\n return item.name;\n }\n\n // Fallback: format scope ID\n // folder_123 → Folder 123\n // sharepoint_abc → Sharepoint Abc\n return scope\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n","/**\n * Core types for mention suggestions data layer\n */\n\n/**\n * MenuScope - A navigable container in the mention menu hierarchy\n *\n * Conceptual model:\n * - SCOPE = Container/Group you navigate INTO (e.g., \"athena_assets\", \"folder_123\")\n * - ITEM = Individual mentionable thing you SELECT (e.g., specific asset, tool)\n *\n * Scopes form a navigation hierarchy:\n * root → athena_assets → folder_123 → subfolder_456\n *\n * Items can be visible in multiple scopes simultaneously:\n * Asset \"Report.pdf\" is in both \"folder_123\" AND \"asset_search\" results\n */\nexport type MenuScope = string;\n\nexport const MentionMenuSection = {\n CURRENT_WEBPAGE: \"current-webpage\",\n OTHER_WEBPAGES: \"other-webpages\",\n LIBRARY: \"library\",\n} as const;\n\nexport type MentionMenuSection =\n (typeof MentionMenuSection)[keyof typeof MentionMenuSection];\n\nexport interface WebpageMention {\n tabId: number;\n title: string;\n url: string;\n isCurrent: boolean;\n}\n\nexport interface WebpageMentionScope {\n primaryTabId: number;\n tabGroupId: number | null;\n allowedTabIds: readonly number[];\n}\n\n/**\n * Selector result - provides current state + loading indicators\n * Used by the UI to get immediate access to data and loading state\n */\nexport interface MenuItemsSelector {\n items: MenuItem[];\n isFetching: boolean;\n hasMore: boolean;\n}\n\n/**\n * MenuItem - individual mentionable item\n * Icon fields match MentionIcon component props exactly - no transforms needed at render time!\n *\n * Multi-scope system: Items can belong to multiple scopes simultaneously\n * Example: An asset can be visible in 'athena_assets', 'folder_123', and 'my_spaces'\n */\nexport interface MenuItem {\n id: string;\n name: string;\n type:\n | 'menu'\n | 'asset'\n | 'folder'\n | 'tool'\n | 'toolkit'\n | 'drive'\n | 'user'\n | 'task'\n | 'tab'\n | 'workspace_item'\n | 'drive_catalog'\n | 'placeholder';\n\n // Icon fields (match MentionIcon component props)\n thumbnailUrl?: string; // For assets: URL/path to thumbnail (e.g., from AthenaTypeToThumb)\n fallbackIcon: string; // For menus/tools: Lucide icon name (e.g., 'Folder', 'Wrench') or emoji\n\n // Multi-scope membership: Which menu scopes this item is visible in\n // Items can belong to multiple scopes simultaneously\n visibleInScopes: Set<MenuScope>; // e.g., Set(['athena_assets', 'folder_123', 'my_spaces'])\n\n // Navigation capability: If present, this item can be navigated into\n // When user selects this item, navigate to this scope\n navigatesToScope?: MenuScope;\n\n // Navigation-only flag: If true, item CANNOT be inserted as mention (only navigate)\n // Use for root categories that are pure navigation containers\n isNavigationOnly?: boolean; // Default: false (most items are mentionable)\n\n // Type-specific metadata\n extra?: Record<string, any>;\n description?: string;\n url?: string;\n menuSection?: MentionMenuSection;\n updatedAt?: string;\n email?: string; // For user type\n version?: string; // For versioned assets\n\n // Legacy compatibility\n parentMenuId?: string;\n}\n\n/**\n * FetchState - fetch status and pagination state for a specific query\n * Managed by orchestrator, not returned by sources\n */\nexport interface FetchState {\n isFetching: boolean;\n hasNextPage: boolean;\n fetchNext: (() => void) | null;\n error: Error | null; // Track errors to prevent infinite retry loops\n\n // Source-specific pagination metadata (offset, cursor, page token, etc.)\n // Each source stores what IT needs between calls\n // Orchestrator doesn't care what's in here!\n meta: unknown;\n}\n\n/**\n * FetchMetadata - Common metadata fields used by orchestrator\n * Sources can extend this with their own fields (e.g., pageToken, cursor)\n */\nexport interface FetchMetadata {\n // Orchestrator fields\n validatedCount?: number; // Number of items fetched and validated so far\n fetchAttempts?: number; // Number of fetch attempts (for safety limits)\n // Source-specific fields can be added via extension or intersection\n [key: string]: unknown;\n}\n\n/**\n * New source to register dynamically\n * Returned by sources when they discover navigable items (folders, catalogs, etc.)\n */\nexport interface SourceToRegister {\n scope: MenuScope; // The scope ID to register\n sourceFn: SourceFn; // The source function to use for this scope\n sourceConfig?: any; // Configuration for the source\n isFlat?: boolean; // Whether this scope should be flat (no navigation arrows)\n}\n\n/**\n * Scope binding to register dynamically\n * Binds a browse scope to a search scope (hot scope swap on query)\n */\nexport interface ScopeBindingToRegister {\n browseScope: MenuScope; // The scope shown when browsing (no query)\n searchScope: MenuScope; // The scope shown when searching (has query)\n}\n\n/**\n * Source result - returned by all source functions\n *\n * Sources come in two flavors:\n * 1. TRANSFORMERS - Transform existing data (no API calls)\n * Examples: tools, toolkits, workspace members, opened spaces\n * Pattern: Read from store/ref → transform → return items\n *\n * 2. FETCHERS - Fetch from API (async operations)\n * Examples: internal assets, folders, SharePoint items\n * Pattern: Call GraphQL/REST → transform response → return items\n *\n * 3. HYBRID - Behavior depends on query\n * Example: Root menu (transformer when no query, fetcher with query)\n *\n * Original design: Sources can return new sources to register!\n * This allows discovered items (folders, catalogs) to be dynamically registered\n * without circular dependencies (orchestrator handles registration centrally)\n */\nexport interface SourceResult {\n // Items to add/update (source sets navigatesToScope on navigable items)\n // Orchestrator will tag these items with the current scope\n items: MenuItem[];\n\n // Pagination metadata (what we learned from this fetch)\n // All sources return this - orchestrator uses it\n pagination?: {\n hasMore: boolean;\n totalCount?: number;\n // Rows the source consumed from the server for this page. Defaults to\n // `items.length`; sources that drop rows after fetching must report the\n // pre-filter count so the next offset does not re-read the same rows.\n consumedCount?: number;\n };\n\n // Source-specific metadata (e.g., pageToken for SharePoint, cursor for pagination)\n // Orchestrator merges this into fetchState.meta for the next fetch\n meta?: Record<string, unknown>;\n\n // New sources to register (for discovered navigable items)\n // Orchestrator will register these in the registry\n sources?: SourceToRegister[];\n\n // New bindings to register (for hot scope swap on query)\n // Example: catalogId → catalogId_search\n bindings?: ScopeBindingToRegister[];\n}\n\n/**\n * Source function context\n *\n * Sources are pure functions - just fetch/transform and return items!\n * Orchestrator handles sync/deduplication via Cache.addItems() with scope tagging\n */\nexport interface SourceContext<TConfig = any> {\n scope: MenuScope; // Current scope we're fetching for\n query: string; // User's search query\n fetchState: FetchState; // Pagination state for this query (includes source-specific meta)\n sourceConfig: TConfig; // Source configuration (can include getters for reactive data!)\n}\n\n/**\n * Source function type\n *\n * Pure function that provides items for a scope + query combination.\n * Can be a transformer (reads from store) or fetcher (calls API).\n * State (pagination, sourceConfig) is stored externally in registry entry.\n */\nexport type SourceFn<TConfig = any> = (context: SourceContext<TConfig>) => Promise<SourceResult>;\n","/**\n * Mention icon component.\n * Maps string icon names to Lucide icon components.\n */\n\nimport type { FC } from \"react\";\nimport {\n BookOpenIcon,\n Building2Icon,\n CalendarIcon,\n CameraIcon,\n CheckSquareIcon,\n CloudIcon,\n CodeIcon,\n DatabaseIcon,\n EyeIcon,\n FileCodeIcon,\n FileIcon,\n FileTextIcon,\n FolderIcon,\n FolderKanbanIcon,\n GlobeIcon,\n HardDriveIcon,\n HeadphonesIcon,\n ImageIcon,\n KeyIcon,\n KeyboardIcon,\n LayoutDashboardIcon,\n LayoutGridIcon,\n LayoutIcon,\n LibraryIcon,\n MailIcon,\n MicIcon,\n MonitorIcon,\n PackageIcon,\n PaletteIcon,\n PenToolIcon,\n PhoneIcon,\n SearchIcon,\n SheetIcon,\n SmartphoneIcon,\n SparklesIcon,\n StarIcon,\n TableIcon,\n UserIcon,\n UsersIcon,\n VideoIcon,\n WrenchIcon,\n ZapIcon,\n WorkflowIcon,\n} from \"lucide-react\";\n\nconst ICON_MAP: Record<string, FC<{ className?: string }>> = {\n // General\n file: FileIcon,\n \"file-text\": FileTextIcon,\n \"file-code\": FileCodeIcon,\n folder: FolderIcon,\n \"folder-kanban\": FolderKanbanIcon,\n globe: GlobeIcon,\n search: SearchIcon,\n star: StarIcon,\n users: UsersIcon,\n user: UserIcon,\n wrench: WrenchIcon,\n package: PackageIcon,\n \"building-2\": Building2Icon,\n \"hard-drive\": HardDriveIcon,\n \"layout-grid\": LayoutGridIcon,\n zap: ZapIcon,\n eye: EyeIcon,\n\n // Chrome tools\n camera: CameraIcon,\n keyboard: KeyboardIcon,\n code: CodeIcon,\n monitor: MonitorIcon,\n\n // Asset types\n image: ImageIcon,\n video: VideoIcon,\n headphones: HeadphonesIcon,\n mic: MicIcon,\n mail: MailIcon,\n calendar: CalendarIcon,\n phone: PhoneIcon,\n database: DatabaseIcon,\n table: TableIcon,\n sheet: SheetIcon,\n palette: PaletteIcon,\n \"pen-tool\": PenToolIcon,\n layout: LayoutIcon,\n \"layout-dashboard\": LayoutDashboardIcon,\n library: LibraryIcon,\n \"book-open\": BookOpenIcon,\n sparkles: SparklesIcon,\n \"check-square\": CheckSquareIcon,\n key: KeyIcon,\n smartphone: SmartphoneIcon,\n cloud: CloudIcon,\n workflow: WorkflowIcon,\n presentation: FileTextIcon, // Fallback for presentation type\n};\n\n/** Backend icon names arrive as Lucide PascalCase (`FolderKanban`). */\nfunction toKebabIconName(name: string): string {\n return name\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1-$2\")\n .toLowerCase();\n}\n\nfunction resolveIcon(name: string): FC<{ className?: string }> | undefined {\n return ICON_MAP[name] ?? ICON_MAP[toKebabIconName(name)];\n}\n\nconst ICON_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9-]*$/;\n\nexport function MentionIcon({\n fallbackIcon,\n thumbnailUrl,\n alt,\n className = \"w-4 h-4 flex-shrink-0\",\n}: {\n fallbackIcon?: string;\n thumbnailUrl?: string;\n alt?: string;\n className?: string;\n}) {\n if (thumbnailUrl) {\n return <img src={thumbnailUrl} alt={alt ?? \"\"} className={className} />;\n }\n const Icon = fallbackIcon ? resolveIcon(fallbackIcon) : undefined;\n if (Icon) return <Icon className={className} />;\n // Emoji fallback; unmapped icon names render as the generic file icon\n if (fallbackIcon && !ICON_NAME_PATTERN.test(fallbackIcon)) {\n return <span className=\"text-sm flex-shrink-0\">{fallbackIcon}</span>;\n }\n return <FileIcon className={className} />;\n}\n","/**\n * Individual menu item in the mention popup.\n * Supports: tools (with description), users (with email), assets, categories.\n */\n\nimport type { MenuItem } from \"../data/types\";\nimport { MentionMenuSection } from \"../data/types\";\nimport { MentionIcon } from \"./mention-icon\";\nimport { cn } from \"../../../../lib/utils\";\n\nexport function MenuItemRow({\n item,\n isSelected,\n onMouseEnter,\n onClick,\n showArrow,\n}: {\n item: MenuItem;\n isSelected: boolean;\n onMouseEnter: () => void;\n onClick: () => void;\n showArrow?: boolean;\n}) {\n const hasTwoLines =\n (item.type === \"tool\" && item.description) ||\n (item.type === \"user\" && item.email) ||\n (item.type === \"workspace_item\" && item.description) ||\n (item.type === \"tab\" && item.description);\n\n return (\n <div\n role=\"button\"\n tabIndex={-1}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n className={cn(\n \"mention-item flex items-center justify-between gap-2 px-2 py-1.5 rounded cursor-pointer transition-colors\",\n \"hover:bg-gray-100\",\n item.menuSection === MentionMenuSection.CURRENT_WEBPAGE &&\n !isSelected &&\n \"bg-sky-50/70\",\n isSelected && \"bg-gray-100 is-selected\",\n )}\n >\n {/* Icon */}\n <span\n className={`flex items-center flex-shrink-0 ${hasTwoLines ? \"self-start mt-0.5\" : \"\"}`}\n >\n <MentionIcon\n fallbackIcon={item.fallbackIcon}\n thumbnailUrl={item.thumbnailUrl}\n alt={item.name}\n />\n </span>\n\n {/* Content */}\n {hasTwoLines ? (\n <div className=\"flex-1 flex flex-col gap-0 min-w-0 -mt-0.5\">\n <span className=\"text-sm leading-tight flex items-center gap-1.5\">\n {item.name}\n {item.extra?.isAdminOnly && (\n <span className=\"w-1.5 h-1.5 rounded-full bg-purple-400 flex-shrink-0\" />\n )}\n {item.extra?.isExperimental && (\n <span className=\"rounded-full bg-blue-50 px-1.5 py-0.5 text-[9px] font-medium text-blue-700\">\n Experimental\n </span>\n )}\n </span>\n <span className=\"text-xs text-gray-500 leading-tight mt-0.5 truncate\">\n {item.type === \"user\" ? item.email : item.description}\n </span>\n </div>\n ) : (\n <span className=\"flex-1 text-sm truncate min-w-0 flex items-center gap-1.5\">\n {item.name}\n {item.extra?.isAdminOnly && (\n <span className=\"w-1.5 h-1.5 rounded-full bg-purple-400 flex-shrink-0\" />\n )}\n {item.extra?.isExperimental && (\n <span className=\"rounded-full bg-blue-50 px-1.5 py-0.5 text-[9px] font-medium text-blue-700\">\n Experimental\n </span>\n )}\n </span>\n )}\n\n {/* Navigation arrow */}\n {showArrow && (\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n <span className=\"text-gray-400 text-sm px-1 rounded transition-all cursor-pointer hover:text-gray-600 hover:bg-gray-200\">\n →\n </span>\n </div>\n )}\n </div>\n );\n}\n","/**\n * Loading skeleton for the mention menu.\n */\n\nexport function MenuSkeleton() {\n return (\n <div className=\"px-1 py-1\">\n {[1, 2, 3, 4].map((i) => (\n <div key={i} className=\"flex items-center gap-2 px-2 py-1.5 rounded animate-pulse\">\n <div className=\"w-4 h-4 bg-gray-200 rounded flex-shrink-0\" />\n <div className=\"h-3.5 bg-gray-200 rounded flex-1\" style={{ maxWidth: `${50 + i * 10}%` }} />\n </div>\n ))}\n </div>\n );\n}\n","/**\n * Scrollable list of menu items with loading and empty states.\n */\n\nimport { Fragment, useEffect, useRef } from \"react\";\nimport { MentionMenuSection, type MenuItem } from \"../data/types\";\nimport { MenuItemRow } from \"./menu-item\";\nimport { MenuSkeleton } from \"./menu-skeleton\";\n\nexport function MenuList({\n items,\n selectedIndex,\n isLoading,\n hasMore,\n onSelect,\n onMouseEnter,\n onLoadMore,\n}: {\n items: MenuItem[];\n selectedIndex: number;\n isLoading?: boolean;\n hasMore?: boolean;\n onSelect: (item: MenuItem) => void;\n onMouseEnter: (index: number) => void;\n onLoadMore?: () => void;\n}) {\n const selectedRef = useRef<HTMLDivElement>(null);\n\n // Auto-scroll selected item into view\n useEffect(() => {\n selectedRef.current?.scrollIntoView({ block: \"nearest\" });\n }, [selectedIndex]);\n\n if (isLoading && items.length === 0) return <MenuSkeleton />;\n\n if (items.length === 0) {\n return (\n <div className=\"px-1 py-1\">\n <div className=\"px-2 py-9 text-center text-sm text-gray-500\">\n <div className=\"mb-1\">No results found</div>\n <div className=\"text-xs text-gray-400\">Try a different search or go back</div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"px-1 py-1\">\n {items.map((item, index) => {\n const previousSection = items[index - 1]?.menuSection;\n const startsOtherWebpages =\n item.menuSection === MentionMenuSection.OTHER_WEBPAGES &&\n previousSection !== MentionMenuSection.OTHER_WEBPAGES;\n const startsLibrary =\n item.menuSection === MentionMenuSection.LIBRARY &&\n (previousSection === MentionMenuSection.CURRENT_WEBPAGE ||\n previousSection === MentionMenuSection.OTHER_WEBPAGES);\n\n return (\n <Fragment key={item.id}>\n {startsOtherWebpages && (\n <div className=\"px-2 pb-1 pt-2 text-[11px] font-medium uppercase tracking-wide text-gray-400\">\n Other webpages in this group\n </div>\n )}\n {startsLibrary && <div className=\"mx-2 my-1 border-t border-gray-100\" />}\n <div ref={index === selectedIndex ? selectedRef : undefined}>\n <MenuItemRow\n item={item}\n isSelected={index === selectedIndex}\n onMouseEnter={() => onMouseEnter(index)}\n onClick={() => onSelect(item)}\n showArrow={!!item.navigatesToScope}\n />\n </div>\n </Fragment>\n );\n })}\n\n {/* Loading more indicator */}\n {isLoading && items.length > 0 && (\n <div className=\"px-2 py-2 text-center\">\n <span className=\"text-xs text-gray-400\">Loading more...</span>\n </div>\n )}\n\n {/* Load more sentinel */}\n {hasMore && !isLoading && onLoadMore && (\n <button\n type=\"button\"\n onClick={onLoadMore}\n className=\"w-full px-2 py-1.5 text-xs text-gray-500 hover:text-gray-700 hover:bg-gray-50 rounded transition-colors text-center\"\n >\n ··· Load more\n </button>\n )}\n </div>\n );\n}\n","/**\n * Breadcrumb navigation for the mention menu.\n */\n\nexport function MenuBreadcrumbs({\n scopePath,\n onNavigate,\n}: {\n scopePath: { id: string; name: string }[];\n onNavigate: (scopeId: string) => void;\n}) {\n return (\n <div className=\"flex items-center gap-1 text-xs text-gray-600 min-w-0\">\n {scopePath.map((item, index) => {\n const isLast = index === scopePath.length - 1;\n const isClickable = !isLast;\n\n return (\n <span key={item.id} className=\"flex items-center gap-1 min-w-0\">\n {isClickable ? (\n <button\n type=\"button\"\n onClick={() => onNavigate(item.id)}\n className=\"truncate hover:underline cursor-pointer transition-all hover:text-gray-800\"\n title={`Go to ${item.name}`}\n >\n {item.name}\n </button>\n ) : (\n <span className=\"truncate font-medium text-gray-800\">\n {item.name}\n </span>\n )}\n {!isLast && <span className=\"text-gray-400 flex-shrink-0\">→</span>}\n </span>\n );\n })}\n </div>\n );\n}\n","/**\n * Summary bar at the bottom of the mention menu.\n * Shows breadcrumbs + back button + optional loading spinner.\n */\n\nimport { MenuBreadcrumbs } from \"./menu-breadcrumbs\";\n\nexport function MenuSummary({\n scopePath,\n onNavigate,\n onBackClick,\n isFetching,\n}: {\n scopePath: { id: string; name: string }[];\n onNavigate: (scopeId: string) => void;\n onBackClick?: () => void;\n isFetching?: boolean;\n}) {\n // Don't show summary at root scope (unless fetching)\n if (scopePath.length <= 1 && !isFetching) return null;\n\n return (\n <div className=\"border-t border-gray-200 px-2 py-2 bg-gray-50\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n {scopePath.length > 1 && (\n <MenuBreadcrumbs scopePath={scopePath} onNavigate={onNavigate} />\n )}\n {isFetching && (\n <span className=\"flex-shrink-0 inline-block w-3 h-3 border border-gray-400 border-t-transparent rounded-full animate-spin\" />\n )}\n </div>\n {onBackClick && (\n <button\n type=\"button\"\n onClick={onBackClick}\n className=\"text-xs text-gray-600 hover:text-gray-800 px-2 py-1 rounded hover:bg-gray-200 transition-colors flex items-center gap-1 flex-shrink-0\"\n title=\"Go back (or press ←)\"\n >\n <span>←</span>\n <span>Back</span>\n </button>\n )}\n </div>\n </div>\n );\n}\n","/**\n * Keyboard navigation for the mention menu.\n *\n * Exposes an imperative handle so MentionSuggestionList can forward keystrokes\n * from the editor into the menu.\n */\n\nimport type { ForwardedRef } from \"react\";\nimport { useImperativeHandle } from \"react\";\nimport type { MenuItem } from \"../data/types\";\n\nexport interface KeyboardNavigationHandle {\n onKeyDown: (event: KeyboardEvent) => boolean;\n}\n\nexport function useKeyboardNavigation(\n ref: ForwardedRef<KeyboardNavigationHandle>,\n opts: {\n items: MenuItem[];\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n onSelect: (item: MenuItem) => void;\n onBack?: () => void;\n onClose: () => void;\n },\n) {\n const { items, selectedIndex, setSelectedIndex, onSelect, onBack, onClose } = opts;\n\n useImperativeHandle(\n ref,\n () => ({\n onKeyDown: (event: KeyboardEvent): boolean => {\n if (items.length === 0 && event.key !== \"Escape\") return false;\n\n switch (event.key) {\n case \"ArrowDown\": {\n const next = (selectedIndex + 1) % items.length;\n setSelectedIndex(next);\n return true;\n }\n case \"ArrowUp\": {\n const prev = (selectedIndex - 1 + items.length) % items.length;\n setSelectedIndex(prev);\n return true;\n }\n case \"Enter\": {\n const item = items[selectedIndex];\n if (item) onSelect(item);\n return true;\n }\n case \"ArrowLeft\": {\n if (onBack) {\n onBack();\n return true;\n }\n return false;\n }\n case \"Backspace\": {\n // Never capture Backspace — let Tiptap handle it naturally.\n // The suggestion plugin closes the popup when you backspace past @.\n return false;\n }\n case \"ArrowRight\": {\n const item = items[selectedIndex];\n if (item?.navigatesToScope) {\n onSelect(item);\n return true;\n }\n return false;\n }\n case \"Escape\": {\n onClose();\n return true;\n }\n default:\n return false;\n }\n },\n }),\n [items, selectedIndex, setSelectedIndex, onSelect, onBack, onClose],\n );\n}\n","import { Store } from '@tanstack/store';\nimport { useState } from 'react';\nimport type { MenuScope } from '../data/types';\n\n/**\n * Stack entry with scope and selected item position\n *\n * When navigating forward, we save the current selectedIndex so we can restore\n * it when navigating back (like browser history).\n */\nexport interface ScopeStackEntry {\n scope: MenuScope;\n selectedIndex: number; // Position of selected item when we left this scope\n breadcrumbLabel?: string; // Display name for this scope, when it isn't a known category\n parentScope?: MenuScope; // Scope we navigated from\n}\n\n/**\n * Menu navigation state - tracks current navigation context\n *\n * This is the \"current UI state\" that changes as user navigates and types.\n * Cleared when menu opens/closes.\n *\n * Uses a navigation stack for proper back button behavior:\n * - Forward navigation: push to stack (with current selectedIndex)\n * - Back navigation: pop from stack (restore selectedIndex)\n * - Current scope: last item in stack\n * - Parent scope: second-to-last item in stack\n */\nexport interface MenuNavigationState {\n // Navigation stack (browser-like history)\n // Example: [{ scope: 'root', selectedIndex: 2 }, { scope: 'folder_123', selectedIndex: 0 }]\n // Current scope = scopeStack[scopeStack.length - 1].scope\n // Parent scope = scopeStack[scopeStack.length - 2].scope\n scopeStack: ScopeStackEntry[];\n\n // Current search query\n query: string;\n\n // Is menu currently active?\n isActive: boolean;\n}\n\n/**\n * Menu navigation store with helper methods\n */\nexport interface MenuNavigationStore extends Store<MenuNavigationState> {\n navigateTo: (\n scope: MenuScope,\n currentSelectedIndex: number,\n options?: { breadcrumbLabel?: string; parentScope?: MenuScope },\n ) => void;\n navigateBack: () => void;\n setQuery: (query: string) => void;\n open: () => void;\n close: () => void;\n}\n\n/**\n * Get current scope from state\n */\nexport function getCurrentScope(state: MenuNavigationState): MenuScope {\n const lastEntry = state.scopeStack[state.scopeStack.length - 1];\n return lastEntry?.scope ?? \"root\";\n}\n\n/**\n * Get parent scope from state (for source inheritance)\n */\nexport function getParentScope(state: MenuNavigationState): MenuScope | undefined {\n if (state.scopeStack.length <= 1) return undefined;\n const parentEntry = state.scopeStack[state.scopeStack.length - 2];\n return parentEntry?.scope;\n}\n\n/**\n * Get selected index from current scope stack entry\n */\nexport function getSelectedIndex(state: MenuNavigationState): number {\n const lastEntry = state.scopeStack[state.scopeStack.length - 1];\n return lastEntry?.selectedIndex ?? 0;\n}\n\n/**\n * useMenuNavigation - Creates per-editor navigation state\n *\n * This is a UI concern - each editor instance gets its own navigation state.\n *\n * Returns a TanStack Store with navigation helper methods.\n */\nexport function useMenuNavigation(): MenuNavigationStore {\n const [store] = useState(() => {\n const baseStore = new Store<MenuNavigationState>({\n scopeStack: [{ scope: 'root', selectedIndex: 0 }],\n query: '',\n isActive: false,\n });\n\n // Extend store with navigation methods\n const navigationStore = baseStore as MenuNavigationStore;\n\n navigationStore.navigateTo = (\n scope: MenuScope,\n currentSelectedIndex: number,\n options?: { breadcrumbLabel?: string; parentScope?: MenuScope },\n ) => {\n const state = baseStore.state;\n\n // Save current selectedIndex in the current entry before navigating forward\n const updatedStack = [...state.scopeStack];\n if (updatedStack.length > 0) {\n updatedStack[updatedStack.length - 1] = {\n ...updatedStack[updatedStack.length - 1],\n selectedIndex: currentSelectedIndex,\n };\n }\n\n // Push new scope with selectedIndex = 0 (start at top of new scope)\n const newStack = [\n ...updatedStack,\n {\n scope,\n selectedIndex: 0,\n breadcrumbLabel: options?.breadcrumbLabel,\n parentScope: options?.parentScope,\n },\n ];\n\n baseStore.setState((prev) => ({\n ...prev,\n scopeStack: newStack,\n query: '',\n }));\n };\n\n navigationStore.navigateBack = () => {\n const state = baseStore.state;\n\n if (state.scopeStack.length <= 1) {\n return;\n }\n\n const newStack = state.scopeStack.slice(0, -1);\n\n baseStore.setState((prev) => ({\n ...prev,\n scopeStack: newStack,\n query: '',\n }));\n };\n\n navigationStore.setQuery = (query: string) => {\n baseStore.setState((prev) => ({ ...prev, query }));\n };\n\n navigationStore.open = () => {\n baseStore.setState(() => ({\n scopeStack: [{ scope: 'root', selectedIndex: 0 }],\n query: '',\n isActive: true,\n }));\n };\n\n navigationStore.close = () => {\n baseStore.setState(() => ({\n scopeStack: [{ scope: 'root', selectedIndex: 0 }],\n query: '',\n isActive: false,\n }));\n };\n\n return navigationStore;\n });\n\n return store;\n}\n","import type { Editor } from '@tiptap/core';\n\n/**\n * Clear text after @ trigger\n *\n * When navigating in the menu, we want to clear the typed query\n * but keep the @ trigger symbol.\n */\nexport function clearTextAfterTrigger(editor: Editor): void {\n const { state } = editor;\n const { from: cursorPos } = state.selection;\n const backwardText = state.doc.textBetween(0, cursorPos, undefined, '\\ufffc');\n const triggerIndex = backwardText.lastIndexOf('@');\n\n if (triggerIndex === -1) return;\n\n const offset = backwardText.length - triggerIndex;\n const from = cursorPos - offset + 1; // +1 to keep the @ symbol\n const to = cursorPos;\n\n if (from < to) {\n // Delete text after @ but keep the @ symbol\n const tr = state.tr.deleteRange(from, to);\n editor.view.dispatch(tr);\n }\n}\n","/**\n * MentionSuggestionList — Main mention menu component.\n *\n * Composed of:\n * - Registry + cache backed data (async fetching)\n * - useMenuNavigation for scope stack management\n * - useKeyboardNavigation for keyboard handling\n * - MenuList for item rendering with loading states\n * - MenuSummary for breadcrumbs + back\n */\n\nimport { useStore } from \"@tanstack/react-store\";\nimport type { Editor } from \"@tiptap/core\";\nimport { forwardRef, useCallback, useEffect, useState } from \"react\";\nimport type { MenuItem } from \"../data/types\";\nimport type { MentionSuggestionsStore } from \"../data/use-mention-suggestions\";\nimport { useMenuItems } from \"../data/use-menu-items\";\nimport { getSearchScope } from \"../data/scope-registry\";\nimport { getScopeName } from \"./get-scope-name\";\nimport { MenuList } from \"./menu-list\";\nimport { MenuSummary } from \"./menu-summary\";\nimport { useKeyboardNavigation, type KeyboardNavigationHandle } from \"./use-keyboard-navigation\";\nimport {\n getCurrentScope,\n getSelectedIndex,\n useMenuNavigation,\n} from \"./use-menu-navigation\";\nimport { clearTextAfterTrigger } from \"./utils\";\n\nexport interface MentionSuggestionListProps {\n store: MentionSuggestionsStore;\n editor: Editor;\n query: string;\n command: (item: MenuItem) => void;\n closeMenu: (dismissedByUser?: boolean) => void;\n}\n\nexport const MentionSuggestionList = forwardRef<\n KeyboardNavigationHandle,\n MentionSuggestionListProps\n>(({ store, editor, query, command, closeMenu }, ref) => {\n const [selectedIndexOverride, setSelectedIndexOverride] = useState<number | null>(null);\n const navStore = useMenuNavigation();\n\n // Get current scope from navigation\n const currentScopeId = useStore(navStore, (s) => getCurrentScope(s));\n const navSelectedIndex = useStore(navStore, (s) => getSelectedIndex(s));\n const selectedIndex = selectedIndexOverride ?? navSelectedIndex;\n const scopeStack = useStore(navStore, (s) => s.scopeStack);\n\n let effectiveScopeId = currentScopeId;\n\n if (query) {\n try {\n const searchScope = getSearchScope(store.state.registry, currentScopeId);\n if (searchScope) {\n effectiveScopeId = searchScope;\n }\n } catch {\n // No search scope binding — use current\n }\n }\n\n // Get items from the data store (reactive, with async fetching)\n const { items, isFetching, hasMore, loadMore } = useMenuItems(store, {\n scope: effectiveScopeId,\n query,\n minItems: 50,\n parentScope: currentScopeId !== effectiveScopeId ? currentScopeId : undefined,\n });\n\n // Reset selection on query or scope change\n useEffect(() => {\n setSelectedIndexOverride(null);\n }, [query, effectiveScopeId]);\n\n // Build scope path for breadcrumbs from the navigation stack\n const scopePath = scopeStack.map((entry) => ({\n id: entry.scope,\n name: entry.breadcrumbLabel ?? getScopeName(entry.scope, store),\n }));\n\n // Handle item selection\n const handleSelect = useCallback(\n (item: MenuItem) => {\n if (item.navigatesToScope) {\n navStore.navigateTo(item.navigatesToScope, selectedIndex, {\n breadcrumbLabel: item.name,\n parentScope: currentScopeId,\n });\n clearTextAfterTrigger(editor);\n setSelectedIndexOverride(null);\n return;\n }\n // Insert mention\n command(item);\n },\n [command, editor, navStore, selectedIndex, currentScopeId],\n );\n\n // Handle back navigation\n const handleBack = useCallback(() => {\n navStore.navigateBack();\n clearTextAfterTrigger(editor);\n setSelectedIndexOverride(null);\n }, [editor, navStore]);\n\n // Handle breadcrumb navigation\n const handleBreadcrumbNavigate = useCallback(\n (targetScopeId: string) => {\n // Navigate to specific scope in the stack\n const targetIdx = scopeStack.findIndex((entry) => entry.scope === targetScopeId);\n\n if (targetIdx >= 0) {\n // Pop stack down to the target\n const popsNeeded = scopeStack.length - 1 - targetIdx;\n for (let i = 0; i < popsNeeded; i++) {\n navStore.navigateBack();\n }\n clearTextAfterTrigger(editor);\n setSelectedIndexOverride(null);\n }\n },\n [editor, navStore, scopeStack],\n );\n\n // Keyboard navigation\n useKeyboardNavigation(ref, {\n items,\n selectedIndex,\n onSelect: handleSelect,\n onBack: currentScopeId !== \"root\" ? handleBack : undefined,\n onClose: () => closeMenu(true),\n setSelectedIndex: (idx: number) => {\n setSelectedIndexOverride(idx);\n },\n });\n\n return (\n <div className=\"bg-white border border-gray-300 rounded shadow-lg min-w-[280px] max-w-[380px] max-h-[320px] flex flex-col\">\n {/* Scrollable items */}\n <div className=\"flex-1 overflow-y-auto\">\n <MenuList\n items={items}\n selectedIndex={selectedIndex}\n isLoading={isFetching}\n hasMore={hasMore}\n onSelect={handleSelect}\n onMouseEnter={(idx) => {\n setSelectedIndexOverride(idx);\n }}\n onLoadMore={loadMore}\n />\n </div>\n\n {/* Bottom summary with breadcrumbs + back */}\n <MenuSummary\n scopePath={scopePath}\n onNavigate={handleBreadcrumbNavigate}\n onBackClick={currentScopeId !== \"root\" ? handleBack : undefined}\n isFetching={isFetching}\n />\n </div>\n );\n});\n\nMentionSuggestionList.displayName = \"MentionSuggestionList\";\n","/**\n * Mention data sources shared by every chat host.\n *\n * Each source function implements the SourceFn interface:\n * (context: SourceContext) => Promise<SourceResult>\n *\n * Sources are either:\n * - FETCHERS: Call GraphQL API (assets, folders, team, etc.)\n * - TRANSFORMERS: Return static/local data (root categories, host-provided items)\n */\n\nimport type {\n MenuItem,\n SourceFn,\n SourceResult,\n SourceToRegister,\n FetchMetadata,\n WebpageMention,\n} from \"../types\";\nimport { MentionMenuSection } from \"../types\";\nimport {\n fetchGraphQL,\n SIMPLE_SEARCH_QUERY,\n PAGINATED_ASSETS_QUERY,\n WORKSPACE_MEMBERS_QUERY,\n TOOL_CATALOG_QUERY,\n type MentionAuthContext,\n type AssetResult,\n type WorkspaceMember,\n type ToolCatalogResult,\n} from \"../api-client\";\nimport { assetTypeToThumb, assetTypeToIcon } from \"./asset-type-icons\";\n\n// ── Helpers ──\n\nfunction assetToMenuItem(asset: AssetResult): MenuItem {\n const isFolder = asset.athenaOriginalType === \"folder\";\n const displayType = asset.athenaConvertedType || asset.athenaOriginalType;\n return {\n id: asset.id,\n name: asset.title || \"Untitled\",\n type: isFolder ? \"folder\" : \"asset\",\n thumbnailUrl: assetTypeToThumb(displayType),\n fallbackIcon: assetTypeToIcon(displayType),\n navigatesToScope: isFolder ? asset.id : undefined,\n visibleInScopes: new Set(),\n updatedAt: asset.updatedAt ?? undefined,\n extra: {\n athenaOriginalType: asset.athenaOriginalType,\n athenaConvertedType: asset.athenaConvertedType,\n parentFolderId: asset.parentFolderId,\n },\n };\n}\n\nasync function querySimpleSearch(\n auth: MentionAuthContext,\n opts: {\n query?: string;\n limit: number;\n offset: number;\n includeTypes?: string[];\n excludeTypes?: string[];\n },\n): Promise<{ items: MenuItem[]; hasMore: boolean }> {\n const searchRequest: Record<string, any> = {\n query: opts.query?.trim() || \"\",\n type: opts.includeTypes || [],\n notType: opts.excludeTypes || [],\n limit: opts.limit,\n offset: opts.offset,\n };\n\n const input = {\n searchRequest,\n returnFullAsset: true,\n shouldCalculateTotal: false,\n sort: { field: \"UPDATED_AT\", direction: \"DESC\" },\n filterColumns: { isArchived: false, isHidden: false },\n };\n\n const data = await fetchGraphQL<{\n simpleSearch: { assets: AssetResult[]; totalCount: number };\n }>(auth, SIMPLE_SEARCH_QUERY, { input });\n\n const assets = data.simpleSearch?.assets || [];\n return {\n items: assets.map(assetToMenuItem),\n hasMore: assets.length === opts.limit,\n };\n}\n\n// ══════════════════════════════════════════════════════════════════════\n// ROOT CATEGORIES (Transformer)\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface RootCategoriesConfig {\n categories: string[];\n getWebpages: () => readonly WebpageMention[];\n}\n\nconst CATEGORY_DEFS: Record<\n string,\n { name: string; icon: string; scope: string }\n> = {\n favorites: { name: \"Favorites\", icon: \"star\", scope: \"favorites\" },\n assets: { name: \"Assets\", icon: \"file-text\", scope: \"athena_assets\" },\n projects: {\n name: \"Projects\",\n icon: \"folder-kanban\",\n scope: \"athena_projects\",\n },\n browse_profiles: {\n name: \"Browse Profiles\",\n icon: \"globe\",\n scope: \"athena_browse_profiles\",\n },\n folders: { name: \"Folders\", icon: \"folder\", scope: \"athena_folders\" },\n tools: { name: \"Tools\", icon: \"wrench\", scope: \"tools\" },\n toolkits: { name: \"Toolkits\", icon: \"package\", scope: \"toolkits\" },\n team: { name: \"Team\", icon: \"users\", scope: \"team\" },\n drives: { name: \"Drives\", icon: \"hard-drive\", scope: \"drive_catalogs\" },\n};\n\nfunction webpageDescription(webpage: WebpageMention): string {\n try {\n const hostname = new URL(webpage.url).hostname;\n return webpage.isCurrent ? `${webpage.title} · ${hostname}` : hostname;\n } catch {\n return webpage.title;\n }\n}\n\nfunction webpageToMenuItem(webpage: WebpageMention): MenuItem {\n return {\n id: `webpage-tab-${webpage.tabId}`,\n name: webpage.isCurrent ? \"This webpage\" : webpage.title,\n type: \"tab\",\n thumbnailUrl: assetTypeToThumb(\"web_page\"),\n fallbackIcon: \"globe\",\n visibleInScopes: new Set([\"root\"]),\n description: webpageDescription(webpage),\n url: webpage.url,\n menuSection: webpage.isCurrent\n ? MentionMenuSection.CURRENT_WEBPAGE\n : MentionMenuSection.OTHER_WEBPAGES,\n extra: {\n tabId: webpage.tabId,\n title: webpage.title,\n isCurrent: webpage.isCurrent,\n },\n };\n}\n\nexport function buildRootMenuItems({\n categories,\n webpages,\n}: {\n categories: readonly string[];\n webpages: readonly WebpageMention[];\n}): MenuItem[] {\n const webpageItems = webpages.map(webpageToMenuItem);\n const categoryItems = categories\n .filter((cat: string) => CATEGORY_DEFS[cat])\n .map((cat: string) => {\n const def = CATEGORY_DEFS[cat];\n return {\n id: cat,\n name: def.name,\n type: \"menu\" as const,\n fallbackIcon: def.icon,\n visibleInScopes: new Set([\"root\"]),\n navigatesToScope: def.scope,\n isNavigationOnly: true,\n menuSection: MentionMenuSection.LIBRARY,\n };\n });\n\n return [...webpageItems, ...categoryItems];\n}\n\nexport const transformRootCategories: SourceFn<RootCategoriesConfig> = async (\n context,\n) => {\n const { sourceConfig } = context;\n const items = buildRootMenuItems({\n categories: sourceConfig.categories,\n webpages: sourceConfig.getWebpages(),\n });\n\n return { items, pagination: { hasMore: false } };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// ASSETS (Fetcher) — All non-folder assets via SimpleSearch\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface AssetsConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchAssets: SourceFn<AssetsConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit,\n offset,\n excludeTypes: [\n \"folder\",\n \"catalog\",\n \"spaces\",\n \"session\",\n \"table\",\n \"task_item\",\n ],\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// FAVORITES (Fetcher) — Favorited assets\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface FavoritesConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchFavorites: SourceFn<FavoritesConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const data = await fetchGraphQL<{\n getPaginatedAssetsForWorkspace: AssetResult[];\n }>(sourceConfig.auth, PAGINATED_ASSETS_QUERY, {\n limit,\n offset,\n parentFolderId: null,\n filterTypes: null,\n filterColumns: {\n isFavorited: true,\n isArchived: false,\n isHidden: false,\n },\n });\n\n const assets = data.getPaginatedAssetsForWorkspace || [];\n const items = assets.map(assetToMenuItem);\n\n return {\n items,\n pagination: { hasMore: assets.length === limit },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// FOLDERS (Fetcher) — All folders as flat list\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface FoldersConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchFolders: SourceFn<FoldersConfig> = async (context) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit,\n offset,\n includeTypes: [\"folder\"],\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// FOLDER CONTENTS (Fetcher) — Contents of a specific folder\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface FolderContentsConfig {\n auth: MentionAuthContext;\n limit?: number;\n}\n\nexport const fetchFolderContents: SourceFn<FolderContentsConfig> = async (\n context,\n) => {\n const { scope, query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n // Scope IS the folder ID (or 'internal_drive' for root)\n const parentFolderId = scope === \"internal_drive\" ? null : scope;\n\n const data = await fetchGraphQL<{\n getPaginatedAssetsForWorkspace: AssetResult[];\n }>(sourceConfig.auth, PAGINATED_ASSETS_QUERY, {\n limit,\n offset,\n parentFolderId,\n filterTypes: null,\n filterColumns: {\n isArchived: false,\n isHidden: false,\n ...(query ? { title: [{ op: \"LIKE\", value: `%${query}%` }] } : {}),\n },\n });\n\n const rawAssets = data.getPaginatedAssetsForWorkspace || [];\n // Exclude catalogs from folder contents\n const assets = rawAssets.filter(\n (a) =>\n a.athenaConvertedType !== \"catalog\" && a.athenaOriginalType !== \"catalog\",\n );\n const items = assets.map(assetToMenuItem);\n\n return {\n items,\n pagination: {\n hasMore: rawAssets.length === limit,\n consumedCount: rawAssets.length,\n },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// PROJECTS (Fetcher) — Project assets\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface TypedAssetsConfig {\n auth: MentionAuthContext;\n includeOnlyTypes: string[];\n limit?: number;\n}\n\nexport const fetchTypedAssets: SourceFn<TypedAssetsConfig> = async (\n context,\n) => {\n const { query, fetchState, sourceConfig } = context;\n const limit = sourceConfig.limit ?? 50;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit,\n offset,\n includeTypes: sourceConfig.includeOnlyTypes,\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// TEAM (Fetcher) — Workspace members\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface TeamConfig {\n auth: MentionAuthContext;\n}\n\nexport const fetchTeam: SourceFn<TeamConfig> = async (context) => {\n const { sourceConfig } = context;\n const { auth } = sourceConfig;\n\n if (!auth.workspaceId) {\n return { items: [], pagination: { hasMore: false } };\n }\n\n const data = await fetchGraphQL<{ getUsersInWorkspace: WorkspaceMember[] }>(\n auth,\n WORKSPACE_MEMBERS_QUERY,\n { workspaceId: auth.workspaceId },\n );\n\n const members = data.getUsersInWorkspace || [];\n const items: MenuItem[] = members.map((member) => {\n const displayName =\n [member.firstName, member.lastName].filter(Boolean).join(\" \").trim() ||\n member.email ||\n \"Unknown User\";\n\n return {\n id: member.email || member.id,\n name: displayName,\n type: \"user\" as const,\n fallbackIcon: \"user\",\n visibleInScopes: new Set<string>(),\n email: member.email ?? undefined,\n extra: { isAdmin: member.isAdmin },\n };\n });\n\n return { items, pagination: { hasMore: false } };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// TOOLS / TOOLKITS (Fetcher) — Mentionable tool catalog\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface ToolCatalogConfig {\n auth: MentionAuthContext;\n}\n\n// getToolkitToToolsMapping is already filtered server-side for the\n// authenticated user (admin-only entries, beta allowlist, workspace registry),\n// so only mention/menu visibility is applied here.\nasync function queryToolCatalog(\n auth: MentionAuthContext,\n): Promise<ToolCatalogResult[\"getToolkitToToolsMapping\"]> {\n const data = await fetchGraphQL<ToolCatalogResult>(auth, TOOL_CATALOG_QUERY);\n return data.getToolkitToToolsMapping;\n}\n\nexport const fetchTools: SourceFn<ToolCatalogConfig> = async (context) => {\n const catalog = await queryToolCatalog(context.sourceConfig.auth);\n\n const items: MenuItem[] = catalog.tools\n .filter((tool) => tool.isMentionable)\n .map((tool) => ({\n id: tool.id,\n name: tool.name,\n type: \"tool\" as const,\n fallbackIcon: tool.icon,\n description: tool.description ?? undefined,\n visibleInScopes: new Set<string>(),\n ...(tool.adminOnly ? { extra: { isAdminOnly: true } } : {}),\n }));\n\n return { items, pagination: { hasMore: false } };\n};\n\nexport const fetchToolkits: SourceFn<ToolCatalogConfig> = async (context) => {\n const catalog = await queryToolCatalog(context.sourceConfig.auth);\n\n const items: MenuItem[] = catalog.toolkits\n .filter((toolkit) => toolkit.isMentionable && !toolkit.hideFromMenu)\n .map((toolkit) => ({\n id: toolkit.name,\n name: toolkit.displayName,\n type: \"toolkit\" as const,\n fallbackIcon: toolkit.icon,\n description: toolkit.description || undefined,\n visibleInScopes: new Set<string>(),\n ...(toolkit.onlyAdmin ? { extra: { isAdminOnly: true } } : {}),\n }));\n\n return { items, pagination: { hasMore: false } };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// DRIVES (Fetcher) — Drive catalog assets\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface DrivesConfig {\n auth: MentionAuthContext;\n}\n\nexport const fetchDrives: SourceFn<DrivesConfig> = async (context) => {\n const { fetchState, sourceConfig } = context;\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n limit: 50,\n offset,\n includeTypes: [\"catalog\"],\n });\n\n // Drive catalogs are navigation-only (navigate into them to see contents)\n const items: MenuItem[] = result.items.map((item) => ({\n ...item,\n type: \"drive_catalog\" as const,\n fallbackIcon: \"hard-drive\",\n isNavigationOnly: true,\n navigatesToScope: item.id,\n }));\n\n // Register folder contents source for each catalog\n const sources: SourceToRegister[] = items.map((item) => ({\n scope: item.id,\n sourceFn: fetchFolderContents,\n sourceConfig: { auth: sourceConfig.auth, limit: 50 },\n }));\n\n return {\n items,\n pagination: { hasMore: result.hasMore },\n sources,\n };\n};\n\n// ══════════════════════════════════════════════════════════════════════\n// GLOBAL SEARCH (Fetcher) — Aggregated search across all sources\n// ══════════════════════════════════════════════════════════════════════\n\nexport interface GlobalSearchConfig {\n auth: MentionAuthContext;\n}\n\nexport const fetchGlobalSearch: SourceFn<GlobalSearchConfig> = async (\n context,\n) => {\n const { query, fetchState, sourceConfig } = context;\n if (!query?.trim()) return { items: [], pagination: { hasMore: false } };\n\n const meta = (fetchState.meta as FetchMetadata) || {};\n const offset = meta.validatedCount || 0;\n\n const result = await querySimpleSearch(sourceConfig.auth, {\n query,\n limit: 50,\n offset,\n excludeTypes: [\"table\", \"catalog\", \"spaces\", \"task_item\", \"session\"],\n });\n\n return {\n items: result.items,\n pagination: { hasMore: result.hasMore },\n };\n};\n","/**\n * Chrome Extension Mention Suggestions Store\n *\n * Full Olympus-style mention store with all categories:\n * Favorites, Assets, Projects, Browse Profiles, Folders,\n * current/group webpages, Team, Workspace, Drives + Global Search.\n *\n * Uses registry + cache architecture from Olympus with\n * async data fetching via GraphQL.\n */\n\nimport { Store } from \"@tanstack/store\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport type { MentionAuthContext } from \"./api-client\";\nimport { useMentionAuth } from \"./api-client\";\nimport { createItemCache, type ItemCache } from \"./item-cache\";\nimport {\n createScopeRegistry,\n registerSource,\n bindScopes,\n type ScopeRegistry,\n} from \"./scope-registry\";\nimport {\n transformRootCategories,\n fetchAssets,\n fetchFavorites,\n fetchFolders,\n fetchFolderContents,\n fetchTypedAssets,\n fetchTeam,\n fetchTools,\n fetchToolkits,\n fetchDrives,\n fetchGlobalSearch,\n} from \"./sources\";\nimport type { WebpageMention } from \"./types\";\n\nexport function webpageMentionFingerprint(\n webpages: readonly WebpageMention[],\n): string {\n return JSON.stringify(\n webpages.map(({ tabId, title, url, isCurrent }) => [\n tabId,\n title,\n url,\n isCurrent,\n ]),\n );\n}\n\n// ── Store types ──\n\nexport interface MentionSuggestionsStoreState {\n registry: ScopeRegistry;\n cache: ItemCache;\n}\n\nexport type MentionSuggestionsStore = Store<MentionSuggestionsStoreState>;\n\n// ── Categories ──\n\n/**\n * All mention menu categories, in display order.\n */\nexport const ROOT_MENTION_CATEGORIES = [\n \"favorites\",\n \"assets\",\n \"projects\",\n \"browse_profiles\",\n \"folders\",\n \"tools\",\n \"toolkits\",\n \"team\",\n \"drives\",\n] as const;\n\nexport type MentionRootCategory = (typeof ROOT_MENTION_CATEGORIES)[number];\n\n// ── Store builder ──\n\nfunction buildStore({\n auth,\n getWebpages,\n rootCategories,\n}: {\n auth: MentionAuthContext;\n getWebpages: () => readonly WebpageMention[];\n rootCategories: readonly MentionRootCategory[];\n}): MentionSuggestionsStore {\n const registry = createScopeRegistry();\n const cache = createItemCache();\n\n // ── Root categories ──\n registerSource(registry, \"root\", transformRootCategories, {\n categories: [...rootCategories],\n getWebpages,\n });\n\n // ── Global search (aggregated) ──\n registerSource(registry, \"global_search\", fetchGlobalSearch, { auth });\n bindScopes(registry, \"root\", \"global_search\");\n\n // ── Assets ──\n registerSource(registry, \"athena_assets\", fetchAssets, { auth, limit: 50 });\n\n // ── Favorites ──\n registerSource(registry, \"favorites\", fetchFavorites, { auth, limit: 50 });\n\n // ── Folders (flat list) ──\n registerSource(\n registry,\n \"athena_folders\",\n fetchFolders,\n { auth, limit: 50 },\n true /* isFlat */,\n );\n\n // ── Internal drive (folder navigation root) ──\n registerSource(registry, \"internal_drive\", fetchFolderContents, {\n auth,\n limit: 50,\n });\n\n // ── Projects ──\n registerSource(registry, \"athena_projects\", fetchTypedAssets, {\n auth,\n includeOnlyTypes: [\"project\"],\n limit: 50,\n });\n\n // ── Browse Profiles ──\n registerSource(registry, \"athena_browse_profiles\", fetchTypedAssets, {\n auth,\n includeOnlyTypes: [\"browse_profile\"],\n limit: 50,\n });\n\n // ── Tools & Toolkits ──\n registerSource(registry, \"tools\", fetchTools, { auth });\n registerSource(registry, \"toolkits\", fetchToolkits, { auth });\n\n // ── Team ──\n registerSource(registry, \"team\", fetchTeam, { auth });\n\n // ── Drives (catalogs) ──\n registerSource(registry, \"drive_catalogs\", fetchDrives, { auth });\n\n return new Store<MentionSuggestionsStoreState>({ registry, cache });\n}\n\n// ── Hook ──\n\n/**\n * Creates a stable MentionSuggestionsStore.\n * Uses MentionAuthCtx for API credentials.\n */\nexport function useMentionSuggestions({\n webpages,\n rootCategories = ROOT_MENTION_CATEGORIES,\n}: {\n webpages: readonly WebpageMention[];\n /** Categories shown at the top level; hosts can narrow the default set. */\n rootCategories?: readonly MentionRootCategory[];\n}): {\n store: MentionSuggestionsStore;\n invalidate: (scope: string) => void;\n} {\n const auth = useMentionAuth();\n const webpagesRef = useRef(webpages);\n webpagesRef.current = webpages;\n\n // Depend on primitive values to avoid rebuilding store on object identity changes\n const store = useMemo(\n () =>\n buildStore({\n auth,\n getWebpages: () => webpagesRef.current,\n rootCategories,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n auth.backendUrl,\n auth.accessToken,\n auth.apiKey,\n auth.workspaceId,\n auth.userId,\n rootCategories.join(\",\"),\n ],\n );\n\n const invalidate = useMemo(\n () => (scope: string) => {\n const state = store.state;\n const { registry, cache } = state;\n\n // Clear scope from cache\n if (cache.items) {\n for (const item of Object.values(cache.items)) {\n item.visibleInScopes.delete(scope);\n }\n // Remove orphaned items\n for (const [id, item] of Object.entries(cache.items)) {\n if (item.visibleInScopes.size === 0) {\n delete cache.items[id];\n }\n }\n }\n\n // Reset fetch states\n if (registry.entries[scope]) {\n registry.entries[scope].fetchStates = {};\n }\n\n store.setState((prev) => ({ ...prev }));\n },\n [store],\n );\n\n const webpageFingerprint = webpageMentionFingerprint(webpages);\n const previousWebpageFingerprintRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (previousWebpageFingerprintRef.current === webpageFingerprint) return;\n previousWebpageFingerprintRef.current = webpageFingerprint;\n invalidate(\"root\");\n }, [invalidate, webpageFingerprint]);\n\n return { store, invalidate };\n}\n","export class PendingAttachmentUploads {\n\tprivate readonly pending = new Set<Promise<void>>();\n\n\ttrack(upload: Promise<void>): Promise<void> {\n\t\tthis.pending.add(upload);\n\t\tvoid upload.then(\n\t\t\t() => this.pending.delete(upload),\n\t\t\t() => this.pending.delete(upload),\n\t\t);\n\t\treturn upload;\n\t}\n\n\tasync waitForIdle(): Promise<void> {\n\t\twhile (this.pending.size > 0) {\n\t\t\tawait Promise.allSettled([...this.pending]);\n\t\t}\n\t}\n}\n","/**\n * Tiptap Composer — Full Olympus mention system integration\n *\n * Uses the ported Olympus infrastructure:\n * - MentionSuggestionList (with scope navigation, breadcrumbs, keyboard nav)\n * - MentionSuggestionPopup (Floating UI positioning)\n * - MentionSuggestionsExtension (Tiptap @ trigger)\n * - MentionExtension (inline mention chips)\n * - useMentionSuggestions (full Olympus categories + async data)\n *\n * Auth credentials for GraphQL are provided via MentionAuthCtx, and the host\n * app (Chrome side panel, Office task pane) supplies any host-only mention\n * items — browser tabs, for instance — through `webpages`.\n */\n\nimport { useRef, useState, useCallback, useEffect, forwardRef, useImperativeHandle } from \"react\";\nimport { useEditor, EditorContent } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Extension, type JSONContent } from \"@tiptap/core\";\nimport { unstable_useComposerInput, useAui } from \"@assistant-ui/react\";\nimport { MentionExtension } from \"../mentions/mention-extension\";\nimport {\n MentionSuggestionsExtension,\n type MentionSuggestionCallbacks,\n type MentionSuggestionRenderProps,\n} from \"../mentions/suggestions/mention-suggestions.extension\";\nimport { MentionSuggestionPopup } from \"../mentions/suggestions/components/mention-suggestion-popup\";\nimport {\n MentionSuggestionList,\n} from \"../mentions/suggestions/components/mention-suggestion-list\";\nimport {\n useMentionSuggestions,\n type MentionRootCategory,\n} from \"../mentions/suggestions/data/use-mention-suggestions\";\nimport type {\n MenuItem,\n WebpageMention,\n} from \"../mentions/suggestions/data/types\";\nimport type { KeyboardNavigationHandle } from \"../mentions/suggestions/components/use-keyboard-navigation\";\nimport {\n registerChatAssetMentionHandler,\n type UploadedChatAsset,\n} from \"@athenaintel/agent-runtime\";\nimport { PendingAttachmentUploads } from \"./pending-attachment-uploads\";\n\n// ── Submit keybind extension ──\n\nconst SubmitKeybind = Extension.create<{ onSubmit: () => void; isMentionOpen: () => boolean }>({\n name: \"submitKeybind\",\n priority: 1000,\n addOptions() {\n return { onSubmit: () => {}, isMentionOpen: () => false };\n },\n addKeyboardShortcuts() {\n return {\n Enter: () => {\n // Don't submit when the mention popup is open — let it handle Enter\n if (this.options.isMentionOpen()) return false;\n this.options.onSubmit();\n return true;\n },\n \"Shift-Enter\": () => {\n this.editor.commands.setHardBreak();\n return true;\n },\n };\n },\n});\n\n// ── CSS for mention chips + editor ──\n\nconst MENTION_STYLES = `\n .mention-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: rgba(148, 163, 184, 0.1);\n color: #475569;\n border: 1px solid #cbd5e1;\n border-radius: 6px;\n padding: 1px 6px;\n font-size: 0.85em;\n font-weight: 500;\n white-space: nowrap;\n user-select: all;\n vertical-align: middle;\n height: 20px;\n line-height: 1;\n }\n .mention-chip-icon {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n }\n .mention-chip-text {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 180px;\n }\n .ProseMirror {\n outline: none;\n min-height: 36px;\n max-height: 120px;\n overflow-y: auto;\n }\n .ProseMirror p {\n margin: 0;\n }\n .ProseMirror p.is-editor-empty:first-child::before {\n content: attr(data-placeholder);\n float: left;\n color: #9ca3af;\n pointer-events: none;\n height: 0;\n }\n`;\n\n/** Convert recovered runtime text without letting Tiptap parse it as HTML. */\nexport function plainTextToTiptapContent(text: string): JSONContent {\n return {\n type: \"doc\",\n content: text.split(\"\\n\").map((line) => ({\n type: \"paragraph\",\n ...(line.length > 0\n ? { content: [{ type: \"text\", text: line }] }\n : {}),\n })),\n };\n}\n\n// ── Main component ──\n\nexport interface TiptapComposerHandle {\n submit: () => Promise<void>;\n addAttachment: (file: File) => Promise<void>;\n insertAssetMention: (asset: UploadedChatAsset) => void;\n}\n\nexport interface TiptapComposerProps {\n placeholder?: string;\n threadId: string;\n disabled?: boolean;\n /** Host-provided browser-tab mentions; empty in hosts without tab access. */\n webpages?: readonly WebpageMention[];\n rootCategories?: readonly MentionRootCategory[];\n onDraftStateChange?: (hasDraft: boolean) => void;\n /**\n * Optional submit interception: called with the serialized draft before the\n * composer-runtime send. Return `true` when the host consumed the draft\n * through another lane (e.g. a live voice session) — the editor clears and\n * the normal send is skipped. Return `false` to fall through unchanged.\n */\n interceptSubmit?: (text: string) => boolean | Promise<boolean>;\n}\n\nconst NO_WEBPAGES: readonly WebpageMention[] = [];\n\nexport const TiptapComposer = forwardRef<\n TiptapComposerHandle,\n TiptapComposerProps\n>(({ placeholder = \"Message Athena... (type @ to mention)\", threadId, disabled = false, webpages = NO_WEBPAGES, rootCategories, onDraftStateChange, interceptSubmit }, outerRef) => {\n const aui = useAui();\n const composerInput = unstable_useComposerInput();\n const applyingRuntimeTextRef = useRef(false);\n const listRef = useRef<KeyboardNavigationHandle>(null);\n const pendingUploadsRef = useRef(new PendingAttachmentUploads());\n const submitInFlightRef = useRef(false);\n\n const { store } = useMentionSuggestions({ webpages, rootCategories });\n\n // Popup state\n const [popupOpen, setPopupOpen] = useState(false);\n const popupOpenRef = useRef(false);\n const [popupProps, setPopupProps] = useState<MentionSuggestionRenderProps | null>(null);\n\n // Suggestion callbacks — drive the popup lifecycle\n const callbacksRef = useRef<MentionSuggestionCallbacks>({\n onStart: (props) => {\n setPopupOpen(true);\n popupOpenRef.current = true;\n setPopupProps(props);\n },\n onUpdate: (props) => {\n setPopupProps(props);\n },\n onKeyDown: (event) => {\n // Route keyboard events to the MentionSuggestionList\n return listRef.current?.onKeyDown(event) ?? false;\n },\n onExit: () => {\n setPopupOpen(false);\n popupOpenRef.current = false;\n setPopupProps(null);\n },\n });\n\n // Editor ref — needed because handleSubmit is created before useEditor returns\n const editorRef = useRef<ReturnType<typeof useEditor>>(null);\n\n // Submit via composer runtime so attachments (screenshots, files) are included.\n // aui.composer.setText() + aui.composer.send() bundles text + pending attachments.\n //\n // Statewire turns a send during an active run into a queued command. Do not\n // cancel first: cancellation aborts the shared run for every connected\n // client and turns a normal queued follow-up into a destructive stop.\n const handleSubmit = useCallback(async () => {\n if (disabled) return;\n if (submitInFlightRef.current) return;\n submitInFlightRef.current = true;\n try {\n await pendingUploadsRef.current.waitForIdle();\n const ed = editorRef.current;\n if (!ed) return;\n const text = ed.getText({ blockSeparator: \"\\n\" }).trim();\n if (!text) return;\n if (!composerInput.canSend) return;\n\n // Interception carries TEXT only: a draft with pending attachments\n // (screenshots, files) must ride the composer-runtime send that\n // bundles them, or the attachments would silently vanish. Attachment\n // state is read only when a host actually intercepts.\n if (interceptSubmit) {\n const hasAttachments =\n (aui.composer.getState().attachments?.length ?? 0) > 0;\n if (!hasAttachments && (await interceptSubmit(text))) {\n ed.commands.clearContent();\n onDraftStateChange?.(false);\n return;\n }\n }\n\n composerInput.setText(text);\n composerInput.send({ steer: false });\n\n ed.commands.clearContent();\n onDraftStateChange?.(false);\n } finally {\n submitInFlightRef.current = false;\n }\n }, [composerInput, disabled, interceptSubmit, onDraftStateChange]);\n\n const handleSubmitRef = useRef(handleSubmit);\n handleSubmitRef.current = handleSubmit;\n\n const addAttachment = useCallback(\n (file: File) =>\n pendingUploadsRef.current.track(aui.composer.addAttachment(file)),\n [aui],\n );\n\n // Handle paste events — intercept images from clipboard and add as attachments\n const handlePaste = useCallback(\n (_view: unknown, event: ClipboardEvent) => {\n const items = event.clipboardData?.items;\n if (!items) return false;\n\n let handled = false;\n for (const item of items) {\n if (item.type.startsWith(\"image/\")) {\n event.preventDefault();\n const blob = item.getAsFile();\n if (blob) {\n const ext = item.type.split(\"/\")[1] || \"png\";\n const file = new File([blob], `pasted-image-${Date.now()}.${ext}`, { type: item.type });\n void addAttachment(file).catch((error: unknown) => {\n console.error(\"[attach] Pasted image upload failed:\", error);\n });\n }\n handled = true;\n }\n }\n return handled;\n },\n [addAttachment],\n );\n\n // Handle drop events — intercept dropped image files\n const handleDrop = useCallback(\n (_view: unknown, event: DragEvent) => {\n const files = event.dataTransfer?.files;\n if (!files?.length) return false;\n\n let handled = false;\n for (const file of files) {\n if (file.type.startsWith(\"image/\")) {\n event.preventDefault();\n void addAttachment(file).catch((error: unknown) => {\n console.error(\"[attach] Dropped image upload failed:\", error);\n });\n handled = true;\n }\n }\n return handled;\n },\n [addAttachment],\n );\n\n const editor = useEditor({\n editable: !disabled,\n extensions: [\n StarterKit.configure({\n heading: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({ placeholder }),\n MentionExtension,\n MentionSuggestionsExtension.configure({\n store,\n callbacks: callbacksRef.current,\n }),\n SubmitKeybind.configure({\n onSubmit: () => void handleSubmitRef.current(),\n isMentionOpen: () => popupOpenRef.current,\n }),\n ],\n editorProps: {\n attributes: {\n class:\n \"w-full resize-none bg-transparent px-1.5 py-2 text-sm leading-snug outline-none\",\n \"data-testid\": \"athena-chat-composer\",\n },\n handlePaste,\n handleDrop,\n },\n onUpdate: ({ editor: updatedEditor }) => {\n const nextText = updatedEditor.getText({ blockSeparator: \"\\n\" });\n if (!applyingRuntimeTextRef.current) {\n composerInput.setText(nextText);\n }\n onDraftStateChange?.(nextText.trim().length > 0);\n },\n immediatelyRender: false,\n });\n\n // Keep ref in sync so handleSubmit always has the editor\n editorRef.current = editor;\n\n useEffect(() => {\n editor?.setEditable(!disabled);\n }, [disabled, editor]);\n\n // This rich editor replaces ComposerPrimitive.Input, so it must mirror its\n // draft into assistant-ui's composer state. Statewire restores that state\n // when a send is rejected during reconnect; mirroring it back into Tiptap\n // preserves the user's message instead of leaving an empty composer.\n useEffect(() => {\n if (!editor) return;\n const editorText = editor.getText({ blockSeparator: \"\\n\" });\n if (editorText === composerInput.value) return;\n applyingRuntimeTextRef.current = true;\n editor.commands.setContent(plainTextToTiptapContent(composerInput.value));\n applyingRuntimeTextRef.current = false;\n onDraftStateChange?.(composerInput.value.trim().length > 0);\n }, [composerInput.value, editor, onDraftStateChange]);\n\n const insertAssetMention = useCallback((asset: UploadedChatAsset) => {\n const currentEditor = editorRef.current;\n if (!currentEditor) throw new Error(\"The chat composer is not ready.\");\n currentEditor\n .chain()\n .focus()\n .insertContent({\n type: \"mention\",\n attrs: {\n type: \"asset\",\n name: asset.title,\n id: asset.id,\n assetType: asset.assetType,\n },\n })\n .insertContent(\" \")\n .run();\n }, []);\n\n useEffect(\n () => registerChatAssetMentionHandler(threadId, insertAssetMention),\n [insertAssetMention, threadId],\n );\n\n useImperativeHandle(\n outerRef,\n () => ({ submit: handleSubmit, addAttachment, insertAssetMention }),\n [addAttachment, handleSubmit, insertAssetMention],\n );\n\n return (\n <>\n <style>{MENTION_STYLES}</style>\n <div\n className=\"flex-1 min-w-0\"\n aria-label=\"Message composer\"\n aria-disabled={disabled}\n >\n <EditorContent editor={editor} />\n </div>\n\n {/* Olympus-style mention popup */}\n {popupOpen && popupProps && editor && (\n <MentionSuggestionPopup clientRect={popupProps.clientRect}>\n <MentionSuggestionList\n ref={listRef}\n store={store}\n editor={editor}\n query={popupProps.query}\n command={(item: MenuItem) => popupProps.command(item)}\n closeMenu={() => {\n setPopupOpen(false);\n editor.commands.focus();\n }}\n />\n </MentionSuggestionPopup>\n )}\n </>\n );\n});\n\nTiptapComposer.displayName = \"TiptapComposer\";\n","import { useId } from \"react\";\nimport type { ChangeEvent, FC, ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nexport const SignInCard: FC<{\n /** e.g. \"Local build abcd1234\" — shown under the heading when set. */\n buildLabel?: string | null;\n subtitle?: ReactNode;\n /** Environment pickers, consent checkboxes, and other host controls. */\n children?: ReactNode;\n error?: string | null;\n /** Hint shown above the button (e.g. host cannot open a dialog). */\n notice?: ReactNode;\n primaryLabel: string;\n primaryPendingLabel: string;\n isPending: boolean;\n disabled?: boolean;\n onPrimary: () => void;\n /** Developer fallbacks and other secondary affordances. */\n footer?: ReactNode;\n}> = ({\n buildLabel,\n subtitle,\n children,\n error,\n notice,\n primaryLabel,\n primaryPendingLabel,\n isPending,\n disabled = false,\n onPrimary,\n footer,\n}) => (\n // `min-h-full` centers the card in hosts whose root is not a flex container.\n <div className=\"flex min-h-full flex-1 flex-col items-center justify-center bg-muted/20 p-5\">\n <div className=\"w-full max-w-sm space-y-5 rounded-2xl border bg-background/95 p-5 shadow-sm\">\n <div className=\"text-center\">\n <h2 className=\"text-base font-semibold tracking-tight text-foreground\">\n Sign in to Athena\n </h2>\n {buildLabel ? (\n <p className=\"mt-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {buildLabel}\n </p>\n ) : null}\n {subtitle ? (\n <p className=\"mt-1.5 text-xs leading-relaxed text-muted-foreground\">\n {subtitle}\n </p>\n ) : null}\n </div>\n\n {children ? <div className=\"space-y-3\">{children}</div> : null}\n\n {notice ? (\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{notice}</p>\n ) : null}\n <div role=\"status\" aria-live=\"polite\">\n {error ? <p className=\"text-xs text-destructive\">{error}</p> : null}\n </div>\n\n <button\n type=\"button\"\n className=\"h-10 w-full rounded-lg bg-primary px-4 text-sm font-semibold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-40\"\n onClick={onPrimary}\n disabled={isPending || disabled}\n >\n {isPending ? primaryPendingLabel : primaryLabel}\n </button>\n\n {footer}\n </div>\n </div>\n);\n\nexport const SignInSelect: FC<{\n id: string;\n label: string;\n value: string;\n options: ReadonlyArray<{ label: string; value: string }>;\n onChange: (value: string) => void;\n /** Resolved endpoint shown under the select. */\n hint?: string | null;\n}> = ({ id, label, value, options, onChange, hint }) => (\n <div className=\"space-y-1.5\">\n <label\n htmlFor={id}\n className=\"text-[10px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n {label}\n </label>\n <select\n id={id}\n className=\"h-10 w-full rounded-lg border bg-background px-3 text-sm outline-none transition-shadow focus:ring-2 focus:ring-ring/20\"\n value={value}\n onChange={(event: ChangeEvent<HTMLSelectElement>) =>\n onChange(event.target.value)\n }\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {hint ? (\n <p className=\"px-1 text-[10px] text-muted-foreground\">{hint}</p>\n ) : null}\n </div>\n);\n\nexport const SignInTextField: FC<{\n label: string;\n placeholder?: string;\n value: string;\n onChange: (value: string) => void;\n type?: \"url\" | \"password\" | \"text\";\n className?: string;\n}> = ({ label, placeholder, value, onChange, type = \"text\", className }) => (\n <label className=\"block space-y-1\">\n <span className=\"text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {label}\n </span>\n <input\n className={cn(\n \"h-9 w-full rounded-md border bg-background px-2.5 text-xs outline-none focus:ring-2 focus:ring-ring/20\",\n className,\n )}\n type={type}\n placeholder={placeholder}\n value={value}\n onChange={(event: ChangeEvent<HTMLInputElement>) =>\n onChange(event.target.value)\n }\n />\n </label>\n);\n\n/** Collapsible section under the primary button, for developer-only logins. */\nexport const SignInFallbackSection: FC<{\n isOpen: boolean;\n onToggle: () => void;\n label: string;\n children: ReactNode;\n}> = ({ isOpen, onToggle, label, children }) => {\n const contentId = useId();\n return (\n <div className=\"border-t pt-3\">\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={contentId}\n className=\"w-full text-left text-[11px] font-medium text-muted-foreground hover:text-foreground\"\n onClick={onToggle}\n >\n {isOpen ? \"Hide\" : \"Show\"} {label}\n </button>\n {isOpen ? (\n <div id={contentId} className=\"mt-3 space-y-2\">\n {children}\n </div>\n ) : null}\n </div>\n );\n};\n\n/** Secondary button matching the fallback section's weight. */\nexport const SignInSecondaryButton: FC<{\n onClick: () => void;\n disabled?: boolean;\n children: ReactNode;\n}> = ({ onClick, disabled = false, children }) => (\n <button\n type=\"button\"\n className=\"h-9 w-full rounded-lg border bg-background text-xs font-medium hover:bg-muted disabled:opacity-40\"\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </button>\n);\n\n/** Checkbox + explanatory copy, used for host data-use disclosures. */\nexport const SignInConsent: FC<{\n checked: boolean;\n onChange: (checked: boolean) => void;\n children: ReactNode;\n}> = ({ checked, onChange, children }) => (\n <label className=\"flex cursor-pointer items-start gap-2.5 rounded-lg border bg-muted/30 p-3 text-xs leading-relaxed text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"mt-0.5 h-4 w-4 shrink-0 accent-primary\"\n checked={checked}\n onChange={(event: ChangeEvent<HTMLInputElement>) =>\n onChange(event.target.checked)\n }\n />\n <span>{children}</span>\n </label>\n);\n","import { Play } from \"lucide-react\";\nimport { type FC, useEffect, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nconst EXIT_ANIMATION_MS = 200;\nconst EXIT_RESET_MS = 2500;\n\n/**\n * Shared Continue action for recoverable chat states.\n *\n * The dispatch waits for the exit animation to paint. If the owning runtime\n * does not leave the recoverable state (for example, the command is rejected),\n * the control resets so the user can try again.\n */\nexport const ContinuePill: FC<{\n onClick: () => void;\n ariaLabel: string;\n dataTestId?: string;\n}> = ({ onClick, ariaLabel, dataTestId }) => {\n const [isExiting, setIsExiting] = useState(false);\n const onClickRef = useRef(onClick);\n const pendingOnClickRef = useRef(onClick);\n onClickRef.current = onClick;\n\n useEffect(() => {\n if (!isExiting) return;\n const dispatchTimer = setTimeout(\n () => pendingOnClickRef.current(),\n EXIT_ANIMATION_MS,\n );\n const resetTimer = setTimeout(() => setIsExiting(false), EXIT_RESET_MS);\n return () => {\n clearTimeout(dispatchTimer);\n clearTimeout(resetTimer);\n };\n }, [isExiting]);\n\n const handleClick = (): void => {\n if (isExiting) return;\n pendingOnClickRef.current = onClickRef.current;\n setIsExiting(true);\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isExiting}\n className={cn(\n \"group inline-flex items-center gap-1.5 rounded-full bg-primary px-3.5 py-1 text-xs font-medium text-primary-foreground shadow-sm\",\n \"transition-all duration-200 ease-out\",\n \"hover:bg-primary/90 hover:shadow-md active:scale-95\",\n \"animate-in fade-in slide-in-from-bottom-1\",\n isExiting && \"pointer-events-none scale-90 opacity-0\",\n )}\n aria-label={ariaLabel}\n data-testid={dataTestId}\n >\n <Play className=\"size-3 fill-current transition-transform duration-200 ease-out group-hover:translate-x-0.5\" />\n <span>Continue</span>\n </button>\n );\n};\n","import { useAuiState } from \"@assistant-ui/react\";\nimport {\n useStatewireRuns,\n useStatewireSendCommand,\n} from \"@assistant-ui/react-statewire\";\nimport {\n ATHENA_RUN_MARKER_CANCELLED,\n ATHENA_RUN_MARKER_FAILED,\n type AthenaRuntimeMessage,\n hasStatewireThreadExtras,\n readRunMarkerFromSourceMessages,\n readRuntimeMessageFromSourceMessages,\n useDeepAgentThreadStatus,\n} from \"@athenaintel/agent-runtime\";\nimport type { ReactElement } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { ContinuePill } from \"./continue-pill\";\nimport { RuntimeMessageCard } from \"./runtime-message\";\n\nexport interface StatewireContinueRunButtonProps {\n /**\n * Also offer Continue while the thread projects `ready`. An old snapshot\n * can report a resting thread whose last persisted ending is still\n * continuable; the marker row that mounts this button knows that.\n */\n allowReadyFallback?: boolean;\n}\n\n/**\n * Dispatches the bare `run/continue` for the live Statewire thread — the\n * heal-then-continue recovery for stopped, errored, and pod-drained runs. The\n * command is exactly what the library's `onResume` emits, so it inherits the\n * optimistic running-flip (the pill unmounts once the dispatch is accepted)\n * and routes rejections to the runtime's shared `onError` policy.\n *\n * Requires `capabilities.continue` on the host thread and a statewire aui\n * scope (throws outside one, like every `useStatewire*` hook).\n */\nexport function StatewireContinueRunButton({\n allowReadyFallback = false,\n}: StatewireContinueRunButtonProps = {}): ReactElement | null {\n const status = useDeepAgentThreadStatus();\n const { runId } = useStatewireRuns();\n const sendCommand = useStatewireSendCommand();\n\n const isSettled = status === \"stopped\" || status === \"error\";\n if (!isSettled && !(allowReadyFallback && status === \"ready\")) return null;\n\n return (\n <ContinuePill\n ariaLabel=\"Continue this run from where it stopped\"\n dataTestId=\"statewire-continue-run\"\n onClick={() => {\n sendCommand({\n type: \"run/continue\",\n ...(runId !== null && { runId }),\n });\n }}\n />\n );\n}\n\n/**\n * Recovery affordance for the latest persisted stopped/failed run marker,\n * for the `runtimeMessageAction` slot of `createAssistantMessage`.\n *\n * Marker messages remain in history forever, so only the current last message\n * may continue. The extras guard keeps Statewire hooks out of read-only or\n * legacy runtimes where they would throw.\n */\nexport function StatewireContinueRunAffordance(): ReactElement | null {\n const messageId = useAuiState((state) => state.message.id);\n const lastMessageId = useAuiState(\n (state) => state.thread.messages.at(-1)?.id,\n );\n const runMarker = useAuiState(\n (state) => readRunMarkerFromSourceMessages(state.message)?.marker,\n );\n const threadExtras = useAuiState((state) => state.thread.extras);\n\n const isContinuableMarker =\n runMarker === ATHENA_RUN_MARKER_CANCELLED ||\n runMarker === ATHENA_RUN_MARKER_FAILED;\n if (messageId !== lastMessageId || !isContinuableMarker) return null;\n if (!hasStatewireThreadExtras(threadExtras)) return null;\n\n return (\n <div className=\"flex w-full justify-center py-1\">\n <StatewireContinueRunButton allowReadyFallback />\n </div>\n );\n}\n\nexport interface StatewireRunEndedFooterProps {\n /** Merged onto the recovery card's default classes. */\n className?: string;\n}\n\n/**\n * Recovery row for a settled run whose persisted ending is no longer the\n * transcript tail — rendered after the messages (`renderMessages`). Rewinds,\n * compaction, and older snapshots can all leave the durable run state\n * recoverable without a marker row that owns the action. Renders nothing on\n * legacy (non-statewire) threads.\n */\nexport function StatewireRunEndedFooter({\n className,\n}: StatewireRunEndedFooterProps = {}): ReactElement | null {\n const threadExtras = useAuiState((state) => state.thread.extras);\n if (!hasStatewireThreadExtras(threadExtras)) return null;\n return <StatewireRunEndedFooterContent className={className} />;\n}\n\nfunction StatewireRunEndedFooterContent({\n className,\n}: StatewireRunEndedFooterProps): ReactElement | null {\n const status = useDeepAgentThreadStatus();\n const { error } = useStatewireRuns();\n const tailEndingKind = useAuiState((state) => {\n const last = state.thread.messages.at(-1);\n return last ? (readRuntimeMessageFromSourceMessages(last)?.kind ?? null) : null;\n });\n const tailEndingSilent = useAuiState((state) => {\n const last = state.thread.messages.at(-1);\n return last ? (readRuntimeMessageFromSourceMessages(last)?.silent ?? false) : false;\n });\n\n if (status !== \"stopped\" && status !== \"error\") return null;\n\n // A send-now promotion intentionally cancels the superseded run without a\n // visible ending. Statewire can briefly report that cancellation as stopped;\n // preserve the silent contract instead of presenting a false recovery state.\n // A genuine error still wins and remains recoverable below.\n if (status === \"stopped\" && tailEndingSilent) return null;\n\n const tailRendersEnding = tailEndingKind !== null && !tailEndingSilent;\n const tailMatchesStatus =\n status === \"error\"\n ? tailEndingKind === \"failed\"\n : tailEndingKind === \"stopped\" || tailEndingKind === \"paused\";\n if (tailRendersEnding && tailMatchesStatus) return null;\n\n const tailOwnsContinue =\n tailRendersEnding &&\n (tailEndingKind === \"stopped\" ||\n tailEndingKind === \"paused\" ||\n tailEndingKind === \"failed\");\n const action = tailOwnsContinue ? undefined : <StatewireContinueRunButton />;\n const message: AthenaRuntimeMessage =\n status === \"error\"\n ? {\n kind: \"failed\",\n reason: \"error\",\n severity: \"error\",\n title: \"Run failed\",\n detail: undefined,\n text: error?.message ? `⚠️ The run failed: ${error.message}` : undefined,\n silent: false,\n isSoleSourceMessage: true,\n }\n : {\n kind: \"stopped\",\n reason: undefined,\n severity: \"info\",\n title: \"Conversation stopped\",\n detail: undefined,\n text: undefined,\n silent: false,\n isSoleSourceMessage: true,\n };\n\n return (\n <RuntimeMessageCard\n message={message}\n action={action}\n className={cn(\"mx-auto max-w-[95%]\", className)}\n />\n );\n}\n"],"names":["__iconNode","LoaderCircleIcon","BotIcon","MessageSquareIcon","RefreshCwIcon","PlusIcon","SearchIcon","ArchiveIcon","params","item","FileIcon","FileTextIcon","FileCodeIcon","FolderIcon","FolderKanbanIcon","GlobeIcon","StarIcon","UsersIcon","UserIcon","WrenchIcon","PackageIcon","Building2Icon","HardDriveIcon","LayoutGridIcon","ZapIcon","EyeIcon","CameraIcon","KeyboardIcon","CodeIcon","MonitorIcon","ImageIcon","VideoIcon","HeadphonesIcon","MicIcon","MailIcon","CalendarIcon","PhoneIcon","DatabaseIcon","TableIcon","SheetIcon","PaletteIcon","PenToolIcon","LayoutIcon","LayoutDashboardIcon","LibraryIcon","BookOpenIcon","SparklesIcon","CheckSquareIcon","KeyIcon","SmartphoneIcon","CloudIcon","WorkflowIcon","offset","Fragment"],"mappings":"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","x_google_ignoreList":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]}
|