@arbidocs/react 0.4.10 → 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.
@@ -1,8 +1,50 @@
1
1
  'use strict';
2
2
 
3
+ var unified = require('unified');
4
+ var remarkParse = require('remark-parse');
5
+ var remarkGfm = require('remark-gfm');
6
+ var remarkStringify = require('remark-stringify');
3
7
  var diff = require('diff');
4
8
 
5
- // src/artifacts/redline-diff.ts
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var remarkParse__default = /*#__PURE__*/_interopDefault(remarkParse);
12
+ var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
13
+ var remarkStringify__default = /*#__PURE__*/_interopDefault(remarkStringify);
14
+
15
+ // src/artifacts/normalize-markdown.ts
16
+ var INTRAWORD_ESCAPED_UNDERSCORE = /(?<=[\p{L}\p{N}])\\_(?=[\p{L}\p{N}])/gu;
17
+ var processor = unified.unified().use(remarkParse__default.default).use(remarkGfm__default.default, { tablePipeAlign: false }).use(remarkStringify__default.default, {
18
+ bullet: "-",
19
+ bulletOther: "*",
20
+ emphasis: "*",
21
+ strong: "*",
22
+ fence: "`",
23
+ fences: true,
24
+ rule: "-",
25
+ listItemIndent: "one",
26
+ incrementListMarker: true,
27
+ resourceLink: false,
28
+ handlers: {
29
+ text: (node, _parent, state, info) => state.safe(node.value, info).replace(INTRAWORD_ESCAPED_UNDERSCORE, "_")
30
+ }
31
+ });
32
+ var cache = /* @__PURE__ */ new Map();
33
+ var CACHE_LIMIT = 16;
34
+ function normalizeMarkdown(text) {
35
+ if (!text) return "";
36
+ const hit = cache.get(text);
37
+ if (hit !== void 0) return hit;
38
+ let out;
39
+ try {
40
+ out = String(processor.processSync(text.replace(/\r\n?/g, "\n"))).replace(/\n*$/, "\n");
41
+ } catch {
42
+ out = text.replace(/\r\n?/g, "\n").replace(/[ \t]+$/gm, "");
43
+ }
44
+ if (cache.size >= CACHE_LIMIT) cache.delete(cache.keys().next().value);
45
+ cache.set(text, out);
46
+ return out;
47
+ }
6
48
  var UNSAFE_LINE = /^(?:\s*(?:```|~~~).*|\s*\|.*\||\s*(?:[-=*_]\s*){3,})\s*$/;
7
49
  var STRUCTURAL_PREFIX = /^(\s*(?:#{1,6}\s+|[-*+]\s+|\d+[.)]\s+|>\s*)+)/;
8
50
  function escapeForHtmlTag(text) {
@@ -35,7 +77,12 @@ function pairContainsUnsafeLine(text) {
35
77
  }
36
78
  return false;
37
79
  }
38
- function buildHybridRedlineMarkdown(baseText, compareText) {
80
+ function matchTail(result, raw) {
81
+ return raw.endsWith("\n") ? result : result.replace(/\n$/, "");
82
+ }
83
+ function buildHybridRedlineMarkdown(rawBase, rawCompare) {
84
+ const baseText = normalizeMarkdown(rawBase);
85
+ const compareText = normalizeMarkdown(rawCompare);
39
86
  const lineChanges = diff.diffLines(baseText, compareText);
40
87
  const out = [];
41
88
  for (let i = 0; i < lineChanges.length; i++) {
@@ -62,7 +109,7 @@ function buildHybridRedlineMarkdown(baseText, compareText) {
62
109
  out.push(cur.value);
63
110
  }
64
111
  }
65
- return out.join("");
112
+ return matchTail(out.join(""), rawCompare);
66
113
  }
67
114
  function fnv1aHex(...parts) {
68
115
  let h = 2166136261;
@@ -167,7 +214,9 @@ function emitWordLevelRegions(basePara, comparePara, reserveId, regions) {
167
214
  }
168
215
  return out.join("");
169
216
  }
170
- function buildHybridRedlineWithRegions(baseText, compareText) {
217
+ function buildHybridRedlineWithRegions(rawBase, rawCompare) {
218
+ const baseText = normalizeMarkdown(rawBase);
219
+ const compareText = normalizeMarkdown(rawCompare);
171
220
  const lineChanges = diff.diffLines(baseText, compareText);
172
221
  const { moveByIndex, moveRegions } = detectMoves(lineChanges);
173
222
  const out = [];
@@ -210,7 +259,7 @@ function buildHybridRedlineWithRegions(baseText, compareText) {
210
259
  out.push(cur.value);
211
260
  }
212
261
  }
213
- return { markdown: out.join(""), regions };
262
+ return { markdown: matchTail(out.join(""), rawCompare), regions };
214
263
  }
215
264
  function revertWordRegion(basePara, comparePara, targetId, reserveId) {
216
265
  const wordChanges = diff.diffWords(basePara, comparePara);
@@ -251,7 +300,9 @@ function revertWordRegion(basePara, comparePara, targetId, reserveId) {
251
300
  }
252
301
  return { text: out.join(""), matched };
253
302
  }
254
- function revertRedlineRegion(baseText, compareText, targetId) {
303
+ function revertRedlineRegion(rawBase, rawCompare, targetId) {
304
+ const baseText = normalizeMarkdown(rawBase);
305
+ const compareText = normalizeMarkdown(rawCompare);
255
306
  const lineChanges = diff.diffLines(baseText, compareText);
256
307
  const { moveByIndex } = detectMoves(lineChanges);
257
308
  const out = [];
@@ -293,11 +344,12 @@ function revertRedlineRegion(baseText, compareText, targetId) {
293
344
  out.push(cur.value);
294
345
  }
295
346
  }
296
- return out.join("");
347
+ return matchTail(out.join(""), rawCompare);
297
348
  }
298
349
 
299
350
  exports.buildHybridRedlineMarkdown = buildHybridRedlineMarkdown;
300
351
  exports.buildHybridRedlineWithRegions = buildHybridRedlineWithRegions;
352
+ exports.normalizeMarkdown = normalizeMarkdown;
301
353
  exports.revertRedlineRegion = revertRedlineRegion;
302
- //# sourceMappingURL=chunk-VJWAP2HJ.cjs.map
303
- //# sourceMappingURL=chunk-VJWAP2HJ.cjs.map
354
+ //# sourceMappingURL=chunk-PATLJSAO.cjs.map
355
+ //# sourceMappingURL=chunk-PATLJSAO.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/artifacts/normalize-markdown.ts","../src/artifacts/redline-diff.ts"],"names":["unified","remarkParse","remarkGfm","remarkStringify","diffLines","diffWords"],"mappings":"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","file":"chunk-PATLJSAO.cjs","sourcesContent":["/**\n * Canonical markdown form. Two texts with the same meaning but different spelling (an editor that\n * escapes `_` and `*`, `*` vs `-` bullets, padded tables, trailing spaces, `&amp;` entities, CRLF)\n * normalise to the identical string, so a diff only reports real edits.\n *\n * Both sides are parsed with the same remark pipeline and re-stringified with fixed options. Pure\n * JS with no DOM, so it runs in a Web Worker too.\n */\nimport { unified } from 'unified'\nimport remarkParse from 'remark-parse'\nimport remarkGfm from 'remark-gfm'\nimport remarkStringify from 'remark-stringify'\n\n// An underscore between two word characters can never open emphasis (CommonMark), so the escape\n// the serializer adds there is noise. Only text nodes are touched: code keeps its backslashes.\nconst INTRAWORD_ESCAPED_UNDERSCORE = /(?<=[\\p{L}\\p{N}])\\\\_(?=[\\p{L}\\p{N}])/gu\n\nconst processor = unified()\n .use(remarkParse)\n // No column alignment: padding would make one wider cell re-space every row of the table.\n .use(remarkGfm, { tablePipeAlign: false })\n .use(remarkStringify, {\n bullet: '-',\n bulletOther: '*',\n emphasis: '*',\n strong: '*',\n fence: '`',\n fences: true,\n rule: '-',\n listItemIndent: 'one',\n incrementListMarker: true,\n resourceLink: false,\n handlers: {\n text: (node, _parent, state, info) =>\n state.safe(node.value, info).replace(INTRAWORD_ESCAPED_UNDERSCORE, '_'),\n },\n })\n\nconst cache = new Map<string, string>()\nconst CACHE_LIMIT = 16\n\n/** Normalise markdown to its canonical spelling. Falls back to a light cleanup if parsing throws. */\nexport function normalizeMarkdown(text: string): string {\n if (!text) return ''\n const hit = cache.get(text)\n if (hit !== undefined) return hit\n let out: string\n try {\n out = String(processor.processSync(text.replace(/\\r\\n?/g, '\\n'))).replace(/\\n*$/, '\\n')\n } catch {\n out = text.replace(/\\r\\n?/g, '\\n').replace(/[ \\t]+$/gm, '')\n }\n if (cache.size >= CACHE_LIMIT) cache.delete(cache.keys().next().value as string)\n cache.set(text, out)\n return out\n}\n","/**\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'\nimport { normalizeMarkdown } from './normalize-markdown'\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\n// The canonical text always ends in one newline; give a result back the caller's own ending.\nfunction matchTail(result: string, raw: string): string {\n return raw.endsWith('\\n') ? result : result.replace(/\\n$/, '')\n}\n\nexport function buildHybridRedlineMarkdown(rawBase: string, rawCompare: string): string {\n // Both sides go through one canonical form so escaping-only differences are not changes.\n const baseText = normalizeMarkdown(rawBase)\n const compareText = normalizeMarkdown(rawCompare)\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 matchTail(out.join(''), rawCompare)\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 rawBase: string,\n rawCompare: string\n): RedlineWithRegions {\n const baseText = normalizeMarkdown(rawBase)\n const compareText = normalizeMarkdown(rawCompare)\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: matchTail(out.join(''), rawCompare), 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(rawBase: string, rawCompare: string, targetId: string): string {\n const baseText = normalizeMarkdown(rawBase)\n const compareText = normalizeMarkdown(rawCompare)\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 matchTail(out.join(''), rawCompare)\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { useArbi } from './chunk-J4MX2W4H.js';
2
1
  import { normalizeCitationMarkup } from './chunk-TGGQGFS3.js';
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
 
@@ -400,5 +400,5 @@ function cleanDraftMarkdown(raw) {
400
400
  }
401
401
 
402
402
  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 };
403
- //# sourceMappingURL=chunk-UV5ZEUNV.js.map
404
- //# sourceMappingURL=chunk-UV5ZEUNV.js.map
403
+ //# sourceMappingURL=chunk-QFELRTTG.js.map
404
+ //# sourceMappingURL=chunk-QFELRTTG.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/credits.ts","../src/hooks.ts","../src/ai/stored-markdown.ts"],"names":[],"mappings":"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","file":"chunk-UV5ZEUNV.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","/**\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\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_LINK = /\\[([^\\]\\n]+)\\]\\(#cite-[\\w-]+\\)/g\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 = line.includes('](#cite-') ? line.replace(CITE_LINK, '$1') : line\n return unlinked === line ? line : balanceBold(unlinked)\n })\n}\n\nconst HEADING = /^#{1,6}\\s/\n/** A whole-line bold title: `**Client Engagement Letter**`. */\nconst BOLD_LINE = /^\\*\\*[^*#].*[^*]\\*\\*$/\n/** How far down a bold line may sit and still be the document's title. */\nconst TITLE_SEARCH_LINES = 15\nconst MAX_PREAMBLE_CHARS = 1200\n\n/** First person, an announcement of the task or a pointer at the instructions: an agent talking. */\nconst NARRATION =\n /\\b(?:I|I'll|I’ll|I've|I’ve|I'm|I’m|I will|I have|I now|I am)\\b|\\b(?:let me|here is|here's|here’s|below is|per the instructions|as requested|based on (?:the|your)|the workspace (?:contains|has|does)|no (?:relevant )?documents? (?:were|was) found)\\b/i\n\n/** Structure a covering note would not have: lists, tables, quotes, code, headings. */\nconst STRUCTURED = /^\\s*(?:[-*+>|]|\\d{1,9}[.)]\\s|#{1,6}\\s|```|~~~)/m\n\n/**\n * Cut what an agent wrote BEFORE the document, when it is narration.\n *\n * HEURISTIC (conservative, so a document is never trimmed by mistake). The document is taken to\n * start at the first `#` heading, or, when there is none, at the first whole-line bold title within\n * the first 15 lines. The text before it is removed only when ALL of these hold:\n * 1. it is short (at most 1200 characters);\n * 2. it is plain prose: no list, table, quote, code or heading;\n * 3. it reads like the agent talking: first person (\"I'll draft ...\"), \"Here is ...\", \"Per the\n * instructions\", \"Based on the ...\" and the like.\n * A document that opens with a dateline, an address or any text that does not trip rule 3 is kept\n * whole. A horizontal rule left at the end of the cut text is dropped with it.\n */\nexport function stripAgentPreamble(text: string): string {\n const lines = text.split('\\n')\n let start = lines.findIndex((l) => HEADING.test(l))\n if (start < 0)\n start = lines.slice(0, TITLE_SEARCH_LINES).findIndex((l) => BOLD_LINE.test(l.trim()))\n if (start <= 0) return text\n const before = lines.slice(0, start).join('\\n').trim()\n if (!before) return lines.slice(start).join('\\n')\n const prose = before.replace(/^\\s*(?:-{3,}|\\*{3,}|_{3,})\\s*$/gm, '').trim()\n if (prose.length > MAX_PREAMBLE_CHARS || STRUCTURED.test(prose) || !NARRATION.test(prose)) {\n return text\n }\n return lines.slice(start).join('\\n')\n}\n\n/**\n * Make the document's title a real heading: a first line that is a bold title (`**Letter**`, even\n * with stray inner `**`) becomes `# Letter`. A document that already opens with a heading is left\n * 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 title = lines[first].trim()\n if (!/^\\*\\*[^*#]/.test(title) || title.length >= 160 || !/\\*\\*$/.test(title)) return text\n lines[first] = `# ${title.replace(/\\*\\*/g, '').trim()}`\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/**\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.\n */\nexport function cleanDraftMarkdown(raw: string): string {\n const stripped = stripAgentPreamble(unwrapCitationLinks(raw))\n return cleanHeadings(promoteBoldTitle(stripped))\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n}\n"]}
1
+ {"version":3,"sources":["../src/credits.ts","../src/hooks.ts","../src/ai/stored-markdown.ts"],"names":[],"mappings":"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","file":"chunk-QFELRTTG.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","/**\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\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_LINK = /\\[([^\\]\\n]+)\\]\\(#cite-[\\w-]+\\)/g\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 = line.includes('](#cite-') ? line.replace(CITE_LINK, '$1') : line\n return unlinked === line ? line : balanceBold(unlinked)\n })\n}\n\nconst HEADING = /^#{1,6}\\s/\n/** A whole-line bold title: `**Client Engagement Letter**`. */\nconst BOLD_LINE = /^\\*\\*[^*#].*[^*]\\*\\*$/\n/** How far down a bold line may sit and still be the document's title. */\nconst TITLE_SEARCH_LINES = 15\nconst MAX_PREAMBLE_CHARS = 1200\n\n/** First person, an announcement of the task or a pointer at the instructions: an agent talking. */\nconst NARRATION =\n /\\b(?:I|I'll|I’ll|I've|I’ve|I'm|I’m|I will|I have|I now|I am)\\b|\\b(?:let me|here is|here's|here’s|below is|per the instructions|as requested|based on (?:the|your)|the workspace (?:contains|has|does)|no (?:relevant )?documents? (?:were|was) found)\\b/i\n\n/** Structure a covering note would not have: lists, tables, quotes, code, headings. */\nconst STRUCTURED = /^\\s*(?:[-*+>|]|\\d{1,9}[.)]\\s|#{1,6}\\s|```|~~~)/m\n\n/**\n * Cut what an agent wrote BEFORE the document, when it is narration.\n *\n * HEURISTIC (conservative, so a document is never trimmed by mistake). The document is taken to\n * start at the first `#` heading, or, when there is none, at the first whole-line bold title within\n * the first 15 lines. The text before it is removed only when ALL of these hold:\n * 1. it is short (at most 1200 characters);\n * 2. it is plain prose: no list, table, quote, code or heading;\n * 3. it reads like the agent talking: first person (\"I'll draft ...\"), \"Here is ...\", \"Per the\n * instructions\", \"Based on the ...\" and the like.\n * A document that opens with a dateline, an address or any text that does not trip rule 3 is kept\n * whole. A horizontal rule left at the end of the cut text is dropped with it.\n */\nexport function stripAgentPreamble(text: string): string {\n const lines = text.split('\\n')\n let start = lines.findIndex((l) => HEADING.test(l))\n if (start < 0)\n start = lines.slice(0, TITLE_SEARCH_LINES).findIndex((l) => BOLD_LINE.test(l.trim()))\n if (start <= 0) return text\n const before = lines.slice(0, start).join('\\n').trim()\n if (!before) return lines.slice(start).join('\\n')\n const prose = before.replace(/^\\s*(?:-{3,}|\\*{3,}|_{3,})\\s*$/gm, '').trim()\n if (prose.length > MAX_PREAMBLE_CHARS || STRUCTURED.test(prose) || !NARRATION.test(prose)) {\n return text\n }\n return lines.slice(start).join('\\n')\n}\n\n/**\n * Make the document's title a real heading: a first line that is a bold title (`**Letter**`, even\n * with stray inner `**`) becomes `# Letter`. A document that already opens with a heading is left\n * 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 title = lines[first].trim()\n if (!/^\\*\\*[^*#]/.test(title) || title.length >= 160 || !/\\*\\*$/.test(title)) return text\n lines[first] = `# ${title.replace(/\\*\\*/g, '').trim()}`\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/**\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.\n */\nexport function cleanDraftMarkdown(raw: string): string {\n const stripped = stripAgentPreamble(unwrapCitationLinks(raw))\n return cleanHeadings(promoteBoldTitle(stripped))\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { getCollisionPadding, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from './chunk-N5SVBDLC.js';
2
1
  import { MarkdownRenderer } from './chunk-TGGQGFS3.js';
2
+ import { getCollisionPadding, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from './chunk-N5SVBDLC.js';
3
3
  import { cn } from './chunk-SN5YV6FF.js';
4
4
  import * as React from 'react';
5
5
  import React__default, { createContext, forwardRef, memo, useContext, useState, useRef, useEffect, useCallback, useId, Fragment as Fragment$1 } from 'react';
@@ -3666,5 +3666,5 @@ function DocumentCard({
3666
3666
  }
3667
3667
 
3668
3668
  export { AgentBadge, AiMarkdown, ArbiBotHeadIcon, AudIcon, Avatar, AvatarFallback, AvatarImage, BASE_COLORS2 as BASE_COLORS, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as 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_GRAY2 as 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, classifyMediaError, configureEntityRegistry, configureRagLabels, configureStatusRegistry, formatElapsed, getDocIcon, getEntityColor2 as getEntityColor, getEntityColorStyles, getEntityIcon, getEntityLabel, getStatusVariant, getTagTypeIcon, getTagTypeLabel, getWorkspaceColor, toggleVariants, useAudioRecorder };
3669
- //# sourceMappingURL=chunk-NVMQLJI4.js.map
3670
- //# sourceMappingURL=chunk-NVMQLJI4.js.map
3669
+ //# sourceMappingURL=chunk-RTULVZOS.js.map
3670
+ //# sourceMappingURL=chunk-RTULVZOS.js.map