@arbidocs/react 0.4.9 → 0.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { useDocuments, useConversations, useAssistantQuery, useConversationThreads, arbiQueryKeys, useWorkspaces, useParsedDocument, useTags, useActivity, useThumbnails } from './chunk-R5SR7R6W.js';
2
- export { DEFAULT_USD_PER_CREDIT, arbiQueryKeys, creditsToUsd, formatCredits, isUsageMetered, useActivity, useAgents, useAssistantQuery, useConfigs, useConversationThreads, useConversations, useDeleteAgents, useDocuments, useFacts, useHealth, useParsedDocument, useProjectInvoices, useProjectUsage, useProjects, useProjectsUsage, useSessions, useTags, useTasks, useThumbnails, useUserUsageToday, useWorkspaces } from './chunk-R5SR7R6W.js';
1
+ import { useDocuments, useConversations, useAssistantQuery, useConversationThreads, arbiQueryKeys, useWorkspaces, useParsedDocument, useTags, useActivity, useThumbnails } from './chunk-QFELRTTG.js';
2
+ export { DEFAULT_USD_PER_CREDIT, arbiQueryKeys, cleanDraftMarkdown, creditsToUsd, formatCredits, isUsageMetered, promoteBoldTitle, repairParsedTitle, stripAgentPreamble, unescapeMarkdown, unwrapCitationLinks, useActivity, useAgents, useAssistantQuery, useConfigs, useConversationThreads, useConversations, useDeleteAgents, useDocuments, useFacts, useHealth, useParsedDocument, useProjectInvoices, useProjectUsage, useProjects, useProjectsUsage, useSessions, useTags, useTasks, useThumbnails, useUserUsageToday, useWorkspaces } from './chunk-QFELRTTG.js';
3
+ import { formatRelativeTime } from './chunk-FSMIN5VX.js';
4
+ export { DEFAULT_NOTIFY_TONE, NotificationBell, Toaster, formatRelativeTime, notify, seedNotifications, selectUnread, toast, useNotify } from './chunk-FSMIN5VX.js';
3
5
  import { MarkMenu, AiMarkdown, Card, Button, Badge, TagEntity, Input, FILE_TYPE_COLORS, getEntityIcon, UserEntity, getEntityColorStyles, AgentBadge, Textarea, Label, Slider, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DocumentEntity, DocumentCard, useAudioRecorder, MicWaveformIndicator, IconToggle, classifyMediaError, formatElapsed, PassageCard } from './chunk-RTULVZOS.js';
4
6
  export { AgentBadge, AiMarkdown, ArbiBotHeadIcon, AudIcon, Avatar, AvatarFallback, AvatarImage, BASE_COLORS, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DictateProvider, DocumentCard, DocumentEntity, ENTITY_MAPPINGS, EmlIcon, EntityIcon, EntityPill, FILE_TYPE_COLORS, HoverCard, HoverCardContent, HoverCardTrigger, IconToggle, ImgIcon, InlineMicButton, Input, Label, MarkMenu, MicRecordingOverlay, MicWaveformIndicator, NEUTRAL_GRAY, PLACEHOLDER_COLOR, PassageCard, PdfIcon, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PresenceLabel, Progress, ProjectEntity, RadioGroup, RadioGroupItem, RagDot, RelevanceDot, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Slider, StatusPill, Switch, TAG_TYPE_ICONS, TAG_TYPE_LABELS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagEntity, Textarea, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserEntity, UserMenu, VISIBILITY_ICONS, VidIcon, VisibilityIcon, badgeVariants, buttonVariants, cardVariants, configureEntityRegistry, configureRagLabels, configureStatusRegistry, formatElapsed, getDocIcon, getEntityColor, getEntityColorStyles, getEntityIcon, getEntityLabel, getStatusVariant, getTagTypeIcon, getTagTypeLabel, getWorkspaceColor, toggleVariants, useAudioRecorder } from './chunk-RTULVZOS.js';
5
7
  import { normalizeCitationMarkup, MarkdownRenderer } from './chunk-TGGQGFS3.js';
6
8
  export { MarkdownRenderer, MarkdownStreamingContext, closeOpenEmphasis, markdownBaseComponents, normalizeCitationMarkup, splitMarkdownBlocks, trimOpenCitation } from './chunk-TGGQGFS3.js';
7
- import { formatRelativeTime } from './chunk-FSMIN5VX.js';
8
- export { DEFAULT_NOTIFY_TONE, NotificationBell, Toaster, formatRelativeTime, notify, seedNotifications, selectUnread, toast, useNotify } from './chunk-FSMIN5VX.js';
9
9
  import { ScrollArea, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from './chunk-N5SVBDLC.js';
10
10
  export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ScrollArea, ScrollBar } from './chunk-N5SVBDLC.js';
11
11
  import { cn } from './chunk-SN5YV6FF.js';
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Helpers for markdown that is STORED (an agent's draft saved as an artifact, then read back from
3
+ * the backend's parse). Pure and SDK-free; they sit next to `normalizeCitationMarkup`, which they
4
+ * build on.
5
+ *
6
+ * Two directions:
7
+ *
8
+ * - Going in (`cleanDraftMarkdown` = `unwrapCitationLinks` + `stripAgentPreamble` +
9
+ * `promoteBoldTitle`): a streamed draft carries citation links, `(*Source: ...*)` notes and
10
+ * sometimes narration before the document. A stored letter should hold only the letter.
11
+ * - Coming out (`unescapeMarkdown`): the backend's parse of a stored `.md` returns the text with
12
+ * markdown punctuation backslash-escaped (`**Fees.**` comes back as `\*\*Fees\.\*\*`).
13
+ */
14
+ /**
15
+ * Undo the backend's escaping of a markdown artifact: `\*\*Scope\.\*\*` becomes `**Scope.**`.
16
+ *
17
+ * THE RULE. Apply this ONLY to text of an artifact that was stored from markdown (an agent draft
18
+ * or an edited version, always uploaded as `.md`): for those the parser escapes every markdown
19
+ * punctuation character, including the backslash itself, so removing one level of escaping is the
20
+ * exact inverse (an author's literal `\*` is stored as `\\\*` and comes back as `\*`). Do not
21
+ * apply it to a PDF or Word parse, where a backslash is just a character.
22
+ *
23
+ * Details:
24
+ * - Only a backslash followed by markdown punctuation (``\ ` * _ { } [ ] ( ) # + - . ! | > ~ <``)
25
+ * is removed; `\n`, `C:\temp` and a trailing backslash are left alone.
26
+ * - Pairs are read left to right, so `\\*` is an escaped backslash followed by a bare `*`.
27
+ * - Fenced code blocks are never touched (the parser does not escape inside them).
28
+ * - Inline code spans: the parser DOES escape `*` and `_` there (`` `a*b` `` comes back as
29
+ * `` `a\*b` ``), so only `\*` and `\_` are undone inside a span; any other backslash in code
30
+ * (`` `re\.x` ``) is a literal and stays.
31
+ */
32
+ declare function unescapeMarkdown(text: string): string;
33
+ /**
34
+ * The parser also mangles the TITLE of a stored markdown document (seen on a real backend): the
35
+ * first heading comes back doubled (`## # Title`) or alone inside a code fence
36
+ * (a fence, `# Title`, a fence). Both are repaired, on the first non-blank line only, so a code
37
+ * block or heading later in the text is never touched. Like `unescapeMarkdown`, apply it only to
38
+ * artifacts stored from markdown.
39
+ */
40
+ declare function repairParsedTitle(text: string): string;
41
+ /**
42
+ * Text for storage from text that carries citations: `normalizeCitationMarkup` first (it hoists
43
+ * list, heading and bold tokens out of the link so unwrapping cannot orphan half of a `**` pair),
44
+ * then `[text](#cite-N)` becomes `text`, `(*Source: ...*)` notes are dropped, and a bold or
45
+ * heading marker that lost its partner is repaired. Fenced code is left alone.
46
+ */
47
+ declare function unwrapCitationLinks(text: string): string;
48
+ /**
49
+ * Cut what an agent wrote BEFORE the document, when it is narration.
50
+ *
51
+ * HEURISTIC (conservative, so a document is never trimmed by mistake). The document is taken to
52
+ * start at the first `#` heading, or, when there is none, at the first whole-line bold title within
53
+ * the first 15 lines. The text before it is removed only when ALL of these hold:
54
+ * 1. it is short (at most 1200 characters);
55
+ * 2. it is plain prose: no list, table, quote, code or heading;
56
+ * 3. it reads like the agent talking: first person ("I'll draft ..."), "Here is ...", "Per the
57
+ * instructions", "Based on the ..." and the like.
58
+ * A document that opens with a dateline, an address or any text that does not trip rule 3 is kept
59
+ * whole. A horizontal rule left at the end of the cut text is dropped with it.
60
+ */
61
+ declare function stripAgentPreamble(text: string): string;
62
+ /**
63
+ * Make the document's title a real heading: a first line that is a bold title (`**Letter**`, even
64
+ * with stray inner `**`) becomes `# Letter`. A document that already opens with a heading is left
65
+ * alone.
66
+ */
67
+ declare function promoteBoldTitle(text: string): string;
68
+ /**
69
+ * Everything a streamed draft needs before it is stored as the artifact's first version:
70
+ * `unwrapCitationLinks`, `stripAgentPreamble`, `promoteBoldTitle`, clean headings, collapsed blank
71
+ * runs, trimmed.
72
+ */
73
+ declare function cleanDraftMarkdown(raw: string): string;
74
+
75
+ export { unwrapCitationLinks as a, cleanDraftMarkdown as c, promoteBoldTitle as p, repairParsedTitle as r, stripAgentPreamble as s, unescapeMarkdown as u };
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Helpers for markdown that is STORED (an agent's draft saved as an artifact, then read back from
3
+ * the backend's parse). Pure and SDK-free; they sit next to `normalizeCitationMarkup`, which they
4
+ * build on.
5
+ *
6
+ * Two directions:
7
+ *
8
+ * - Going in (`cleanDraftMarkdown` = `unwrapCitationLinks` + `stripAgentPreamble` +
9
+ * `promoteBoldTitle`): a streamed draft carries citation links, `(*Source: ...*)` notes and
10
+ * sometimes narration before the document. A stored letter should hold only the letter.
11
+ * - Coming out (`unescapeMarkdown`): the backend's parse of a stored `.md` returns the text with
12
+ * markdown punctuation backslash-escaped (`**Fees.**` comes back as `\*\*Fees\.\*\*`).
13
+ */
14
+ /**
15
+ * Undo the backend's escaping of a markdown artifact: `\*\*Scope\.\*\*` becomes `**Scope.**`.
16
+ *
17
+ * THE RULE. Apply this ONLY to text of an artifact that was stored from markdown (an agent draft
18
+ * or an edited version, always uploaded as `.md`): for those the parser escapes every markdown
19
+ * punctuation character, including the backslash itself, so removing one level of escaping is the
20
+ * exact inverse (an author's literal `\*` is stored as `\\\*` and comes back as `\*`). Do not
21
+ * apply it to a PDF or Word parse, where a backslash is just a character.
22
+ *
23
+ * Details:
24
+ * - Only a backslash followed by markdown punctuation (``\ ` * _ { } [ ] ( ) # + - . ! | > ~ <``)
25
+ * is removed; `\n`, `C:\temp` and a trailing backslash are left alone.
26
+ * - Pairs are read left to right, so `\\*` is an escaped backslash followed by a bare `*`.
27
+ * - Fenced code blocks are never touched (the parser does not escape inside them).
28
+ * - Inline code spans: the parser DOES escape `*` and `_` there (`` `a*b` `` comes back as
29
+ * `` `a\*b` ``), so only `\*` and `\_` are undone inside a span; any other backslash in code
30
+ * (`` `re\.x` ``) is a literal and stays.
31
+ */
32
+ declare function unescapeMarkdown(text: string): string;
33
+ /**
34
+ * The parser also mangles the TITLE of a stored markdown document (seen on a real backend): the
35
+ * first heading comes back doubled (`## # Title`) or alone inside a code fence
36
+ * (a fence, `# Title`, a fence). Both are repaired, on the first non-blank line only, so a code
37
+ * block or heading later in the text is never touched. Like `unescapeMarkdown`, apply it only to
38
+ * artifacts stored from markdown.
39
+ */
40
+ declare function repairParsedTitle(text: string): string;
41
+ /**
42
+ * Text for storage from text that carries citations: `normalizeCitationMarkup` first (it hoists
43
+ * list, heading and bold tokens out of the link so unwrapping cannot orphan half of a `**` pair),
44
+ * then `[text](#cite-N)` becomes `text`, `(*Source: ...*)` notes are dropped, and a bold or
45
+ * heading marker that lost its partner is repaired. Fenced code is left alone.
46
+ */
47
+ declare function unwrapCitationLinks(text: string): string;
48
+ /**
49
+ * Cut what an agent wrote BEFORE the document, when it is narration.
50
+ *
51
+ * HEURISTIC (conservative, so a document is never trimmed by mistake). The document is taken to
52
+ * start at the first `#` heading, or, when there is none, at the first whole-line bold title within
53
+ * the first 15 lines. The text before it is removed only when ALL of these hold:
54
+ * 1. it is short (at most 1200 characters);
55
+ * 2. it is plain prose: no list, table, quote, code or heading;
56
+ * 3. it reads like the agent talking: first person ("I'll draft ..."), "Here is ...", "Per the
57
+ * instructions", "Based on the ..." and the like.
58
+ * A document that opens with a dateline, an address or any text that does not trip rule 3 is kept
59
+ * whole. A horizontal rule left at the end of the cut text is dropped with it.
60
+ */
61
+ declare function stripAgentPreamble(text: string): string;
62
+ /**
63
+ * Make the document's title a real heading: a first line that is a bold title (`**Letter**`, even
64
+ * with stray inner `**`) becomes `# Letter`. A document that already opens with a heading is left
65
+ * alone.
66
+ */
67
+ declare function promoteBoldTitle(text: string): string;
68
+ /**
69
+ * Everything a streamed draft needs before it is stored as the artifact's first version:
70
+ * `unwrapCitationLinks`, `stripAgentPreamble`, `promoteBoldTitle`, clean headings, collapsed blank
71
+ * runs, trimmed.
72
+ */
73
+ declare function cleanDraftMarkdown(raw: string): string;
74
+
75
+ export { unwrapCitationLinks as a, cleanDraftMarkdown as c, promoteBoldTitle as p, repairParsedTitle as r, stripAgentPreamble as s, unescapeMarkdown as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbidocs/react",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "description": "React hooks and provider for the ARBI SDK",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -69,8 +69,8 @@
69
69
  "build-storybook": "storybook build"
70
70
  },
71
71
  "dependencies": {
72
- "@arbidocs/sdk": "0.4.9",
73
- "@arbidocs/client": "0.4.9",
72
+ "@arbidocs/sdk": "0.4.11",
73
+ "@arbidocs/client": "0.4.11",
74
74
  "@radix-ui/react-avatar": "^1.2.0",
75
75
  "@radix-ui/react-checkbox": "^1.3.5",
76
76
  "@radix-ui/react-collapsible": "^1.1.14",
@@ -102,8 +102,11 @@
102
102
  "react-markdown": "^10.0.0",
103
103
  "rehype-raw": "^7.0.0",
104
104
  "remark-gfm": "^4.0.0",
105
+ "remark-parse": "^11.0.0",
106
+ "remark-stringify": "^11.0.0",
105
107
  "sonner": "^2.0.7",
106
108
  "tailwind-merge": "^3.6.0",
109
+ "unified": "^11.0.5",
107
110
  "zustand": "^5.0.14"
108
111
  },
109
112
  "peerDependencies": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/credits.ts","../src/hooks.ts"],"names":["useArbi","useQuery","useMutation","useQueryClient","useQueries","useMemo"],"mappings":"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","file":"chunk-E7UO2JSR.cjs","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 whole credits at the API boundary: 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/** \"1,234 credits\" / \"1 credit\". The backend reports whole credits; this rounds away float dust. */\nexport function formatCredits(credits: number, options: FormatCreditsOptions = {}): string {\n const { unit = true, locale = 'en-US' } = options\n const whole = Math.round(Number.isFinite(credits) ? credits : 0)\n const digits = whole.toLocaleString(locale)\n return unit ? `${digits} ${whole === 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 project on the `dev` plan belongs to a deployment with\n * billing switched off: the backend only records AI usage per project when billing is enabled, so\n * an all-zero response there means \"not metered\", not \"nothing happened\". Show a note instead of\n * silent zeros.\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} 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 documents: (workspaceId: string) => ['arbi', 'documents', workspaceId] as const,\n conversations: (workspaceId: string) => ['arbi', 'conversations', workspaceId] 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 tasks: () => ['arbi', 'tasks'] 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 taskRuns: (taskId: string) => ['arbi', 'taskRuns', taskId] 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/** 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(workspaceId: string | undefined, options?: { enabled?: boolean }) {\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 })\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 }\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 })\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 docIds: string[]\n previousResponseId?: string | null\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 and the task list (a deleted\n * agent's tasks 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.tasks() }),\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// ── Scheduled tasks ──────────────────────────────────────────────────────────\n\n/** List the caller's scheduled agent tasks. */\nexport function useTasks(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.tasks(),\n queryFn: () => arbi.tasks.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/credits.ts","../src/hooks.ts"],"names":[],"mappings":"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","file":"chunk-R5SR7R6W.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 whole credits at the API boundary: 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/** \"1,234 credits\" / \"1 credit\". The backend reports whole credits; this rounds away float dust. */\nexport function formatCredits(credits: number, options: FormatCreditsOptions = {}): string {\n const { unit = true, locale = 'en-US' } = options\n const whole = Math.round(Number.isFinite(credits) ? credits : 0)\n const digits = whole.toLocaleString(locale)\n return unit ? `${digits} ${whole === 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 project on the `dev` plan belongs to a deployment with\n * billing switched off: the backend only records AI usage per project when billing is enabled, so\n * an all-zero response there means \"not metered\", not \"nothing happened\". Show a note instead of\n * silent zeros.\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} 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 documents: (workspaceId: string) => ['arbi', 'documents', workspaceId] as const,\n conversations: (workspaceId: string) => ['arbi', 'conversations', workspaceId] 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 tasks: () => ['arbi', 'tasks'] 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 taskRuns: (taskId: string) => ['arbi', 'taskRuns', taskId] 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/** 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(workspaceId: string | undefined, options?: { enabled?: boolean }) {\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 })\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 }\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 })\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 docIds: string[]\n previousResponseId?: string | null\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 and the task list (a deleted\n * agent's tasks 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.tasks() }),\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// ── Scheduled tasks ──────────────────────────────────────────────────────────\n\n/** List the caller's scheduled agent tasks. */\nexport function useTasks(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.tasks(),\n queryFn: () => arbi.tasks.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/artifacts/redline-diff.ts"],"names":[],"mappings":"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","file":"chunk-RKWNX32A.js","sourcesContent":["/**\n * Redline diff core\n *\n * Pure (no DOM, no Worker globals) logic for building a Word-style redline\n * markdown string from two flattened document texts. Lives outside the\n * worker file so it's straightforward to unit test.\n *\n * Strategy: hybrid line + word diff with structural safety.\n * 1. `diffLines` splits the texts into add/remove/equal blocks.\n * 2. For an adjacent [removed, added] pair (a modified region):\n * - If either side contains markdown structure that can't safely host\n * inline tags (code fences, table rows, horizontal rules), fall back\n * to block-level wrapping (whole-line del/ins, line by line).\n * - Otherwise run `diffWords`. Markdown leading markers (#, -, *, 1., >)\n * become unchanged word tokens, so when only the heading/list text\n * changes the marker stays *outside* the inline tags and the heading\n * still parses.\n * 3. Pure removed / added blocks (no paired counterpart) are wrapped\n * line-by-line so structural prefixes stay outside the tag.\n */\n\nimport { diffLines, diffWords } from 'diff'\n\n// Lines that can't safely host inline <del>/<ins> tags without breaking\n// markdown parsing. Code fences, table rows, and horizontal rules.\nconst UNSAFE_LINE = /^(?:\\s*(?:```|~~~).*|\\s*\\|.*\\||\\s*(?:[-=*_]\\s*){3,})\\s*$/\n\n// Block-level markdown structural prefix. When present on a line, putting\n// it INSIDE an inline tag stops the heading/list/blockquote from parsing,\n// so we always preserve it outside the wrapping tag.\nconst STRUCTURAL_PREFIX = /^(\\s*(?:#{1,6}\\s+|[-*+]\\s+|\\d+[.)]\\s+|>\\s*)+)/\n\nfunction escapeForHtmlTag(text: string): string {\n return text.replace(/</g, '&lt;').replace(/>/g, '&gt;')\n}\n\nfunction wrapLineAsRedline(line: string, tag: 'del' | 'ins'): string {\n if (line === '' || line.trim() === '') return line\n if (UNSAFE_LINE.test(line)) {\n return `<${tag}>${escapeForHtmlTag(line)}</${tag}>`\n }\n const m = line.match(STRUCTURAL_PREFIX)\n if (m) {\n const prefix = m[1]\n const rest = line.slice(prefix.length)\n if (rest === '') return line\n return `${prefix}<${tag}>${escapeForHtmlTag(rest)}</${tag}>`\n }\n return `<${tag}>${escapeForHtmlTag(line)}</${tag}>`\n}\n\nfunction wrapBlockAsRedline(block: string, tag: 'del' | 'ins'): string {\n const lines = block.split('\\n')\n return lines\n .map((line, i) => {\n const wrapped = wrapLineAsRedline(line, tag)\n return i < lines.length - 1 ? wrapped + '\\n' : wrapped\n })\n .join('')\n}\n\nfunction pairContainsUnsafeLine(text: string): boolean {\n for (const line of text.split('\\n')) {\n if (UNSAFE_LINE.test(line)) return true\n }\n return false\n}\n\nexport function buildHybridRedlineMarkdown(baseText: string, compareText: string): string {\n const lineChanges = diffLines(baseText, compareText)\n const out: string[] = []\n\n for (let i = 0; i < lineChanges.length; i++) {\n const cur = lineChanges[i]\n const next = lineChanges[i + 1]\n\n if (cur.removed && next?.added) {\n if (pairContainsUnsafeLine(cur.value) || pairContainsUnsafeLine(next.value)) {\n out.push(wrapBlockAsRedline(cur.value, 'del'))\n out.push(wrapBlockAsRedline(next.value, 'ins'))\n } else {\n const wordChanges = diffWords(cur.value, next.value)\n for (const w of wordChanges) {\n if (w.removed) out.push(`<del>${escapeForHtmlTag(w.value)}</del>`)\n else if (w.added) out.push(`<ins>${escapeForHtmlTag(w.value)}</ins>`)\n else out.push(w.value)\n }\n }\n i++ // consume the paired added entry\n } else if (cur.removed) {\n out.push(wrapBlockAsRedline(cur.value, 'del'))\n } else if (cur.added) {\n out.push(wrapBlockAsRedline(cur.value, 'ins'))\n } else {\n out.push(cur.value)\n }\n }\n\n return out.join('')\n}\n\n// ─── Regions extension ────────────────────────────────────────────────────────\n//\n// Same redline as above, but every <del>/<ins> tag carries a stable\n// `data-cid` attribute identifying the \"change region\" it belongs to. A\n// region is the smallest independently revertable change:\n//\n// - inside a safe [REM, ADD] pair, each contiguous changed-word run is its\n// own region, so a single button can revert one phrase without touching\n// other edits in the same paragraph;\n// - unsafe pairs (tables, code fences, horizontal rules) are still one\n// region for the whole block, since line-level wrapping can't safely\n// split them;\n// - a non-adjacent [removed text == added text] pair is a *move*: both\n// endpoints share one cid, render green, and one undo reverts the move.\n//\n// `revertRedlineRegion` mirrors the same walk and rebuilds the working-tree text\n// with one region \"as if it never changed\", so cids round-trip identically\n// from build → render → revert.\n\nexport type RegionKind = 'replace' | 'remove' | 'add' | 'move'\n\nexport interface RedlineRegion {\n id: string\n kind: RegionKind\n baseText: string // what the base side has for this slice\n compareText: string // what the compare side has for this slice\n}\n\nexport interface RedlineWithRegions {\n markdown: string\n regions: RedlineRegion[]\n}\n\n// Tiny deterministic hash (FNV-1a 32-bit, hex). Stable across runs and JS\n// runtimes, with no Node-only deps so this stays browser-safe.\nfunction fnv1aHex(...parts: string[]): string {\n let h = 0x811c9dc5\n for (const part of parts) {\n h ^= 0x5f5f\n h = Math.imul(h, 0x01000193) >>> 0\n for (let i = 0; i < part.length; i++) {\n h ^= part.charCodeAt(i)\n h = Math.imul(h, 0x01000193) >>> 0\n }\n }\n return ('00000000' + h.toString(16)).slice(-8)\n}\n\n// First char of the cid encodes the kind so consumers can style without a\n// region-table lookup: p=replace r=remove a=add m=move.\nfunction makeRegionId(\n kind: RegionKind,\n baseText: string,\n compareText: string,\n seq: number\n): string {\n const prefix = kind === 'replace' ? 'p' : kind === 'remove' ? 'r' : kind === 'add' ? 'a' : 'm'\n return `${prefix}${fnv1aHex(kind, baseText, compareText, String(seq))}`\n}\n\n// Move detection: a non-adjacent removed/added pair with identical text is a\n// move. Returns the move endpoints' lineChanges-indices plus a region per\n// distinct move.\nfunction detectMoves(lineChanges: { value: string; removed?: boolean; added?: boolean }[]): {\n moveByIndex: Map<number, string>\n moveRegions: RedlineRegion[]\n} {\n const moveByIndex = new Map<number, string>()\n const moveRegions: RedlineRegion[] = []\n const removedByText = new Map<string, number[]>()\n const addedByText = new Map<string, number[]>()\n\n for (let i = 0; i < lineChanges.length; i++) {\n const c = lineChanges[i]\n if (c.removed) {\n const arr = removedByText.get(c.value) ?? []\n arr.push(i)\n removedByText.set(c.value, arr)\n } else if (c.added) {\n const arr = addedByText.get(c.value) ?? []\n arr.push(i)\n addedByText.set(c.value, arr)\n }\n }\n\n let seq = 0\n for (const [text, removedIdx] of removedByText) {\n const addedIdx = addedByText.get(text)\n if (!addedIdx || addedIdx.length === 0) continue\n if (text.trim().length === 0) continue\n const n = Math.min(removedIdx.length, addedIdx.length)\n for (let k = 0; k < n; k++) {\n const rI = removedIdx[k]\n const aI = addedIdx[k]\n if (aI === rI + 1 || rI === aI + 1) continue // adjacent = replace, not move\n if (moveByIndex.has(rI) || moveByIndex.has(aI)) continue\n const id = makeRegionId('move', text, text, seq++)\n moveByIndex.set(rI, id)\n moveByIndex.set(aI, id)\n moveRegions.push({ id, kind: 'move', baseText: text, compareText: text })\n }\n }\n\n return { moveByIndex, moveRegions }\n}\n\nfunction wrapLineWithCid(line: string, tag: 'del' | 'ins', cid: string): string {\n if (line === '' || line.trim() === '') return line\n if (UNSAFE_LINE.test(line)) {\n return `<${tag} data-cid=\"${cid}\">${escapeForHtmlTag(line)}</${tag}>`\n }\n const m = line.match(STRUCTURAL_PREFIX)\n if (m) {\n const prefix = m[1]\n const rest = line.slice(prefix.length)\n if (rest === '') return line\n return `${prefix}<${tag} data-cid=\"${cid}\">${escapeForHtmlTag(rest)}</${tag}>`\n }\n return `<${tag} data-cid=\"${cid}\">${escapeForHtmlTag(line)}</${tag}>`\n}\n\nfunction wrapBlockWithCid(block: string, tag: 'del' | 'ins', cid: string): string {\n const lines = block.split('\\n')\n return lines\n .map((line, i) => {\n const wrapped = wrapLineWithCid(line, tag, cid)\n return i < lines.length - 1 ? wrapped + '\\n' : wrapped\n })\n .join('')\n}\n\n// Word-level region emission inside a safe [REM, ADD] pair.\nfunction emitWordLevelRegions(\n basePara: string,\n comparePara: string,\n reserveId: (kind: RegionKind, baseT: string, compareT: string) => string,\n regions: RedlineRegion[]\n): string {\n const wordChanges = diffWords(basePara, comparePara)\n const out: string[] = []\n let k = 0\n while (k < wordChanges.length) {\n const w = wordChanges[k]\n const wNext = wordChanges[k + 1]\n if (w.removed && wNext?.added) {\n const id = reserveId('replace', w.value, wNext.value)\n regions.push({ id, kind: 'replace', baseText: w.value, compareText: wNext.value })\n out.push(`<del data-cid=\"${id}\">${escapeForHtmlTag(w.value)}</del>`)\n out.push(`<ins data-cid=\"${id}\">${escapeForHtmlTag(wNext.value)}</ins>`)\n k += 2\n } else if (w.removed) {\n const id = reserveId('remove', w.value, '')\n regions.push({ id, kind: 'remove', baseText: w.value, compareText: '' })\n out.push(`<del data-cid=\"${id}\">${escapeForHtmlTag(w.value)}</del>`)\n k++\n } else if (w.added) {\n const id = reserveId('add', '', w.value)\n regions.push({ id, kind: 'add', baseText: '', compareText: w.value })\n out.push(`<ins data-cid=\"${id}\">${escapeForHtmlTag(w.value)}</ins>`)\n k++\n } else {\n out.push(w.value)\n k++\n }\n }\n return out.join('')\n}\n\nexport function buildHybridRedlineWithRegions(\n baseText: string,\n compareText: string\n): RedlineWithRegions {\n const lineChanges = diffLines(baseText, compareText)\n const { moveByIndex, moveRegions } = detectMoves(lineChanges)\n const out: string[] = []\n const regions: RedlineRegion[] = [...moveRegions]\n const seenIds = new Map<string, number>()\n\n const reserveId = (kind: RegionKind, baseT: string, compareT: string): string => {\n const baseHash = fnv1aHex(kind, baseT, compareT)\n const seq = seenIds.get(baseHash) ?? 0\n seenIds.set(baseHash, seq + 1)\n return makeRegionId(kind, baseT, compareT, seq)\n }\n\n for (let i = 0; i < lineChanges.length; i++) {\n const cur = lineChanges[i]\n const next = lineChanges[i + 1]\n const moveId = moveByIndex.get(i)\n\n if (moveId) {\n const tag = cur.removed ? 'del' : 'ins'\n out.push(wrapBlockWithCid(cur.value, tag, moveId))\n continue\n }\n\n if (cur.removed && next?.added) {\n if (pairContainsUnsafeLine(cur.value) || pairContainsUnsafeLine(next.value)) {\n const id = reserveId('replace', cur.value, next.value)\n regions.push({ id, kind: 'replace', baseText: cur.value, compareText: next.value })\n out.push(wrapBlockWithCid(cur.value, 'del', id))\n out.push(wrapBlockWithCid(next.value, 'ins', id))\n } else {\n out.push(emitWordLevelRegions(cur.value, next.value, reserveId, regions))\n }\n i++\n } else if (cur.removed) {\n const id = reserveId('remove', cur.value, '')\n regions.push({ id, kind: 'remove', baseText: cur.value, compareText: '' })\n out.push(wrapBlockWithCid(cur.value, 'del', id))\n } else if (cur.added) {\n const id = reserveId('add', '', cur.value)\n regions.push({ id, kind: 'add', baseText: '', compareText: cur.value })\n out.push(wrapBlockWithCid(cur.value, 'ins', id))\n } else {\n out.push(cur.value)\n }\n }\n\n return { markdown: out.join(''), regions }\n}\n\n// Word-level partial revert inside a [REM, ADD] pair.\nfunction revertWordRegion(\n basePara: string,\n comparePara: string,\n targetId: string,\n reserveId: (kind: RegionKind, baseT: string, compareT: string) => string\n): { text: string; matched: boolean } {\n const wordChanges = diffWords(basePara, comparePara)\n const out: string[] = []\n let matched = false\n let k = 0\n while (k < wordChanges.length) {\n const w = wordChanges[k]\n const wNext = wordChanges[k + 1]\n if (w.removed && wNext?.added) {\n const id = reserveId('replace', w.value, wNext.value)\n if (id === targetId) {\n out.push(w.value)\n matched = true\n } else {\n out.push(wNext.value)\n }\n k += 2\n } else if (w.removed) {\n const id = reserveId('remove', w.value, '')\n if (id === targetId) {\n out.push(w.value)\n matched = true\n }\n k++\n } else if (w.added) {\n const id = reserveId('add', '', w.value)\n if (id !== targetId) {\n out.push(w.value)\n } else {\n matched = true\n }\n k++\n } else {\n out.push(w.value)\n k++\n }\n }\n return { text: out.join(''), matched }\n}\n\n// Apply a per-region revert: rebuild the working-tree text from scratch by\n// walking the same diff and treating the target region as unchanged from\n// the base. Walking the diff ourselves (rather than string-replacing in the\n// working tree) means we don't have to worry about ambiguous matches.\nexport function revertRedlineRegion(\n baseText: string,\n compareText: string,\n targetId: string\n): string {\n const lineChanges = diffLines(baseText, compareText)\n const { moveByIndex } = detectMoves(lineChanges)\n const out: string[] = []\n const seenIds = new Map<string, number>()\n\n const reserveId = (kind: RegionKind, baseT: string, compareT: string): string => {\n const baseHash = fnv1aHex(kind, baseT, compareT)\n const seq = seenIds.get(baseHash) ?? 0\n seenIds.set(baseHash, seq + 1)\n return makeRegionId(kind, baseT, compareT, seq)\n }\n\n for (let i = 0; i < lineChanges.length; i++) {\n const cur = lineChanges[i]\n const next = lineChanges[i + 1]\n const moveId = moveByIndex.get(i)\n\n if (moveId) {\n if (moveId === targetId) {\n if (cur.removed) out.push(cur.value)\n } else {\n if (cur.added) out.push(cur.value)\n }\n continue\n }\n\n if (cur.removed && next?.added) {\n if (pairContainsUnsafeLine(cur.value) || pairContainsUnsafeLine(next.value)) {\n const id = reserveId('replace', cur.value, next.value)\n out.push(id === targetId ? cur.value : next.value)\n } else {\n const { text, matched } = revertWordRegion(cur.value, next.value, targetId, reserveId)\n out.push(matched ? text : next.value)\n }\n i++\n } else if (cur.removed) {\n const id = reserveId('remove', cur.value, '')\n if (id === targetId) out.push(cur.value)\n } else if (cur.added) {\n const id = reserveId('add', '', cur.value)\n if (id !== targetId) out.push(cur.value)\n } else {\n out.push(cur.value)\n }\n }\n\n return out.join('')\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/artifacts/redline-diff.ts"],"names":["diffLines","diffWords"],"mappings":"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","file":"chunk-VJWAP2HJ.cjs","sourcesContent":["/**\n * Redline diff core\n *\n * Pure (no DOM, no Worker globals) logic for building a Word-style redline\n * markdown string from two flattened document texts. Lives outside the\n * worker file so it's straightforward to unit test.\n *\n * Strategy: hybrid line + word diff with structural safety.\n * 1. `diffLines` splits the texts into add/remove/equal blocks.\n * 2. For an adjacent [removed, added] pair (a modified region):\n * - If either side contains markdown structure that can't safely host\n * inline tags (code fences, table rows, horizontal rules), fall back\n * to block-level wrapping (whole-line del/ins, line by line).\n * - Otherwise run `diffWords`. Markdown leading markers (#, -, *, 1., >)\n * become unchanged word tokens, so when only the heading/list text\n * changes the marker stays *outside* the inline tags and the heading\n * still parses.\n * 3. Pure removed / added blocks (no paired counterpart) are wrapped\n * line-by-line so structural prefixes stay outside the tag.\n */\n\nimport { diffLines, diffWords } from 'diff'\n\n// Lines that can't safely host inline <del>/<ins> tags without breaking\n// markdown parsing. Code fences, table rows, and horizontal rules.\nconst UNSAFE_LINE = /^(?:\\s*(?:```|~~~).*|\\s*\\|.*\\||\\s*(?:[-=*_]\\s*){3,})\\s*$/\n\n// Block-level markdown structural prefix. When present on a line, putting\n// it INSIDE an inline tag stops the heading/list/blockquote from parsing,\n// so we always preserve it outside the wrapping tag.\nconst STRUCTURAL_PREFIX = /^(\\s*(?:#{1,6}\\s+|[-*+]\\s+|\\d+[.)]\\s+|>\\s*)+)/\n\nfunction escapeForHtmlTag(text: string): string {\n return text.replace(/</g, '&lt;').replace(/>/g, '&gt;')\n}\n\nfunction wrapLineAsRedline(line: string, tag: 'del' | 'ins'): string {\n if (line === '' || line.trim() === '') return line\n if (UNSAFE_LINE.test(line)) {\n return `<${tag}>${escapeForHtmlTag(line)}</${tag}>`\n }\n const m = line.match(STRUCTURAL_PREFIX)\n if (m) {\n const prefix = m[1]\n const rest = line.slice(prefix.length)\n if (rest === '') return line\n return `${prefix}<${tag}>${escapeForHtmlTag(rest)}</${tag}>`\n }\n return `<${tag}>${escapeForHtmlTag(line)}</${tag}>`\n}\n\nfunction wrapBlockAsRedline(block: string, tag: 'del' | 'ins'): string {\n const lines = block.split('\\n')\n return lines\n .map((line, i) => {\n const wrapped = wrapLineAsRedline(line, tag)\n return i < lines.length - 1 ? wrapped + '\\n' : wrapped\n })\n .join('')\n}\n\nfunction pairContainsUnsafeLine(text: string): boolean {\n for (const line of text.split('\\n')) {\n if (UNSAFE_LINE.test(line)) return true\n }\n return false\n}\n\nexport function buildHybridRedlineMarkdown(baseText: string, compareText: string): string {\n const lineChanges = diffLines(baseText, compareText)\n const out: string[] = []\n\n for (let i = 0; i < lineChanges.length; i++) {\n const cur = lineChanges[i]\n const next = lineChanges[i + 1]\n\n if (cur.removed && next?.added) {\n if (pairContainsUnsafeLine(cur.value) || pairContainsUnsafeLine(next.value)) {\n out.push(wrapBlockAsRedline(cur.value, 'del'))\n out.push(wrapBlockAsRedline(next.value, 'ins'))\n } else {\n const wordChanges = diffWords(cur.value, next.value)\n for (const w of wordChanges) {\n if (w.removed) out.push(`<del>${escapeForHtmlTag(w.value)}</del>`)\n else if (w.added) out.push(`<ins>${escapeForHtmlTag(w.value)}</ins>`)\n else out.push(w.value)\n }\n }\n i++ // consume the paired added entry\n } else if (cur.removed) {\n out.push(wrapBlockAsRedline(cur.value, 'del'))\n } else if (cur.added) {\n out.push(wrapBlockAsRedline(cur.value, 'ins'))\n } else {\n out.push(cur.value)\n }\n }\n\n return out.join('')\n}\n\n// ─── Regions extension ────────────────────────────────────────────────────────\n//\n// Same redline as above, but every <del>/<ins> tag carries a stable\n// `data-cid` attribute identifying the \"change region\" it belongs to. A\n// region is the smallest independently revertable change:\n//\n// - inside a safe [REM, ADD] pair, each contiguous changed-word run is its\n// own region, so a single button can revert one phrase without touching\n// other edits in the same paragraph;\n// - unsafe pairs (tables, code fences, horizontal rules) are still one\n// region for the whole block, since line-level wrapping can't safely\n// split them;\n// - a non-adjacent [removed text == added text] pair is a *move*: both\n// endpoints share one cid, render green, and one undo reverts the move.\n//\n// `revertRedlineRegion` mirrors the same walk and rebuilds the working-tree text\n// with one region \"as if it never changed\", so cids round-trip identically\n// from build → render → revert.\n\nexport type RegionKind = 'replace' | 'remove' | 'add' | 'move'\n\nexport interface RedlineRegion {\n id: string\n kind: RegionKind\n baseText: string // what the base side has for this slice\n compareText: string // what the compare side has for this slice\n}\n\nexport interface RedlineWithRegions {\n markdown: string\n regions: RedlineRegion[]\n}\n\n// Tiny deterministic hash (FNV-1a 32-bit, hex). Stable across runs and JS\n// runtimes, with no Node-only deps so this stays browser-safe.\nfunction fnv1aHex(...parts: string[]): string {\n let h = 0x811c9dc5\n for (const part of parts) {\n h ^= 0x5f5f\n h = Math.imul(h, 0x01000193) >>> 0\n for (let i = 0; i < part.length; i++) {\n h ^= part.charCodeAt(i)\n h = Math.imul(h, 0x01000193) >>> 0\n }\n }\n return ('00000000' + h.toString(16)).slice(-8)\n}\n\n// First char of the cid encodes the kind so consumers can style without a\n// region-table lookup: p=replace r=remove a=add m=move.\nfunction makeRegionId(\n kind: RegionKind,\n baseText: string,\n compareText: string,\n seq: number\n): string {\n const prefix = kind === 'replace' ? 'p' : kind === 'remove' ? 'r' : kind === 'add' ? 'a' : 'm'\n return `${prefix}${fnv1aHex(kind, baseText, compareText, String(seq))}`\n}\n\n// Move detection: a non-adjacent removed/added pair with identical text is a\n// move. Returns the move endpoints' lineChanges-indices plus a region per\n// distinct move.\nfunction detectMoves(lineChanges: { value: string; removed?: boolean; added?: boolean }[]): {\n moveByIndex: Map<number, string>\n moveRegions: RedlineRegion[]\n} {\n const moveByIndex = new Map<number, string>()\n const moveRegions: RedlineRegion[] = []\n const removedByText = new Map<string, number[]>()\n const addedByText = new Map<string, number[]>()\n\n for (let i = 0; i < lineChanges.length; i++) {\n const c = lineChanges[i]\n if (c.removed) {\n const arr = removedByText.get(c.value) ?? []\n arr.push(i)\n removedByText.set(c.value, arr)\n } else if (c.added) {\n const arr = addedByText.get(c.value) ?? []\n arr.push(i)\n addedByText.set(c.value, arr)\n }\n }\n\n let seq = 0\n for (const [text, removedIdx] of removedByText) {\n const addedIdx = addedByText.get(text)\n if (!addedIdx || addedIdx.length === 0) continue\n if (text.trim().length === 0) continue\n const n = Math.min(removedIdx.length, addedIdx.length)\n for (let k = 0; k < n; k++) {\n const rI = removedIdx[k]\n const aI = addedIdx[k]\n if (aI === rI + 1 || rI === aI + 1) continue // adjacent = replace, not move\n if (moveByIndex.has(rI) || moveByIndex.has(aI)) continue\n const id = makeRegionId('move', text, text, seq++)\n moveByIndex.set(rI, id)\n moveByIndex.set(aI, id)\n moveRegions.push({ id, kind: 'move', baseText: text, compareText: text })\n }\n }\n\n return { moveByIndex, moveRegions }\n}\n\nfunction wrapLineWithCid(line: string, tag: 'del' | 'ins', cid: string): string {\n if (line === '' || line.trim() === '') return line\n if (UNSAFE_LINE.test(line)) {\n return `<${tag} data-cid=\"${cid}\">${escapeForHtmlTag(line)}</${tag}>`\n }\n const m = line.match(STRUCTURAL_PREFIX)\n if (m) {\n const prefix = m[1]\n const rest = line.slice(prefix.length)\n if (rest === '') return line\n return `${prefix}<${tag} data-cid=\"${cid}\">${escapeForHtmlTag(rest)}</${tag}>`\n }\n return `<${tag} data-cid=\"${cid}\">${escapeForHtmlTag(line)}</${tag}>`\n}\n\nfunction wrapBlockWithCid(block: string, tag: 'del' | 'ins', cid: string): string {\n const lines = block.split('\\n')\n return lines\n .map((line, i) => {\n const wrapped = wrapLineWithCid(line, tag, cid)\n return i < lines.length - 1 ? wrapped + '\\n' : wrapped\n })\n .join('')\n}\n\n// Word-level region emission inside a safe [REM, ADD] pair.\nfunction emitWordLevelRegions(\n basePara: string,\n comparePara: string,\n reserveId: (kind: RegionKind, baseT: string, compareT: string) => string,\n regions: RedlineRegion[]\n): string {\n const wordChanges = diffWords(basePara, comparePara)\n const out: string[] = []\n let k = 0\n while (k < wordChanges.length) {\n const w = wordChanges[k]\n const wNext = wordChanges[k + 1]\n if (w.removed && wNext?.added) {\n const id = reserveId('replace', w.value, wNext.value)\n regions.push({ id, kind: 'replace', baseText: w.value, compareText: wNext.value })\n out.push(`<del data-cid=\"${id}\">${escapeForHtmlTag(w.value)}</del>`)\n out.push(`<ins data-cid=\"${id}\">${escapeForHtmlTag(wNext.value)}</ins>`)\n k += 2\n } else if (w.removed) {\n const id = reserveId('remove', w.value, '')\n regions.push({ id, kind: 'remove', baseText: w.value, compareText: '' })\n out.push(`<del data-cid=\"${id}\">${escapeForHtmlTag(w.value)}</del>`)\n k++\n } else if (w.added) {\n const id = reserveId('add', '', w.value)\n regions.push({ id, kind: 'add', baseText: '', compareText: w.value })\n out.push(`<ins data-cid=\"${id}\">${escapeForHtmlTag(w.value)}</ins>`)\n k++\n } else {\n out.push(w.value)\n k++\n }\n }\n return out.join('')\n}\n\nexport function buildHybridRedlineWithRegions(\n baseText: string,\n compareText: string\n): RedlineWithRegions {\n const lineChanges = diffLines(baseText, compareText)\n const { moveByIndex, moveRegions } = detectMoves(lineChanges)\n const out: string[] = []\n const regions: RedlineRegion[] = [...moveRegions]\n const seenIds = new Map<string, number>()\n\n const reserveId = (kind: RegionKind, baseT: string, compareT: string): string => {\n const baseHash = fnv1aHex(kind, baseT, compareT)\n const seq = seenIds.get(baseHash) ?? 0\n seenIds.set(baseHash, seq + 1)\n return makeRegionId(kind, baseT, compareT, seq)\n }\n\n for (let i = 0; i < lineChanges.length; i++) {\n const cur = lineChanges[i]\n const next = lineChanges[i + 1]\n const moveId = moveByIndex.get(i)\n\n if (moveId) {\n const tag = cur.removed ? 'del' : 'ins'\n out.push(wrapBlockWithCid(cur.value, tag, moveId))\n continue\n }\n\n if (cur.removed && next?.added) {\n if (pairContainsUnsafeLine(cur.value) || pairContainsUnsafeLine(next.value)) {\n const id = reserveId('replace', cur.value, next.value)\n regions.push({ id, kind: 'replace', baseText: cur.value, compareText: next.value })\n out.push(wrapBlockWithCid(cur.value, 'del', id))\n out.push(wrapBlockWithCid(next.value, 'ins', id))\n } else {\n out.push(emitWordLevelRegions(cur.value, next.value, reserveId, regions))\n }\n i++\n } else if (cur.removed) {\n const id = reserveId('remove', cur.value, '')\n regions.push({ id, kind: 'remove', baseText: cur.value, compareText: '' })\n out.push(wrapBlockWithCid(cur.value, 'del', id))\n } else if (cur.added) {\n const id = reserveId('add', '', cur.value)\n regions.push({ id, kind: 'add', baseText: '', compareText: cur.value })\n out.push(wrapBlockWithCid(cur.value, 'ins', id))\n } else {\n out.push(cur.value)\n }\n }\n\n return { markdown: out.join(''), regions }\n}\n\n// Word-level partial revert inside a [REM, ADD] pair.\nfunction revertWordRegion(\n basePara: string,\n comparePara: string,\n targetId: string,\n reserveId: (kind: RegionKind, baseT: string, compareT: string) => string\n): { text: string; matched: boolean } {\n const wordChanges = diffWords(basePara, comparePara)\n const out: string[] = []\n let matched = false\n let k = 0\n while (k < wordChanges.length) {\n const w = wordChanges[k]\n const wNext = wordChanges[k + 1]\n if (w.removed && wNext?.added) {\n const id = reserveId('replace', w.value, wNext.value)\n if (id === targetId) {\n out.push(w.value)\n matched = true\n } else {\n out.push(wNext.value)\n }\n k += 2\n } else if (w.removed) {\n const id = reserveId('remove', w.value, '')\n if (id === targetId) {\n out.push(w.value)\n matched = true\n }\n k++\n } else if (w.added) {\n const id = reserveId('add', '', w.value)\n if (id !== targetId) {\n out.push(w.value)\n } else {\n matched = true\n }\n k++\n } else {\n out.push(w.value)\n k++\n }\n }\n return { text: out.join(''), matched }\n}\n\n// Apply a per-region revert: rebuild the working-tree text from scratch by\n// walking the same diff and treating the target region as unchanged from\n// the base. Walking the diff ourselves (rather than string-replacing in the\n// working tree) means we don't have to worry about ambiguous matches.\nexport function revertRedlineRegion(\n baseText: string,\n compareText: string,\n targetId: string\n): string {\n const lineChanges = diffLines(baseText, compareText)\n const { moveByIndex } = detectMoves(lineChanges)\n const out: string[] = []\n const seenIds = new Map<string, number>()\n\n const reserveId = (kind: RegionKind, baseT: string, compareT: string): string => {\n const baseHash = fnv1aHex(kind, baseT, compareT)\n const seq = seenIds.get(baseHash) ?? 0\n seenIds.set(baseHash, seq + 1)\n return makeRegionId(kind, baseT, compareT, seq)\n }\n\n for (let i = 0; i < lineChanges.length; i++) {\n const cur = lineChanges[i]\n const next = lineChanges[i + 1]\n const moveId = moveByIndex.get(i)\n\n if (moveId) {\n if (moveId === targetId) {\n if (cur.removed) out.push(cur.value)\n } else {\n if (cur.added) out.push(cur.value)\n }\n continue\n }\n\n if (cur.removed && next?.added) {\n if (pairContainsUnsafeLine(cur.value) || pairContainsUnsafeLine(next.value)) {\n const id = reserveId('replace', cur.value, next.value)\n out.push(id === targetId ? cur.value : next.value)\n } else {\n const { text, matched } = revertWordRegion(cur.value, next.value, targetId, reserveId)\n out.push(matched ? text : next.value)\n }\n i++\n } else if (cur.removed) {\n const id = reserveId('remove', cur.value, '')\n if (id === targetId) out.push(cur.value)\n } else if (cur.added) {\n const id = reserveId('add', '', cur.value)\n if (id !== targetId) out.push(cur.value)\n } else {\n out.push(cur.value)\n }\n }\n\n return out.join('')\n}\n"]}