@arbidocs/react 0.4.31 → 0.4.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/dist/artifacts/index.cjs +16 -16
  3. package/dist/artifacts/index.js +3 -3
  4. package/dist/{chunk-G3SWUES3.js → chunk-5JGBZQD4.js} +405 -123
  5. package/dist/chunk-5JGBZQD4.js.map +1 -0
  6. package/dist/{chunk-EOOHRPFM.cjs → chunk-775VGSKN.cjs} +59 -10
  7. package/dist/chunk-775VGSKN.cjs.map +1 -0
  8. package/dist/{chunk-6YSHODMG.js → chunk-FOEYFNQ4.js} +59 -10
  9. package/dist/chunk-FOEYFNQ4.js.map +1 -0
  10. package/dist/{chunk-6BLXIF4R.cjs → chunk-PW7GGG7E.cjs} +9 -7
  11. package/dist/chunk-PW7GGG7E.cjs.map +1 -0
  12. package/dist/{chunk-OBTCAI4E.js → chunk-UDOPD3GK.js} +12 -4
  13. package/dist/chunk-UDOPD3GK.js.map +1 -0
  14. package/dist/{chunk-ULED4SBT.cjs → chunk-UFSATX3N.cjs} +412 -125
  15. package/dist/chunk-UFSATX3N.cjs.map +1 -0
  16. package/dist/{chunk-NDG44JWI.js → chunk-V3A7JDJV.js} +8 -6
  17. package/dist/chunk-V3A7JDJV.js.map +1 -0
  18. package/dist/{chunk-YSZJCWDD.cjs → chunk-Z4M7JB4L.cjs} +12 -4
  19. package/dist/chunk-Z4M7JB4L.cjs.map +1 -0
  20. package/dist/{index-CcbVSNSP.d.cts → index-C7OqcKY3.d.cts} +3 -1
  21. package/dist/{index-CcbVSNSP.d.ts → index-C7OqcKY3.d.ts} +3 -1
  22. package/dist/{index-C99tcxue.d.cts → index-CUxIcC5j.d.cts} +19 -7
  23. package/dist/{index-C99tcxue.d.ts → index-CUxIcC5j.d.ts} +19 -7
  24. package/dist/index.cjs +360 -531
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +60 -10
  27. package/dist/index.d.ts +60 -10
  28. package/dist/index.js +25 -212
  29. package/dist/index.js.map +1 -1
  30. package/dist/shell/index.cjs +6 -6
  31. package/dist/shell/index.d.cts +1 -1
  32. package/dist/shell/index.d.ts +1 -1
  33. package/dist/shell/index.js +1 -1
  34. package/dist/ui/index.cjs +134 -130
  35. package/dist/ui/index.d.cts +1 -1
  36. package/dist/ui/index.d.ts +1 -1
  37. package/dist/ui/index.js +2 -2
  38. package/package.json +3 -3
  39. package/dist/chunk-6BLXIF4R.cjs.map +0 -1
  40. package/dist/chunk-6YSHODMG.js.map +0 -1
  41. package/dist/chunk-EOOHRPFM.cjs.map +0 -1
  42. package/dist/chunk-G3SWUES3.js.map +0 -1
  43. package/dist/chunk-NDG44JWI.js.map +0 -1
  44. package/dist/chunk-OBTCAI4E.js.map +0 -1
  45. package/dist/chunk-ULED4SBT.cjs.map +0 -1
  46. package/dist/chunk-YSZJCWDD.cjs.map +0 -1
@@ -1,15 +1,17 @@
1
- import { normalizeCitationMarkup } from './chunk-6YSHODMG.js';
1
+ import { normalizeCitationMarkup } from './chunk-FOEYFNQ4.js';
2
2
  import { useArbi } from './chunk-J4MX2W4H.js';
3
3
  import { useMemo } from 'react';
4
4
  import { useQuery, useMutation, useQueryClient, useQueries } from '@tanstack/react-query';
5
5
 
6
6
  // src/credits.ts
7
7
  var DEFAULT_USD_PER_CREDIT = 0.01;
8
+ var WHOLE_CREDITS_FROM = 100;
8
9
  function formatCredits(credits, options = {}) {
9
10
  const { unit = true, locale = "en-US" } = options;
10
- const whole = Math.round(Number.isFinite(credits) ? credits : 0);
11
- const digits = whole.toLocaleString(locale);
12
- return unit ? `${digits} ${whole === 1 ? "credit" : "credits"}` : digits;
11
+ const safe = Number.isFinite(credits) ? credits : 0;
12
+ const rounded = Math.abs(safe) >= WHOLE_CREDITS_FROM ? Math.round(safe) : Math.round(safe * 100) / 100;
13
+ const digits = rounded.toLocaleString(locale, { maximumFractionDigits: 2 });
14
+ return unit ? `${digits} ${rounded === 1 ? "credit" : "credits"}` : digits;
13
15
  }
14
16
  function creditsToUsd(credits, usdPerCredit = DEFAULT_USD_PER_CREDIT) {
15
17
  return credits * usdPerCredit;
@@ -538,5 +540,5 @@ function cleanDraftMarkdown(raw) {
538
540
  }
539
541
 
540
542
  export { DEFAULT_USD_PER_CREDIT, arbiQueryKeys, cleanDraftMarkdown, cleanDraftWithReport, creditsToUsd, formatCredits, isUsageMetered, promoteBoldTitle, repairParsedStructure, repairParsedTitle, stripAgentPreamble, unescapeMarkdown, unwrapCitationLinks, useActivity, useAgents, useAssistantQuery, useConfigs, useConversationThreads, useConversations, useDeleteAgents, useDocuments, useFacts, useHealth, useParsedDocument, useProjectInvoices, useProjectUsage, useProjects, useProjectsUsage, useSessions, useTags, useThumbnails, useUserUsageToday, useWorkspaceUsers, useWorkspaces };
541
- //# sourceMappingURL=chunk-NDG44JWI.js.map
542
- //# sourceMappingURL=chunk-NDG44JWI.js.map
543
+ //# sourceMappingURL=chunk-V3A7JDJV.js.map
544
+ //# sourceMappingURL=chunk-V3A7JDJV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/credits.ts","../src/hooks.ts","../src/ai/stored-markdown.ts"],"names":[],"mappings":"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","file":"chunk-V3A7JDJV.js","sourcesContent":["/**\n * Credits: the unit the ARBI backend reports AI usage in.\n *\n * The usage endpoints (`/v1/user/projects/{id}/usage`, `/me/usage/today`) convert the metered USD\n * spend into credits at the API boundary (fractional, rounded to 2 decimals, because a small\n * deployment spends well under one credit a day): 1 credit = `CREDITS_TO_AI_USD`, which is $0.01 on\n * a default deployment. The fields are still named `spend` / `total_spend` in the schema, but they\n * hold CREDITS, never dollars. Label them as credits; use {@link creditsToUsd} only when a\n * dollar figure is genuinely wanted, with the deployment's own rate.\n */\n\n/** Dollars per credit on a default deployment (`CREDITS_TO_AI_USD`). */\nexport const DEFAULT_USD_PER_CREDIT = 0.01\n\nexport interface FormatCreditsOptions {\n /** Append the unit (\"12 credits\"). Default true; pass false inside a column headed \"Credits\". */\n unit?: boolean\n /** BCP 47 locale for the digit grouping. Default `en-US`. */\n locale?: string\n}\n\n/** Amounts at or above this show as whole credits; below it, up to 2 decimals. */\nconst WHOLE_CREDITS_FROM = 100\n\n/**\n * \"0.47 credits\" / \"1 credit\" / \"1.5 credits\" / \"1,235 credits\". The backend reports fractional\n * credits (2 decimals). Amounts under 100 keep up to 2 decimals with trailing zeros trimmed;\n * amounts of 100 and over round to whole credits. Only exactly 1 is singular.\n */\nexport function formatCredits(credits: number, options: FormatCreditsOptions = {}): string {\n const { unit = true, locale = 'en-US' } = options\n const safe = Number.isFinite(credits) ? credits : 0\n const rounded =\n Math.abs(safe) >= WHOLE_CREDITS_FROM ? Math.round(safe) : Math.round(safe * 100) / 100\n const digits = rounded.toLocaleString(locale, { maximumFractionDigits: 2 })\n return unit ? `${digits} ${rounded === 1 ? 'credit' : 'credits'}` : digits\n}\n\n/** The dollar value of an amount of credits. `usdPerCredit` defaults to {@link DEFAULT_USD_PER_CREDIT}. */\nexport function creditsToUsd(\n credits: number,\n usdPerCredit: number = DEFAULT_USD_PER_CREDIT\n): number {\n return credits * usdPerCredit\n}\n\n/** The slice of a usage response that tells whether anything was recorded. */\nexport interface UsageTotals {\n total_spend: number\n total_tokens: number\n total_requests: number\n}\n\n/**\n * Was this usage actually metered? A `dev`-plan project with an all-zero response (no spend, no\n * tokens, no requests) is treated as \"not metered\", so the UI shows a note instead of silent\n * zeros. Any recorded tokens or requests mean usage was metered, even when the spend rounds to 0\n * (the backend now records usage when billing is off, and a tiny spend can be 0.00 credits).\n */\nexport function isUsageMetered(\n usage: UsageTotals,\n subscription: string | null | undefined\n): boolean {\n const empty = usage.total_spend === 0 && usage.total_tokens === 0 && usage.total_requests === 0\n return !(empty && subscription === 'dev')\n}\n","/**\n * React Query hooks that use the Arbi instance from context.\n */\n\nimport { useMemo } from 'react'\nimport { useQuery, useQueries, useMutation, useQueryClient } from '@tanstack/react-query'\nimport type {\n SSEStreamResult,\n SSEStreamStartData,\n ResponseOutputItemDoneEvent,\n ArtifactEvent,\n UserMessageEvent,\n MessageMetadataPayload,\n QueryOptions,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport type { ParsedDocument } from './documents/parsed-types'\nimport { isUsageMetered } from './credits'\n\n// ── Query keys ──────────────────────────────────────────────────────────────\n\nexport const arbiQueryKeys = {\n workspaces: () => ['arbi', 'workspaces'] as const,\n workspaceUsers: (workspaceId: string) => ['arbi', 'workspaceUsers', workspaceId] as const,\n documents: (workspaceId: string) => ['arbi', 'documents', workspaceId] as const,\n conversations: (workspaceId: string) => ['arbi', 'conversations', workspaceId] as const,\n /** Every workspace's conversation list (and threads): the prefix a conversation write invalidates. */\n allConversations: () => ['arbi', 'conversations'] as const,\n conversationThreads: (workspaceId: string, conversationId: string) =>\n ['arbi', 'conversations', workspaceId, 'threads', conversationId] as const,\n tags: (workspaceId: string) => ['arbi', 'tags', workspaceId] as const,\n thumbnails: (docIds: string[]) => ['arbi', 'thumbnails', [...docIds].sort().join(',')] as const,\n parsedDoc: (docId: string, stage: string) => ['arbi', 'parsedDoc', docId, stage] as const,\n agents: () => ['arbi', 'agents'] as const,\n sessions: () => ['arbi', 'sessions'] as const,\n health: () => ['arbi', 'health'] as const,\n workflows: () => ['arbi', 'workflows'] as const,\n facts: (workspaceId: string) => ['arbi', 'facts', workspaceId] as const,\n configs: () => ['arbi', 'configs'] as const,\n activity: () => ['arbi', 'activity'] as const,\n projects: () => ['arbi', 'projects'] as const,\n projectUsage: (projectExtId: string, monthsBack: number) =>\n ['arbi', 'projectUsage', projectExtId, monthsBack] as const,\n projectInvoices: (projectExtId: string) => ['arbi', 'projectInvoices', projectExtId] as const,\n userUsageToday: () => ['arbi', 'userUsageToday'] as const,\n contacts: () => ['arbi', 'contacts'] as const,\n skills: () => ['arbi', 'skills'] as const,\n /** An agent's pinned config; `undefined` = the library default config. */\n agentConfig: (agentExtId?: string) => ['arbi', 'agentConfig', agentExtId ?? 'default'] as const,\n agentWorkspaces: (agentExtId: string) => ['arbi', 'agentWorkspaces', agentExtId] as const,\n models: () => ['arbi', 'models'] as const,\n /** The signed-in user's own profile (name, picture, email). */\n profile: () => ['arbi', 'profile'] as const,\n /** The signed-in user's settings record (notification preferences, flags). */\n userSettings: () => ['arbi', 'userSettings'] as const,\n}\n\n// ── Hooks ───────────────────────────────────────────────────────────────────\n\n/** Workspace people for mentions, ownership and sign-off. */\nexport function useWorkspaceUsers(\n workspaceId: string | undefined,\n options?: {\n enabled?: boolean\n beforeFetch?: () => Promise<unknown>\n }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workspaceUsers(workspaceId ?? ''),\n enabled: !!workspaceId && (options?.enabled ?? arbi.hasWorkspace),\n queryFn: async () => {\n await options?.beforeFetch?.()\n if (arbi.getWorkspaceId() !== workspaceId) throw new Error('The selected workspace changed.')\n return arbi.workspaces.listUsers()\n },\n refetchInterval: 30_000,\n })\n}\n\n/** List the logged-in user's workspaces. */\nexport function useWorkspaces(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workspaces(),\n queryFn: () => arbi.workspaces.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n/** List documents in a workspace. */\nexport function useDocuments(workspaceId: string | undefined, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.documents(workspaceId ?? ''),\n queryFn: () => arbi.documents.list(),\n enabled: (options?.enabled ?? true) && !!workspaceId && arbi.hasWorkspace,\n })\n}\n\n/** List conversations in a workspace. */\nexport function useConversations(\n workspaceId: string | undefined,\n options?: { enabled?: boolean; live?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.conversations(workspaceId ?? ''),\n queryFn: () => arbi.conversations.list(),\n enabled: (options?.enabled ?? true) && !!workspaceId && arbi.hasWorkspace,\n refetchInterval: options?.live\n ? (query) =>\n query.state.data?.some((conversation) => conversation.status === 'generating')\n ? 3000\n : 15000\n : false,\n })\n}\n\n/**\n * A conversation's stored threads (each with its message history, citations data included).\n * Always refetched on mount: a conversation that was open before may have new turns.\n */\nexport function useConversationThreads(\n workspaceId: string | undefined,\n conversationId: string | undefined,\n options?: { enabled?: boolean; live?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.conversationThreads(workspaceId ?? '', conversationId ?? ''),\n queryFn: () => arbi.conversations.getThreads(conversationId as string),\n enabled: (options?.enabled ?? true) && !!workspaceId && !!conversationId && arbi.hasWorkspace,\n gcTime: 0,\n refetchInterval: options?.live ? 3000 : false,\n })\n}\n\n/** List tags in a workspace. */\nexport function useTags(workspaceId: string | undefined, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.tags(workspaceId ?? ''),\n queryFn: () => arbi.tags.list(),\n enabled: (options?.enabled ?? true) && !!workspaceId && arbi.hasWorkspace,\n })\n}\n\n/**\n * Batch-fetch first-page thumbnails for a set of documents. Returns a map of\n * doc external id → `data:image/webp` URI (or `null` when no thumbnail exists).\n * Cached for a few minutes since thumbnails are effectively immutable per doc.\n */\nexport function useThumbnails(docIds: string[], options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.thumbnails(docIds),\n queryFn: () => arbi.documents.getThumbnails(docIds),\n enabled: (options?.enabled ?? true) && docIds.length > 0 && arbi.hasWorkspace,\n staleTime: 5 * 60_000,\n })\n}\n\n/**\n * Fetch a document's parsed content (chunks grouped by page) for the review\n * viewer. `stage` defaults to `final` (fully processed); `marker`/`subchunk`\n * expose earlier pipeline stages.\n */\nexport function useParsedDocument(\n docId: string | undefined,\n stage: string = 'final',\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.parsedDoc(docId ?? '', stage),\n queryFn: () =>\n arbi.documents.getParsedContent(docId as string, stage) as unknown as Promise<ParsedDocument>,\n enabled: (options?.enabled ?? true) && !!docId && arbi.hasWorkspace,\n })\n}\n\n/** Send a streaming query to the RAG assistant. Returns a mutation. */\nexport function useAssistantQuery() {\n const arbi = useArbi()\n\n return useMutation<\n SSEStreamResult,\n Error,\n {\n question: string\n agentId?: string\n workspaceId?: string\n activeArtifactExtId?: string\n docIds: string[]\n previousResponseId?: string | null\n conversationId?: string\n assistantMode?: QueryOptions['assistantMode']\n mentions?: QueryOptions['mentions']\n model?: string\n onToken?: (content: string) => void\n /** Aborts the request and the stream; the mutation then rejects with an `AbortError`. */\n signal?: AbortSignal\n onStreamStart?: (data: SSEStreamStartData) => void\n onUserMessage?: (data: UserMessageEvent) => void\n onMetadata?: (data: MessageMetadataPayload) => void\n onOutputItemDone?: (data: ResponseOutputItemDoneEvent) => void\n onArtifact?: (data: ArtifactEvent) => void\n onError?: (message: string) => void\n onComplete?: () => void\n }\n >({\n mutationFn: ({ question, ...options }) => arbi.assistant.query(question, options),\n })\n}\n\n/** List agents owned by the current user. */\nexport function useAgents(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.agents(),\n queryFn: () => arbi.agents.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n/**\n * Delete agents. Returns a mutation. Refreshes the agent list, the workflow list and the conversation list\n * (a deleted agent's workflows and work go with it), and drops the deleted agents' own config and workspace queries.\n */\nexport function useDeleteAgents() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation<unknown, Error, { agentExtIds: string[] }>({\n mutationFn: ({ agentExtIds }) => arbi.agents.delete(agentExtIds),\n onSuccess: (_result, { agentExtIds }) => {\n for (const id of agentExtIds) {\n qc.removeQueries({ queryKey: arbiQueryKeys.agentConfig(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.agentWorkspaces(id) })\n }\n return Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.agents() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.workflows() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.allConversations() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.configs() }),\n ])\n },\n })\n}\n\n/** List active sessions. */\nexport function useSessions(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.sessions(),\n queryFn: () => arbi.sessions.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n/** Authorize a delegated session (generates claim code). Returns a mutation. */\n\n/** Check backend health. */\nexport function useHealth(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.health(),\n queryFn: () => arbi.health.check(),\n enabled: options?.enabled,\n })\n}\n\n// ── Workspace notes ──────────────────────────────────────────────────────────\n\n/** List the open workspace's facts. */\nexport function useFacts(\n workspaceId: string | undefined,\n options?: { enabled?: boolean; pinnedOnly?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.facts(workspaceId ?? ''),\n queryFn: () => arbi.facts.list({ pinnedOnly: options?.pinnedOnly }),\n enabled: (options?.enabled ?? true) && !!workspaceId && arbi.hasWorkspace,\n })\n}\n\n// ── Behaviour-template configs ───────────────────────────────────────────────\n\n/** List the caller's saved agent configurations (behaviour templates). */\nexport function useConfigs(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.configs(),\n queryFn: () => arbi.agentConfig.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n// ── Activity feed ─────────────────────────────────────────────────────────────\n\n/**\n * List the caller's durable activity feed, newest first.\n *\n * Activity entries are backend-originated, to-self log lines that are always\n * read — they are deliberately kept out of the normal notifications/DM feed and\n * never affect the unread badge, so this is a separate, opt-in query.\n */\nexport function useActivity(options?: { enabled?: boolean; limit?: number; offset?: number }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.activity(),\n queryFn: () => arbi.dm.listActivity({ limit: options?.limit, offset: options?.offset }),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n// ── Projects, usage & spend ───────────────────────────────────────────────────\n\n/** List the logged-in user's projects (billing accounts). */\nexport function useProjects(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.projects(),\n queryFn: () => arbi.projects.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n/**\n * AI usage breakdown for a project's billing period. `monthsBack` selects the period (0 =\n * current, 1 = previous month, …).\n *\n * The response's `total_spend` / `spend` fields are CREDITS, not dollars (see `formatCredits`).\n * `metered` is `false` when the deployment does not record usage (a `dev`-plan project with all\n * zeros): show \"usage is not metered here\" instead of zeros. It is `undefined` until the usage\n * has loaded.\n */\nexport function useProjectUsage(\n projectExtId: string | undefined,\n monthsBack: number = 0,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n const usage = useQuery({\n queryKey: arbiQueryKeys.projectUsage(projectExtId ?? '', monthsBack),\n queryFn: () => arbi.projects.usage(projectExtId as string, monthsBack),\n enabled: (options?.enabled ?? true) && !!projectExtId && arbi.isLoggedIn,\n })\n const projects = useProjects({ enabled: !!projectExtId && (options?.enabled ?? true) })\n const subscription = projects.data?.find((p) => p.external_id === projectExtId)?.subscription\n const metered = usage.data ? isUsageMetered(usage.data, subscription) : undefined\n return { ...usage, metered }\n}\n\n/** One day of aggregated usage across projects (for a spend/token trend). */\nexport interface AggregatedDailyUsage {\n date: string\n /** Credits used that day (not dollars). */\n credits: number\n totalTokens: number\n apiRequests: number\n}\n\n/** One model group's aggregated usage across projects (for a breakdown). */\nexport interface AggregatedModelGroupUsage {\n model: string\n /** Credits used by this model group (not dollars). */\n credits: number\n totalTokens: number\n promptTokens: number\n completionTokens: number\n successfulRequests: number\n}\n\n/** Aggregated AI usage + spend across several projects. */\nexport interface ProjectsUsageAggregate {\n /** Summed usage across the projects, in CREDITS (1 credit = $0.01 by default), not dollars. */\n totalCredits: number\n /** Summed token count across the projects. */\n totalTokens: number\n /** Summed API request count across the projects. */\n totalRequests: number\n /** Per-day totals merged across every project, oldest first. */\n daily: AggregatedDailyUsage[]\n /** Per-model-group totals merged across every project, most credits first. */\n modelGroups: AggregatedModelGroupUsage[]\n /**\n * False when none of the loaded projects records usage (billing is off on this deployment), so\n * zeros mean \"not metered\". True while anything real was recorded, or before data arrived.\n */\n metered: boolean\n /** True while any per-project query is still loading. */\n isLoading: boolean\n /** True if any per-project query errored. */\n isError: boolean\n}\n\n/**\n * Firm-wide AI usage + spend: aggregates {@link useProjectUsage} across several\n * projects (e.g. all of a firm's matters) in parallel and merges the real totals,\n * the daily trend, and the per-model breakdown. Shares the per-project query\n * cache, so it costs nothing extra where a project's usage is already loaded.\n * Numbers are genuine — zero projects (or zero billed work) yields zero totals;\n * callers render that honestly.\n */\nexport function useProjectsUsage(\n projectExtIds: string[],\n monthsBack: number = 0,\n options?: { enabled?: boolean }\n): ProjectsUsageAggregate {\n const arbi = useArbi()\n const enabled = (options?.enabled ?? true) && arbi.isLoggedIn\n const projects = useProjects({ enabled: enabled && projectExtIds.length > 0 })\n const results = useQueries({\n queries: projectExtIds.map((id) => ({\n queryKey: arbiQueryKeys.projectUsage(id, monthsBack),\n queryFn: () => arbi.projects.usage(id, monthsBack),\n enabled: enabled && !!id,\n })),\n })\n\n // Recompute only when a query's data actually changes (not on every parent\n // render — the dashboard re-renders often while a digest streams).\n const signature =\n results.map((r) => `${r.status}:${r.dataUpdatedAt ?? 0}`).join('|') +\n `#${projects.dataUpdatedAt}`\n\n return useMemo(() => {\n const dailyMap = new Map<string, AggregatedDailyUsage>()\n const modelMap = new Map<string, AggregatedModelGroupUsage>()\n let totalCredits = 0\n let anyData = false\n let anyMetered = false\n let totalTokens = 0\n let totalRequests = 0\n\n results.forEach((r, i) => {\n const d = r.data\n if (!d) return\n anyData = true\n const subscription = projects.data?.find(\n (p) => p.external_id === projectExtIds[i]\n )?.subscription\n if (isUsageMetered(d, subscription)) anyMetered = true\n totalCredits += d.total_spend ?? 0\n totalTokens += d.total_tokens ?? 0\n totalRequests += d.total_requests ?? 0\n\n for (const day of d.daily ?? []) {\n const cur = dailyMap.get(day.date) ?? {\n date: day.date,\n credits: 0,\n totalTokens: 0,\n apiRequests: 0,\n }\n cur.credits += day.spend ?? 0\n cur.totalTokens += day.total_tokens ?? 0\n cur.apiRequests += day.api_requests ?? 0\n dailyMap.set(day.date, cur)\n }\n\n for (const [model, mg] of Object.entries(d.model_groups ?? {})) {\n const cur = modelMap.get(model) ?? {\n model,\n credits: 0,\n totalTokens: 0,\n promptTokens: 0,\n completionTokens: 0,\n successfulRequests: 0,\n }\n cur.credits += mg.spend ?? 0\n cur.totalTokens += mg.total_tokens ?? 0\n cur.promptTokens += mg.prompt_tokens ?? 0\n cur.completionTokens += mg.completion_tokens ?? 0\n cur.successfulRequests += mg.successful_requests ?? 0\n modelMap.set(model, cur)\n }\n })\n\n return {\n totalCredits,\n totalTokens,\n totalRequests,\n daily: [...dailyMap.values()].sort((a, b) => a.date.localeCompare(b.date)),\n modelGroups: [...modelMap.values()].sort(\n (a, b) => b.credits - a.credits || b.totalTokens - a.totalTokens\n ),\n metered: !anyData || anyMetered,\n isLoading: results.some((r) => r.isLoading),\n isError: results.some((r) => r.isError),\n }\n }, [signature])\n}\n\n/** List the Stripe invoices for a project's subscription. */\nexport function useProjectInvoices(\n projectExtId: string | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.projectInvoices(projectExtId ?? ''),\n queryFn: () => arbi.projects.invoices(projectExtId as string),\n enabled: (options?.enabled ?? true) && !!projectExtId && arbi.isLoggedIn,\n })\n}\n\n/** Today's deployment-wide credit use for the current user (`credits_used`, in credits). */\nexport function useUserUsageToday(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.userUsageToday(),\n queryFn: () => arbi.user.usageToday(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n","/**\n * Helpers for markdown that is STORED (an agent's draft saved as an artifact, then read back from\n * the backend's parse). Pure and SDK-free; they sit next to `normalizeCitationMarkup`, which they\n * build on.\n *\n * Two directions:\n *\n * - Going in (`cleanDraftMarkdown` = `unwrapCitationLinks` + `stripAgentPreamble` +\n * `promoteBoldTitle`): a streamed draft carries citation links, `(*Source: ...*)` notes and\n * sometimes narration before the document. A stored letter should hold only the letter.\n * - Coming out (`unescapeMarkdown`): the backend's parse of a stored `.md` returns the text with\n * markdown punctuation backslash-escaped (`**Fees.**` comes back as `\\*\\*Fees\\.\\*\\*`).\n */\n\nimport { normalizeCitationMarkup } from './normalize-citations'\n\nconst FENCE = /^\\s*(```|~~~)/\n\n/** Run `fn` on every line outside a fenced code block. */\nfunction mapOutsideFences(text: string, fn: (line: string) => string): string {\n let inFence = false\n return text\n .split('\\n')\n .map((line) => {\n if (FENCE.test(line)) {\n inFence = !inFence\n return line\n }\n return inFence ? line : fn(line)\n })\n .join('\\n')\n}\n\n// ---------------------------------------------------------------------------------------------\n// Coming out: undo the parser's escaping\n// ---------------------------------------------------------------------------------------------\n\n/** A backslash followed by markdown punctuation: the only thing the parser's escaping produces. */\nconst ESCAPED_PUNCTUATION = /\\\\([\\\\`*_{}[\\]()#+\\-.!|>~<])/g\n/** The only escapes the parser puts inside an inline code span. */\nconst ESCAPED_EMPHASIS = /\\\\([*_])/g\nconst INLINE_CODE = /(`+)(?!`)(.+?)(?<!`)\\1(?!`)/g\n\n/**\n * Undo the backend's escaping of a markdown artifact: `\\*\\*Scope\\.\\*\\*` becomes `**Scope.**`.\n *\n * THE RULE. Apply this ONLY to text of an artifact that was stored from markdown (an agent draft\n * or an edited version, always uploaded as `.md`): for those the parser escapes every markdown\n * punctuation character, including the backslash itself, so removing one level of escaping is the\n * exact inverse (an author's literal `\\*` is stored as `\\\\\\*` and comes back as `\\*`). Do not\n * apply it to a PDF or Word parse, where a backslash is just a character.\n *\n * Details:\n * - Only a backslash followed by markdown punctuation (``\\ ` * _ { } [ ] ( ) # + - . ! | > ~ <``)\n * is removed; `\\n`, `C:\\temp` and a trailing backslash are left alone.\n * - Pairs are read left to right, so `\\\\*` is an escaped backslash followed by a bare `*`.\n * - Fenced code blocks are never touched (the parser does not escape inside them).\n * - Inline code spans: the parser DOES escape `*` and `_` there (`` `a*b` `` comes back as\n * `` `a\\*b` ``), so only `\\*` and `\\_` are undone inside a span; any other backslash in code\n * (`` `re\\.x` ``) is a literal and stays.\n */\nexport function unescapeMarkdown(text: string): string {\n if (!text.includes('\\\\')) return text\n return mapOutsideFences(text, (line) => {\n if (!line.includes('\\\\')) return line\n let out = ''\n let last = 0\n for (const span of line.matchAll(INLINE_CODE)) {\n const at = span.index ?? 0\n out +=\n line.slice(last, at).replace(ESCAPED_PUNCTUATION, '$1') +\n span[0].replace(ESCAPED_EMPHASIS, '$1')\n last = at + span[0].length\n }\n return out + line.slice(last).replace(ESCAPED_PUNCTUATION, '$1')\n })\n}\n\n/**\n * The parser also mangles the TITLE of a stored markdown document (seen on a real backend): the\n * first heading comes back doubled (`## # Title`) or alone inside a code fence\n * (a fence, `# Title`, a fence). Both are repaired, on the first non-blank line only, so a code\n * block or heading later in the text is never touched. Like `unescapeMarkdown`, apply it only to\n * artifacts stored from markdown.\n */\nexport function repairParsedTitle(text: string): string {\n const lines = text.split('\\n')\n const first = lines.findIndex((l) => l.trim())\n if (first < 0) return text\n const doubled = /^#{1,6}\\s+(#{1,6}\\s+\\S.*)$/.exec(lines[first])\n if (doubled) {\n lines[first] = doubled[1]\n return lines.join('\\n')\n }\n if (/^\\s*```\\s*$/.test(lines[first]) && /^#{1,6}\\s+\\S/.test(lines[first + 1] ?? '')) {\n if (/^\\s*```\\s*$/.test(lines[first + 2] ?? '')) lines.splice(first + 2, 1)\n else return text\n lines.splice(first, 1)\n return lines.join('\\n')\n }\n return text\n}\n\nconst DOUBLED_HEADING = /^#{1,6}\\s+(#{1,6}\\s+\\S.*)$/\nconst LIST_HEADING = /^[-*+]\\s+(#{1,6}\\s+\\S.*)$/\nconst LIST_IN_LIST = /^[-*+]\\s+[-*+]\\s+(\\S.*)$/\nconst LIST_ORDINAL = /^[-*+]\\s+(\\d{1,9})([.)])\\s+(\\S.*)$/\nconst LIST_ITEM_LINE = /^\\s*(?:[-*+]|\\d{1,9}[.)])\\s/\nconst TABLE_DELIMITER_CELL = /^:?-{1,}:?$/\n\n/** `1. a 2. b 3. c` (one line) split where the next ordinal follows: `['1. a', '2. b', '3. c']`. */\nfunction splitRunOfOrdinals(first: number, delimiter: string, rest: string): string[] {\n const items: string[] = []\n let n = first\n let remaining = rest\n for (;;) {\n const next = new RegExp(`^(.+?)\\\\s+${n + 1}\\\\${delimiter}\\\\s+(\\\\S.*)$`).exec(remaining)\n if (!next) break\n items.push(`${n}${delimiter} ${next[1]}`)\n n += 1\n remaining = next[2]\n }\n items.push(`${n}${delimiter} ${remaining}`)\n return items\n}\n\n/**\n * A table the parser put on ONE line (`| h | h | |---|---| | a | b |`, rows joined by a space, which\n * leaves one empty cell between rows) back as a pipe table. `null` when the line is not that shape.\n */\nfunction rebuildFlatTable(line: string): string[] | null {\n const trimmed = line.trim()\n if (!trimmed.startsWith('|') || !trimmed.endsWith('|')) return null\n const cells = trimmed\n .slice(1, -1)\n .split('|')\n .map((c) => c.trim())\n const firstRule = cells.findIndex((c) => TABLE_DELIMITER_CELL.test(c))\n if (firstRule < 2 || cells[firstRule - 1] !== '') return null\n const columns = firstRule - 1\n const rows: string[][] = []\n for (let at = 0; at < cells.length; at += columns + 1) {\n const row = cells.slice(at, at + columns)\n const gap = cells[at + columns]\n if (row.length !== columns || (gap !== undefined && gap !== '')) return null\n rows.push(row)\n }\n const [header, rule, ...body] = rows\n if (!rule.every((c) => TABLE_DELIMITER_CELL.test(c))) return null\n const fmt = (row: string[]): string => `| ${row.join(' | ')} |`\n return [fmt(header), fmt(rule.map(() => '---')), ...body.map(fmt)]\n}\n\n/**\n * Undo how the backend's parse of a stored `.md` restructures it (seen on a real backend):\n * - a heading comes back doubled (`## # Title`) or as a list item (`- # Title`);\n * - every list item gets a `- ` of its own on top of the original marker, so `* a` returns as\n * `- * a` and `1. a` as `- 1. a`, which a markdown editor loads as a list inside a list item\n * (and saves as `- - a`); a run of ordinals can come back on one line (`- 1. a 2. b`);\n * - a table comes back on one line.\n * List nesting and the bullet/ordered difference of a flat `- x` cannot be recovered, so items\n * stay flat. Items of one list are kept tight (no blank line between them). Fenced code is\n * never touched. Like `unescapeMarkdown`, apply it only to artifacts stored from markdown.\n */\nexport function repairParsedStructure(text: string): string {\n const out: string[] = []\n let inFence = false\n for (const line of text.split('\\n')) {\n if (FENCE.test(line)) {\n inFence = !inFence\n out.push(line)\n continue\n }\n if (inFence) {\n out.push(line)\n continue\n }\n const table = rebuildFlatTable(line)\n if (table) {\n out.push(...table)\n continue\n }\n const heading = DOUBLED_HEADING.exec(line) ?? LIST_HEADING.exec(line)\n if (heading) {\n out.push(heading[1])\n continue\n }\n const ordinal = LIST_ORDINAL.exec(line)\n if (ordinal) {\n out.push(...splitRunOfOrdinals(Number(ordinal[1]), ordinal[2], ordinal[3]))\n continue\n }\n const nested = LIST_IN_LIST.exec(line)\n out.push(nested ? `- ${nested[1]}` : line)\n }\n // Items parsed as separate chunks arrive one blank line apart: that is one tight list.\n return out\n .filter(\n (line, i) =>\n !(\n line === '' &&\n LIST_ITEM_LINE.test(out[i - 1] ?? '') &&\n LIST_ITEM_LINE.test(out[i + 1] ?? '')\n )\n )\n .join('\\n')\n}\n\n// ---------------------------------------------------------------------------------------------\n// Going in: clean a streamed draft before it is stored\n// ---------------------------------------------------------------------------------------------\n\n/** `(*Source: Terms.pdf*)`, `(Sources: a, b)` and the italic form `*(Source: ...)*`. */\nconst SOURCE_NOTE =\n /[ \\t]*(?:\\*+\\(\\s*Sources?\\s*:[^)\\n]*\\)\\*+|\\(\\s*\\*{0,2}\\s*Sources?\\s*:[^)\\n]*\\))/gi\nconst CITE_TOKEN = /^\\]\\(#cite-[\\w-]+\\)/\n\n/**\n * Remove the citation links of ONE line and keep every word. A link is `[text](#cite-N)`, but the\n * model also writes brackets inside the text (`[We act for [PLACEHOLDER].](#cite-1)`) and links that\n * overlap other brackets, so a regex cannot find the opening bracket. This scans the line with a\n * stack of `[`: a `](#cite-N)` takes the nearest open `[` with it (both are removed, the text\n * between stays); a plain `]` closes the nearest `[`; a `](#cite-N)` with no open `[` loses only\n * the marker. Brackets that are not part of a link are never touched.\n */\nfunction removeCitationLinks(line: string): string {\n if (!line.includes('](#cite-')) return line\n const drop = new Set<number>()\n const open: number[] = []\n for (let i = 0; i < line.length; i++) {\n const c = line[i]\n if (c === '[') open.push(i)\n else if (c === ']') {\n const token = CITE_TOKEN.exec(line.slice(i, i + 40))\n if (token) {\n const opener = open.pop()\n if (opener !== undefined) drop.add(opener)\n for (let k = i; k < i + token[0].length; k++) drop.add(k)\n i += token[0].length - 1\n } else open.pop()\n }\n }\n let out = ''\n for (let i = 0; i < line.length; i++) if (!drop.has(i)) out += line[i]\n return out\n}\n\n/** A line whose `**` do not pair up (one half was wrapped into a link) loses the stray marks. */\nfunction balanceBold(line: string): string {\n // A bold-wrapped heading (`**# Title**`) is just a heading.\n if (/^\\s*\\*\\*#{1,6}\\s/.test(line)) return line.replace(/\\*\\*/g, '').trim()\n if ((line.match(/\\*\\*/g)?.length ?? 0) % 2 === 0) return line\n if (/^#{1,6}\\s/.test(line)) return line.replace(/\\*\\*/g, '')\n return line.replace(/\\*\\*\\s*$/, '').replace(/^(\\s*(?:[-*]\\s+)?)\\*\\*(?=\\s)/, '$1')\n}\n\n/**\n * Text for storage from text that carries citations: `normalizeCitationMarkup` first (it hoists\n * list, heading and bold tokens out of the link so unwrapping cannot orphan half of a `**` pair),\n * then `[text](#cite-N)` becomes `text`, `(*Source: ...*)` notes are dropped, and a bold or\n * heading marker that lost its partner is repaired. Fenced code is left alone.\n */\nexport function unwrapCitationLinks(text: string): string {\n const withoutNotes = mapOutsideFences(text, (line) => line.replace(SOURCE_NOTE, ''))\n return mapOutsideFences(normalizeCitationMarkup(withoutNotes), (line) => {\n const unlinked = removeCitationLinks(line)\n return unlinked === line ? line : balanceBold(unlinked)\n })\n}\n\nconst HEADING = /^#{1,6}\\s+\\S/\nconst HR_ONLY = /^\\s*(?:-{3,}|\\*{3,}|_{3,})\\s*$/\n/** A whole-line bold title: `**Client Engagement Letter**`. */\nconst BOLD_LINE = /^\\*\\*[^*#].*\\*\\*$/\nconst MAX_PREAMBLE_CHARS = 900\nconst MAX_PREAMBLE_PARAGRAPHS = 4\nconst MAX_TITLE_CHARS = 100\n\n/**\n * How a paragraph of agent narration opens. An ALLOW-LIST: a paragraph that opens any other way is\n * treated as document text and never removed.\n */\nconst NARRATION_OPENER =\n /^(?:I(?:['’](?:ll|ve|m|d))?\\s|let me\\b|here(?:['’]s| is| are)\\b|below is\\b|sure[,.! ]|certainly[,.! ]|of course[,.! ]|okay[,.! ]|based on (?:the|your|my)\\b|per the (?:user|instructions?)|as requested\\b|the workspace\\b|no (?:relevant |workspace |matching )?documents?\\b|there (?:are|is) no (?:relevant |workspace )?documents?\\b|after (?:reviewing|reading|searching)\\b)/i\n\n/** Structure a covering note would not have: lists, tables, quotes, code, headings, bold, links. */\nconst STRUCTURED = /^\\s*(?:[-*+>|]|\\d{1,9}[.)]\\s|#{1,6}\\s|```|~~~)|\\*\\*|\\]\\(/m\n\n/**\n * Cut the agent's narration written BEFORE the document. Strictly non-destructive: if in doubt the\n * text is returned whole (a stray sentence is easy to delete, a lost clause is not recoverable).\n *\n * Text is removed only when ALL of these hold:\n * 1. a real markdown heading line (`# Title`, any level) follows it, and the cut stops exactly at\n * the FIRST such line (never at a bold line, never at a line that merely contains `**`);\n * 2. what precedes it is at most 4 paragraphs and 900 characters of plain prose (horizontal rules\n * between them are ignored): no list, table, quote, code, heading, bold or link;\n * 3. EVERY paragraph opens with an allow-listed narration opener: first person (\"I'll ...\",\n * \"I now have ...\"), \"Let me\", \"Here is/are\", \"Below is\", \"Sure\", \"Based on the ...\", \"Per the\n * instructions\", \"As requested\", \"The workspace ...\", \"No (relevant) documents ...\", \"There is\n * no document ...\", \"After reviewing ...\".\n * Anything else (a dateline, an address, a salutation, a sentence of the letter) keeps the text whole.\n */\nexport function stripAgentPreamble(text: string): string {\n const lines = text.split('\\n')\n const start = lines.findIndex((l) => HEADING.test(l))\n if (start <= 0) return text\n const before = lines\n .slice(0, start)\n .filter((l) => !HR_ONLY.test(l))\n .join('\\n')\n .trim()\n if (!before) return lines.slice(start).join('\\n')\n const paragraphs = before.split(/\\n\\s*\\n/).map((p) => p.trim())\n const narration =\n before.length <= MAX_PREAMBLE_CHARS &&\n paragraphs.length <= MAX_PREAMBLE_PARAGRAPHS &&\n !STRUCTURED.test(before) &&\n paragraphs.every((p) => NARRATION_OPENER.test(p))\n return narration ? lines.slice(start).join('\\n') : text\n}\n\n/**\n * Make the document's title a real heading: the FIRST non-blank line of the text, when it is a\n * short whole-line bold title (`**Letter**`, even with a stray inner `**`), becomes `# Letter`.\n * Nothing else is ever promoted: not a later line, not a mid-sentence fragment (the title must\n * start with a capital or digit, be at most 100 characters, hold no sentence break and not end in\n * `,` `;` or `:`), and a document that already opens with a heading is left alone.\n */\nexport function promoteBoldTitle(text: string): string {\n const lines = text.split('\\n')\n const first = lines.findIndex((l) => l.trim())\n if (first < 0) return text\n const line = lines[first].trim()\n if (!BOLD_LINE.test(line)) return text\n const title = line.replace(/\\*\\*/g, '').trim()\n if (\n title.length === 0 ||\n title.length > MAX_TITLE_CHARS ||\n !/^[\\p{Lu}\\d]/u.test(title) ||\n /[,;:]$/.test(title) ||\n /[.!?]\\s+\\S/.test(title)\n ) {\n return text\n }\n lines[first] = `# ${title}`\n return lines.join('\\n')\n}\n\n/** Tidy headings only: strip stray bold marks from heading lines (`# **Title**`). */\nfunction cleanHeadings(text: string): string {\n return mapOutsideFences(text, (line) =>\n /^\\s*#{1,6}\\s/.test(line) ? line.replace(/\\*\\*/g, '').trim() : line\n )\n}\n\n/** Which stage of the cleanup produced the text that is returned. */\nexport type DraftCleanStage = 'cleaned' | 'unwrapped' | 'raw'\n\nexport interface DraftCleanReport {\n /** What to store. */\n text: string\n /**\n * `cleaned`: the full cleanup. `unwrapped`: only the citation links were removed (the preamble or\n * title step was rejected by the guard). `raw`: the input as streamed (even link removal was\n * rejected).\n */\n stage: DraftCleanStage\n /** Length of the returned text over the length of the input without its citation markup. */\n ratio: number\n /** Which steps changed the text before the guard (for logs). */\n changedBy: ('citations' | 'preamble' | 'title')[]\n /** The guard rejected a step because it would have lost content. */\n guarded: boolean\n}\n\nconst MIN_RATIO = 0.7\nconst countMatches = (text: string, re: RegExp): number => text.match(re)?.length ?? 0\nconst LIST_NUMBER = /^\\s*\\d{1,9}[.)]\\s/gm\nconst HEADING_LINE = /^#{1,6}\\s/gm\n/** The text with only its citation markup gone: the floor no cleanup may go far under. */\nconst withoutCitationMarkup = (raw: string): string =>\n mapOutsideFences(raw.replace(SOURCE_NOTE, ''), removeCitationLinks).trim()\nconst tidy = (text: string): string => text.replace(/\\n{3,}/g, '\\n\\n').trim()\n/** `after` is `before` with a leading part removed (a prefix cut, never a cut in the middle). */\nconst isPrefixCut = (before: string, after: string): boolean =>\n before.trimEnd().endsWith(after.trim())\n/** Nothing structural was lost: headings and numbered items are all still there. */\nconst keepsStructure = (candidate: string, reference: string): boolean =>\n countMatches(candidate, LIST_NUMBER) >= countMatches(reference, LIST_NUMBER) &&\n countMatches(candidate, HEADING_LINE) >= countMatches(reference, HEADING_LINE)\n\n/** The three text steps of the cleanup; replaceable so the guard can be tested. */\nexport interface DraftCleanSteps {\n unwrap: (text: string) => string\n strip: (text: string) => string\n promote: (text: string) => string\n}\nconst DEFAULT_CLEAN_STEPS: DraftCleanSteps = {\n unwrap: unwrapCitationLinks,\n strip: stripAgentPreamble,\n promote: promoteBoldTitle,\n}\n\n/**\n * `cleanDraftMarkdown` with a safety net and a report, for storing a streamed draft. Each stage is\n * accepted only if it provably cost nothing but narration and citation markup:\n * - links removed: at least 70% of the text length remains and no heading or numbered item is lost\n * (else `raw`, the input exactly as streamed);\n * - narration removed: only a pure prefix of the text may go, and nothing structural;\n * - title and heading tidy: at least 70% of the text remains and no heading or numbered item is lost.\n * A rejected stage falls back to the previous one (`cleaned` -> `unwrapped` -> `raw`).\n */\nexport function cleanDraftWithReport(\n raw: string,\n steps: DraftCleanSteps = DEFAULT_CLEAN_STEPS\n): DraftCleanReport {\n const floor = withoutCitationMarkup(raw)\n const ratio = (t: string): number => (floor.length ? t.length / floor.length : 1)\n const unwrapped = tidy(steps.unwrap(raw))\n const stripped = tidy(steps.strip(unwrapped))\n const titled = tidy(cleanHeadings(steps.promote(stripped)))\n const changedBy: DraftCleanReport['changedBy'] = []\n if (unwrapped !== raw.trim()) changedBy.push('citations')\n if (stripped !== unwrapped) changedBy.push('preamble')\n if (titled !== stripped) changedBy.push('title')\n\n const unwrappedOk = unwrapped.length >= MIN_RATIO * floor.length && keepsStructure(unwrapped, raw)\n if (!unwrappedOk) return { text: raw, stage: 'raw', ratio: 1, changedBy, guarded: true }\n const strippedOk =\n stripped === unwrapped ||\n (isPrefixCut(unwrapped, stripped) && keepsStructure(stripped, unwrapped))\n const titledOk = titled.length >= MIN_RATIO * stripped.length && keepsStructure(titled, stripped)\n if (strippedOk && titledOk) {\n return { text: titled, stage: 'cleaned', ratio: ratio(titled), changedBy, guarded: false }\n }\n return { text: unwrapped, stage: 'unwrapped', ratio: ratio(unwrapped), changedBy, guarded: true }\n}\n\n/**\n * Everything a streamed draft needs before it is stored as the artifact's first version:\n * `unwrapCitationLinks`, `stripAgentPreamble`, `promoteBoldTitle`, clean headings, collapsed blank\n * runs, trimmed, under the guard of `cleanDraftWithReport` (use it to know which stage was kept).\n */\nexport function cleanDraftMarkdown(raw: string): string {\n return cleanDraftWithReport(raw).text\n}\n"]}
@@ -4,6 +4,7 @@ var chunkOBNTJEEO_cjs = require('./chunk-OBNTJEEO.cjs');
4
4
  var chunkS6A6FSG7_cjs = require('./chunk-S6A6FSG7.cjs');
5
5
  var sonner = require('sonner');
6
6
  var zustand = require('zustand');
7
+ var react = require('react');
7
8
  var lucideReact = require('lucide-react');
8
9
  var jsxRuntime = require('react/jsx-runtime');
9
10
 
@@ -100,6 +101,7 @@ var GLYPH = {
100
101
  function NotificationBell({
101
102
  renderTrigger,
102
103
  onNavigate,
104
+ onSelectNotification,
103
105
  onMarkRead,
104
106
  onMarkAllRead,
105
107
  muted = false,
@@ -112,13 +114,14 @@ function NotificationBell({
112
114
  side = "bottom",
113
115
  align = "end"
114
116
  }) {
117
+ const [open, setOpen] = react.useState(false);
115
118
  const notifications = useNotify((s) => s.notifications);
116
119
  const unread = useNotify(selectUnread);
117
120
  const markAllRead = useNotify((s) => s.markAllRead);
118
121
  const markRead = useNotify((s) => s.markRead);
119
122
  const tone = (v) => toneClassNames?.[v] ?? DEFAULT_NOTIFY_TONE[v];
120
123
  const visible = notifications.filter((n) => !n.ambient);
121
- return /* @__PURE__ */ jsxRuntime.jsxs(chunkOBNTJEEO_cjs.DropdownMenu, { children: [
124
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkOBNTJEEO_cjs.DropdownMenu, { open, onOpenChange: setOpen, children: [
122
125
  /* @__PURE__ */ jsxRuntime.jsx(chunkOBNTJEEO_cjs.DropdownMenuTrigger, { asChild: true, children: renderTrigger ? renderTrigger({
123
126
  unread,
124
127
  ariaLabel: `Notifications${unread ? `, ${unread} unread` : ""}`,
@@ -150,7 +153,7 @@ function NotificationBell({
150
153
  side,
151
154
  sideOffset: 8,
152
155
  collisionPadding: 12,
153
- className: "w-[360px] rounded-lg border-border/60 p-0 shadow-lg",
156
+ className: "w-60 rounded-lg border-border/60 p-0 shadow-lg",
154
157
  "data-testid": `${testId}-panel`,
155
158
  "data-topbar-popover": "",
156
159
  children: [
@@ -214,6 +217,11 @@ function NotificationBell({
214
217
  onClick: () => {
215
218
  markRead(n.id);
216
219
  if (!n.read) onMarkRead?.(n.id);
220
+ setOpen(false);
221
+ if (onSelectNotification) {
222
+ onSelectNotification(n);
223
+ return;
224
+ }
217
225
  if (n.onSelect) n.onSelect();
218
226
  else if (n.href) onNavigate?.(n.href);
219
227
  },
@@ -282,5 +290,5 @@ exports.notify = notify;
282
290
  exports.seedNotifications = seedNotifications;
283
291
  exports.selectUnread = selectUnread;
284
292
  exports.useNotify = useNotify;
285
- //# sourceMappingURL=chunk-YSZJCWDD.cjs.map
286
- //# sourceMappingURL=chunk-YSZJCWDD.cjs.map
293
+ //# sourceMappingURL=chunk-Z4M7JB4L.cjs.map
294
+ //# sourceMappingURL=chunk-Z4M7JB4L.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/notifications/notify-store.ts","../src/lib/format-relative-time.ts","../src/notifications/NotificationBell.tsx","../src/notifications/Toaster.tsx"],"names":["create","toast","CheckCircle2","XCircle","AlertTriangle","Info","useState","jsxs","DropdownMenu","jsx","DropdownMenuTrigger","Bell","DropdownMenuContent","CheckCheck","cn","BellOff","DropdownMenuItem","X","ScrollArea","Sonner"],"mappings":"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","file":"chunk-Z4M7JB4L.cjs","sourcesContent":["/**\n * App notification store — the one shared toast + notification-centre. A single\n * `notify.*` call pops a transient toast (rendered by <Toaster/>, on sonner) and,\n * unless `{ record: false }`, records a persistent entry for the topbar bell.\n *\n * notify.success('Saved') // toast + centre entry\n * notify.error('Upload failed', { record: false }) // toast only\n *\n * sonner owns the transient toast lifecycle (stacking, timing, dismissal); this\n * store owns only the persistent centre history (what the <NotificationBell/>\n * shows). Brand-neutral: no seed data (inject via `seedNotifications`), no app\n * imports. For full sonner power (custom content, `toast.dismiss`, …) the raw\n * `toast` is re-exported.\n */\nimport { type ReactNode } from 'react'\n// This module IS the sanctioned toast engine home — the app-level rule that\n// steers callers to sendNotification()/notify() doesn't apply here.\n// eslint-disable-next-line no-restricted-imports\nimport { toast } from 'sonner'\nimport { create } from 'zustand'\n\nexport { toast }\n\nexport type NotifyVariant = 'success' | 'error' | 'info' | 'warning'\n\nexport interface AppNotification {\n id: string\n title: string\n description?: string\n variant: NotifyVariant\n /** Epoch ms the entry was recorded. */\n ts: number\n read: boolean\n /** Optional in-app link the entry deep-links to (passed to the bell's onNavigate). */\n href?: string\n /** Optional click action — wins over `href` when both are present. Session\n * history only; entries are never serialized, so a closure is safe here. */\n onSelect?: () => void\n /** Routine session activity (\"Opening workspace…\", \"Saved\") — kept for the\n * log but not something that demands attention: excluded from the unread\n * badge and from the bell's default list (shown under \"All activity\"). */\n ambient?: boolean\n /** Where the entry comes from. Session entries (`record`) have none; a\n * backend bridge stamps its own (e.g. 'server') so {@link syncSource} can\n * replace exactly its slice on every refetch without touching the rest. */\n source?: string\n}\n\nexport interface NotifyOptions {\n description?: string\n /** Also record a persistent notification-centre entry (default true). */\n record?: boolean\n href?: string\n duration?: number\n /** A toast action button (sonner). */\n action?: { label: ReactNode; onClick: () => void }\n /** Override the toast glyph (sonner). */\n icon?: ReactNode\n /** Record as routine session activity (see {@link AppNotification.ambient}). */\n ambient?: boolean\n}\n\ninterface NotifyState {\n notifications: AppNotification[]\n markRead: (id: string) => void\n markAllRead: () => void\n removeNotification: (id: string) => void\n clearNotifications: () => void\n /** Replace the centre's history (e.g. seed a demo/initial set). */\n seed: (items: AppNotification[]) => void\n /** Record a centre entry (used by `notify.*`; sonner renders the toast). */\n record: (note: AppNotification) => void\n /** Reconcile one source's slice with fresh truth (e.g. a backend list on\n * every refetch): entries stamped with `source` are replaced wholesale —\n * including their read state, which the source owns — while entries from\n * other sources (session activity) stay untouched. Newest first. */\n syncSource: (source: string, items: AppNotification[]) => void\n}\n\nlet seq = 0\nconst uid = () => `n${Date.now().toString(36)}${(seq++).toString(36)}`\n\nexport const useNotify = create<NotifyState>((set) => ({\n notifications: [],\n markRead: (id) =>\n set((s) => ({\n notifications: s.notifications.map((n) => (n.id === id ? { ...n, read: true } : n)),\n })),\n markAllRead: () =>\n set((s) => ({ notifications: s.notifications.map((n) => ({ ...n, read: true })) })),\n removeNotification: (id) =>\n set((s) => ({ notifications: s.notifications.filter((n) => n.id !== id) })),\n clearNotifications: () => set({ notifications: [] }),\n seed: (items) => set({ notifications: items }),\n record: (note) => set((s) => ({ notifications: [note, ...s.notifications].slice(0, 50) })),\n syncSource: (source, items) =>\n set((s) => ({\n notifications: [\n ...items.map((n) => ({ ...n, source })),\n ...s.notifications.filter((n) => n.source !== source),\n ]\n .sort((a, b) => b.ts - a.ts)\n .slice(0, 100),\n })),\n}))\n\n/** Ergonomic helper — `notify.success('Saved')` — toast (sonner) + optional centre entry. */\nfunction make(variant: NotifyVariant) {\n return (title: string, opts: NotifyOptions = {}): string => {\n toast[variant](title, {\n description: opts.description,\n duration: opts.duration,\n action: opts.action,\n icon: opts.icon,\n })\n const id = uid()\n if (opts.record !== false) {\n useNotify.getState().record({\n id,\n title,\n description: opts.description,\n variant,\n ts: Date.now(),\n read: false,\n href: opts.href,\n ambient: opts.ambient,\n })\n }\n return id\n }\n}\nexport const notify = {\n success: make('success'),\n error: make('error'),\n info: make('info'),\n warning: make('warning'),\n}\n\n/** Replace the notification centre's history — inject a seed/initial set. */\nexport function seedNotifications(items: AppNotification[]): void {\n useNotify.getState().seed(items)\n}\n\n/** Unread count selector for the topbar bell — ambient session activity never\n * demands attention, so it never counts. */\nexport const selectUnread = (s: NotifyState): number =>\n s.notifications.filter((n) => !n.read && !n.ambient).length\n\n/** Default glyph colour per variant (raw palette, override via `toneClassNames`). */\nexport const DEFAULT_NOTIFY_TONE: Record<NotifyVariant, string> = {\n success: 'text-green-600',\n error: 'text-destructive',\n warning: 'text-amber-500',\n info: 'text-blue-500',\n}\n","/** Relative-time formatting shared by the notification bell and the DM kit (no type imports, so the\n * SDK-free `/shell` entry can use it). */\n\nconst RELATIVE = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' })\nconst DIVISIONS: Array<{ amount: number; unit: Intl.RelativeTimeFormatUnit }> = [\n { amount: 60, unit: 'seconds' },\n { amount: 60, unit: 'minutes' },\n { amount: 24, unit: 'hours' },\n { amount: 7, unit: 'days' },\n { amount: 4.34524, unit: 'weeks' },\n { amount: 12, unit: 'months' },\n { amount: Number.POSITIVE_INFINITY, unit: 'years' },\n]\n\n/** Compact relative time, e.g. \"2 hours ago\", \"just now\". */\nexport function formatRelativeTime(iso: string): string {\n const then = Date.parse(iso)\n if (Number.isNaN(then)) return ''\n let duration = (then - Date.now()) / 1000\n if (Math.abs(duration) < 45) return 'just now'\n for (const division of DIVISIONS) {\n if (Math.abs(duration) < division.amount) {\n return RELATIVE.format(Math.round(duration), division.unit)\n }\n duration /= division.amount\n }\n return ''\n}\n","/**\n * NotificationBell — the topbar notification centre: a bell with an unread badge\n * that opens a dropdown of recorded entries (newest first) with an unread dot,\n * relative time and optional deep-link. \"Mark all read\" clears the badge. Backed\n * by the shared {@link useNotify} store (the same one the <Toaster/> renders).\n *\n * Firm-agnostic: navigation is a callback (`onNavigate`), styling tracks semantic\n * tokens, and per-variant glyph colours are overridable via `toneClassNames`.\n */\nimport { useState, type ReactElement } from 'react'\nimport {\n Bell,\n BellOff,\n CheckCheck,\n CheckCircle2,\n AlertTriangle,\n XCircle,\n Info,\n X,\n} from 'lucide-react'\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n} from '../ui/dropdown-menu'\nimport { ScrollArea } from '../ui/scroll-area'\nimport { cn } from '../lib/utils'\nimport { formatRelativeTime } from '../lib/format-relative-time'\nimport {\n useNotify,\n selectUnread,\n DEFAULT_NOTIFY_TONE,\n type NotifyVariant,\n type AppNotification,\n} from './notify-store'\n\nconst GLYPH: Record<NotifyVariant, typeof Info> = {\n success: CheckCircle2,\n error: XCircle,\n warning: AlertTriangle,\n info: Info,\n}\n\n/** What a custom bell trigger needs to render itself. */\nexport interface NotificationBellTriggerState {\n /** Unread count (0 when none). */\n unread: number\n /** Accessible name, including the count: \"Notifications, 2 unread\". */\n ariaLabel: string\n testId: string\n}\n\nexport interface NotificationBellProps {\n /**\n * Replaces the default icon button with the host's own trigger (for example a labelled sidebar\n * row). It must forward its ref and rest props: it is mounted as the dropdown trigger.\n */\n renderTrigger?: (state: NotificationBellTriggerState) => ReactElement\n /** Called with an entry's `href` when it's clicked (e.g. router navigate). */\n onNavigate?: (href: string) => void\n /** Open this entry in the host notification centre instead of following its link. */\n onSelectNotification?: (notification: AppNotification) => void\n /** Called after an entry is locally marked read — the hook for a backend\n * bridge to propagate read state upstream (filter by the ids it owns). */\n onMarkRead?: (id: string) => void\n /** Called after \"Mark all read\" — same upstream-propagation hook. */\n onMarkAllRead?: () => void\n /** Toast muting — the bell is where notification behaviour is controlled, so\n * the mute switch lives in its header. Omit `onToggleMute` to hide it. */\n muted?: boolean\n onToggleMute?: () => void\n /** Override per-variant glyph colours (e.g. brand emerald for success). */\n toneClassNames?: Partial<Record<NotifyVariant, string>>\n emptyText?: string\n /** Footer link to the app's full notification surface. Omit to hide. */\n onViewAll?: () => void\n viewAllLabel?: string\n testId?: string\n /** Where the panel opens relative to the bell (a sidebar-footer bell opens upward). */\n side?: 'top' | 'right' | 'bottom' | 'left'\n align?: 'start' | 'center' | 'end'\n}\n\nexport function NotificationBell({\n renderTrigger,\n onNavigate,\n onSelectNotification,\n onMarkRead,\n onMarkAllRead,\n muted = false,\n onToggleMute,\n toneClassNames,\n emptyText = \"You're all caught up.\",\n onViewAll,\n viewAllLabel = 'View all',\n testId = 'notifications',\n side = 'bottom',\n align = 'end',\n}: NotificationBellProps) {\n const [open, setOpen] = useState(false)\n const notifications = useNotify((s) => s.notifications)\n const unread = useNotify(selectUnread)\n const markAllRead = useNotify((s) => s.markAllRead)\n const markRead = useNotify((s) => s.markRead)\n const tone = (v: NotifyVariant) => toneClassNames?.[v] ?? DEFAULT_NOTIFY_TONE[v]\n\n // Ambient entries (routine session activity — \"Opening workspace…\") are kept\n // for the log but never surfaced in the bell panel: they never badge and are\n // always filtered out here.\n const visible = notifications.filter((n) => !n.ambient)\n\n return (\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger asChild>\n {renderTrigger ? (\n renderTrigger({\n unread,\n ariaLabel: `Notifications${unread ? `, ${unread} unread` : ''}`,\n testId,\n })\n ) : (\n <button\n className=\"relative flex size-9 pointer-coarse:size-11 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n data-testid={testId}\n aria-label={`Notifications${unread ? `, ${unread} unread` : ''}`}\n title=\"Notifications\"\n >\n <Bell className=\"size-5\" />\n {unread > 0 && (\n <span\n className=\"absolute -right-0.5 -top-0.5 flex min-w-4 items-center justify-center rounded-full bg-primary px-1 text-xs font-semibold leading-4 text-primary-foreground\"\n data-testid={`${testId}-badge`}\n >\n {unread > 9 ? '9+' : unread}\n </span>\n )}\n </button>\n )}\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align={align}\n side={side}\n sideOffset={8}\n collisionPadding={12}\n className=\"w-60 rounded-lg border-border/60 p-0 shadow-lg\"\n data-testid={`${testId}-panel`}\n data-topbar-popover=\"\"\n >\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-3.5 py-2.5 pointer-coarse:py-0\">\n <p className=\"text-sm font-semibold text-foreground\">Notifications</p>\n <div className=\"flex items-center gap-3 pointer-coarse:gap-1\">\n {unread > 0 && (\n <button\n onClick={() => {\n markAllRead()\n onMarkAllRead?.()\n }}\n className=\"flex items-center gap-1 text-xs font-medium text-primary transition-colors hover:opacity-80 pointer-coarse:min-h-11 pointer-coarse:px-2\"\n data-testid={`${testId}-mark-all`}\n >\n <CheckCheck className=\"size-3.5\" /> Mark all read\n </button>\n )}\n {onToggleMute && (\n <button\n onClick={onToggleMute}\n aria-pressed={muted}\n title={muted ? 'Unmute notifications' : 'Mute notifications'}\n aria-label={muted ? 'Unmute notifications' : 'Mute notifications'}\n className={cn(\n 'flex size-6 items-center justify-center rounded-md transition-colors hover:bg-accent pointer-coarse:size-11',\n muted ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'\n )}\n data-testid={`${testId}-mute`}\n >\n <BellOff className=\"size-3.5\" />\n </button>\n )}\n {/* Explicit close — the dropdown otherwise only dismisses via\n tap-outside/Escape, which isn't discoverable on touch and (at\n mobile width, see blocks.css) the panel covers most\n of the screen so there's nothing to tap outside of. Radix\n closes a DropdownMenu on any item select by default, so a\n plain item with no other effect doubles as a close button. */}\n <DropdownMenuItem\n className=\"flex size-6 items-center justify-center rounded-md p-0 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus:bg-accent pointer-coarse:size-11\"\n aria-label=\"Close notifications\"\n data-testid={`${testId}-close`}\n >\n <X className=\"size-3.5\" />\n </DropdownMenuItem>\n </div>\n </div>\n {muted && (\n <p\n className=\"border-b border-border/60 bg-amber-500/10 px-3.5 py-1.5 text-xs text-muted-foreground\"\n data-testid={`${testId}-muted-note`}\n >\n Toasts are muted — everything still lands here.\n </p>\n )}\n\n {visible.length === 0 ? (\n <div className=\"px-3.5 py-10 text-center text-sm text-muted-foreground\">{emptyText}</div>\n ) : (\n <ScrollArea className=\"max-h-[380px]\">\n <ul data-testid={`${testId}-list`}>\n {visible.map((n) => {\n const Glyph = GLYPH[n.variant]\n return (\n <li key={n.id}>\n <button\n onClick={() => {\n markRead(n.id)\n if (!n.read) onMarkRead?.(n.id)\n setOpen(false)\n if (onSelectNotification) {\n onSelectNotification(n)\n return\n }\n // The specific action wins over the generic deep link.\n if (n.onSelect) n.onSelect()\n else if (n.href) onNavigate?.(n.href)\n }}\n className={cn(\n 'flex w-full items-start gap-3 border-b border-border/60 px-3.5 py-3 text-left transition-colors hover:bg-accent',\n !n.read && 'bg-accent/40'\n )}\n data-testid={`${testId}-item`}\n data-notification-id={n.id}\n >\n <Glyph className={cn('mt-0.5 size-4 shrink-0', tone(n.variant))} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium leading-snug text-foreground\">\n {n.title}\n </p>\n {n.description && (\n <p className=\"mt-0.5 line-clamp-2 text-xs leading-relaxed text-muted-foreground\">\n {n.description}\n </p>\n )}\n <p className=\"mt-1 text-xs text-muted-foreground/80\">\n {formatRelativeTime(new Date(n.ts).toISOString())}\n </p>\n </div>\n {!n.read && (\n <span className=\"mt-1.5 size-2 shrink-0 rounded-full bg-primary\" />\n )}\n </button>\n </li>\n )\n })}\n </ul>\n </ScrollArea>\n )}\n {onViewAll && (\n // A real menu item, not a bare button: selecting it must CLOSE the\n // dropdown on its way to the full surface.\n <DropdownMenuItem\n onClick={onViewAll}\n className=\"justify-center rounded-none border-t border-border px-3.5 py-2.5 text-xs font-medium text-primary focus:text-primary pointer-coarse:min-h-11\"\n data-testid={`${testId}-view-all`}\n >\n {viewAllLabel}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n","/**\n * Toaster — the one shared toast surface, built on sonner (the mature engine:\n * stacking, swipe-to-dismiss, a11y, timing). Mount once near the app root; any\n * code then calls `notify.*(...)` (or the re-exported `toast`) from anywhere.\n *\n * Firm-agnostic: every sonner `ToasterProps` passes through, so a consumer sets\n * its own `position` / `theme` / `toastOptions`. The defaults give a neutral\n * shadcn-token card that both apps can override.\n */\nimport { Toaster as Sonner, type ToasterProps } from 'sonner'\n\nexport type { ToasterProps }\n\nconst DEFAULT_TOAST_OPTIONS: ToasterProps['toastOptions'] = {\n classNames: {\n toast:\n 'group toast group-[.toaster]:bg-card group-[.toaster]:text-foreground group-[.toaster]:border group-[.toaster]:border-border group-[.toaster]:shadow-lg group-[.toaster]:rounded-lg',\n description: 'group-[.toast]:text-muted-foreground',\n actionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',\n cancelButton: 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground',\n },\n}\n\nexport function Toaster({ toastOptions, ...props }: ToasterProps) {\n return (\n <Sonner\n className=\"toaster group\"\n toastOptions={toastOptions ?? DEFAULT_TOAST_OPTIONS}\n {...props}\n />\n )\n}\n"]}
@@ -89,6 +89,8 @@ interface NotificationBellProps {
89
89
  renderTrigger?: (state: NotificationBellTriggerState) => ReactElement;
90
90
  /** Called with an entry's `href` when it's clicked (e.g. router navigate). */
91
91
  onNavigate?: (href: string) => void;
92
+ /** Open this entry in the host notification centre instead of following its link. */
93
+ onSelectNotification?: (notification: AppNotification) => void;
92
94
  /** Called after an entry is locally marked read — the hook for a backend
93
95
  * bridge to propagate read state upstream (filter by the ids it owns). */
94
96
  onMarkRead?: (id: string) => void;
@@ -109,7 +111,7 @@ interface NotificationBellProps {
109
111
  side?: 'top' | 'right' | 'bottom' | 'left';
110
112
  align?: 'start' | 'center' | 'end';
111
113
  }
112
- declare function NotificationBell({ renderTrigger, onNavigate, onMarkRead, onMarkAllRead, muted, onToggleMute, toneClassNames, emptyText, onViewAll, viewAllLabel, testId, side, align, }: NotificationBellProps): React.JSX.Element;
114
+ declare function NotificationBell({ renderTrigger, onNavigate, onSelectNotification, onMarkRead, onMarkAllRead, muted, onToggleMute, toneClassNames, emptyText, onViewAll, viewAllLabel, testId, side, align, }: NotificationBellProps): React.JSX.Element;
113
115
 
114
116
  declare function Toaster({ toastOptions, ...props }: ToasterProps): React.JSX.Element;
115
117
 
@@ -89,6 +89,8 @@ interface NotificationBellProps {
89
89
  renderTrigger?: (state: NotificationBellTriggerState) => ReactElement;
90
90
  /** Called with an entry's `href` when it's clicked (e.g. router navigate). */
91
91
  onNavigate?: (href: string) => void;
92
+ /** Open this entry in the host notification centre instead of following its link. */
93
+ onSelectNotification?: (notification: AppNotification) => void;
92
94
  /** Called after an entry is locally marked read — the hook for a backend
93
95
  * bridge to propagate read state upstream (filter by the ids it owns). */
94
96
  onMarkRead?: (id: string) => void;
@@ -109,7 +111,7 @@ interface NotificationBellProps {
109
111
  side?: 'top' | 'right' | 'bottom' | 'left';
110
112
  align?: 'start' | 'center' | 'end';
111
113
  }
112
- declare function NotificationBell({ renderTrigger, onNavigate, onMarkRead, onMarkAllRead, muted, onToggleMute, toneClassNames, emptyText, onViewAll, viewAllLabel, testId, side, align, }: NotificationBellProps): React.JSX.Element;
114
+ declare function NotificationBell({ renderTrigger, onNavigate, onSelectNotification, onMarkRead, onMarkAllRead, muted, onToggleMute, toneClassNames, emptyText, onViewAll, viewAllLabel, testId, side, align, }: NotificationBellProps): React.JSX.Element;
113
115
 
114
116
  declare function Toaster({ toastOptions, ...props }: ToasterProps): React.JSX.Element;
115
117
 
@@ -6,7 +6,7 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
6
6
  import { VariantProps } from 'class-variance-authority';
7
7
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
8
8
  import * as lucide_react from 'lucide-react';
9
- import { LucideIcon, StickyNote } from 'lucide-react';
9
+ import { LucideIcon, LucideProps, StickyNote } from 'lucide-react';
10
10
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
11
11
  import * as DialogPrimitive from '@radix-ui/react-dialog';
12
12
  import { DialogProps } from '@radix-ui/react-dialog';
@@ -106,6 +106,8 @@ interface SharedItem {
106
106
  is_shared?: boolean | null;
107
107
  }
108
108
  interface VisibilityToggleProps {
109
+ /** Explicit Me / Workspace selector for creation forms. */
110
+ presentation?: 'toggle' | 'select';
109
111
  /** Single item or array of items with shared/is_shared field */
110
112
  items: SharedItem | SharedItem[];
111
113
  /** Called with true to share, false to unshare */
@@ -126,7 +128,7 @@ interface VisibilityToggleProps {
126
128
  workspaceLabel?: string;
127
129
  'data-testid'?: string;
128
130
  }
129
- declare function VisibilityToggle({ items, onToggle, disabled, disabledTooltip, disablePrivate, showLabel, showTooltip, tooltipActive, tooltipInactive, tooltipMixed, label, workspaceLabel, 'data-testid': dataTestId, }: VisibilityToggleProps): React$1.JSX.Element;
131
+ declare function VisibilityToggle({ items, presentation, onToggle, disabled, disabledTooltip, disablePrivate, showLabel, showTooltip, tooltipActive, tooltipInactive, tooltipMixed, label, workspaceLabel, 'data-testid': dataTestId, }: VisibilityToggleProps): React$1.JSX.Element;
130
132
 
131
133
  /**
132
134
  * DictateContext
@@ -297,7 +299,7 @@ declare const DialogOverlay: React$1.ForwardRefExoticComponent<Omit<DialogPrimit
297
299
  * - `sheet`: bottom sheet, full width, rounded top corners (forms and pickers).
298
300
  * - `full`: full-height sheet that stops below the status bar (large editors, wizards).
299
301
  */
300
- type DialogPresentation = 'center' | 'sheet' | 'full';
302
+ type DialogPresentation = 'center' | 'sheet' | 'full' | 'right';
301
303
  declare const DialogContent: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & {
302
304
  hideCloseButton?: boolean;
303
305
  /** Phone presentation (see {@link DialogPresentation}). Defaults to `center`. */
@@ -364,7 +366,7 @@ interface MarkMenuProps extends Omit<HTMLAttributes<HTMLElement>, 'children' | '
364
366
  * Keyboard: Enter/Space/ArrowDown open it and move into it, arrows move, Escape closes and
365
367
  * returns focus to the mark. Rows are 44px high on coarse pointers.
366
368
  */
367
- declare function MarkMenu({ as, href, items, preview, menuLabel, shouldClickRunPrimary, openDelay, closeDelay, testId, menuTestId, triggerRef: externalRef, className, children, onPointerDown, onPointerEnter, onPointerLeave, onFocus, onBlur, onKeyDown, ...rest }: MarkMenuProps): React$1.JSX.Element;
369
+ declare function MarkMenu({ as, href, items, preview, menuLabel, shouldClickRunPrimary, openDelay, closeDelay, testId, menuTestId, triggerRef: externalRef, className, children, onPointerDown, onPointerEnter, onPointerMove, onPointerLeave, onFocus, onBlur, onKeyDown, ...rest }: MarkMenuProps): React$1.JSX.Element;
368
370
 
369
371
  declare const DropdownMenu: React$1.FC<DropdownMenuPrimitive.DropdownMenuProps>;
370
372
  declare const DropdownMenuTrigger: React$1.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
@@ -630,11 +632,17 @@ interface PassageCardProps {
630
632
  }
631
633
  declare function PassageCard({ header, score, headerRight, active, onClick, footer, className, children, 'data-testid': testId, }: PassageCardProps): React__default.JSX.Element;
632
634
 
635
+ /** Thread visibility uses both shape and color across entity labels and grids. */
636
+ declare function ThreadVisibilityIcon({ shared, className, ...props }: LucideProps & {
637
+ shared: boolean;
638
+ }): React$1.JSX.Element;
639
+
633
640
  /**
634
641
  * EntityPill Component
635
642
  *
636
643
  * Base component for pill-style entity displays. Provides consistent styling and
637
- * interaction patterns. Promoted verbatim from the ARBI app (import paths only
644
+ * interaction patterns. At rest it is plain icon + text (no fill, no border); the
645
+ * fill appears on hover, so a row of entities does not read as a row of buttons. Promoted verbatim from the ARBI app (import paths only
638
646
  * changed to resolve within the SDK).
639
647
  *
640
648
  * Pattern: [Icon] [Label] [Optional: secondary text] [MoreVertical when interactive]
@@ -735,6 +743,8 @@ interface DocumentEntityProps {
735
743
  viewing?: boolean;
736
744
  /** Small overlay pinned to the icon's corner (e.g. an "available offline" pip). */
737
745
  iconBadge?: React__default.ReactNode;
746
+ /** Small content right after the name, inside the click area (e.g. a status glyph). */
747
+ status?: React__default.ReactNode;
738
748
  /** Trailing control rendered outside the click area (e.g. a ⋯ actions menu). */
739
749
  actions?: React__default.ReactNode;
740
750
  /** When true, the pill fills the available width and the name truncates via
@@ -751,7 +761,7 @@ interface DocumentEntityProps {
751
761
  /** Forwarded to the pill so a surface can address this document's chip. */
752
762
  'data-testid'?: string;
753
763
  }
754
- declare function DocumentEntity({ doc, icon, size, labelMaxWidth, labelClassName, onClick, onIconClick, viewing, iconBadge, actions, tooltipContent, className, fullWidth, noClamp, 'data-testid': testId, }: DocumentEntityProps): React__default.JSX.Element;
764
+ declare function DocumentEntity({ doc, icon, size, labelMaxWidth, labelClassName, onClick, onIconClick, viewing, iconBadge, status, actions, tooltipContent, className, fullWidth, noClamp, 'data-testid': testId, }: DocumentEntityProps): React__default.JSX.Element;
755
765
 
756
766
  /**
757
767
  * TagEntity Component
@@ -886,6 +896,8 @@ interface UserEntityProps {
886
896
  displayName?: string;
887
897
  /** Avatar image URL, if any. */
888
898
  picture?: string | null;
899
+ /** Optional image treatment for platform logos inside the normal avatar. */
900
+ avatarImageClassName?: string;
889
901
  /** Avatar background colour class for non-agents (e.g. 'bg-blue-500'). */
890
902
  colorClass?: string;
891
903
  /** Whether this user is an agent — drives the dashed ring + bot badge. */
@@ -1410,4 +1422,4 @@ declare function DocumentCard({ doc, thumbnailUrl, status, selected, onToggleSel
1410
1422
 
1411
1423
  declare function cn(...inputs: ClassValue[]): string;
1412
1424
 
1413
- export { DropdownMenuLabel as $, AgentBadge as A, BASE_COLORS as B, Card as C, CommandShortcut as D, Dialog as E, DialogClose as F, DialogContent as G, DialogDescription as H, DialogFooter as I, DialogHeader as J, DialogOverlay as K, DialogPortal as L, type DialogPresentation as M, DialogTitle as N, DialogTrigger as O, type DictateContextValue as P, DictateProvider as Q, DocumentCard as R, type DocumentCardProps as S, DocumentEntity as T, type DocumentEntityProps as U, type DocumentLike as V, DropdownMenu as W, DropdownMenuCheckboxItem as X, DropdownMenuContent as Y, DropdownMenuGroup as Z, DropdownMenuItem as _, AiMarkdown as a, type StatusBadgeProps as a$, DropdownMenuPortal as a0, DropdownMenuRadioGroup as a1, DropdownMenuRadioItem as a2, DropdownMenuSeparator as a3, DropdownMenuShortcut as a4, DropdownMenuSub as a5, DropdownMenuSubContent as a6, DropdownMenuSubTrigger as a7, DropdownMenuTrigger as a8, ENTITY_MAPPINGS as a9, PopoverTrigger as aA, type PresenceDisplayStatus as aB, PresenceLabel as aC, Progress as aD, ProjectEntity as aE, type ProjectEntityProps as aF, type ProjectRelation as aG, RadioGroup as aH, RadioGroupItem as aI, type Rag as aJ, RagDot as aK, RelevanceDot as aL, ScrollArea as aM, ScrollBar as aN, Select as aO, SelectContent as aP, SelectGroup as aQ, SelectItem as aR, SelectLabel as aS, SelectScrollDownButton as aT, SelectScrollUpButton as aU, SelectSeparator as aV, SelectTrigger as aW, SelectValue as aX, Separator as aY, Slider as aZ, type StatusBadgeComponent as a_, EntityIcon as aa, type EntityIconComponent as ab, EntityPill as ac, type EntityRegistryOverride as ad, type EntityType as ae, HoverCard as af, HoverCardContent as ag, HoverCardTrigger as ah, IconToggle as ai, type IconToggleProps as aj, Input as ak, type InputProps as al, Label as am, MarkMenu as an, type MarkMenuItem as ao, type MarkMenuProps as ap, MarkdownRenderer as aq, type MarkdownRendererProps as ar, MarkdownStreamingContext as as, NEUTRAL_GRAY as at, PLACEHOLDER_COLOR as au, PassageCard as av, type PassageCardProps as aw, Popover as ax, PopoverAnchor as ay, PopoverContent as az, Avatar as b, StatusPill as b0, type StatusPillProps as b1, type StatusVariant as b2, Switch as b3, TAG_TYPE_ICONS as b4, TAG_TYPE_LABELS as b5, Table as b6, TableBody as b7, TableCaption as b8, TableCell as b9, VISIBILITY_ICONS as bA, VisibilityIcon as bB, VisibilityToggle as bC, type VisibilityToggleProps as bD, badgeVariants as bE, buttonVariants as bF, cardVariants as bG, closeOpenEmphasis as bH, cn as bI, configureEntityRegistry as bJ, configureRagLabels as bK, configureStatusRegistry as bL, getDocIcon as bM, getEntityColor as bN, getEntityColorStyles as bO, getEntityIcon as bP, getEntityLabel as bQ, getStatusVariant as bR, getTagTypeIcon as bS, getTagTypeLabel as bT, getWorkspaceColor as bU, markdownBaseComponents as bV, normalizeCitationMarkup as bW, splitMarkdownBlocks as bX, toggleVariants as bY, trimOpenCitation as bZ, TableFooter as ba, TableHead as bb, TableHeader as bc, TableRow as bd, Tabs as be, TabsContent as bf, TabsList as bg, TabsTrigger as bh, TagEntity as bi, type TagEntityProps as bj, type TagLike as bk, Textarea as bl, type TextareaProps as bm, Toggle as bn, ToggleGroup as bo, ToggleGroupItem as bp, Tooltip as bq, TooltipContent as br, TooltipProvider as bs, TooltipTrigger as bt, UserEntity as bu, type UserEntityProps as bv, UserMenu as bw, type UserMenuItem as bx, type UserMenuProps as by, type UserMenuStatus as bz, AvatarFallback as c, AvatarImage as d, Badge as e, type BadgeProps as f, Button as g, type ButtonProps as h, CardContent as i, CardDescription as j, CardFooter as k, CardHeader as l, type CardProps as m, CardTitle as n, Checkbox as o, Collapsible as p, CollapsibleContent as q, CollapsibleTrigger as r, Command as s, CommandDialog as t, CommandEmpty as u, CommandGroup as v, CommandInput as w, CommandItem as x, CommandList as y, CommandSeparator as z };
1425
+ export { DropdownMenuLabel as $, AgentBadge as A, BASE_COLORS as B, Card as C, CommandShortcut as D, Dialog as E, DialogClose as F, DialogContent as G, DialogDescription as H, DialogFooter as I, DialogHeader as J, DialogOverlay as K, DialogPortal as L, type DialogPresentation as M, DialogTitle as N, DialogTrigger as O, type DictateContextValue as P, DictateProvider as Q, DocumentCard as R, type DocumentCardProps as S, DocumentEntity as T, type DocumentEntityProps as U, type DocumentLike as V, DropdownMenu as W, DropdownMenuCheckboxItem as X, DropdownMenuContent as Y, DropdownMenuGroup as Z, DropdownMenuItem as _, AiMarkdown as a, type StatusBadgeProps as a$, DropdownMenuPortal as a0, DropdownMenuRadioGroup as a1, DropdownMenuRadioItem as a2, DropdownMenuSeparator as a3, DropdownMenuShortcut as a4, DropdownMenuSub as a5, DropdownMenuSubContent as a6, DropdownMenuSubTrigger as a7, DropdownMenuTrigger as a8, ENTITY_MAPPINGS as a9, PopoverTrigger as aA, type PresenceDisplayStatus as aB, PresenceLabel as aC, Progress as aD, ProjectEntity as aE, type ProjectEntityProps as aF, type ProjectRelation as aG, RadioGroup as aH, RadioGroupItem as aI, type Rag as aJ, RagDot as aK, RelevanceDot as aL, ScrollArea as aM, ScrollBar as aN, Select as aO, SelectContent as aP, SelectGroup as aQ, SelectItem as aR, SelectLabel as aS, SelectScrollDownButton as aT, SelectScrollUpButton as aU, SelectSeparator as aV, SelectTrigger as aW, SelectValue as aX, Separator as aY, Slider as aZ, type StatusBadgeComponent as a_, EntityIcon as aa, type EntityIconComponent as ab, EntityPill as ac, type EntityRegistryOverride as ad, type EntityType as ae, HoverCard as af, HoverCardContent as ag, HoverCardTrigger as ah, IconToggle as ai, type IconToggleProps as aj, Input as ak, type InputProps as al, Label as am, MarkMenu as an, type MarkMenuItem as ao, type MarkMenuProps as ap, MarkdownRenderer as aq, type MarkdownRendererProps as ar, MarkdownStreamingContext as as, NEUTRAL_GRAY as at, PLACEHOLDER_COLOR as au, PassageCard as av, type PassageCardProps as aw, Popover as ax, PopoverAnchor as ay, PopoverContent as az, Avatar as b, StatusPill as b0, type StatusPillProps as b1, type StatusVariant as b2, Switch as b3, TAG_TYPE_ICONS as b4, TAG_TYPE_LABELS as b5, Table as b6, TableBody as b7, TableCaption as b8, TableCell as b9, type UserMenuStatus as bA, VISIBILITY_ICONS as bB, VisibilityIcon as bC, VisibilityToggle as bD, type VisibilityToggleProps as bE, badgeVariants as bF, buttonVariants as bG, cardVariants as bH, closeOpenEmphasis as bI, cn as bJ, configureEntityRegistry as bK, configureRagLabels as bL, configureStatusRegistry as bM, getDocIcon as bN, getEntityColor as bO, getEntityColorStyles as bP, getEntityIcon as bQ, getEntityLabel as bR, getStatusVariant as bS, getTagTypeIcon as bT, getTagTypeLabel as bU, getWorkspaceColor as bV, markdownBaseComponents as bW, normalizeCitationMarkup as bX, splitMarkdownBlocks as bY, toggleVariants as bZ, trimOpenCitation as b_, TableFooter as ba, TableHead as bb, TableHeader as bc, TableRow as bd, Tabs as be, TabsContent as bf, TabsList as bg, TabsTrigger as bh, TagEntity as bi, type TagEntityProps as bj, type TagLike as bk, Textarea as bl, type TextareaProps as bm, ThreadVisibilityIcon as bn, Toggle as bo, ToggleGroup as bp, ToggleGroupItem as bq, Tooltip as br, TooltipContent as bs, TooltipProvider as bt, TooltipTrigger as bu, UserEntity as bv, type UserEntityProps as bw, UserMenu as bx, type UserMenuItem as by, type UserMenuProps as bz, AvatarFallback as c, AvatarImage as d, Badge as e, type BadgeProps as f, Button as g, type ButtonProps as h, CardContent as i, CardDescription as j, CardFooter as k, CardHeader as l, type CardProps as m, CardTitle as n, Checkbox as o, Collapsible as p, CollapsibleContent as q, CollapsibleTrigger as r, Command as s, CommandDialog as t, CommandEmpty as u, CommandGroup as v, CommandInput as w, CommandItem as x, CommandList as y, CommandSeparator as z };
@@ -6,7 +6,7 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
6
6
  import { VariantProps } from 'class-variance-authority';
7
7
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
8
8
  import * as lucide_react from 'lucide-react';
9
- import { LucideIcon, StickyNote } from 'lucide-react';
9
+ import { LucideIcon, LucideProps, StickyNote } from 'lucide-react';
10
10
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
11
11
  import * as DialogPrimitive from '@radix-ui/react-dialog';
12
12
  import { DialogProps } from '@radix-ui/react-dialog';
@@ -106,6 +106,8 @@ interface SharedItem {
106
106
  is_shared?: boolean | null;
107
107
  }
108
108
  interface VisibilityToggleProps {
109
+ /** Explicit Me / Workspace selector for creation forms. */
110
+ presentation?: 'toggle' | 'select';
109
111
  /** Single item or array of items with shared/is_shared field */
110
112
  items: SharedItem | SharedItem[];
111
113
  /** Called with true to share, false to unshare */
@@ -126,7 +128,7 @@ interface VisibilityToggleProps {
126
128
  workspaceLabel?: string;
127
129
  'data-testid'?: string;
128
130
  }
129
- declare function VisibilityToggle({ items, onToggle, disabled, disabledTooltip, disablePrivate, showLabel, showTooltip, tooltipActive, tooltipInactive, tooltipMixed, label, workspaceLabel, 'data-testid': dataTestId, }: VisibilityToggleProps): React$1.JSX.Element;
131
+ declare function VisibilityToggle({ items, presentation, onToggle, disabled, disabledTooltip, disablePrivate, showLabel, showTooltip, tooltipActive, tooltipInactive, tooltipMixed, label, workspaceLabel, 'data-testid': dataTestId, }: VisibilityToggleProps): React$1.JSX.Element;
130
132
 
131
133
  /**
132
134
  * DictateContext
@@ -297,7 +299,7 @@ declare const DialogOverlay: React$1.ForwardRefExoticComponent<Omit<DialogPrimit
297
299
  * - `sheet`: bottom sheet, full width, rounded top corners (forms and pickers).
298
300
  * - `full`: full-height sheet that stops below the status bar (large editors, wizards).
299
301
  */
300
- type DialogPresentation = 'center' | 'sheet' | 'full';
302
+ type DialogPresentation = 'center' | 'sheet' | 'full' | 'right';
301
303
  declare const DialogContent: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & {
302
304
  hideCloseButton?: boolean;
303
305
  /** Phone presentation (see {@link DialogPresentation}). Defaults to `center`. */
@@ -364,7 +366,7 @@ interface MarkMenuProps extends Omit<HTMLAttributes<HTMLElement>, 'children' | '
364
366
  * Keyboard: Enter/Space/ArrowDown open it and move into it, arrows move, Escape closes and
365
367
  * returns focus to the mark. Rows are 44px high on coarse pointers.
366
368
  */
367
- declare function MarkMenu({ as, href, items, preview, menuLabel, shouldClickRunPrimary, openDelay, closeDelay, testId, menuTestId, triggerRef: externalRef, className, children, onPointerDown, onPointerEnter, onPointerLeave, onFocus, onBlur, onKeyDown, ...rest }: MarkMenuProps): React$1.JSX.Element;
369
+ declare function MarkMenu({ as, href, items, preview, menuLabel, shouldClickRunPrimary, openDelay, closeDelay, testId, menuTestId, triggerRef: externalRef, className, children, onPointerDown, onPointerEnter, onPointerMove, onPointerLeave, onFocus, onBlur, onKeyDown, ...rest }: MarkMenuProps): React$1.JSX.Element;
368
370
 
369
371
  declare const DropdownMenu: React$1.FC<DropdownMenuPrimitive.DropdownMenuProps>;
370
372
  declare const DropdownMenuTrigger: React$1.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
@@ -630,11 +632,17 @@ interface PassageCardProps {
630
632
  }
631
633
  declare function PassageCard({ header, score, headerRight, active, onClick, footer, className, children, 'data-testid': testId, }: PassageCardProps): React__default.JSX.Element;
632
634
 
635
+ /** Thread visibility uses both shape and color across entity labels and grids. */
636
+ declare function ThreadVisibilityIcon({ shared, className, ...props }: LucideProps & {
637
+ shared: boolean;
638
+ }): React$1.JSX.Element;
639
+
633
640
  /**
634
641
  * EntityPill Component
635
642
  *
636
643
  * Base component for pill-style entity displays. Provides consistent styling and
637
- * interaction patterns. Promoted verbatim from the ARBI app (import paths only
644
+ * interaction patterns. At rest it is plain icon + text (no fill, no border); the
645
+ * fill appears on hover, so a row of entities does not read as a row of buttons. Promoted verbatim from the ARBI app (import paths only
638
646
  * changed to resolve within the SDK).
639
647
  *
640
648
  * Pattern: [Icon] [Label] [Optional: secondary text] [MoreVertical when interactive]
@@ -735,6 +743,8 @@ interface DocumentEntityProps {
735
743
  viewing?: boolean;
736
744
  /** Small overlay pinned to the icon's corner (e.g. an "available offline" pip). */
737
745
  iconBadge?: React__default.ReactNode;
746
+ /** Small content right after the name, inside the click area (e.g. a status glyph). */
747
+ status?: React__default.ReactNode;
738
748
  /** Trailing control rendered outside the click area (e.g. a ⋯ actions menu). */
739
749
  actions?: React__default.ReactNode;
740
750
  /** When true, the pill fills the available width and the name truncates via
@@ -751,7 +761,7 @@ interface DocumentEntityProps {
751
761
  /** Forwarded to the pill so a surface can address this document's chip. */
752
762
  'data-testid'?: string;
753
763
  }
754
- declare function DocumentEntity({ doc, icon, size, labelMaxWidth, labelClassName, onClick, onIconClick, viewing, iconBadge, actions, tooltipContent, className, fullWidth, noClamp, 'data-testid': testId, }: DocumentEntityProps): React__default.JSX.Element;
764
+ declare function DocumentEntity({ doc, icon, size, labelMaxWidth, labelClassName, onClick, onIconClick, viewing, iconBadge, status, actions, tooltipContent, className, fullWidth, noClamp, 'data-testid': testId, }: DocumentEntityProps): React__default.JSX.Element;
755
765
 
756
766
  /**
757
767
  * TagEntity Component
@@ -886,6 +896,8 @@ interface UserEntityProps {
886
896
  displayName?: string;
887
897
  /** Avatar image URL, if any. */
888
898
  picture?: string | null;
899
+ /** Optional image treatment for platform logos inside the normal avatar. */
900
+ avatarImageClassName?: string;
889
901
  /** Avatar background colour class for non-agents (e.g. 'bg-blue-500'). */
890
902
  colorClass?: string;
891
903
  /** Whether this user is an agent — drives the dashed ring + bot badge. */
@@ -1410,4 +1422,4 @@ declare function DocumentCard({ doc, thumbnailUrl, status, selected, onToggleSel
1410
1422
 
1411
1423
  declare function cn(...inputs: ClassValue[]): string;
1412
1424
 
1413
- export { DropdownMenuLabel as $, AgentBadge as A, BASE_COLORS as B, Card as C, CommandShortcut as D, Dialog as E, DialogClose as F, DialogContent as G, DialogDescription as H, DialogFooter as I, DialogHeader as J, DialogOverlay as K, DialogPortal as L, type DialogPresentation as M, DialogTitle as N, DialogTrigger as O, type DictateContextValue as P, DictateProvider as Q, DocumentCard as R, type DocumentCardProps as S, DocumentEntity as T, type DocumentEntityProps as U, type DocumentLike as V, DropdownMenu as W, DropdownMenuCheckboxItem as X, DropdownMenuContent as Y, DropdownMenuGroup as Z, DropdownMenuItem as _, AiMarkdown as a, type StatusBadgeProps as a$, DropdownMenuPortal as a0, DropdownMenuRadioGroup as a1, DropdownMenuRadioItem as a2, DropdownMenuSeparator as a3, DropdownMenuShortcut as a4, DropdownMenuSub as a5, DropdownMenuSubContent as a6, DropdownMenuSubTrigger as a7, DropdownMenuTrigger as a8, ENTITY_MAPPINGS as a9, PopoverTrigger as aA, type PresenceDisplayStatus as aB, PresenceLabel as aC, Progress as aD, ProjectEntity as aE, type ProjectEntityProps as aF, type ProjectRelation as aG, RadioGroup as aH, RadioGroupItem as aI, type Rag as aJ, RagDot as aK, RelevanceDot as aL, ScrollArea as aM, ScrollBar as aN, Select as aO, SelectContent as aP, SelectGroup as aQ, SelectItem as aR, SelectLabel as aS, SelectScrollDownButton as aT, SelectScrollUpButton as aU, SelectSeparator as aV, SelectTrigger as aW, SelectValue as aX, Separator as aY, Slider as aZ, type StatusBadgeComponent as a_, EntityIcon as aa, type EntityIconComponent as ab, EntityPill as ac, type EntityRegistryOverride as ad, type EntityType as ae, HoverCard as af, HoverCardContent as ag, HoverCardTrigger as ah, IconToggle as ai, type IconToggleProps as aj, Input as ak, type InputProps as al, Label as am, MarkMenu as an, type MarkMenuItem as ao, type MarkMenuProps as ap, MarkdownRenderer as aq, type MarkdownRendererProps as ar, MarkdownStreamingContext as as, NEUTRAL_GRAY as at, PLACEHOLDER_COLOR as au, PassageCard as av, type PassageCardProps as aw, Popover as ax, PopoverAnchor as ay, PopoverContent as az, Avatar as b, StatusPill as b0, type StatusPillProps as b1, type StatusVariant as b2, Switch as b3, TAG_TYPE_ICONS as b4, TAG_TYPE_LABELS as b5, Table as b6, TableBody as b7, TableCaption as b8, TableCell as b9, VISIBILITY_ICONS as bA, VisibilityIcon as bB, VisibilityToggle as bC, type VisibilityToggleProps as bD, badgeVariants as bE, buttonVariants as bF, cardVariants as bG, closeOpenEmphasis as bH, cn as bI, configureEntityRegistry as bJ, configureRagLabels as bK, configureStatusRegistry as bL, getDocIcon as bM, getEntityColor as bN, getEntityColorStyles as bO, getEntityIcon as bP, getEntityLabel as bQ, getStatusVariant as bR, getTagTypeIcon as bS, getTagTypeLabel as bT, getWorkspaceColor as bU, markdownBaseComponents as bV, normalizeCitationMarkup as bW, splitMarkdownBlocks as bX, toggleVariants as bY, trimOpenCitation as bZ, TableFooter as ba, TableHead as bb, TableHeader as bc, TableRow as bd, Tabs as be, TabsContent as bf, TabsList as bg, TabsTrigger as bh, TagEntity as bi, type TagEntityProps as bj, type TagLike as bk, Textarea as bl, type TextareaProps as bm, Toggle as bn, ToggleGroup as bo, ToggleGroupItem as bp, Tooltip as bq, TooltipContent as br, TooltipProvider as bs, TooltipTrigger as bt, UserEntity as bu, type UserEntityProps as bv, UserMenu as bw, type UserMenuItem as bx, type UserMenuProps as by, type UserMenuStatus as bz, AvatarFallback as c, AvatarImage as d, Badge as e, type BadgeProps as f, Button as g, type ButtonProps as h, CardContent as i, CardDescription as j, CardFooter as k, CardHeader as l, type CardProps as m, CardTitle as n, Checkbox as o, Collapsible as p, CollapsibleContent as q, CollapsibleTrigger as r, Command as s, CommandDialog as t, CommandEmpty as u, CommandGroup as v, CommandInput as w, CommandItem as x, CommandList as y, CommandSeparator as z };
1425
+ export { DropdownMenuLabel as $, AgentBadge as A, BASE_COLORS as B, Card as C, CommandShortcut as D, Dialog as E, DialogClose as F, DialogContent as G, DialogDescription as H, DialogFooter as I, DialogHeader as J, DialogOverlay as K, DialogPortal as L, type DialogPresentation as M, DialogTitle as N, DialogTrigger as O, type DictateContextValue as P, DictateProvider as Q, DocumentCard as R, type DocumentCardProps as S, DocumentEntity as T, type DocumentEntityProps as U, type DocumentLike as V, DropdownMenu as W, DropdownMenuCheckboxItem as X, DropdownMenuContent as Y, DropdownMenuGroup as Z, DropdownMenuItem as _, AiMarkdown as a, type StatusBadgeProps as a$, DropdownMenuPortal as a0, DropdownMenuRadioGroup as a1, DropdownMenuRadioItem as a2, DropdownMenuSeparator as a3, DropdownMenuShortcut as a4, DropdownMenuSub as a5, DropdownMenuSubContent as a6, DropdownMenuSubTrigger as a7, DropdownMenuTrigger as a8, ENTITY_MAPPINGS as a9, PopoverTrigger as aA, type PresenceDisplayStatus as aB, PresenceLabel as aC, Progress as aD, ProjectEntity as aE, type ProjectEntityProps as aF, type ProjectRelation as aG, RadioGroup as aH, RadioGroupItem as aI, type Rag as aJ, RagDot as aK, RelevanceDot as aL, ScrollArea as aM, ScrollBar as aN, Select as aO, SelectContent as aP, SelectGroup as aQ, SelectItem as aR, SelectLabel as aS, SelectScrollDownButton as aT, SelectScrollUpButton as aU, SelectSeparator as aV, SelectTrigger as aW, SelectValue as aX, Separator as aY, Slider as aZ, type StatusBadgeComponent as a_, EntityIcon as aa, type EntityIconComponent as ab, EntityPill as ac, type EntityRegistryOverride as ad, type EntityType as ae, HoverCard as af, HoverCardContent as ag, HoverCardTrigger as ah, IconToggle as ai, type IconToggleProps as aj, Input as ak, type InputProps as al, Label as am, MarkMenu as an, type MarkMenuItem as ao, type MarkMenuProps as ap, MarkdownRenderer as aq, type MarkdownRendererProps as ar, MarkdownStreamingContext as as, NEUTRAL_GRAY as at, PLACEHOLDER_COLOR as au, PassageCard as av, type PassageCardProps as aw, Popover as ax, PopoverAnchor as ay, PopoverContent as az, Avatar as b, StatusPill as b0, type StatusPillProps as b1, type StatusVariant as b2, Switch as b3, TAG_TYPE_ICONS as b4, TAG_TYPE_LABELS as b5, Table as b6, TableBody as b7, TableCaption as b8, TableCell as b9, type UserMenuStatus as bA, VISIBILITY_ICONS as bB, VisibilityIcon as bC, VisibilityToggle as bD, type VisibilityToggleProps as bE, badgeVariants as bF, buttonVariants as bG, cardVariants as bH, closeOpenEmphasis as bI, cn as bJ, configureEntityRegistry as bK, configureRagLabels as bL, configureStatusRegistry as bM, getDocIcon as bN, getEntityColor as bO, getEntityColorStyles as bP, getEntityIcon as bQ, getEntityLabel as bR, getStatusVariant as bS, getTagTypeIcon as bT, getTagTypeLabel as bU, getWorkspaceColor as bV, markdownBaseComponents as bW, normalizeCitationMarkup as bX, splitMarkdownBlocks as bY, toggleVariants as bZ, trimOpenCitation as b_, TableFooter as ba, TableHead as bb, TableHeader as bc, TableRow as bd, Tabs as be, TabsContent as bf, TabsList as bg, TabsTrigger as bh, TagEntity as bi, type TagEntityProps as bj, type TagLike as bk, Textarea as bl, type TextareaProps as bm, ThreadVisibilityIcon as bn, Toggle as bo, ToggleGroup as bp, ToggleGroupItem as bq, Tooltip as br, TooltipContent as bs, TooltipProvider as bt, TooltipTrigger as bu, UserEntity as bv, type UserEntityProps as bw, UserMenu as bx, type UserMenuItem as by, type UserMenuProps as bz, AvatarFallback as c, AvatarImage as d, Badge as e, type BadgeProps as f, Button as g, type ButtonProps as h, CardContent as i, CardDescription as j, CardFooter as k, CardHeader as l, type CardProps as m, CardTitle as n, Checkbox as o, Collapsible as p, CollapsibleContent as q, CollapsibleTrigger as r, Command as s, CommandDialog as t, CommandEmpty as u, CommandGroup as v, CommandInput as w, CommandItem as x, CommandList as y, CommandSeparator as z };