@deepcitation/deepcitation-js 1.1.50 → 1.1.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +36 -105
  2. package/lib/chunk-2NSFXPOT.js +3 -0
  3. package/lib/chunk-2NSFXPOT.js.map +1 -0
  4. package/lib/chunk-BDSA6VGC.js +125 -0
  5. package/lib/chunk-BDSA6VGC.js.map +1 -0
  6. package/lib/chunk-BWQLFMTV.js +2 -0
  7. package/lib/chunk-BWQLFMTV.js.map +1 -0
  8. package/lib/chunk-DS6SOU4L.cjs +2 -0
  9. package/lib/chunk-DS6SOU4L.cjs.map +1 -0
  10. package/lib/chunk-DXWF2DZT.cjs +3 -0
  11. package/lib/chunk-DXWF2DZT.cjs.map +1 -0
  12. package/lib/{chunk-R57DQBOT.js → chunk-NQVJSWPX.js} +2 -2
  13. package/lib/chunk-NQVJSWPX.js.map +1 -0
  14. package/lib/chunk-WS4CQVDI.cjs +125 -0
  15. package/lib/chunk-WS4CQVDI.cjs.map +1 -0
  16. package/lib/chunk-XHLUZPJG.cjs +3 -0
  17. package/lib/chunk-XHLUZPJG.cjs.map +1 -0
  18. package/lib/{chunk-QUW3L3UU.cjs → chunk-ZPFYJ5C7.cjs} +2 -2
  19. package/lib/chunk-ZPFYJ5C7.cjs.map +1 -0
  20. package/lib/chunk-ZVAQJKWO.js +3 -0
  21. package/lib/chunk-ZVAQJKWO.js.map +1 -0
  22. package/lib/client/index.cjs +1 -1
  23. package/lib/client/index.d.cts +182 -13
  24. package/lib/client/index.d.ts +182 -13
  25. package/lib/client/index.js +1 -1
  26. package/lib/{index-fvVBZYVK.d.cts → index-BnL6sEku.d.cts} +156 -29
  27. package/lib/{index-fvVBZYVK.d.ts → index-BnL6sEku.d.ts} +156 -29
  28. package/lib/index.cjs +8 -1
  29. package/lib/index.cjs.map +1 -1
  30. package/lib/index.d.cts +341 -34
  31. package/lib/index.d.ts +341 -34
  32. package/lib/index.js +8 -1
  33. package/lib/index.js.map +1 -1
  34. package/lib/prompts/index.cjs +1 -1
  35. package/lib/prompts/index.d.cts +177 -55
  36. package/lib/prompts/index.d.ts +177 -55
  37. package/lib/prompts/index.js +1 -1
  38. package/lib/react/index.cjs +7 -5
  39. package/lib/react/index.cjs.map +1 -1
  40. package/lib/react/index.d.cts +546 -43
  41. package/lib/react/index.d.ts +546 -43
  42. package/lib/react/index.js +7 -5
  43. package/lib/react/index.js.map +1 -1
  44. package/lib/styles.css +1 -1
  45. package/lib/types/index.cjs +1 -1
  46. package/lib/types/index.d.cts +1 -1
  47. package/lib/types/index.d.ts +1 -1
  48. package/lib/types/index.js +1 -1
  49. package/lib/{utils-q6anRKO_.d.cts → utils-9u5S1n64.d.cts} +5 -5
  50. package/lib/{utils-DuacFTtu.d.ts → utils-wOZ3zyWd.d.ts} +5 -5
  51. package/package.json +13 -6
  52. package/lib/chunk-4ILSZKAP.cjs +0 -3
  53. package/lib/chunk-4ILSZKAP.cjs.map +0 -1
  54. package/lib/chunk-ALJ2ZQ2S.cjs +0 -3
  55. package/lib/chunk-ALJ2ZQ2S.cjs.map +0 -1
  56. package/lib/chunk-KBDVUQEE.js +0 -72
  57. package/lib/chunk-KBDVUQEE.js.map +0 -1
  58. package/lib/chunk-LLLVZOXB.js +0 -3
  59. package/lib/chunk-LLLVZOXB.js.map +0 -1
  60. package/lib/chunk-PJWAX2VG.cjs +0 -72
  61. package/lib/chunk-PJWAX2VG.cjs.map +0 -1
  62. package/lib/chunk-QUW3L3UU.cjs.map +0 -1
  63. package/lib/chunk-R57DQBOT.js.map +0 -1
  64. package/lib/chunk-TDGYSF3B.js +0 -3
  65. package/lib/chunk-TDGYSF3B.js.map +0 -1
package/README.md CHANGED
@@ -2,155 +2,86 @@
2
2
 
3
3
  # @deepcitation/deepcitation-js
4
4
 
5
- **Instantly trustworthy AI content with eliminated hallucination risk.**
5
+ **Verify AI citations against source documents. Visual proof for every claim.**
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@deepcitation/deepcitation-js.svg)](https://www.npmjs.com/package/@deepcitation/deepcitation-js)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
9
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)](https://www.npmjs.com/package/@deepcitation/deepcitation-js)
10
10
 
11
- [Documentation](https://deepcitation.com/docs) · [Get API Key](https://deepcitation.com/signup) · [Examples](./examples)
11
+ [Documentation](https://docs.deepcitation.com) · [Get API Key](https://deepcitation.com/signup) · [Examples](./examples) · [Agent Integration](./INTEGRATION.md)
12
12
 
13
13
  </div>
14
14
 
15
15
  ---
16
16
 
17
- ## Overview
17
+ **Spot hallucinations instantly.** Visual evidence for every AI citation:
18
18
 
19
- LLMs hallucinate citations and cite pages that don't exist. **Citations alone are not enough.**
19
+ <div align="center">
20
+ <a href="https://github.com/DeepCitation/deepcitation-js/blob/main/examples/assets/deepcitation-demo-medical.avif">
21
+ <img src="https://raw.githubusercontent.com/DeepCitation/deepcitation-js/main/examples/assets/deepcitation-demo-medical.avif" alt="DeepCitation Demo - solid underlines for verified citations, wavy red for hallucinations" width="600" />
22
+ </a>
23
+ </div>
20
24
 
21
- DeepCitation solves this by deterministically verifying every citation against your sources. We provide visual proof for every claim, making content instantly trustworthy and safer to present to users.
25
+ **Multiple display variants.** From inline linter-style underlines to chips, badges, and superscripts:
26
+
27
+ <details>
28
+ <summary><strong>View Component Showcase</strong></summary>
22
29
 
23
30
  <div align="center">
24
- <img src="./examples/assets/deepcitation-medical-demo.gif" alt="DeepCitation demo showing instant certainty with verified inline citations" width="700" />
25
- <br />
26
- <em>DeepCitation demo showing instant certainty with verified inline citations</em>
31
+ <img src="https://raw.githubusercontent.com/DeepCitation/deepcitation-js/main/tests/playwright/specs/__snapshots__/visualShowcase.spec.tsx-snapshots/desktop-showcase-chromium-linux.png" alt="DeepCitation Component Showcase" width="700" />
27
32
  </div>
28
33
 
29
- ```
30
- Before: "Recent results indicate 35% EF [1]" → ❓ Did the LLM make this up?
31
- After: "Recent results indicate 35% EF [1]" → ✅ Verified on page 1, line 12 (with screenshot)
32
- ```
34
+ </details>
33
35
 
34
- ## Installation
36
+ ## Install
35
37
 
36
38
  ```bash
37
39
  npm install @deepcitation/deepcitation-js
38
40
  ```
39
41
 
40
- ## Documentation
41
-
42
- Full documentation is available at [deepcitation.com/docs](https://deepcitation.com/docs).
43
-
44
42
  ## Quick Start
45
43
 
46
- DeepCitation works in three steps: **Pre-Prompt**, **Post-Prompt**, and **Display**.
47
-
48
- ### Step 1: Pre-Prompt
49
-
50
- Upload attachments and enhance your prompt with citation instructions.
51
-
52
44
  ```typescript
53
45
  import { DeepCitation, wrapCitationPrompt } from "@deepcitation/deepcitation-js";
46
+ import { CitationComponent } from "@deepcitation/deepcitation-js/react";
54
47
 
48
+ // 1. Upload sources
55
49
  const deepcitation = new DeepCitation({ apiKey: process.env.DEEPCITATION_API_KEY });
50
+ const { deepTextPromptPortion } = await deepcitation.prepareFiles([{ file: pdfBuffer, filename: "report.pdf" }]);
56
51
 
57
- // Upload source files
58
- const { fileDataParts, deepTextPromptPortion } = await deepcitation.prepareFiles([
59
- { file: pdfBuffer, filename: "report.pdf" },
60
- ]);
61
-
62
- // Wrap prompts with citation instructions
52
+ // 2. Wrap prompts & call LLM
63
53
  const { enhancedSystemPrompt, enhancedUserPrompt } = wrapCitationPrompt({
64
54
  systemPrompt: "You are a helpful assistant...",
65
55
  userPrompt: "Analyze this document",
66
56
  deepTextPromptPortion,
67
57
  });
68
58
 
69
- // Call your LLM
70
- const response = await llm.chat({
71
- messages: [
72
- { role: "system", content: enhancedSystemPrompt },
73
- { role: "user", content: enhancedUserPrompt },
74
- ],
75
- });
76
- ```
77
-
78
- ### Step 2: Post-Prompt
59
+ // 3. Verify citations
60
+ const { verifications } = await deepcitation.verify({ llmOutput: response.content });
79
61
 
80
- Verify citations against the attachments.
81
-
82
- ```typescript
83
- const result = await deepcitation.verify({
84
- llmOutput: response.content,
85
- });
86
-
87
- // result.verifications contains verification status + visual proof
88
- const { verifications } = result;
89
- ```
90
-
91
- ### Step 3: Display
92
-
93
- Parse the LLM output and render verified citations inline with React components.
94
-
95
- ```tsx
96
- import { CitationComponent } from "@deepcitation/deepcitation-js/react";
97
- import { parseCitation, generateCitationKey } from "@deepcitation/deepcitation-js";
98
- import "@deepcitation/deepcitation-js/react/styles.css";
99
-
100
- function Response({ llmOutput, verifications }) {
101
- const renderWithCitations = (text: string) => {
102
- const parts = text.split(/(<cite\s+[^>]*\/>)/g);
103
-
104
- return parts.map((part, index) => {
105
- if (part.startsWith("<cite")) {
106
- const { citation } = parseCitation(part);
107
- const citationKey = generateCitationKey(citation);
108
-
109
- return (
110
- <CitationComponent
111
- key={index}
112
- citation={citation}
113
- verification={verifications[citationKey]}
114
- />
115
- );
116
- }
117
- return <span key={index}>{part}</span>;
118
- });
119
- };
120
-
121
- return <div>{renderWithCitations(llmOutput)}</div>;
122
- }
62
+ // 4. Display with React
63
+ <CitationComponent citation={citation} verification={verifications[key]} />
123
64
  ```
124
65
 
125
- ## Examples
66
+ ## React Components
126
67
 
127
- Check out the [examples directory](./examples) for complete, runnable examples:
68
+ | Component | Description |
69
+ |-----------|-------------|
70
+ | `CitationComponent` | Inline citations with 6 variants: `linter` (default), `chip`, `brackets`, `text`, `superscript`, `badge` |
71
+ | `UrlCitationComponent` | URL citations with favicon and status badges |
128
72
 
129
- - [**basic-verification**](./examples/basic-verification) Core 3-step workflow
130
- - [**nextjs-ai-sdk**](./examples/nextjs-ai-sdk) – Full-stack Next.js chat app
131
-
132
- ```bash
133
- cd examples/basic-verification
134
- npm install
135
- cp .env.example .env # Add your API keys
136
- npm run start:openai
137
- ```
73
+ > Requires Tailwind CSS or import `@deepcitation/deepcitation-js/styles.css`
138
74
 
139
75
  ## Supported Formats
140
76
 
141
- - **Documents:** PDF (Text & Scanned), DOCX, XLSX, PPTX, HTML
142
- - **Images:** JPG, PNG, TIFF, WebP, HEIC
143
- - **Web:** Public URLs
144
-
145
- ## Support
146
-
147
- - **Feature requests:** [GitHub Discussions](https://github.com/deepcitation/deepcitation-js/discussions)
148
- - **Bug reports:** [GitHub Issues](https://github.com/deepcitation/deepcitation-js/issues)
77
+ PDF, DOCX, XLSX, PPTX, HTML, Images (JPG, PNG, TIFF, WebP, HEIC), URLs
149
78
 
150
- ## Contributing
79
+ ## Resources
151
80
 
152
- We welcome contributions! Please start a discussion in [GitHub Discussions](https://github.com/deepcitation/deepcitation-js/discussions) before submitting a pull request.
81
+ - [Full Documentation](https://docs.deepcitation.com)
82
+ - [Examples](./examples) – Basic verification, Next.js chat app
83
+ - [Integration Guide](./INTEGRATION.md) – For AI coding assistants
153
84
 
154
85
  ## License
155
86
 
156
- MIT License - see [LICENSE](./LICENSE) for details.
87
+ [MIT](./LICENSE)
@@ -0,0 +1,3 @@
1
+ import {a,b}from'./chunk-BDSA6VGC.js';function et(t){return new TextEncoder().encode(t)}function nt(t){let e=1732584193,r=4023233417,i=2562383102,n=271733878,s=3285377520,l=t.length,a=l*8,c=l+1+8,d=Math.ceil(c/64)*64,p=new ArrayBuffer(d),o=new Uint8Array(p),f=new DataView(p);o.set(t),o[l]=128,f.setUint32(d-8,Math.floor(a/4294967296),false),f.setUint32(d-4,a>>>0,false);let h=new Uint32Array(80);for(let A=0;A<d;A+=64){for(let _=0;_<16;_++)h[_]=f.getUint32(A+_*4,false);for(let _=16;_<80;_++){let I=h[_-3]^h[_-8]^h[_-14]^h[_-16];h[_]=I<<1|I>>>31;}let T=e,u=r,y=i,b=n,C=s;for(let _=0;_<80;_++){let I,x;_<20?(I=u&y|~u&b,x=1518500249):_<40?(I=u^y^b,x=1859775393):_<60?(I=u&y|u&b|y&b,x=2400959708):(I=u^y^b,x=3395469782);let m=(T<<5|T>>>27)+I+C+x+h[_]>>>0;C=b,b=y,y=(u<<30|u>>>2)>>>0,u=T,T=m;}e=e+T>>>0,r=r+u>>>0,i=i+y>>>0,n=n+b>>>0,s=s+C>>>0;}let g=A=>A.toString(16).padStart(8,"0");return g(e)+g(r)+g(i)+g(n)+g(s)}function $(t){try{if(!t)return "";let e=typeof t=="string"?t:JSON.stringify(t);return nt(et(e))}catch(e){console.error("Error in making the hash:",e);}return ""}var it={n:"id",a:"attachment_id",r:"reasoning",f:"full_phrase",k:"anchor_text",p:"page_id",l:"line_ids",t:"timestamps"};function rt(t){return typeof t=="object"&&t!==null&&"id"in t&&typeof t.id=="number"}function V(t,e){let r={};for(let[i,n]of Object.entries(t)){let s=it[i]||i;if((i==="t"||i==="timestamps")&&n&&typeof n=="object"){let l=n;r.timestamps={start_time:l.s??l.start_time,end_time:l.e??l.end_time};}else r[s]=n;}if(e&&!r.attachment_id&&(r.attachment_id=e),!rt(r))throw new Error("Invalid citation data: missing or invalid 'id' field");return r}function st(t){if(typeof t!="object"||t===null||Array.isArray(t))return false;let e=Object.values(t);return e.length>0&&e.every(Array.isArray)}function at(t){let e=[];for(let[r,i]of Object.entries(t))for(let n of i)typeof n=="object"&&n!==null&&e.push(V(n,r));return e}function K(t){return st(t)?at(t):(Array.isArray(t)?t:[t]).map(r=>V(r))}function ot(t){let e=t.trim(),r=[],i=e;e=e.replace(/^```(?:json)?\s*/i,"").replace(/\s*```$/,""),e!==i&&r.push("removed markdown code block markers");let n=e;if(e=e.replace(/,(\s*[\]\}])/g,"$1"),e!==n&&r.push("removed trailing commas"),e.startsWith("[")&&!e.endsWith("]")){let s=(e.match(/\[/g)||[]).length,l=(e.match(/\]/g)||[]).length;if(s>l){let a=s-l;e=e+"]".repeat(a),r.push(`added ${a} closing bracket(s)`);}}if(e.includes("{")){let s=(e.match(/\{/g)||[]).length,l=(e.match(/\}/g)||[]).length;if(s>l){let a=s-l;e=e+"}".repeat(a),r.push(`added ${a} closing brace(s)`);}}return {repaired:e,repairs:r}}function U(t){if(!t||typeof t!="string")return {visibleText:"",citations:[],citationMap:new Map,success:false,error:"Invalid input: expected a string"};let e=t.indexOf(a);if(e===-1)return {visibleText:t.trim(),citations:[],citationMap:new Map,success:true};let r=t.substring(0,e).trim(),i=t.indexOf(b,e),n=e+a.length,s=i!==-1?i:t.length,l=t.substring(n,s).trim(),a$1=[],c=new Map;if(l)try{let d=JSON.parse(l);a$1=K(d);}catch(d){try{let{repaired:p,repairs:o}=ot(l),f=JSON.parse(p);a$1=K(f),o.length>0&&console.warn("[DeepCitation] JSON repair was triggered for citation data.",`Repairs applied: ${o.join(", ")}.`,`Initial parse error: ${d instanceof Error?d.message:"Unknown error"}`);}catch(p){return {visibleText:r,citations:[],citationMap:new Map,success:false,error:`Failed to parse citation JSON. Initial error: ${d instanceof Error?d.message:"Unknown error"}. Repair error: ${p instanceof Error?p.message:"Unknown error"}`}}}for(let d of a$1)typeof d.id=="number"&&c.set(d.id,d);return {visibleText:r,citations:a$1,citationMap:c,success:true}}function ct(t){let e=t.match(/^(\d+)_(\d+)$/);if(e){let i=parseInt(e[1],10),n=parseInt(e[2],10);return {pageNumber:i,startPageId:`page_number_${i}_index_${n}`}}let r=t.match(/page[_a-zA-Z]*(\d+)_index_(\d+)/i);if(r){let i=parseInt(r[1],10),n=parseInt(r[2],10);return {pageNumber:i,startPageId:`page_number_${i}_index_${n}`}}return {pageNumber:void 0,startPageId:void 0}}function lt(t,e){let r,i,n=t.page_id;if(n){let a=ct(n);r=a.pageNumber,i=a.startPageId;}let s;t.timestamps&&(s={startTime:t.timestamps.start_time,endTime:t.timestamps.end_time});let l=t.line_ids?.length?[...t.line_ids].sort((a,c)=>a-c):void 0;return {attachmentId:t.attachment_id,pageNumber:r,startPageId:i,fullPhrase:t.full_phrase,anchorText:t.anchor_text,citationNumber:e??t.id,lineIds:l,reasoning:t.reasoning,timestamps:s}}function Z(t){let e=U(t);if(!e.success||e.citations.length===0)return {};let r={};for(let i of e.citations){let n=lt(i);if(n.fullPhrase){let s=k(n);r[s]=n;}}return r}function X(t){return typeof t=="string"&&t.includes(a)}function Nt(t){return U(t).visibleText}function Mt(t,e){let{citationMap:r,showAnchorText:i,replacer:n}=e||{};return t.replace(/\[(\d+)\]/g,(s,l)=>{let a=parseInt(l,10),c=r?.get(a);return n?n(a,c):i&&c?.anchor_text?c.anchor_text:""})}function Pt(t){let e=[],r=/\[(\d+)\]/g,i;for(;(i=r.exec(t))!==null;)e.push(parseInt(i[1],10));return e}var dt=/page[\_a-zA-Z]*(\d+)_index_(\d+)/,ut=/page[_a-zA-Z]*(\d+)_index_(\d+)/i,pt=/^(\d+)_(\d+)$/,J=/<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*\/>/g,B=new Map;function ft(t){let e=B.get(t);return e||(e=new RegExp(`${t}='((?:[^'\\\\]|\\\\.)*)'`),B.set(t,e)),e}var gt=1e3,mt=50;function ht(t){if(!t)return;let e=[],r=t.split(",");for(let i of r){let n=i.trim();if(n)if(n.includes("-")){let[s,l]=n.split("-"),a=parseInt(s,10),c=parseInt(l,10);if(!isNaN(a)&&!isNaN(c)&&a<=c){let d=c-a+1;if(d>gt){e.push(a);let p=Math.min(mt-2,d-2);if(p>0){let o=Math.max(1,Math.floor((c-a)/(p+1)));for(let f=1;f<=p;f++){let h=a+o*f;h<c&&e.push(h);}}e.push(c);}else for(let p=a;p<=c;p++)e.push(p);}else isNaN(a)||e.push(a);}else {let s=parseInt(n,10);isNaN(s)||e.push(s);}}if(e.length!==0)return [...new Set(e)].sort((i,n)=>i-n)}function Y(t){let e=t?.status,r=["not_found"].includes(e||""),i=["found_anchor_text_only","partial_text_found","found_on_other_page","found_on_other_line","first_word_found"].includes(e||""),n=["found","found_phrase_missed_anchor_text"].includes(e||"")||i,s=["pending","loading",null,void 0].includes(e);return {isVerified:n,isMiss:r,isPartialMatch:i,isPending:s}}var _t=(t,e,r,i)=>{let n=x=>{if(!x)return;let m=x;return (m.startsWith("'")||m.startsWith('"'))&&(m=m.slice(1)),(m.endsWith("'")||m.endsWith('"'))&&!m.endsWith("\\'")&&!m.endsWith('\\"')&&(m=m.slice(0,-1)),m=m.replace(/\\"/g,'"'),m=m.replace(/\\'/g,"'"),m=m.replace(/\\n/g," "),m=m.replace(/\\\\/g,"\\"),m},s=r?.current?r.current++:void 0,l=t.substring(0,t.indexOf("<cite")),a=t.includes("/>")?t.slice(t.indexOf("/>")+2):"",c=t.substring(t.indexOf("<cite"),t.indexOf("/>")+2),d=(x,m)=>{for(let R of m){let E=ft(R),P=x.match(E);if(P)return P[1]}},p=d(c,["attachment_id","attachmentId","file_id","fileId"]),o=p?.length===20?p:e||p,f=d(c,["start_page_id","startPageId","start_page_key","startPageKey","start_page"]),h,g;if(f){let x=f.match(dt);x&&(h=parseInt(x[1]),g=parseInt(x[2]));}let A=n(d(c,["full_phrase","fullPhrase"])),T=n(d(c,["anchor_text","anchorText","key_span","keySpan"])),u=n(d(c,["reasoning"])),y=n(d(c,["value"])),b;try{let m=d(c,["line_ids","lineIds"])?.replace(/[A-Za-z_[\](){}:]/g,"");b=m?ht(m):void 0;}catch(x){i&&console.error("Error parsing lineIds",x);}let C=d(c,["timestamps"]),_;if(C){let[x,m]=C.split("-")||[];_={startTime:x,endTime:m};}let I={attachmentId:o,pageNumber:h,startPageId:`page_number_${h||1}_index_${g||0}`,fullPhrase:A,anchorText:T||y,citationNumber:s,lineIds:b,beforeCite:l,timestamps:_,reasoning:u};return {beforeCite:l,afterCite:a,citation:I}},xt=(t,e)=>{if(!t)return null;let r=t.fullPhrase??t.full_phrase,i=t.startPageId??t.start_page_id??t.startPageKey??t.start_page_key,n=t.anchorText??t.anchor_text??t.keySpan??t.key_span,s=t.lineIds??t.line_ids,l=t.attachmentId??t.attachment_id??t.fileId??t.file_id,a=t.reasoning,c=t.value;if(!r)return null;let d;if(i){let f=i.match(ut);if(f)d=parseInt(f[1],10);else {let h=i.match(pt);h&&(d=parseInt(h[1],10));}}let p=s?.length?[...s].sort((f,h)=>f-h):void 0;return {attachmentId:l,pageNumber:d,fullPhrase:r,citationNumber:e,lineIds:p,anchorText:n||c,reasoning:a}},W=t=>typeof t=="object"&&t!==null&&("fullPhrase"in t||"full_phrase"in t||"startPageId"in t||"start_page_id"in t||"startPageKey"in t||"start_page_key"in t||"anchorText"in t||"anchor_text"in t||"keySpan"in t||"key_span"in t||"lineIds"in t||"line_ids"in t),v=t=>Array.isArray(t)?t.length>0&&t.some(W):typeof t=="object"&&t!==null?W(t):false,j=t=>{let e={},r=Array.isArray(t)?t:[t],i=1;for(let n of r){let s=xt(n,i++);if(s&&s.fullPhrase){let l=k(s);e[l]=s;}}return e},yt=50,O=(t,e,r=0)=>{if(!(r>yt||!t||typeof t!="object")){if(t.citation&&v(t.citation)){let i=Array.isArray(t.citation)?t.citation:[t.citation];e.push(...i);}if(t.citations&&v(t.citations)){let i=Array.isArray(t.citations)?t.citations:[t.citations];e.push(...i);}if(Array.isArray(t))for(let i of t)O(i,e,r+1);else for(let i of Object.keys(t))i!=="citation"&&i!=="citations"&&O(t[i],e,r+1);}},F=t=>{let e=H(t),r=new RegExp(J.source,J.flags),i=e.match(r);if(!i||i.length===0)return {};let n={},s={current:1};for(let l of i){let{citation:a}=_t(l,void 0,s);if(a&&a.fullPhrase){let c=k(a);n[c]=a;}}return n},vt=t=>{if(!t)return {};let e={};if(typeof t=="object"){if(v(t)){let n=j(t);Object.assign(e,n);}else {let n=[];if(O(t,n),n.length>0){let s=j(n);Object.assign(e,s);}}let r=JSON.stringify(t),i=F(r);Object.assign(e,i);}else if(typeof t=="string"){if(X(t)){let i=Z(t);Object.assign(e,i);}let r=F(t);Object.assign(e,r);}return e};function Ot(t){let e=new Map,r=Array.isArray(t)?t.map((i,n)=>[k(i)||String(n+1),i]):Object.entries(t);for(let[i,n]of r){let s=n.attachmentId||"";e.has(s)||e.set(s,{}),e.get(s)[i]=n;}return e}function Lt(t){let e={},r=Array.isArray(t)?t.map((i,n)=>[k(i)||String(n+1),i]):Object.entries(t);for(let[i,n]of r){let s=n.attachmentId||"";e[s]||(e[s]={}),e[s][i]=n;}return e}var Ct=/page[_a-zA-Z]*(\d+)/;var q=/<cite\s+[^>]*?\/>/g,It=t=>{let e={},r=/([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(['"])((?:[^'"\\]|\\.)*)\2/g,i;for(;(i=r.exec(t))!==null;){let n=i[1].toLowerCase().replace(/([a-z])([A-Z])/g,"$1_$2").toLowerCase(),s=i[3],l=n==="fileid"||n==="file_id"||n==="attachmentid"?"attachment_id":n==="anchortext"||n==="anchor_text"||n==="keyspan"||n==="key_span"?"anchor_text":n==="fullphrase"?"full_phrase":n==="lineids"?"line_ids":n==="pageid"||n==="page_id"||n==="startpageid"||n==="start_pageid"||n==="start_page_id"||n==="startpagekey"||n==="start_pagekey"||n==="start_page_key"||n==="pagekey"||n==="page_key"?"start_page_id":n;e[l]=s;}return e},bt=t=>{let e=Y(t);return e.isMiss?"\u274C":e.isVerified&&!e.isPartialMatch?"\u2611\uFE0F":e.isPartialMatch?"\u2705":e.isPending?"\u231B":"\u25CC"},Vt=(t,e={})=>{let{leaveAnchorTextBehind:r=false,verifications:i,showVerificationStatus:n=false}=e,s=0,l=new RegExp(q.source,q.flags);return t.replace(l,a=>{s++;let c=It(a),d="";if(r&&c.anchor_text&&(d=c.anchor_text.replace(/\\'/g,"'").replace(/\\"/g,'"')),n&&i){let p,o=u=>{if(!u)return;let y=u.match(Ct);return y?parseInt(y[1],10):void 0},f=u=>{if(!u)return;let y=1e3,b=50,_=u.replace(/(\d+)-(\d+)/g,(I,x,m)=>{let R=parseInt(x,10),E=parseInt(m,10);if(R<=E){let P=E-R+1;if(P>y){let N=[R],S=Math.min(b-2,P-2);if(S>0){let tt=Math.max(1,Math.floor((E-R)/(S+1)));for(let D=1;D<=S;D++){let z=R+tt*D;z<E&&N.push(z);}}return N.push(E),N.join(",")}let L=[];for(let N=R;N<=E;N++)L.push(N);return L.join(",")}return x}).split(",").map(I=>parseInt(I.trim(),10)).filter(I=>!isNaN(I));return _.length>0?_:void 0},h=u=>u?.replace(/\\'/g,"'").replace(/\\"/g,'"'),g={attachmentId:c.attachment_id,pageNumber:o(c.start_page_id),fullPhrase:h(c.full_phrase),anchorText:h(c.anchor_text),lineIds:f(c.line_ids)},A=k(g);if(p=i[A],!p){let u=String(s);p=i[u];}let T=bt(p);d=d?`${d}${T}`:T;}return d})},Ut=t=>t.replace(/<page_number_\d+_index_\d+>/g,"").replace(/<\/page_number_\d+_index_\d+>/g,"").trim(),Zt=t=>{let e=/<line id="[^"]*">|<\/line>/g;return t.replace(e,"")},Q=t=>{if(!t)return null;let e=t.match(/\d+/)?.[0];return e?parseInt(e):null},At=t=>{let e=t.match(/^(<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>)([\s\S]*?)<\/cite>$/);if(!e){let a=t.match(/^(<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>)$/);if(a){let c=a[1].replace(/>$/," />");return M(c)}return M(t)}let[,r,i]=e;if(!i||!i.trim())return M(t);let n=r.replace(/>$/," />"),s=i.trim(),l=M(n);return s+l},H=t=>{let e=t?.trim()||"";e=e.replace(/(?<![<a-zA-Z])cite\s+(attachment_id|file_id|fileId|attachmentId)\s*=/gi,"<cite $1=");let r=e.split(/(<cite[\s\S]*?(?:\/>|<\/cite>|>(?=\s*$|[\r\n])(?![\s\S]*<\/cite>)))/gm);if(r.length<=1){let i=e.match(/<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>/g);if(i&&i.length>0){let n=e.replace(/<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>/g,s=>s.replace(/>$/," />"));return M(n)}return M(e)}return e=r.map(i=>i.startsWith("<cite")?At(i):i).join(""),e},M=t=>{let e=t;e=e.replace(/\\_/g,"_"),e=e.replace(/><\/cite>/g,"/>");let r=p=>{let o=p.toLowerCase();return o==="fullphrase"||o==="full_phrase"?"full_phrase":o==="lineids"||o==="line_ids"?"line_ids":o==="startpageid"||o==="start_pageid"||o==="start_page_id"||o==="startpagekey"||o==="start_pagekey"||o==="start_page_key"?"start_page_id":o==="fileid"||o==="file_id"||o==="attachmentid"||o==="attachment_id"?"attachment_id":o==="anchortext"||o==="anchor_text"||o==="keyspan"||o==="key_span"?"anchor_text":o==="reasoning"||o==="value"?o:o==="timestamps"||o==="timestamp"||o==="timestamps"?"timestamps":o},i={"&quot;":'"',"&apos;":"'","&lt;":"<","&gt;":">","&amp;":"&"},n=/&(?:quot|apos|lt|gt|amp);/g,s=p=>p.replace(n,o=>i[o]||o),l=/(fullPhrase|full_phrase|anchorText|anchor_text|keySpan|key_span|reasoning|value)\s*=\s*(['"])([\s\S]*?)(?=\s+(?:line_ids|lineIds|timestamps|fileId|file_id|attachmentId|attachment_id|start_page_id|start_pageId|startPageId|start_page_key|start_pageKey|startPageKey|anchorText|anchor_text|keySpan|key_span|reasoning|value|full_phrase)\s*=|\s*\/>|['"]>)/gm;e=e.replace(l,(p,o,f,h)=>{let g=h;return g.endsWith(f)&&(g=g.slice(0,-1)),g=g.replace(/(\r?\n)+|(\*|_){2,}|\*/g,A=>A.includes(`
2
+ `)||A.includes("\r")?" ":""),g=s(g),g=g.replace(/\\\\'/g,"'").replace(/\\'/g,"'").replace(/'/g,"\\'"),g=g.replace(/\\\\"/g,'"').replace(/\\"/g,'"').replace(/"/g,'\\"'),`${r(o)}='${g}'`});let a=1e3,c=50;e=e.replace(/(line_ids|lineIds|timestamps)=['"]?([\[\]\(\){}A-Za-z0-9_\-, ]+)['"]?(\s*\/?>|\s+)/gm,(p,o,f,h)=>{let g=f.replace(/[A-Za-z\[\]\(\){}]/g,"");return g=g.replace(/(\d+)-(\d+)/g,(A,T,u)=>{let y=parseInt(T,10),b=parseInt(u,10);if(y<=b){let C=b-y+1;if(C>a){let I=[y],x=Math.min(c-2,C-2);if(x>0){let m=Math.max(1,Math.floor((b-y)/(x+1)));for(let R=1;R<=x;R++){let E=y+m*R;E<b&&I.push(E);}}return I.push(b),I.join(",")}let _=[];for(let I=y;I<=b;I++)_.push(I);return _.join(",")}else return String(y)}),g=g.replace(/,+/g,",").replace(/^,|,$/g,""),`${r(o)}='${g}'${h}`});let d=p=>{let o=/([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(['"])((?:[^'"\\\n]|\\.)*)(?:\2)/g,f={},h;for(;h=o.exec(p);){let C=h[1],_=h[3],I=r(C);f[I]=_;}let g=Object.keys(f);if(g.length===0)return p;let A=typeof f.timestamps=="string"&&f.timestamps.length>0,T=g.filter(C=>C.startsWith("start_page")),u=[];f.attachment_id&&u.push("attachment_id"),A?(f.full_phrase&&u.push("full_phrase"),f.anchor_text&&u.push("anchor_text"),u.push("timestamps")):(T.includes("start_page_id")&&u.push("start_page_id"),T.filter(C=>C!=="start_page_id").sort().forEach(C=>u.push(C)),f.full_phrase&&u.push("full_phrase"),f.anchor_text&&u.push("anchor_text"),f.line_ids&&u.push("line_ids")),f.reasoning&&u.push("reasoning"),f.value&&u.push("value");let y=new Set(u);return g.filter(C=>!y.has(C)).sort().forEach(C=>u.push(C)),`<cite ${u.map(C=>`${C}='${f[C]}'`).join(" ")} />`};return e=e.replace(/<cite\b[\s\S]*?\/>/gm,p=>d(p)),e};function Wt(...t){return t.filter(Boolean).join(" ")}function Tt(t){return t.type==="url"||typeof t.url=="string"&&t.url.length>0}function k(t){let e=t.pageNumber||Q(t.startPageId),r=[t.attachmentId||"",e?.toString()||"",t.fullPhrase||"",t.anchorText?.toString()||"",t.lineIds?.join(",")||"",t.timestamps?.startTime||"",t.timestamps?.endTime||""];return Tt(t)&&r.push(t.url||"",t.title||"",t.domain||""),$(r.join("|")).slice(0,16)}function jt(t){let e=[t.attachmentId||"",t.label||"",t.verifiedFullPhrase||"",t.verifiedAnchorText||"",t.verifiedLineIds?.join(",")||"",t.verifiedPageNumber?.toString()||"",t.verifiedTimestamps?.startTime||"",t.verifiedTimestamps?.endTime||"",t.verifiedMatchSnippet||"",t.hitIndexWithinPage?.toString()||""];return $(e.join("|")).slice(0,16)}function Ft(t){let e=Math.random().toString(36).slice(2,11);return `${t}-${e}`}function Ht(t,e={}){let{fallbackDisplay:r}=e;return t.anchorText?.toString()||t.citationNumber?.toString()||r||"1"}function Yt(t){return t.citationNumber?.toString()||"1"}function qt(t){return t.anchorText?.toString()||""}function Qt(...t){return t.filter(Boolean).join(" ")}var te=4,ee=1;export{_t as A,vt as B,Ot as C,Lt as D,$ as a,Wt as b,Tt as c,k as d,jt as e,Ft as f,Ht as g,Yt as h,qt as i,Qt as j,te as k,ee as l,bt as m,Vt as n,Ut as o,Zt as p,Q as q,H as r,U as s,lt as t,Z as u,X as v,Nt as w,Mt as x,Pt as y,Y as z};//# sourceMappingURL=chunk-2NSFXPOT.js.map
3
+ //# sourceMappingURL=chunk-2NSFXPOT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/sha.ts","../src/parsing/citationParser.ts","../src/parsing/parseCitation.ts","../src/parsing/normalizeCitation.ts","../src/react/utils.ts"],"names":["utf8Encode","str","sha1","message","h0","h1","h2","h3","h4","msgLen","bitLen","totalLen","paddedLen","padded","paddedView","dataView","w","offset","i","val","a","b","c","d","e","f","k","temp","hex","n","sha1Hash","data","error","COMPACT_KEY_MAP","isValidCitationData","obj","expandCompactKeys","attachmentId","result","key","value","fullKey","ts","isGroupedFormat","parsed","values","flattenGroupedCitations","grouped","citations","citationArray","citation","parseCitationsFromJson","repairJson","jsonString","repaired","repairs","beforeMarkdownRemoval","beforeTrailingCommas","openBrackets","closeBrackets","addedCount","openBraces","closeBraces","parseDeferredCitationResponse","llmResponse","startIndex","CITATION_DATA_START_DELIMITER","visibleText","endIndex","CITATION_DATA_END_DELIMITER","jsonStartIndex","jsonEndIndex","citationMap","initialError","repairError","parsePageId","pageId","compactMatch","pageNum","index","legacyMatch","deferredCitationToCitation","citationNumber","pageNumber","startPageId","timestamps","lineIds","getAllCitationsFromDeferredResponse","citationKey","generateCitationKey","hasDeferredCitations","response","extractVisibleText","replaceDeferredMarkers","text","options","showAnchorText","replacer","match","idStr","id","getCitationMarkerIds","ids","regex","PAGE_ID_FULL_REGEX","PAGE_ID_SIMPLE_REGEX","SIMPLE_PAGE_INDEX_REGEX","CITE_TAG_REGEX","attributeRegexCache","getAttributeRegex","name","MAX_LINE_ID_RANGE_SIZE","LARGE_RANGE_SAMPLE_COUNT","parseLineIds","lineIdsString","parts","part","trimmed","startStr","endStr","start","end","rangeSize","sampleCount","step","sample","num","getCitationStatus","verification","status","isMiss","isPartialMatch","isVerified","isPending","parseCitation","fragment","mdAttachmentId","citationCounterRef","isVerbose","cleanAndUnescape","beforeCite","afterCite","middleCite","extractAttribute","tag","attrNames","rawAttachmentId","startPageIdRaw","pageIndex","pageMatch","fullPhrase","anchorText","reasoning","timestampsRaw","startTime","endTime","parseJsonCitation","jsonCitation","rawLineIds","simpleMatch","hasCitationProperties","item","isJsonCitationFormat","extractJsonCitations","items","MAX_TRAVERSAL_DEPTH","findJsonCitationsInObject","found","depth","extractXmlCitations","normalizedText","normalizeCitations","citeRegex","matches","getAllCitationsFromLlmOutput","llmOutput","jsonCitations","foundJsonCitations","xmlCitations","deferredCitations","groupCitationsByAttachmentId","entries","idx","groupCitationsByAttachmentIdObject","PAGE_NUMBER_REGEX","parseCiteAttributes","citeTag","attrs","attrRegex","normalizedKey","getVerificationTextIndicator","replaceCitations","markdownWithCitations","leaveAnchorTextBehind","verifications","showVerificationStatus","citationIndex","citationRegex","output","parsePageNumber","lineIdsStr","MAX_RANGE_SIZE","SAMPLE_COUNT","nums","_match","startNum","endNum","samples","range","s","unescapeQuotes","numericKey","indicator","removePageNumberMetadata","pageText","removeLineIdMetadata","lineIdRegex","getCitationPageNumber","extractAndRelocateCitationContent","citePart","nonSelfClosingMatch","unclosedMatch","selfClosingTag","normalizeCitationContent","openingTag","innerContent","relocatedContent","normalizedCitation","trimmedResponse","citationParts","input","normalized","canonicalizeCiteAttributeKey","lowerKey","htmlEntityMap","htmlEntityRegex","decodeHtmlEntities","textAttributeRegex","openQuote","rawContent","content","rawValue","trailingChars","cleanedValue","_rangeMatch","reorderCiteTagAttributes","rawKey","keys","hasTimestamps","startPageIds","ordered","used","cn","classes","isUrlCitation","keyParts","generateVerificationKey","generateCitationInstanceId","randomSuffix","getCitationDisplayText","fallbackDisplay","getCitationNumber","getCitationAnchorText","classNames","CITATION_X_PADDING","CITATION_Y_PADDING"],"mappings":"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","file":"chunk-2NSFXPOT.js","sourcesContent":["/**\n * Pure JavaScript SHA-1 implementation.\n * Based on the FIPS 180-4 specification.\n * No external dependencies.\n */\n\nfunction utf8Encode(str: string): Uint8Array {\n const encoder = new TextEncoder();\n return encoder.encode(str);\n}\n\nfunction sha1(message: Uint8Array): string {\n // Initial hash values\n let h0 = 0x67452301;\n let h1 = 0xefcdab89;\n let h2 = 0x98badcfe;\n let h3 = 0x10325476;\n let h4 = 0xc3d2e1f0;\n\n // Pre-processing: adding padding bits\n const msgLen = message.length;\n const bitLen = msgLen * 8;\n\n // Calculate padded length: message + 1 (0x80) + padding + 8 (length)\n // Total must be multiple of 64 bytes (512 bits)\n const totalLen = msgLen + 1 + 8; // minimum: msg + 0x80 + 64-bit length\n const paddedLen = Math.ceil(totalLen / 64) * 64;\n\n // Create padded buffer\n const padded = new ArrayBuffer(paddedLen);\n const paddedView = new Uint8Array(padded);\n const dataView = new DataView(padded);\n\n // Copy message\n paddedView.set(message);\n\n // Append bit '1' (0x80)\n paddedView[msgLen] = 0x80;\n\n // Append length as 64-bit big-endian (in bits)\n // High 32 bits (for messages > 512MB, which we don't support)\n dataView.setUint32(paddedLen - 8, Math.floor(bitLen / 0x100000000), false);\n // Low 32 bits\n dataView.setUint32(paddedLen - 4, bitLen >>> 0, false);\n\n // Process each 512-bit (64-byte) chunk\n const w = new Uint32Array(80);\n\n for (let offset = 0; offset < paddedLen; offset += 64) {\n // Break chunk into sixteen 32-bit big-endian words\n for (let i = 0; i < 16; i++) {\n w[i] = dataView.getUint32(offset + i * 4, false);\n }\n\n // Extend the sixteen 32-bit words into eighty 32-bit words\n for (let i = 16; i < 80; i++) {\n const val = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];\n w[i] = (val << 1) | (val >>> 31);\n }\n\n // Initialize working variables\n let a = h0;\n let b = h1;\n let c = h2;\n let d = h3;\n let e = h4;\n\n // Main loop\n for (let i = 0; i < 80; i++) {\n let f: number;\n let k: number;\n\n if (i < 20) {\n f = (b & c) | (~b & d);\n k = 0x5a827999;\n } else if (i < 40) {\n f = b ^ c ^ d;\n k = 0x6ed9eba1;\n } else if (i < 60) {\n f = (b & c) | (b & d) | (c & d);\n k = 0x8f1bbcdc;\n } else {\n f = b ^ c ^ d;\n k = 0xca62c1d6;\n }\n\n const temp = (((a << 5) | (a >>> 27)) + f + e + k + w[i]) >>> 0;\n e = d;\n d = c;\n c = ((b << 30) | (b >>> 2)) >>> 0;\n b = a;\n a = temp;\n }\n\n // Add this chunk's hash to result\n h0 = (h0 + a) >>> 0;\n h1 = (h1 + b) >>> 0;\n h2 = (h2 + c) >>> 0;\n h3 = (h3 + d) >>> 0;\n h4 = (h4 + e) >>> 0;\n }\n\n // Produce the final hash value (160-bit) as hex string\n const hex = (n: number) => n.toString(16).padStart(8, \"0\");\n return hex(h0) + hex(h1) + hex(h2) + hex(h3) + hex(h4);\n}\n\n/**\n * Computes a SHA-1 hash of the provided data.\n * Used internally by generateCitationKey in react/utils.ts\n */\nexport function sha1Hash(data: string | any): string {\n try {\n if (!data) return \"\";\n const str = typeof data === \"string\" ? data : JSON.stringify(data);\n return sha1(utf8Encode(str));\n } catch (error) {\n console.error(\"Error in making the hash:\", error);\n }\n return \"\";\n}\n","/**\n * Citation Parser\n *\n * Implements the \"Split & Parse\" strategy for the deferred JSON citation pattern.\n * This parser extracts citations from LLM responses that use [N] markers in text\n * and include a JSON data block at the end.\n *\n * Algorithm:\n * 1. Detection: Look for the start delimiter <<<CITATION_DATA>>>\n * 2. Splitting: Separate visible content from the citation data block\n * 3. Data Extraction: Extract the JSON string between delimiters\n * 4. Sanitization: Parse with JSON.parse, with fallback repair for common issues\n * 5. Hydration: Map the JSON objects to a usable format\n */\n\nimport { type Citation } from \"../types/citation.js\";\nimport { generateCitationKey } from \"../react/utils.js\";\nimport {\n CITATION_DATA_START_DELIMITER,\n CITATION_DATA_END_DELIMITER,\n type CitationData,\n type CompactCitationData,\n type ParsedCitationResponse,\n} from \"../prompts/citationPrompts.js\";\n\n/**\n * Map of compact keys to their full CitationData equivalents.\n */\nconst COMPACT_KEY_MAP: Record<string, keyof CitationData> = {\n n: \"id\",\n a: \"attachment_id\",\n r: \"reasoning\",\n f: \"full_phrase\",\n k: \"anchor_text\",\n p: \"page_id\",\n l: \"line_ids\",\n t: \"timestamps\",\n} as const;\n\n/**\n * Map for timestamp sub-keys.\n */\nconst TIMESTAMP_KEY_MAP: Record<string, string> = {\n s: \"start_time\",\n e: \"end_time\",\n} as const;\n\n/**\n * Type guard to validate that an object has the required CitationData structure.\n * Ensures at minimum the id field is present and is a number.\n */\nfunction isValidCitationData(obj: unknown): obj is CitationData {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"id\" in obj &&\n typeof (obj as Record<string, unknown>).id === \"number\"\n );\n}\n\n/**\n * Expands compact citation data to the full CitationData format.\n * Handles both compact keys (n, a, r, f, k, p, l, t) and full keys.\n *\n * @param data - Raw citation object (may have compact or full keys)\n * @param attachmentId - Optional attachment_id to inject (for grouped format)\n * @returns Normalized CitationData with full keys\n * @throws Error if the resulting data doesn't have a valid id field\n */\nfunction expandCompactKeys(\n data: CompactCitationData | CitationData | Record<string, unknown>,\n attachmentId?: string\n): CitationData {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data)) {\n // Check if this is a compact key\n const fullKey = COMPACT_KEY_MAP[key] || key;\n\n // Handle timestamps specially (nested object with s/e keys)\n if ((key === \"t\" || key === \"timestamps\") && value && typeof value === \"object\") {\n const ts = value as Record<string, unknown>;\n result.timestamps = {\n start_time: ts.s ?? ts.start_time,\n end_time: ts.e ?? ts.end_time,\n };\n } else {\n result[fullKey] = value;\n }\n }\n\n // Inject attachment_id if provided (from grouped format)\n if (attachmentId && !result.attachment_id) {\n result.attachment_id = attachmentId;\n }\n\n // Runtime validation to ensure type safety\n if (!isValidCitationData(result)) {\n throw new Error(\"Invalid citation data: missing or invalid 'id' field\");\n }\n\n return result;\n}\n\n/**\n * Checks if the parsed JSON is in grouped format (object with attachment IDs as keys)\n * vs flat format (array of citations).\n */\nfunction isGroupedFormat(parsed: unknown): parsed is Record<string, unknown[]> {\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return false;\n }\n // Check if all values are arrays (grouped format)\n const values = Object.values(parsed);\n return values.length > 0 && values.every(Array.isArray);\n}\n\n/**\n * Flattens grouped citation format into a flat array.\n * Grouped format: { \"attachmentId\": [citations...], ... }\n * Flat format: [{ attachment_id: \"...\", ...citation }, ...]\n */\nfunction flattenGroupedCitations(\n grouped: Record<string, unknown[]>\n): CitationData[] {\n const citations: CitationData[] = [];\n\n for (const [attachmentId, citationArray] of Object.entries(grouped)) {\n for (const citation of citationArray) {\n if (typeof citation === \"object\" && citation !== null) {\n citations.push(expandCompactKeys(citation as Record<string, unknown>, attachmentId));\n }\n }\n }\n\n return citations;\n}\n\n/**\n * Helper to parse citations from JSON, handling both grouped and flat formats.\n */\nfunction parseCitationsFromJson(parsed: unknown): CitationData[] {\n // Check for grouped format: { \"attachmentId\": [citations...], ... }\n if (isGroupedFormat(parsed)) {\n return flattenGroupedCitations(parsed);\n }\n\n // Flat format: array of citations or single citation\n const rawCitations = Array.isArray(parsed) ? parsed : [parsed];\n return rawCitations.map((c) => expandCompactKeys(c as Record<string, unknown>));\n}\n\nexport type { CitationData, ParsedCitationResponse } from \"../prompts/citationPrompts.js\";\n\n/**\n * Attempts to repair malformed JSON.\n * Handles common LLM output issues like:\n * - Trailing commas\n * - Single quotes instead of double quotes (in JSON context)\n * - Missing closing brackets\n * - Unescaped newlines in strings\n *\n * @param jsonString - The potentially malformed JSON string\n * @returns The repaired JSON string\n */\nfunction repairJson(jsonString: string): { repaired: string; repairs: string[] } {\n let repaired = jsonString.trim();\n const repairs: string[] = [];\n\n // Remove any markdown code block markers that might be present\n const beforeMarkdownRemoval = repaired;\n repaired = repaired.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```$/, \"\");\n if (repaired !== beforeMarkdownRemoval) {\n repairs.push(\"removed markdown code block markers\");\n }\n\n // Fix trailing commas before ] or }\n const beforeTrailingCommas = repaired;\n repaired = repaired.replace(/,(\\s*[\\]\\}])/g, \"$1\");\n if (repaired !== beforeTrailingCommas) {\n repairs.push(\"removed trailing commas\");\n }\n\n // Fix missing closing bracket if we have an opening [\n if (repaired.startsWith(\"[\") && !repaired.endsWith(\"]\")) {\n // Check if we have unclosed array\n const openBrackets = (repaired.match(/\\[/g) || []).length;\n const closeBrackets = (repaired.match(/\\]/g) || []).length;\n if (openBrackets > closeBrackets) {\n const addedCount = openBrackets - closeBrackets;\n repaired = repaired + \"]\".repeat(addedCount);\n repairs.push(`added ${addedCount} closing bracket(s)`);\n }\n }\n\n // Fix missing closing brace if we have an opening {\n if (repaired.includes(\"{\")) {\n const openBraces = (repaired.match(/\\{/g) || []).length;\n const closeBraces = (repaired.match(/\\}/g) || []).length;\n if (openBraces > closeBraces) {\n const addedCount = openBraces - closeBraces;\n repaired = repaired + \"}\".repeat(addedCount);\n repairs.push(`added ${addedCount} closing brace(s)`);\n }\n }\n\n return { repaired, repairs };\n}\n\n\n/**\n * Parses a citation response from an LLM.\n *\n * This function:\n * 1. Finds the <<<CITATION_DATA>>> delimiter in the response\n * 2. Splits the response into visible text and citation data\n * 3. Parses the JSON citation data\n * 4. Returns a structured result with both\n *\n * @param llmResponse - The full LLM response text\n * @returns ParsedCitationResponse with visible text and parsed citations\n *\n * @example\n * ```typescript\n * const response = `\n * The company grew 45% [1].\n *\n * <<<CITATION_DATA>>>\n * [{\"id\": 1, \"attachment_id\": \"abc\", \"full_phrase\": \"grew 45%\", \"anchor_text\": \"45%\"}]\n * <<<END_CITATION_DATA>>>\n * `;\n *\n * const parsed = parseDeferredCitationResponse(response);\n * console.log(parsed.visibleText); // \"The company grew 45% [1].\"\n * console.log(parsed.citations); // [{id: 1, attachment_id: \"abc\", ...}]\n * ```\n */\nexport function parseDeferredCitationResponse(\n llmResponse: string\n): ParsedCitationResponse {\n if (!llmResponse || typeof llmResponse !== \"string\") {\n return {\n visibleText: \"\",\n citations: [],\n citationMap: new Map(),\n success: false,\n error: \"Invalid input: expected a string\",\n };\n }\n\n // Find the start delimiter\n const startIndex = llmResponse.indexOf(CITATION_DATA_START_DELIMITER);\n\n // No citation data block found - return full text as visible\n if (startIndex === -1) {\n return {\n visibleText: llmResponse.trim(),\n citations: [],\n citationMap: new Map(),\n success: true,\n };\n }\n\n // Extract visible text (everything before the delimiter)\n const visibleText = llmResponse.substring(0, startIndex).trim();\n\n // Find the end delimiter\n const endIndex = llmResponse.indexOf(\n CITATION_DATA_END_DELIMITER,\n startIndex\n );\n\n // Extract the JSON block\n const jsonStartIndex = startIndex + CITATION_DATA_START_DELIMITER.length;\n const jsonEndIndex =\n endIndex !== -1 ? endIndex : llmResponse.length;\n const jsonString = llmResponse.substring(jsonStartIndex, jsonEndIndex).trim();\n\n // Parse the JSON\n let citations: CitationData[] = [];\n const citationMap = new Map<number, CitationData>();\n\n if (jsonString) {\n try {\n // First attempt: direct JSON.parse\n const parsed = JSON.parse(jsonString);\n citations = parseCitationsFromJson(parsed);\n } catch (initialError) {\n // Second attempt: repair and retry\n try {\n const { repaired, repairs } = repairJson(jsonString);\n const parsed = JSON.parse(repaired);\n citations = parseCitationsFromJson(parsed);\n\n // Log warning when repair was necessary\n if (repairs.length > 0) {\n console.warn(\n \"[DeepCitation] JSON repair was triggered for citation data.\",\n `Repairs applied: ${repairs.join(\", \")}.`,\n `Initial parse error: ${initialError instanceof Error ? initialError.message : \"Unknown error\"}`\n );\n }\n } catch (repairError) {\n return {\n visibleText,\n citations: [],\n citationMap: new Map(),\n success: false,\n error: `Failed to parse citation JSON. Initial error: ${initialError instanceof Error ? initialError.message : \"Unknown error\"}. Repair error: ${repairError instanceof Error ? repairError.message : \"Unknown error\"}`,\n };\n }\n }\n }\n\n // Map citations by ID for O(1) lookups\n for (const citation of citations) {\n if (typeof citation.id === \"number\") {\n citationMap.set(citation.id, citation);\n }\n }\n\n return {\n visibleText,\n citations,\n citationMap,\n success: true,\n };\n}\n\n/**\n * Parses a page_id string to extract page number and index.\n * Supports both compact \"N_I\" format and legacy \"page_number_N_index_I\" format.\n *\n * @param pageId - The page ID string\n * @returns Object with pageNumber and normalized startPageId, or undefined values\n */\nfunction parsePageId(pageId: string): { pageNumber?: number; startPageId?: string } {\n // Try compact format first: \"N_I\" (e.g., \"2_1\")\n const compactMatch = pageId.match(/^(\\d+)_(\\d+)$/);\n if (compactMatch) {\n const pageNum = parseInt(compactMatch[1], 10);\n const index = parseInt(compactMatch[2], 10);\n return {\n pageNumber: pageNum,\n startPageId: `page_number_${pageNum}_index_${index}`,\n };\n }\n\n // Try legacy format: \"page_number_N_index_I\" or variations\n const legacyMatch = pageId.match(/page[_a-zA-Z]*(\\d+)_index_(\\d+)/i);\n if (legacyMatch) {\n const pageNum = parseInt(legacyMatch[1], 10);\n const index = parseInt(legacyMatch[2], 10);\n return {\n pageNumber: pageNum,\n startPageId: `page_number_${pageNum}_index_${index}`,\n };\n }\n\n return { pageNumber: undefined, startPageId: undefined };\n}\n\n/**\n * Converts a CitationData object to the standard Citation format.\n *\n * @param data - The citation data\n * @param citationNumber - Optional override for citation number (defaults to data.id)\n * @returns Standard Citation object\n */\nexport function deferredCitationToCitation(\n data: CitationData,\n citationNumber?: number\n): Citation {\n // Parse page number from page_id (supports both \"N_I\" and \"page_number_N_index_I\")\n let pageNumber: number | undefined;\n let startPageId: string | undefined;\n const pageId = data.page_id;\n if (pageId) {\n const parsed = parsePageId(pageId);\n pageNumber = parsed.pageNumber;\n startPageId = parsed.startPageId;\n }\n\n // Parse timestamps for AV citations\n let timestamps: { startTime?: string; endTime?: string } | undefined;\n if (data.timestamps) {\n timestamps = {\n startTime: data.timestamps.start_time,\n endTime: data.timestamps.end_time,\n };\n }\n\n // Sort lineIds if present\n const lineIds = data.line_ids?.length\n ? [...data.line_ids].sort((a, b) => a - b)\n : undefined;\n\n return {\n attachmentId: data.attachment_id,\n pageNumber,\n startPageId,\n fullPhrase: data.full_phrase,\n anchorText: data.anchor_text,\n citationNumber: citationNumber ?? data.id,\n lineIds,\n reasoning: data.reasoning,\n timestamps,\n };\n}\n\n/**\n * Extracts all citations from a citation response and returns them\n * in the standard dictionary format used by the verification API.\n *\n * This function parses the response, converts each citation to the standard\n * Citation format, and generates deterministic keys for each.\n *\n * @param llmResponse - The full LLM response with citation block\n * @returns Dictionary of parsed Citation objects keyed by citation key\n *\n * @example\n * ```typescript\n * const citations = getAllCitationsFromDeferredResponse(llmOutput);\n * // Returns: { \"abc123...\": { attachmentId: \"...\", fullPhrase: \"...\", ... }, ... }\n * ```\n */\nexport function getAllCitationsFromDeferredResponse(\n llmResponse: string\n): { [key: string]: Citation } {\n const parsed = parseDeferredCitationResponse(llmResponse);\n\n if (!parsed.success || parsed.citations.length === 0) {\n return {};\n }\n\n const citations: { [key: string]: Citation } = {};\n\n for (const data of parsed.citations) {\n const citation = deferredCitationToCitation(data);\n if (citation.fullPhrase) {\n const citationKey = generateCitationKey(citation);\n citations[citationKey] = citation;\n }\n }\n\n return citations;\n}\n\n/**\n * Checks if a response contains citation markers.\n *\n * @param response - The LLM response to check\n * @returns True if the response contains the citation data delimiter\n */\nexport function hasDeferredCitations(response: string): boolean {\n return (\n typeof response === \"string\" &&\n response.includes(CITATION_DATA_START_DELIMITER)\n );\n}\n\n/**\n * Extracts just the visible text from a response,\n * removing the citation data block.\n *\n * @param llmResponse - The full LLM response\n * @returns The visible text portion only\n */\nexport function extractVisibleText(llmResponse: string): string {\n const parsed = parseDeferredCitationResponse(llmResponse);\n return parsed.visibleText;\n}\n\n/**\n * Replaces [N] citation markers in text with optional content.\n *\n * @param text - The text containing [N] markers\n * @param options - Configuration for replacement\n * @returns The text with markers replaced\n *\n * @example\n * ```typescript\n * const text = \"Revenue grew 45% [1] in Q4 [2].\";\n *\n * // Remove markers entirely\n * replaceDeferredMarkers(text);\n * // Returns: \"Revenue grew 45% in Q4.\"\n *\n * // Replace with anchor texts\n * replaceDeferredMarkers(text, {\n * citationMap: new Map([[1, { anchor_text: \"45%\" }], [2, { anchor_text: \"Q4\" }]]),\n * showAnchorText: true,\n * });\n * // Returns: \"Revenue grew 45% 45% in Q4 Q4.\"\n * ```\n */\nexport function replaceDeferredMarkers(\n text: string,\n options?: {\n /** Map of citation IDs to their data */\n citationMap?: Map<number, CitationData>;\n /** Whether to show the anchor text after the marker */\n showAnchorText?: boolean;\n /** Custom replacement function */\n replacer?: (id: number, data?: CitationData) => string;\n }\n): string {\n const { citationMap, showAnchorText, replacer } = options || {};\n\n // Match [N] patterns where N is one or more digits\n return text.replace(/\\[(\\d+)\\]/g, (match, idStr) => {\n const id = parseInt(idStr, 10);\n const data = citationMap?.get(id);\n\n // Custom replacer takes precedence\n if (replacer) {\n return replacer(id, data);\n }\n\n // Show anchor text if requested\n if (showAnchorText && data?.anchor_text) {\n return data.anchor_text;\n }\n\n // Default: remove marker\n return \"\";\n });\n}\n\n/**\n * Gets all citation marker IDs found in a text.\n *\n * @param text - The text to scan for [N] markers\n * @returns Array of citation IDs in order of appearance\n */\nexport function getCitationMarkerIds(text: string): number[] {\n const ids: number[] = [];\n const regex = /\\[(\\d+)\\]/g;\n let match;\n\n while ((match = regex.exec(text)) !== null) {\n ids.push(parseInt(match[1], 10));\n }\n\n return ids;\n}\n","import { type Verification } from \"../types/verification.js\";\nimport {\n type Citation,\n type CitationStatus,\n type CitationRecord,\n} from \"../types/citation.js\";\nimport { normalizeCitations } from \"./normalizeCitation.js\";\nimport { generateCitationKey } from \"../react/utils.js\";\nimport {\n hasDeferredCitations,\n getAllCitationsFromDeferredResponse,\n} from \"./citationParser.js\";\n\n/**\n * Module-level compiled regexes for hot-path operations.\n *\n * IMPORTANT: These regexes are compiled once at module load time to avoid\n * the overhead of regex compilation on every function call. This is a\n * significant performance optimization for parsing-heavy workloads.\n *\n * ## Safe usage patterns for global (/g) regexes:\n *\n * Regexes with the global flag maintain internal state (lastIndex).\n * Here's when each usage pattern is safe:\n *\n * ```typescript\n * // SAFE: String.match() creates a new matcher internally\n * const matches = text.match(CITE_TAG_REGEX);\n *\n * // SAFE: Non-global regexes don't have lastIndex issues\n * const isMatch = PAGE_ID_FULL_REGEX.test(text);\n * const match = PAGE_ID_FULL_REGEX.exec(text);\n *\n * // REQUIRED: Create fresh instance for .exec() loops with global regexes\n * const regex = new RegExp(CITE_TAG_REGEX.source, CITE_TAG_REGEX.flags);\n * let match;\n * while ((match = regex.exec(text)) !== null) { ... }\n *\n * // UNSAFE: Don't reuse global regex with .exec() in loops\n * // while ((match = CITE_TAG_REGEX.exec(text)) !== null) // BUG!\n * ```\n *\n * Performance fix: avoids regex recompilation on every function call.\n */\nconst PAGE_ID_FULL_REGEX = /page[\\_a-zA-Z]*(\\d+)_index_(\\d+)/;\nconst PAGE_ID_SIMPLE_REGEX = /page[_a-zA-Z]*(\\d+)_index_(\\d+)/i;\nconst SIMPLE_PAGE_INDEX_REGEX = /^(\\d+)_(\\d+)$/;\nconst CITE_TAG_REGEX = /<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*\\/>/g;\n\nconst attributeRegexCache = new Map<string, RegExp>();\n\nfunction getAttributeRegex(name: string): RegExp {\n let regex = attributeRegexCache.get(name);\n if (!regex) {\n regex = new RegExp(`${name}='((?:[^'\\\\\\\\]|\\\\\\\\.)*)'`);\n attributeRegexCache.set(name, regex);\n }\n return regex;\n}\n\n/**\n * Maximum allowed range size for line ID expansion.\n * Prevents memory exhaustion from malicious inputs like \"1-1000000\".\n */\nconst MAX_LINE_ID_RANGE_SIZE = 1000;\n\n/**\n * Number of sample points to use when a range is too large to fully expand.\n * Samples are evenly distributed across the range to maintain verification accuracy.\n */\nconst LARGE_RANGE_SAMPLE_COUNT = 50;\n\n/**\n * Parses a line_ids string that may contain individual numbers, ranges, or both.\n * Examples: \"1,2,3\", \"5-10\", \"1,5-7,10\", \"20-20\"\n *\n * Performance: Range expansion is limited to MAX_LINE_ID_RANGE_SIZE to prevent\n * quadratic memory allocation from malicious inputs. For larger ranges, evenly\n * distributed sample points are used to maintain verification accuracy.\n *\n * @param lineIdsString - The raw line_ids string (e.g., \"1,5-7,10\")\n * @returns Sorted array of unique line IDs, or undefined if empty/invalid\n */\nfunction parseLineIds(lineIdsString: string): number[] | undefined {\n if (!lineIdsString) return undefined;\n\n const lineIds: number[] = [];\n const parts = lineIdsString.split(\",\");\n\n for (const part of parts) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n\n // Check if this part is a range (e.g., \"5-10\")\n if (trimmed.includes(\"-\")) {\n const [startStr, endStr] = trimmed.split(\"-\");\n const start = parseInt(startStr, 10);\n const end = parseInt(endStr, 10);\n\n if (!isNaN(start) && !isNaN(end) && start <= end) {\n const rangeSize = end - start + 1;\n\n if (rangeSize > MAX_LINE_ID_RANGE_SIZE) {\n // Performance fix: use sampling for large ranges to maintain accuracy\n // Include start and end, plus evenly distributed samples using Math.floor\n // for predictable behavior. Deduplication happens at the end via Set.\n // Note: No warning logged to avoid spamming production logs.\n lineIds.push(start);\n const sampleCount = Math.min(LARGE_RANGE_SAMPLE_COUNT - 2, rangeSize - 2);\n if (sampleCount > 0) {\n // Use Math.floor for predictable sampling, ensuring step >= 1\n const step = Math.max(1, Math.floor((end - start) / (sampleCount + 1)));\n for (let i = 1; i <= sampleCount; i++) {\n const sample = start + step * i;\n // Ensure we don't exceed the range end\n if (sample < end) {\n lineIds.push(sample);\n }\n }\n }\n lineIds.push(end);\n } else {\n // Expand the full range\n for (let i = start; i <= end; i++) {\n lineIds.push(i);\n }\n }\n } else if (!isNaN(start)) {\n // If only start is valid, just use it\n lineIds.push(start);\n }\n } else {\n // Single number\n const num = parseInt(trimmed, 10);\n if (!isNaN(num)) {\n lineIds.push(num);\n }\n }\n }\n\n if (lineIds.length === 0) return undefined;\n\n // Sort and deduplicate\n return [...new Set(lineIds)].sort((a, b) => a - b);\n}\n\n/**\n * Calculates the verification status of a citation based on the found highlight and search state.\n *\n * @param verification - The found highlight location, or null/undefined if not found\n * @returns An object containing boolean flags for verification status\n */\nexport function getCitationStatus(\n verification: Verification | null | undefined\n): CitationStatus {\n const status = verification?.status;\n\n const isMiss = [\"not_found\"].includes(status || \"\");\n\n // Partial matches: something found but not ideal (amber indicator)\n const isPartialMatch = [\n \"found_anchor_text_only\", // Only anchor text found, not full phrase\n \"partial_text_found\",\n \"found_on_other_page\",\n \"found_on_other_line\",\n \"first_word_found\"\n ].includes(status || \"\");\n\n // Verified: exact match or partial match (green or amber indicator)\n const isVerified = [\"found\", \"found_phrase_missed_anchor_text\"].includes(status || \"\") || isPartialMatch;\n\n const isPending = [\"pending\", \"loading\", null, undefined].includes(status);\n\n return { isVerified, isMiss, isPartialMatch, isPending };\n}\n\nexport const parseCitation = (\n fragment: string,\n mdAttachmentId?: string | null,\n citationCounterRef?: any | null,\n isVerbose?: boolean\n) => {\n // Helper: Remove wrapper quotes and fully unescape content\n // Handles: \\' -> ', \\\" -> \", \\n -> space, \\\\ -> \\\n const cleanAndUnescape = (str?: string) => {\n if (!str) return undefined;\n let result = str;\n // Remove surrounding quotes if present, but only if not escaped\n // Check start: remove leading quote only if it exists\n if (result.startsWith(\"'\") || result.startsWith('\"')) {\n result = result.slice(1);\n }\n // Check end: remove trailing quote only if it's not escaped (not preceded by \\)\n if ((result.endsWith(\"'\") || result.endsWith('\"')) && !result.endsWith(\"\\\\'\") && !result.endsWith('\\\\\"')) {\n result = result.slice(0, -1);\n }\n // Replace escaped double quotes with actual double quotes\n result = result.replace(/\\\\\"/g, '\"');\n // Replace escaped single quotes with actual single quotes\n result = result.replace(/\\\\'/g, \"'\");\n // Replace literal \\n sequences with spaces (newlines in attribute values)\n result = result.replace(/\\\\n/g, \" \");\n // Replace double backslashes with single backslash\n result = result.replace(/\\\\\\\\/g, \"\\\\\");\n return result;\n };\n\n const citationNumber = citationCounterRef?.current\n ? citationCounterRef.current++\n : undefined;\n\n const beforeCite = fragment.substring(0, fragment.indexOf(\"<cite\"));\n const afterCite = fragment.includes(\"/>\")\n ? fragment.slice(fragment.indexOf(\"/>\") + 2)\n : \"\";\n const middleCite = fragment.substring(\n fragment.indexOf(\"<cite\"),\n fragment.indexOf(\"/>\") + 2\n );\n\n const extractAttribute = (tag: string, attrNames: string[]): string | undefined => {\n for (const name of attrNames) {\n const regex = getAttributeRegex(name);\n const match = tag.match(regex);\n if (match) {\n return match[1];\n }\n }\n return undefined;\n };\n\n // Extract all attributes by name (order-independent)\n let rawAttachmentId = extractAttribute(middleCite, ['attachment_id', 'attachmentId', 'file_id', 'fileId']);\n let attachmentId = rawAttachmentId?.length === 20 ? rawAttachmentId : mdAttachmentId || rawAttachmentId;\n\n const startPageIdRaw = extractAttribute(middleCite, ['start_page_id', 'startPageId', 'start_page_key', 'startPageKey', 'start_page']);\n let pageNumber: number | undefined;\n let pageIndex: number | undefined;\n if (startPageIdRaw) {\n // Performance fix: use module-level compiled regex\n const pageMatch = startPageIdRaw.match(PAGE_ID_FULL_REGEX);\n if (pageMatch) {\n pageNumber = parseInt(pageMatch[1]);\n pageIndex = parseInt(pageMatch[2]);\n }\n }\n\n // Use helper to handle escaped quotes inside the phrase\n let fullPhrase = cleanAndUnescape(extractAttribute(middleCite, ['full_phrase', 'fullPhrase']));\n let anchorText = cleanAndUnescape(extractAttribute(middleCite, ['anchor_text', 'anchorText', 'key_span', 'keySpan']));\n let reasoning = cleanAndUnescape(extractAttribute(middleCite, ['reasoning']));\n let value = cleanAndUnescape(extractAttribute(middleCite, ['value']));\n\n let lineIds: number[] | undefined;\n try {\n const lineIdsRaw = extractAttribute(middleCite, ['line_ids', 'lineIds']);\n const lineIdsString = lineIdsRaw?.replace(/[A-Za-z_[\\](){}:]/g, \"\");\n lineIds = lineIdsString ? parseLineIds(lineIdsString) : undefined;\n } catch (e) {\n if (isVerbose) console.error(\"Error parsing lineIds\", e);\n }\n\n // Check for AV citation (has timestamps instead of line_ids)\n const timestampsRaw = extractAttribute(middleCite, ['timestamps']);\n let timestamps: { startTime?: string; endTime?: string } | undefined;\n\n if (timestampsRaw) {\n const [startTime, endTime] = timestampsRaw.split(\"-\") || [];\n timestamps = { startTime, endTime };\n }\n\n const citation: Citation = {\n attachmentId: attachmentId,\n pageNumber,\n startPageId: `page_number_${pageNumber || 1}_index_${pageIndex || 0}`,\n fullPhrase,\n anchorText: anchorText || value,\n citationNumber,\n lineIds,\n beforeCite,\n timestamps,\n reasoning,\n };\n\n return {\n beforeCite,\n afterCite,\n citation,\n };\n};\n\n/**\n * Parses a JSON-based citation object into a Citation.\n * Supports both camelCase and snake_case property names.\n *\n * @param jsonCitation - The JSON citation object (can have camelCase or snake_case properties)\n * @param citationNumber - Optional citation number for ordering\n * @returns Parsed Citation object\n */\nconst parseJsonCitation = (\n jsonCitation: any,\n citationNumber?: number\n): Citation | null => {\n if (!jsonCitation) {\n return null;\n }\n\n // Support both camelCase and snake_case property names (with backward compatibility)\n const fullPhrase = jsonCitation.fullPhrase ?? jsonCitation.full_phrase;\n const startPageId = jsonCitation.startPageId ?? jsonCitation.start_page_id ?? jsonCitation.startPageKey ?? jsonCitation.start_page_key;\n const anchorText = jsonCitation.anchorText ?? jsonCitation.anchor_text ?? jsonCitation.keySpan ?? jsonCitation.key_span;\n const rawLineIds = jsonCitation.lineIds ?? jsonCitation.line_ids;\n const attachmentId = jsonCitation.attachmentId ?? jsonCitation.attachment_id ?? jsonCitation.fileId ?? jsonCitation.file_id;\n const reasoning = jsonCitation.reasoning;\n const value = jsonCitation.value;\n\n if (!fullPhrase) {\n return null;\n }\n\n // Parse startPageId format: \"page_number_PAGE_index_INDEX\" or simple \"PAGE_INDEX\"\n let pageNumber: number | undefined;\n if (startPageId) {\n // Try full format first: page_number_5_index_2 or pageId_5_index_2\n // Performance fix: use module-level compiled regex\n const pageMatch = startPageId.match(PAGE_ID_SIMPLE_REGEX);\n if (pageMatch) {\n pageNumber = parseInt(pageMatch[1], 10);\n } else {\n // Try simple n_m format: 5_4 (page 5, index 4)\n const simpleMatch = startPageId.match(SIMPLE_PAGE_INDEX_REGEX);\n if (simpleMatch) {\n pageNumber = parseInt(simpleMatch[1], 10);\n }\n }\n }\n\n // Sort lineIds if present\n const lineIds = rawLineIds?.length\n ? [...rawLineIds].sort((a: number, b: number) => a - b)\n : undefined;\n\n const citation: Citation = {\n attachmentId,\n pageNumber,\n fullPhrase,\n citationNumber,\n lineIds,\n anchorText: anchorText || value,\n reasoning,\n };\n\n return citation;\n};\n\n/**\n * Checks if an object has citation-like properties (camelCase or snake_case).\n */\nconst hasCitationProperties = (item: any): boolean =>\n typeof item === \"object\" &&\n item !== null &&\n (\"fullPhrase\" in item ||\n \"full_phrase\" in item ||\n \"startPageId\" in item ||\n \"start_page_id\" in item ||\n \"startPageKey\" in item ||\n \"start_page_key\" in item ||\n \"anchorText\" in item ||\n \"anchor_text\" in item ||\n \"keySpan\" in item ||\n \"key_span\" in item ||\n \"lineIds\" in item ||\n \"line_ids\" in item);\n\n/**\n * Checks if the input appears to be JSON-based citations.\n * Looks for array of objects with citation-like properties (supports both camelCase and snake_case).\n */\nconst isJsonCitationFormat = (data: any): data is Citation[] | Citation => {\n if (Array.isArray(data)) {\n return data.length > 0 && data.some(hasCitationProperties);\n }\n if (typeof data === \"object\" && data !== null) {\n return hasCitationProperties(data);\n }\n return false;\n};\n\n/**\n * Extracts citations from JSON format (array or single object).\n */\nconst extractJsonCitations = (\n data: Citation[] | Citation\n): CitationRecord => {\n const citations: CitationRecord = {};\n const items = Array.isArray(data) ? data : [data];\n\n let citationNumber = 1;\n for (const item of items) {\n const citation = parseJsonCitation(item, citationNumber++);\n if (citation && citation.fullPhrase) {\n const citationKey = generateCitationKey(citation);\n citations[citationKey] = citation;\n }\n }\n\n return citations;\n};\n\n/**\n * Maximum recursion depth for JSON citation traversal.\n * Prevents stack overflow from deeply nested or circular objects.\n */\nconst MAX_TRAVERSAL_DEPTH = 50;\n\n/**\n * Recursively traverses an object looking for `citation` or `citations` properties\n * that match our JSON citation format.\n *\n * Performance fix: Depth limit prevents stack overflow from malicious/circular objects.\n *\n * @param obj - Object to traverse\n * @param found - Array to collect found citations\n * @param depth - Current recursion depth (internal)\n */\nconst findJsonCitationsInObject = (obj: any, found: Citation[], depth = 0): void => {\n // Performance fix: prevent stack overflow with depth limit\n if (depth > MAX_TRAVERSAL_DEPTH || !obj || typeof obj !== \"object\") return;\n\n // Check for citation/citations properties\n if (obj.citation && isJsonCitationFormat(obj.citation)) {\n const items = Array.isArray(obj.citation) ? obj.citation : [obj.citation];\n found.push(...items);\n }\n if (obj.citations && isJsonCitationFormat(obj.citations)) {\n const items = Array.isArray(obj.citations)\n ? obj.citations\n : [obj.citations];\n found.push(...items);\n }\n\n // Recurse into object properties\n if (Array.isArray(obj)) {\n for (const item of obj) {\n findJsonCitationsInObject(item, found, depth + 1);\n }\n } else {\n for (const key of Object.keys(obj)) {\n if (key !== \"citation\" && key !== \"citations\") {\n findJsonCitationsInObject(obj[key], found, depth + 1);\n }\n }\n }\n};\n\n/**\n * Extracts XML citations from text using <cite ... /> tags.\n */\nconst extractXmlCitations = (text: string): CitationRecord => {\n const normalizedText = normalizeCitations(text);\n\n // Find all <cite ... /> tags\n // Performance fix: use module-level compiled regex (create fresh instance to reset lastIndex)\n const citeRegex = new RegExp(CITE_TAG_REGEX.source, CITE_TAG_REGEX.flags);\n const matches = normalizedText.match(citeRegex);\n\n if (!matches || matches.length === 0) return {};\n\n const citations: CitationRecord = {};\n const citationCounterRef = { current: 1 };\n\n for (const match of matches) {\n const { citation } = parseCitation(match, undefined, citationCounterRef);\n if (citation && citation.fullPhrase) {\n const citationKey = generateCitationKey(citation);\n citations[citationKey] = citation;\n }\n }\n\n return citations;\n};\n\n/**\n * Extracts all citations from LLM output.\n * Supports both XML <cite ... /> tags (embedded in strings/markdown) and JSON-based citation formats.\n *\n * For object input:\n * - Traverses the object looking for `citation` or `citations` properties matching JSON format\n * - Also stringifies the object to find embedded XML citations in markdown content\n *\n * **IMPORTANT**: Returns an OBJECT (CitationRecord), NOT an array.\n * To check if empty, use `Object.keys(citations).length === 0`.\n *\n * @param llmOutput - The LLM output (string or object)\n * @returns CitationRecord - An object/dictionary of citations keyed by citationKey (a 16-char hash).\n * This is NOT an array. Use Object.keys(), Object.values(), or Object.entries() to iterate.\n *\n * @example\n * ```typescript\n * const citations = getAllCitationsFromLlmOutput(llmResponse);\n * // Returns: { \"a1b2c3d4e5f67890\": { pageNumber: 1, ... }, \"f9e8d7c6b5a43210\": { ... } }\n *\n * // Check if empty (NOT citations.length!)\n * if (Object.keys(citations).length === 0) {\n * console.log(\"No citations found\");\n * }\n *\n * // Get count\n * const count = Object.keys(citations).length;\n *\n * // Iterate\n * for (const [citationKey, citation] of Object.entries(citations)) {\n * console.log(`Citation ${citationKey}:`, citation.fullPhrase);\n * }\n * ```\n */\nexport const getAllCitationsFromLlmOutput = (\n llmOutput: unknown\n): CitationRecord => {\n if (!llmOutput) return {};\n\n const citations: CitationRecord = {};\n\n if (typeof llmOutput === \"object\") {\n // Check if the root object itself is JSON citation format\n if (isJsonCitationFormat(llmOutput)) {\n const jsonCitations = extractJsonCitations(llmOutput);\n Object.assign(citations, jsonCitations);\n } else {\n // Traverse object for nested citation/citations properties\n const foundJsonCitations: Citation[] = [];\n findJsonCitationsInObject(llmOutput, foundJsonCitations);\n\n if (foundJsonCitations.length > 0) {\n const jsonCitations = extractJsonCitations(foundJsonCitations);\n Object.assign(citations, jsonCitations);\n }\n }\n\n // Also stringify and parse for embedded XML citations in markdown\n const text = JSON.stringify(llmOutput);\n const xmlCitations = extractXmlCitations(text);\n Object.assign(citations, xmlCitations);\n } else if (typeof llmOutput === \"string\") {\n // Check for deferred JSON format (<<<CITATION_DATA>>>)\n if (hasDeferredCitations(llmOutput)) {\n const deferredCitations = getAllCitationsFromDeferredResponse(llmOutput);\n Object.assign(citations, deferredCitations);\n }\n // Also parse for XML citations (both formats can coexist)\n const xmlCitations = extractXmlCitations(llmOutput);\n Object.assign(citations, xmlCitations);\n }\n\n return citations;\n};\n\n/**\n * Groups citations by their attachmentId for multi-file verification scenarios.\n * This is useful when you have citations from multiple files and need to\n * verify them against their respective attachments.\n *\n * @param citations - Array of Citation objects or a CitationRecord (object/dictionary)\n * @returns Map of attachmentId to CitationRecord (dictionary of citations from that file)\n *\n * @example\n * ```typescript\n * const citations = getAllCitationsFromLlmOutput(response.content);\n * const citationsByAttachment = groupCitationsByAttachmentId(citations);\n *\n * // Verify citations for each file\n * for (const [attachmentId, fileCitations] of citationsByAttachment) {\n * const verified = await deepcitation.verifyCitations(attachmentId, fileCitations);\n * // Process verification results...\n * }\n * ```\n */\nexport function groupCitationsByAttachmentId(\n citations: Citation[] | CitationRecord\n): Map<string, CitationRecord> {\n const grouped = new Map<string, CitationRecord>();\n\n // Normalize input to entries\n const entries: [string, Citation][] = Array.isArray(citations)\n ? citations.map((c, idx) => [generateCitationKey(c) || String(idx + 1), c])\n : Object.entries(citations);\n\n for (const [key, citation] of entries) {\n const attachmentId = citation.attachmentId || \"\";\n\n if (!grouped.has(attachmentId)) {\n grouped.set(attachmentId, {});\n }\n\n grouped.get(attachmentId)![key] = citation;\n }\n\n return grouped;\n}\n\n/**\n * Groups citations by their attachmentId and returns as a plain object.\n * Alternative to groupCitationsByAttachmentId that returns a plain object instead of a Map.\n *\n * @param citations - Array of Citation objects or a CitationRecord (object/dictionary)\n * @returns Object with attachmentId keys mapping to CitationRecord dictionaries\n *\n * @example\n * ```typescript\n * const citations = getAllCitationsFromLlmOutput(response.content);\n * const citationsByAttachment = groupCitationsByAttachmentIdObject(citations);\n *\n * // Verify citations for each file using Promise.all\n * const verificationPromises = Object.entries(citationsByAttachment).map(\n * ([attachmentId, fileCitations]) => deepcitation.verifyCitations(attachmentId, fileCitations)\n * );\n * const results = await Promise.all(verificationPromises);\n * ```\n */\nexport function groupCitationsByAttachmentIdObject(\n citations: Citation[] | CitationRecord\n): Record<string, CitationRecord> {\n const grouped: Record<string, CitationRecord> = {};\n\n // Normalize input to entries\n const entries: [string, Citation][] = Array.isArray(citations)\n ? citations.map((c, idx) => [generateCitationKey(c) || String(idx + 1), c])\n : Object.entries(citations);\n\n for (const [key, citation] of entries) {\n const attachmentId = citation.attachmentId || \"\";\n\n if (!grouped[attachmentId]) {\n grouped[attachmentId] = {};\n }\n\n grouped[attachmentId][key] = citation;\n }\n\n return grouped;\n}\n","import type { Verification } from \"../types/verification.js\";\nimport type { Citation } from \"../types/citation.js\";\nimport { getCitationStatus } from \"./parseCitation.js\";\nimport { generateCitationKey } from \"../react/utils.js\";\n\n/**\n * Module-level compiled regexes for hot-path operations.\n *\n * IMPORTANT: These regexes are compiled once at module load time to avoid\n * the overhead of regex compilation on every function call.\n *\n * Note on global flag (/g): Regexes with the global flag maintain internal\n * state (lastIndex). To avoid state pollution across calls, we create fresh\n * instances from these patterns when using methods that rely on lastIndex:\n *\n * // SAFE: Create new instance from source pattern\n * const regex = new RegExp(CITE_TAG_REGEX.source, CITE_TAG_REGEX.flags);\n *\n * Performance fix: avoids regex recompilation on every function call.\n */\nconst PAGE_NUMBER_REGEX = /page[_a-zA-Z]*(\\d+)/;\nconst RANGE_EXPANSION_REGEX = /(\\d+)-(\\d+)/g;\nconst CITE_TAG_REGEX = /<cite\\s+[^>]*?\\/>/g;\n\nexport interface ReplaceCitationsOptions {\n /**\n * If true, leaves the anchor_text text behind when removing citations.\n * @default false\n */\n leaveAnchorTextBehind?: boolean;\n\n /**\n * Map of citation keys to verification results.\n * Used to determine verification status for each citation.\n */\n verifications?: Record<string, Verification>;\n\n /**\n * If true and verifications are provided, appends a verification status indicator.\n * Uses: ✓ (verified), ⚠ (partial), ✗ (not found), ◌ (pending)\n * @default false\n */\n showVerificationStatus?: boolean;\n}\n\n/**\n * Parse attributes from a cite tag in any order.\n * Returns an object with all found attributes.\n */\nconst parseCiteAttributes = (\n citeTag: string\n): Record<string, string | undefined> => {\n const attrs: Record<string, string | undefined> = {};\n\n // Match attribute patterns: key='value' or key=\"value\"\n const attrRegex =\n /([a-zA-Z_][a-zA-Z0-9_]*)\\s*=\\s*(['\"])((?:[^'\"\\\\]|\\\\.)*)\\2/g;\n let match;\n\n while ((match = attrRegex.exec(citeTag)) !== null) {\n const key = match[1]\n .toLowerCase()\n .replace(/([a-z])([A-Z])/g, \"$1_$2\")\n .toLowerCase();\n const value = match[3];\n\n // Normalize key names\n const normalizedKey =\n key === \"fileid\" || key === \"file_id\" || key === \"attachmentid\"\n ? \"attachment_id\"\n : key === \"anchortext\" || key === \"anchor_text\" || key === \"keyspan\" || key === \"key_span\"\n ? \"anchor_text\"\n : key === \"fullphrase\"\n ? \"full_phrase\"\n : key === \"lineids\"\n ? \"line_ids\"\n : key === \"pageid\" || key === \"page_id\" || key === \"startpageid\" || key === \"start_pageid\" || key === \"start_page_id\" || key === \"startpagekey\" || key === \"start_pagekey\" || key === \"start_page_key\" || key === \"pagekey\" || key === \"page_key\"\n ? \"start_page_id\"\n : key;\n\n attrs[normalizedKey] = value;\n }\n\n return attrs;\n};\n\n/**\n * Get verification status indicator character for plain text/terminal output.\n * Returns: ☑️ (fully verified), ✅ (partial match), ❌ (not found), ⌛ (pending/null), ◌ (unknown)\n *\n * For web UI, use the React CitationComponent instead which provides\n * proper styled indicators with colors and accessibility.\n */\nexport const getVerificationTextIndicator = (\n verification: Verification | null | undefined\n): string => {\n const status = getCitationStatus(verification);\n\n if (status.isMiss) return \"❌\";\n // Check for fully verified (not partial) first\n if (status.isVerified && !status.isPartialMatch) return \"☑️\";\n // Then check for partial match\n if (status.isPartialMatch) return \"✅\";\n\n if (status.isPending) return \"⌛\";\n\n return \"◌\";\n};\n\n/**\n * Replaces citation tags in markdown text with optional replacement content.\n *\n * @param markdownWithCitations - The text containing <cite /> tags\n * @param options - Configuration options\n * @returns The text with citations replaced\n *\n * @example\n * ```typescript\n * // Remove all citations\n * const clean = replaceCitations(llmOutput);\n *\n * // Leave anchor_text text behind\n * const withAnchorTexts = replaceCitations(llmOutput, { leaveAnchorTextBehind: true });\n *\n * // Show verification status indicators\n * const withStatus = replaceCitations(llmOutput, {\n * leaveAnchorTextBehind: true,\n * verifications: verificationMap,\n * showVerificationStatus: true,\n * });\n * // Output: \"Revenue grew 45% year-over-year Revenue Growth✓\"\n * ```\n */\nexport const replaceCitations = (\n markdownWithCitations: string,\n options: ReplaceCitationsOptions = {}\n): string => {\n const {\n leaveAnchorTextBehind = false,\n verifications,\n showVerificationStatus = false,\n } = options;\n\n // Track citation index for matching with numbered verification keys\n let citationIndex = 0;\n\n // Performance fix: use module-level compiled regex (create fresh instance to reset lastIndex)\n const citationRegex = new RegExp(CITE_TAG_REGEX.source, CITE_TAG_REGEX.flags);\n\n return markdownWithCitations.replace(citationRegex, (match) => {\n citationIndex++;\n const attrs = parseCiteAttributes(match);\n\n // Determine what to output\n let output = \"\";\n\n if (leaveAnchorTextBehind && attrs.anchor_text) {\n // Unescape the anchor_text value\n output = attrs.anchor_text.replace(/\\\\'/g, \"'\").replace(/\\\\\"/g, '\"');\n }\n\n // Add verification status if requested\n if (showVerificationStatus && verifications) {\n // Try to find verification by various key strategies\n let verification: Verification | undefined;\n\n // Build a Citation object from parsed attributes to generate the key\n const parsePageNumber = (startPageId?: string): number | undefined => {\n if (!startPageId) return undefined;\n // Performance fix: use module-level compiled regex\n const match = startPageId.match(PAGE_NUMBER_REGEX);\n return match ? parseInt(match[1], 10) : undefined;\n };\n\n const parseLineIds = (lineIdsStr?: string): number[] | undefined => {\n if (!lineIdsStr) return undefined;\n\n // Performance fix: limit range expansion to prevent memory exhaustion\n const MAX_RANGE_SIZE = 1000;\n const SAMPLE_COUNT = 50;\n\n // First expand ranges (e.g., \"62-63\" -> \"62,63\")\n let expanded = lineIdsStr.replace(\n /(\\d+)-(\\d+)/g,\n (_match, start, end) => {\n const startNum = parseInt(start, 10);\n const endNum = parseInt(end, 10);\n if (startNum <= endNum) {\n const rangeSize = endNum - startNum + 1;\n // For large ranges, use sampling to maintain accuracy\n if (rangeSize > MAX_RANGE_SIZE) {\n const samples = [startNum];\n const sampleCount = Math.min(SAMPLE_COUNT - 2, rangeSize - 2);\n if (sampleCount > 0) {\n // Use Math.floor for predictable sampling, ensuring step >= 1\n const step = Math.max(1, Math.floor((endNum - startNum) / (sampleCount + 1)));\n for (let i = 1; i <= sampleCount; i++) {\n const sample = startNum + step * i;\n // Ensure we don't exceed the range end\n if (sample < endNum) {\n samples.push(sample);\n }\n }\n }\n samples.push(endNum);\n return samples.join(\",\");\n }\n const range = [];\n for (let i = startNum; i <= endNum; i++) {\n range.push(i);\n }\n return range.join(\",\");\n }\n return start;\n }\n );\n\n const nums = expanded.split(\",\").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n));\n return nums.length > 0 ? nums : undefined;\n };\n\n // Unescape quotes in fullPhrase and anchorText to match how citations are parsed\n // by getAllCitationsFromLlmOutput (which returns unescaped values)\n const unescapeQuotes = (str: string | undefined): string | undefined =>\n str?.replace(/\\\\'/g, \"'\").replace(/\\\\\"/g, '\"');\n\n const citation: Citation = {\n attachmentId: attrs.attachment_id,\n pageNumber: parsePageNumber(attrs.start_page_id),\n fullPhrase: unescapeQuotes(attrs.full_phrase),\n anchorText: unescapeQuotes(attrs.anchor_text),\n lineIds: parseLineIds(attrs.line_ids),\n };\n\n // Strategy 1: Match by citationKey (hash) - most reliable\n const citationKey = generateCitationKey(citation);\n verification = verifications[citationKey];\n\n // Strategy 2: Fall back to numbered keys (1, 2, 3, etc.)\n if (!verification) {\n const numericKey = String(citationIndex);\n verification = verifications[numericKey];\n }\n\n const indicator = getVerificationTextIndicator(verification);\n output = output ? `${output}${indicator}` : indicator;\n }\n\n return output;\n });\n};\n\nexport const removePageNumberMetadata = (pageText: string): string => {\n return pageText\n .replace(/<page_number_\\d+_index_\\d+>/g, \"\")\n .replace(/<\\/page_number_\\d+_index_\\d+>/g, \"\")\n .trim();\n};\n\nexport const removeLineIdMetadata = (pageText: string): string => {\n const lineIdRegex = /<line id=\"[^\"]*\">|<\\/line>/g;\n return pageText.replace(lineIdRegex, \"\");\n};\n\nexport const getCitationPageNumber = (\n startPageId?: string | null\n): number | null => {\n //page_number_{page_number}_index_{page_index} or page_number_{page_number} or page_id_{page_number}_index_{page_index}\n if (!startPageId) return null;\n\n //regex first \\d+ is the page number\n const pageNumber = startPageId.match(/\\d+/)?.[0];\n return pageNumber ? parseInt(pageNumber) : null;\n};\n\n/**\n * Extracts content from a non-self-closing citation tag and moves it before the citation.\n * Converts <cite ...>content</cite> to: content<cite ... />\n *\n * @param citePart - The citation part that may contain inner content\n * @returns The normalized citation with content moved before it\n */\nconst extractAndRelocateCitationContent = (citePart: string): string => {\n // Check if this is a non-self-closing citation: <cite ...>content</cite>\n // Match: <cite with attributes> then content then </cite>\n // The attribute regex handles escaped quotes: (?:[^'\\\\]|\\\\.)* matches non-quote/non-backslash OR backslash+any\n const nonSelfClosingMatch = citePart.match(\n /^(<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>)([\\s\\S]*?)<\\/cite>$/\n );\n\n if (!nonSelfClosingMatch) {\n // Check if this is an unclosed citation ending with just >\n // Pattern: <cite attributes> (no closing tag)\n const unclosedMatch = citePart.match(\n /^(<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>)$/\n );\n if (unclosedMatch) {\n // Convert <cite ... > to self-closing <cite ... />\n const selfClosingTag = unclosedMatch[1].replace(/>$/, \" />\");\n return normalizeCitationContent(selfClosingTag);\n }\n // Already self-closing or doesn't match pattern, normalize as-is\n return normalizeCitationContent(citePart);\n }\n\n const [, openingTag, innerContent] = nonSelfClosingMatch;\n\n // If there's no inner content, just normalize the citation\n if (!innerContent || !innerContent.trim()) {\n return normalizeCitationContent(citePart);\n }\n\n // Extract the attributes from the opening tag\n // Convert <cite attributes> to <cite attributes />\n const selfClosingTag = openingTag.replace(/>$/, \" />\");\n\n // Move inner content before the citation and normalize\n // The inner content is trimmed to avoid extra whitespace issues\n const relocatedContent = innerContent.trim();\n\n // Normalize the self-closing citation tag\n const normalizedCitation = normalizeCitationContent(selfClosingTag);\n\n // Return content followed by the citation\n return relocatedContent + normalizedCitation;\n};\n\nexport const normalizeCitations = (response: string): string => {\n let trimmedResponse = response?.trim() || \"\";\n\n // Fix missing < before cite tags\n // LLMs sometimes output 'cite' without the leading '<'\n // Match 'cite' followed by a space and attribute pattern, but NOT preceded by '<' or a letter\n // This avoids matching words like \"excite\" or \"recite\"\n trimmedResponse = trimmedResponse.replace(\n /(?<![<a-zA-Z])cite\\s+(attachment_id|file_id|fileId|attachmentId)\\s*=/gi,\n \"<cite $1=\"\n );\n\n // Split on citation tags - captures three patterns:\n // 1. Self-closing: <cite ... />\n // 2. With closing tag: <cite ...>content</cite>\n // 3. Unclosed (ends with >): <cite ...> (no closing tag, no </cite> anywhere after)\n // Pattern 3 uses negative lookahead to avoid matching when </cite> follows\n const citationParts = trimmedResponse.split(\n /(<cite[\\s\\S]*?(?:\\/>|<\\/cite>|>(?=\\s*$|[\\r\\n])(?![\\s\\S]*<\\/cite>)))/gm\n );\n if (citationParts.length <= 1) {\n // Handle unclosed citations by converting to self-closing\n const unclosedMatch = trimmedResponse.match(/<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>/g);\n if (unclosedMatch && unclosedMatch.length > 0) {\n const result = trimmedResponse.replace(\n /<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>/g,\n (match) => match.replace(/>$/, ' />')\n );\n return normalizeCitationContent(result);\n }\n return normalizeCitationContent(trimmedResponse);\n }\n\n trimmedResponse = citationParts\n .map((part) =>\n part.startsWith(\"<cite\")\n ? extractAndRelocateCitationContent(part)\n : part\n )\n .join(\"\");\n\n return trimmedResponse;\n};\n\nconst normalizeCitationContent = (input: string): string => {\n let normalized = input;\n\n // 0. Unescape all backslash-escaped underscores\n // This handles Markdown-processed output where underscores get escaped (e.g., attachment\\_id -> attachment_id, page\\_number\\_1 -> page_number_1)\n normalized = normalized.replace(/\\\\_/g, \"_\");\n\n // 1. Standardize self-closing tags\n // Replace ></cite> with /> for consistency\n normalized = normalized.replace(/><\\/cite>/g, \"/>\");\n\n const canonicalizeCiteAttributeKey = (key: string): string => {\n const lowerKey = key.toLowerCase();\n if (lowerKey === \"fullphrase\" || lowerKey === \"full_phrase\")\n return \"full_phrase\";\n if (lowerKey === \"lineids\" || lowerKey === \"line_ids\") return \"line_ids\";\n if (\n lowerKey === \"startpageid\" ||\n lowerKey === \"start_pageid\" ||\n lowerKey === \"start_page_id\" ||\n lowerKey === \"startpagekey\" ||\n lowerKey === \"start_pagekey\" ||\n lowerKey === \"start_page_key\"\n )\n return \"start_page_id\";\n if (\n lowerKey === \"fileid\" ||\n lowerKey === \"file_id\" ||\n lowerKey === \"attachmentid\" ||\n lowerKey === \"attachment_id\"\n )\n return \"attachment_id\";\n if (lowerKey === \"anchortext\" || lowerKey === \"anchor_text\" || lowerKey === \"keyspan\" || lowerKey === \"key_span\") return \"anchor_text\";\n if (lowerKey === \"reasoning\" || lowerKey === \"value\") return lowerKey;\n if (\n lowerKey === \"timestamps\" ||\n lowerKey === \"timestamp\" ||\n lowerKey === \"timestamps\"\n )\n return \"timestamps\";\n\n return lowerKey;\n };\n\n const htmlEntityMap: Record<string, string> = {\n '&quot;': '\"',\n '&apos;': \"'\",\n '&lt;': '<',\n '&gt;': '>',\n '&amp;': '&',\n };\n const htmlEntityRegex = /&(?:quot|apos|lt|gt|amp);/g;\n const decodeHtmlEntities = (str: string) => {\n return str.replace(htmlEntityRegex, (match) => htmlEntityMap[match] || match);\n };\n\n const textAttributeRegex =\n /(fullPhrase|full_phrase|anchorText|anchor_text|keySpan|key_span|reasoning|value)\\s*=\\s*(['\"])([\\s\\S]*?)(?=\\s+(?:line_ids|lineIds|timestamps|fileId|file_id|attachmentId|attachment_id|start_page_id|start_pageId|startPageId|start_page_key|start_pageKey|startPageKey|anchorText|anchor_text|keySpan|key_span|reasoning|value|full_phrase)\\s*=|\\s*\\/>|['\"]>)/gm;\n\n normalized = normalized.replace(\n textAttributeRegex,\n (_match, key, openQuote, rawContent) => {\n let content = rawContent;\n\n if (content.endsWith(openQuote)) {\n content = content.slice(0, -1);\n }\n\n // Flatten newlines and remove markdown markers\n content = content.replace(/(\\r?\\n)+|(\\*|_){2,}|\\*/g, (match: string) => {\n if (match.includes('\\n') || match.includes('\\r')) return ' ';\n return '';\n });\n\n content = decodeHtmlEntities(content);\n\n // Normalize quotes\n content = content.replace(/\\\\\\\\'/g, \"'\").replace(/\\\\'/g, \"'\").replace(/'/g, \"\\\\'\");\n content = content.replace(/\\\\\\\\\"/g, '\"').replace(/\\\\\"/g, '\"').replace(/\"/g, '\\\\\"');\n\n return `${canonicalizeCiteAttributeKey(key)}='${content}'`;\n }\n );\n // Performance fix: limit range expansion to prevent memory exhaustion\n const MAX_RANGE_SIZE = 1000;\n const SAMPLE_COUNT = 50;\n\n normalized = normalized.replace(\n /(line_ids|lineIds|timestamps)=['\"]?([\\[\\]\\(\\){}A-Za-z0-9_\\-, ]+)['\"]?(\\s*\\/?>|\\s+)/gm,\n (_match, key, rawValue, trailingChars) => {\n // Clean up the value (remove generic text, keep numbers/separators)\n let cleanedValue = rawValue.replace(/[A-Za-z\\[\\]\\(\\){}]/g, \"\");\n\n // Expand ranges (e.g., \"1-3\" -> \"1,2,3\")\n cleanedValue = cleanedValue.replace(\n /(\\d+)-(\\d+)/g,\n (_rangeMatch: string, start: string, end: string) => {\n const startNum = parseInt(start, 10);\n const endNum = parseInt(end, 10);\n\n // Handle ascending range\n if (startNum <= endNum) {\n const rangeSize = endNum - startNum + 1;\n // For large ranges, use sampling to maintain accuracy\n if (rangeSize > MAX_RANGE_SIZE) {\n const samples = [startNum];\n const sampleCount = Math.min(SAMPLE_COUNT - 2, rangeSize - 2);\n if (sampleCount > 0) {\n // Use Math.floor for predictable sampling, ensuring step >= 1\n const step = Math.max(1, Math.floor((endNum - startNum) / (sampleCount + 1)));\n for (let i = 1; i <= sampleCount; i++) {\n const sample = startNum + step * i;\n // Ensure we don't exceed the range end\n if (sample < endNum) {\n samples.push(sample);\n }\n }\n }\n samples.push(endNum);\n return samples.join(\",\");\n }\n const range = [];\n for (let i = startNum; i <= endNum; i++) {\n range.push(i);\n }\n return range.join(\",\");\n } else {\n // Fallback for weird descending ranges or just return start\n return String(startNum);\n }\n }\n );\n\n // Normalize commas\n cleanedValue = cleanedValue.replace(/,+/g, \",\").replace(/^,|,$/g, \"\");\n\n // Return standardized format: key='value' + preserved trailing characters (space or />)\n return `${canonicalizeCiteAttributeKey(\n key\n )}='${cleanedValue}'${trailingChars}`;\n }\n );\n\n // 4. Re-order <cite ... /> attributes to match the strict parsing expectations in `citationParser.ts`\n // (the parser uses regexes that assume a canonical attribute order).\n const reorderCiteTagAttributes = (tag: string): string => {\n // Match both single-quoted and double-quoted attributes\n const attrRegex =\n /([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(['\"])((?:[^'\"\\\\\\n]|\\\\.)*)(?:\\2)/g;\n const attrs: Record<string, string> = {};\n let match: RegExpExecArray | null;\n\n while ((match = attrRegex.exec(tag))) {\n const rawKey = match[1];\n const value = match[3]; // match[2] is the quote character\n const key = canonicalizeCiteAttributeKey(rawKey);\n attrs[key] = value;\n }\n\n // If we didn't find any parsable attrs, don't touch the tag.\n const keys = Object.keys(attrs);\n if (keys.length === 0) return tag;\n\n const hasTimestamps =\n typeof attrs.timestamps === \"string\" && attrs.timestamps.length > 0;\n const startPageIds = keys.filter((k) => k.startsWith(\"start_page\"));\n\n const ordered: string[] = [];\n\n // Shared first\n if (attrs.attachment_id) ordered.push(\"attachment_id\");\n\n if (hasTimestamps) {\n // AV citations: attachment_id, full_phrase, anchor_text, timestamps, (optional reasoning/value), then any extras\n if (attrs.full_phrase) ordered.push(\"full_phrase\");\n if (attrs.anchor_text) ordered.push(\"anchor_text\");\n ordered.push(\"timestamps\");\n } else {\n // Document citations: attachment_id, start_page*, full_phrase, anchor_text, line_ids, (optional reasoning/value), then any extras\n if (startPageIds.includes(\"start_page_id\"))\n ordered.push(\"start_page_id\");\n startPageIds\n .filter((k) => k !== \"start_page_id\")\n .sort()\n .forEach((k) => ordered.push(k));\n\n if (attrs.full_phrase) ordered.push(\"full_phrase\");\n if (attrs.anchor_text) ordered.push(\"anchor_text\");\n if (attrs.line_ids) ordered.push(\"line_ids\");\n }\n\n // Optional attrs supported by the parser (but not required)\n if (attrs.reasoning) ordered.push(\"reasoning\");\n if (attrs.value) ordered.push(\"value\");\n\n // Any remaining attributes, stable + deterministic (alpha)\n const used = new Set(ordered);\n keys\n .filter((k) => !used.has(k))\n .sort()\n .forEach((k) => ordered.push(k));\n\n const rebuiltAttrs = ordered.map((k) => `${k}='${attrs[k]}'`).join(\" \");\n return `<cite ${rebuiltAttrs} />`;\n };\n\n normalized = normalized.replace(/<cite\\b[\\s\\S]*?\\/>/gm, (tag) =>\n reorderCiteTagAttributes(tag)\n );\n\n return normalized;\n};\n","import type { Citation } from \"../types/citation.js\";\nimport type { Verification } from \"../types/verification.js\";\nimport { sha1Hash } from \"../utils/sha.js\";\nimport { getCitationPageNumber } from \"../parsing/normalizeCitation.js\";\n\n// =============================================================================\n// UTILITY FUNCTIONS\n// =============================================================================\n\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n\n/**\n * Type guard to check if a citation is a URL citation (type: \"url\" or has url field).\n */\nexport function isUrlCitation(citation: Citation): boolean {\n return citation.type === \"url\" || (typeof citation.url === \"string\" && citation.url.length > 0);\n}\n\n/**\n * Generates a unique, deterministic key for a citation based on its content.\n * Works with both document and URL citation types.\n *\n * For URL citations, the URL is included in the key generation for uniqueness.\n *\n * @param citation - The citation to generate a key for\n * @returns A unique, deterministic key for the citation\n */\nexport function generateCitationKey(citation: Citation): string {\n const pageNumber =\n citation.pageNumber || getCitationPageNumber(citation.startPageId);\n\n // Base key parts for all citations\n const keyParts = [\n citation.attachmentId || \"\",\n pageNumber?.toString() || \"\",\n citation.fullPhrase || \"\",\n citation.anchorText?.toString() || \"\",\n citation.lineIds?.join(\",\") || \"\",\n citation.timestamps?.startTime || \"\",\n citation.timestamps?.endTime || \"\",\n ];\n\n // Add URL-specific fields if present\n if (isUrlCitation(citation)) {\n keyParts.push(\n citation.url || \"\",\n citation.title || \"\",\n citation.domain || \"\",\n );\n }\n\n return sha1Hash(keyParts.join(\"|\")).slice(0, 16);\n}\n\n/**\n * Generates a unique, deterministic key for a verification based on its content.\n * @param verification - The verification to generate a key for\n * @returns\n */\nexport function generateVerificationKey(verification: Verification): string {\n const keyParts = [\n verification.attachmentId || \"\",\n verification.label || \"\",\n verification.verifiedFullPhrase || \"\",\n verification.verifiedAnchorText || \"\",\n verification.verifiedLineIds?.join(\",\") || \"\",\n verification.verifiedPageNumber?.toString() || \"\",\n\n verification.verifiedTimestamps?.startTime || \"\",\n verification.verifiedTimestamps?.endTime || \"\",\n\n verification.verifiedMatchSnippet || \"\",\n verification.hitIndexWithinPage?.toString() || \"\",\n ];\n\n return sha1Hash(keyParts.join(\"|\")).slice(0, 16);\n}\n\n/**\n * Generates a unique instance ID for a citation component render.\n * Combines the citation key with a random suffix for uniqueness.\n */\nexport function generateCitationInstanceId(citationKey: string): string {\n const randomSuffix = Math.random().toString(36).slice(2, 11);\n return `${citationKey}-${randomSuffix}`;\n}\n\n/**\n * Gets the display text for a citation (anchorText with fallback to number).\n */\nexport function getCitationDisplayText(\n citation: Citation,\n options: {\n fallbackDisplay?: string | null;\n } = {}\n): string {\n const { fallbackDisplay } = options;\n return (\n citation.anchorText?.toString() ||\n citation.citationNumber?.toString() ||\n fallbackDisplay ||\n \"1\"\n );\n}\n\n/**\n * Gets the citation number as a string.\n */\nexport function getCitationNumber(citation: Citation): string {\n return citation.citationNumber?.toString() || \"1\";\n}\n\n/**\n * Gets the anchorText text from a citation.\n */\nexport function getCitationAnchorText(citation: Citation): string {\n return citation.anchorText?.toString() || \"\";\n}\n\n/**\n * Joins class names, filtering out falsy values.\n * This is a minimal implementation for the base component.\n */\nexport function classNames(\n ...classes: (string | undefined | null | false)[]\n): string {\n return classes.filter(Boolean).join(\" \");\n}\n\n/**\n * Default padding values for citation styling.\n */\nexport const CITATION_X_PADDING = 4;\nexport const CITATION_Y_PADDING = 1;\n"]}