@deepcitation/deepcitation-js 1.1.49 → 1.1.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -157
- package/lib/chunk-2HINOG74.js +3 -0
- package/lib/chunk-2HINOG74.js.map +1 -0
- package/lib/chunk-4UWAUWYL.cjs +3 -0
- package/lib/chunk-4UWAUWYL.cjs.map +1 -0
- package/lib/chunk-5XGN7UAV.js +2 -0
- package/lib/chunk-5XGN7UAV.js.map +1 -0
- package/lib/chunk-7TORYXU4.cjs +3 -0
- package/lib/chunk-7TORYXU4.cjs.map +1 -0
- package/lib/chunk-BDSA6VGC.js +125 -0
- package/lib/chunk-BDSA6VGC.js.map +1 -0
- package/lib/chunk-BEYJEW3Y.js +2 -0
- package/lib/chunk-BEYJEW3Y.js.map +1 -0
- package/lib/chunk-BWQLFMTV.js +2 -0
- package/lib/chunk-BWQLFMTV.js.map +1 -0
- package/lib/{chunk-F2MMVEVC.cjs → chunk-BYLIBOAU.cjs} +2 -1
- package/lib/chunk-BYLIBOAU.cjs.map +1 -0
- package/lib/chunk-DS6SOU4L.cjs +2 -0
- package/lib/chunk-DS6SOU4L.cjs.map +1 -0
- package/lib/{chunk-UUR2SQKU.cjs → chunk-HL3AXCDL.cjs} +2 -1
- package/lib/chunk-HL3AXCDL.cjs.map +1 -0
- package/lib/chunk-N7FTXSGM.js +3 -0
- package/lib/chunk-N7FTXSGM.js.map +1 -0
- package/lib/chunk-WS4CQVDI.cjs +125 -0
- package/lib/chunk-WS4CQVDI.cjs.map +1 -0
- package/lib/client/index.cjs +2 -1
- package/lib/client/index.cjs.map +1 -0
- package/lib/client/index.d.cts +58 -13
- package/lib/client/index.d.ts +58 -13
- package/lib/client/index.js +2 -1
- package/lib/client/index.js.map +1 -0
- package/lib/{index-fvVBZYVK.d.ts → index-BHjI8Bh1.d.cts} +61 -22
- package/lib/{index-fvVBZYVK.d.cts → index-BHjI8Bh1.d.ts} +61 -22
- package/lib/index.cjs +2 -1
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +137 -16
- package/lib/index.d.ts +137 -16
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -0
- package/lib/prompts/index.cjs +2 -1
- package/lib/prompts/index.cjs.map +1 -0
- package/lib/prompts/index.d.cts +177 -55
- package/lib/prompts/index.d.ts +177 -55
- package/lib/prompts/index.js +2 -1
- package/lib/prompts/index.js.map +1 -0
- package/lib/react/index.cjs +8 -5
- package/lib/react/index.cjs.map +1 -0
- package/lib/react/index.d.cts +348 -21
- package/lib/react/index.d.ts +348 -21
- package/lib/react/index.js +8 -5
- package/lib/react/index.js.map +1 -0
- package/lib/styles.css +1 -1
- package/lib/types/index.cjs +2 -1
- package/lib/types/index.cjs.map +1 -0
- package/lib/types/index.d.cts +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.js +2 -1
- package/lib/types/index.js.map +1 -0
- package/lib/{utils-q6anRKO_.d.cts → utils-CCi9_JTv.d.cts} +5 -5
- package/lib/{utils-DuacFTtu.d.ts → utils-CoSP-i76.d.ts} +5 -5
- package/package.json +165 -152
- package/src/tailwind.css +5 -5
- package/lib/chunk-2PRW5PVT.cjs +0 -2
- package/lib/chunk-3XSZLKJW.js +0 -2
- package/lib/chunk-D2TKEF6D.cjs +0 -2
- package/lib/chunk-DHVODVIA.cjs +0 -71
- package/lib/chunk-HRCAI3NV.js +0 -1
- package/lib/chunk-ND6LFDGK.js +0 -71
- package/lib/chunk-O2XFH626.js +0 -1
- package/lib/chunk-PKXMJNRX.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-5XGN7UAV.js"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use strict';var chunk4UWAUWYL_cjs=require('./chunk-4UWAUWYL.cjs'),chunkBYLIBOAU_cjs=require('./chunk-BYLIBOAU.cjs');var w="https://api.deepcitation.com";function C(s,t){if(typeof Buffer<"u"&&Buffer.isBuffer(s)){let e=Uint8Array.from(s);return {blob:new Blob([e]),name:t||"document"}}if(s instanceof Blob)return {blob:s,name:t||(s instanceof File?s.name:"document")};throw new Error("Invalid file type. Expected File, Blob, or Buffer.")}async function d(s,t){return (await s.json().catch(()=>({})))?.error?.message||`${t} failed with status ${s.status}`}var y=class{constructor(t){chunkBYLIBOAU_cjs.a(this,"apiKey");chunkBYLIBOAU_cjs.a(this,"apiUrl");if(!t.apiKey)throw new Error("DeepCitation API key is required. Get one at https://deepcitation.com/dashboard");this.apiKey=t.apiKey,this.apiUrl=t.apiUrl?.replace(/\/$/,"")||w;}async uploadFile(t,e){let{blob:p,name:n}=C(t,e?.filename),i=new FormData;i.append("file",p,n),e?.attachmentId&&i.append("attachmentId",e.attachmentId),e?.filename&&i.append("filename",e.filename);let a=await fetch(`${this.apiUrl}/prepareFile`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:i});if(!a.ok)throw new Error(await d(a,"Upload"));return await a.json()}async convertToPdf(t){let e=typeof t=="string"?{url:t}:t,{url:p,file:n,filename:i,attachmentId:a}=e;if(!p&&!n)throw new Error("Either url or file must be provided");let o;if(p)o=await fetch(`${this.apiUrl}/convertFile`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({url:p,filename:i,attachmentId:a})});else {let{blob:f,name:l}=C(n,i),r=new FormData;r.append("file",f,l),a&&r.append("attachmentId",a),i&&r.append("filename",i),o=await fetch(`${this.apiUrl}/convertFile`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});}if(!o.ok)throw new Error(await d(o,"Conversion"));return await o.json()}async prepareConvertedFile(t){let e=await fetch(`${this.apiUrl}/prepareFile`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({attachmentId:t.attachmentId})});if(!e.ok)throw new Error(await d(e,"Prepare"));return await e.json()}async prepareUrl(t){let e=await fetch(`${this.apiUrl}/prepareFile`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({url:t.url,attachmentId:t.attachmentId,filename:t.filename,unsafeFastUrlOutput:t.unsafeFastUrlOutput})});if(!e.ok)throw new Error(await d(e,"Prepare URL"));return await e.json()}async prepareFiles(t){if(t.length===0)return {fileDataParts:[]};let e=t.map(({file:i,filename:a,attachmentId:o})=>this.uploadFile(i,{filename:a,attachmentId:o}).then(f=>({result:f,filename:a})));return {fileDataParts:(await Promise.all(e)).map(({result:i,filename:a})=>({attachmentId:i.attachmentId,deepTextPromptPortion:i.deepTextPromptPortion,filename:a||i.metadata?.filename}))}}async verifyAttachment(t,e,p){let n={};if(Array.isArray(e))for(let l of e){let r=chunk4UWAUWYL_cjs.d(l);n[r]=l;}else if(typeof e=="object"&&e!==null)if("fullPhrase"in e||"value"in e){let l=chunk4UWAUWYL_cjs.d(e);n[l]=e;}else Object.assign(n,e);else throw new Error("Invalid citations format");if(Object.keys(n).length===0)return {verifications:{}};let i=`${this.apiUrl}/verifyCitations`,a={data:{attachmentId:t,citations:n,outputImageFormat:p?.outputImageFormat||"avif"}},o=await fetch(i,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(a)});if(!o.ok)throw new Error(await d(o,"Verification"));return await o.json()}async verify(t,e){let{llmOutput:p,outputImageFormat:n="avif"}=t;if(e||(e=chunk4UWAUWYL_cjs.B(p)),Object.keys(e).length===0)return {verifications:{}};let i=new Map;for(let[r,c]of Object.entries(e)){let u=c.attachmentId||"";i.has(u)||i.set(u,{}),i.get(u)[r]=c;}let a=[],o={};for(let[r,c]of i)r?a.push(this.verifyAttachment(r,c,{outputImageFormat:n})):(Object.assign(o,c),typeof console<"u"&&console.warn&&console.warn(`[DeepCitation] ${Object.keys(c).length} citation(s) skipped: missing attachmentId`));let f=await Promise.all(a),l={};for(let r of f)Object.assign(l,r.verifications);for(let r of Object.keys(o))l[r]={status:"skipped"};return {verifications:l}}};
|
|
2
|
+
exports.a=y;//# sourceMappingURL=chunk-7TORYXU4.cjs.map
|
|
3
|
+
//# sourceMappingURL=chunk-7TORYXU4.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/DeepCitation.ts"],"names":["DEFAULT_API_URL","toBlob","file","filename","uint8","extractErrorMessage","response","fallbackAction","DeepCitation","config","__publicField","options","blob","name","formData","input","inputObj","url","attachmentId","files","uploadPromises","result","citations","citationMap","citation","key","generateCitationKey","requestUrl","requestBody","llmOutput","outputImageFormat","getAllCitationsFromLlmOutput","citationsByAttachment","verificationPromises","skippedCitations","fileCitations","results","allVerifications"],"mappings":"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","file":"chunk-7TORYXU4.cjs","sourcesContent":["import { getAllCitationsFromLlmOutput } from \"../parsing/parseCitation.js\";\nimport { generateCitationKey } from \"../react/utils.js\";\nimport type { Citation } from \"../types/index.js\";\nimport type {\n CitationInput,\n ConvertFileInput,\n ConvertFileResponse,\n DeepCitationConfig,\n FileDataPart,\n FileInput,\n PrepareConvertedFileOptions,\n PrepareFilesResult,\n PrepareUrlOptions,\n UploadFileOptions,\n UploadFileResponse,\n VerifyInput,\n VerifyCitationsOptions,\n VerifyCitationsResponse,\n} from \"./types.js\";\n\nconst DEFAULT_API_URL = \"https://api.deepcitation.com\";\n\n/** Convert File/Blob/Buffer to a Blob suitable for FormData */\nfunction toBlob(\n file: File | Blob | Buffer,\n filename?: string\n): { blob: Blob; name: string } {\n if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(file)) {\n const uint8 = Uint8Array.from(file);\n return { blob: new Blob([uint8]), name: filename || \"document\" };\n }\n if (file instanceof Blob) {\n return {\n blob: file,\n name: filename || (file instanceof File ? file.name : \"document\"),\n };\n }\n throw new Error(\"Invalid file type. Expected File, Blob, or Buffer.\");\n}\n\n/** Extract error message from API response */\nasync function extractErrorMessage(\n response: Response,\n fallbackAction: string\n): Promise<string> {\n const error = await response.json().catch(() => ({}));\n return (\n error?.error?.message ||\n `${fallbackAction} failed with status ${response.status}`\n );\n}\n\n/**\n * DeepCitation client for file upload and citation verification.\n *\n * @example\n * ```typescript\n * import { DeepCitation } from '@deepcitation/deepcitation-js';\n *\n * const dc = new DeepCitation({ apiKey: process.env.DEEPCITATION_API_KEY });\n *\n * // Upload a file\n * const { attachmentId, promptContent } = await deepcitation.uploadFile(file);\n *\n * // Include promptContent in your LLM messages\n * const response = await llm.chat({\n * messages: [\n * { role: \"system\", content: wrapSystemCitationPrompt({ systemPrompt }) },\n * { role: \"user\", content: userMessage + \"\\n\\n\" + promptContent },\n * ]\n * });\n *\n * // Verify citations in the LLM output\n * const citations = getAllCitationsFromLlmOutput(response);\n * const verified = await deepcitation.verifyCitations(attachmentId, citations);\n * ```\n */\nexport class DeepCitation {\n private readonly apiKey: string;\n private readonly apiUrl: string;\n\n /**\n * Create a new DeepCitation client instance.\n *\n * @param config - Configuration options\n * @throws Error if apiKey is not provided\n */\n constructor(config: DeepCitationConfig) {\n if (!config.apiKey) {\n throw new Error(\n \"DeepCitation API key is required. Get one at https://deepcitation.com/dashboard\"\n );\n }\n this.apiKey = config.apiKey;\n this.apiUrl = config.apiUrl?.replace(/\\/$/, \"\") || DEFAULT_API_URL;\n }\n\n /**\n * Upload a file for citation verification.\n *\n * Supported file types:\n * - PDF documents\n * - Images (PNG, JPEG, WebP, AVIF, HEIC)\n * - Coming soon: DOCX, XLSX, plain text\n *\n * @param file - The file to upload (File, Blob, or Buffer)\n * @param options - Optional upload options\n * @returns Upload response with attachmentId and extracted text\n *\n * @example\n * ```typescript\n * // Browser with File object\n * const file = document.querySelector('input[type=\"file\"]').files[0];\n * const result = await deepcitation.uploadFile(file);\n *\n * // Node.js with Buffer\n * const buffer = fs.readFileSync('document.pdf');\n * const result = await deepcitation.uploadFile(buffer, { filename: 'document.pdf' });\n * ```\n */\n async uploadFile(\n file: File | Blob | Buffer,\n options?: UploadFileOptions\n ): Promise<UploadFileResponse> {\n const { blob, name } = toBlob(file, options?.filename);\n const formData = new FormData();\n formData.append(\"file\", blob, name);\n\n if (options?.attachmentId) formData.append(\"attachmentId\", options.attachmentId);\n if (options?.filename) formData.append(\"filename\", options.filename);\n\n const response = await fetch(`${this.apiUrl}/prepareFile`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n body: formData,\n });\n\n if (!response.ok) {\n throw new Error(await extractErrorMessage(response, \"Upload\"));\n }\n\n return (await response.json()) as UploadFileResponse;\n }\n\n /**\n * Convert a URL or Office file to PDF for citation verification.\n * The converted file can then be processed with prepareConvertedFile().\n *\n * Supported Office formats:\n * - Microsoft Word (.doc, .docx)\n * - Microsoft Excel (.xls, .xlsx)\n * - Microsoft PowerPoint (.ppt, .pptx)\n * - OpenDocument (.odt, .ods, .odp)\n * - Rich Text Format (.rtf)\n * - CSV (.csv)\n *\n * @param input - URL string or object with URL/file options\n * @returns Conversion result with attachmentId for prepareConvertedFile\n *\n * @example\n * ```typescript\n * // Convert a URL to PDF\n * const result = await deepcitation.convertToPdf({ url: \"https://example.com/article\" });\n *\n * // Convert an Office document\n * const result = await deepcitation.convertToPdf({\n * file: docxBuffer,\n * filename: \"report.docx\"\n * });\n *\n * // Then prepare the file for verification\n * const { deepTextPromptPortion, attachmentId } = await deepcitation.prepareConvertedFile({\n * attachmentId: result.attachmentId\n * });\n * ```\n */\n async convertToPdf(\n input: ConvertFileInput | string\n ): Promise<ConvertFileResponse> {\n const inputObj: ConvertFileInput =\n typeof input === \"string\" ? { url: input } : input;\n const { url, file, filename, attachmentId } = inputObj;\n\n if (!url && !file) {\n throw new Error(\"Either url or file must be provided\");\n }\n\n let response: Response;\n\n if (url) {\n response = await fetch(`${this.apiUrl}/convertFile`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ url, filename, attachmentId }),\n });\n } else {\n const { blob, name } = toBlob(file!, filename);\n const formData = new FormData();\n formData.append(\"file\", blob, name);\n if (attachmentId) formData.append(\"attachmentId\", attachmentId);\n if (filename) formData.append(\"filename\", filename);\n\n response = await fetch(`${this.apiUrl}/convertFile`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n body: formData,\n });\n }\n\n if (!response.ok) {\n throw new Error(await extractErrorMessage(response, \"Conversion\"));\n }\n\n return (await response.json()) as ConvertFileResponse;\n }\n\n /**\n * Prepare a previously converted file for citation verification.\n * Use this after calling convertToPdf() to extract text and get deepTextPromptPortion.\n *\n * @param options - Options with attachmentId from convertFile\n * @returns Upload response with attachmentId and extracted text\n *\n * @example\n * ```typescript\n * // First convert the file\n * const converted = await deepcitation.convertToPdf({ url: \"https://example.com/article\" });\n *\n * // Then prepare it for verification\n * const { deepTextPromptPortion, attachmentId } = await deepcitation.prepareConvertedFile({\n * attachmentId: converted.attachmentId\n * });\n *\n * // Use deepTextPromptPortion in your LLM prompt...\n * ```\n */\n async prepareConvertedFile(\n options: PrepareConvertedFileOptions\n ): Promise<UploadFileResponse> {\n const response = await fetch(`${this.apiUrl}/prepareFile`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n attachmentId: options.attachmentId,\n }),\n });\n\n if (!response.ok) {\n throw new Error(await extractErrorMessage(response, \"Prepare\"));\n }\n\n return (await response.json()) as UploadFileResponse;\n }\n\n /**\n * Prepare a URL for citation verification.\n *\n * This is a convenience method that handles URL conversion and text extraction\n * in a single call. The API will convert the URL to PDF and extract text content\n * for citation verification.\n *\n * Note: URLs and Office files take ~30s to process vs. <1s for images/PDFs.\n *\n * @param options - URL and optional settings\n * @returns Upload response with attachmentId and extracted text for LLM prompts\n *\n * @example\n * ```typescript\n * // Prepare a URL for citation verification\n * const { attachmentId, deepTextPromptPortion } = await deepcitation.prepareUrl({\n * url: \"https://example.com/article\"\n * });\n *\n * // Use deepTextPromptPortion in your LLM prompt\n * const { enhancedSystemPrompt, enhancedUserPrompt } = wrapCitationPrompt({\n * systemPrompt,\n * userPrompt: question,\n * deepTextPromptPortion,\n * });\n *\n * // Verify citations\n * const verified = await deepcitation.verifyAttachment(attachmentId, citations);\n * ```\n */\n async prepareUrl(options: PrepareUrlOptions): Promise<UploadFileResponse> {\n const response = await fetch(`${this.apiUrl}/prepareFile`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n url: options.url,\n attachmentId: options.attachmentId,\n filename: options.filename,\n unsafeFastUrlOutput: options.unsafeFastUrlOutput,\n }),\n });\n\n if (!response.ok) {\n throw new Error(await extractErrorMessage(response, \"Prepare URL\"));\n }\n\n return (await response.json()) as UploadFileResponse;\n }\n\n /**\n * Upload multiple files for citation verification and get structured content.\n * This is the recommended way to prepare files for LLM prompts.\n *\n * @param files - Array of files to upload with optional filenames and attachmentIds\n * @returns Object containing fileDataParts for verification and deepTextPromptPortion for LLM\n *\n * @example\n * ```typescript\n * const { fileDataParts, deepTextPromptPortion } = await deepcitation.prepareFiles([\n * { file: pdfBuffer, filename: \"report.pdf\" },\n * { file: invoiceBuffer, filename: \"invoice.pdf\" },\n * ]);\n *\n * // Use deepTextPromptPortion in wrapCitationPrompt\n * const { enhancedSystemPrompt, enhancedUserPrompt } = wrapCitationPrompt({\n * systemPrompt,\n * userPrompt,\n * deepTextPromptPortion\n * });\n *\n * // Use fileDataParts later for verification\n * const result = await deepcitation.verify({ llmOutput, fileDataParts });\n * ```\n */\n async prepareFiles(files: FileInput[]): Promise<PrepareFilesResult> {\n if (files.length === 0) {\n return { fileDataParts: [] };\n }\n\n // Upload all files in parallel\n const uploadPromises = files.map(({ file, filename, attachmentId }) =>\n this.uploadFile(file, { filename, attachmentId }).then((result) => ({\n result,\n filename,\n }))\n );\n\n const uploadResults = await Promise.all(uploadPromises);\n\n // Extract file data parts with deepTextPromptPortion included (single source of truth)\n const fileDataParts: FileDataPart[] = uploadResults.map(\n ({ result, filename }) => ({\n attachmentId: result.attachmentId,\n deepTextPromptPortion: result.deepTextPromptPortion,\n filename: filename || result.metadata?.filename,\n })\n );\n\n return { fileDataParts };\n }\n\n /**\n * Verify citations against a single attachment/file.\n *\n * For most use cases, prefer `verify()` which automatically parses citations\n * from LLM output and handles multiple attachments. Use this method when you\n * need fine-grained control over per-attachment verification.\n *\n * @param attachmentId - The attachment ID returned from uploadFile\n * @param citations - Citations to verify (from getAllCitationsFromLlmOutput)\n * @param options - Optional verification options\n * @returns Verification results with status and proof images\n *\n * @example\n * ```typescript\n * import { getAllCitationsFromLlmOutput } from '@deepcitation/deepcitation-js';\n *\n * const citations = getAllCitationsFromLlmOutput(llmResponse);\n * const verified = await deepcitation.verifyAttachment(attachmentId, citations);\n *\n * for (const [key, result] of Object.entries(verified.verifications)) {\n * console.log(key, result.status);\n * // \"found\", \"partial_text_found\", \"not_found\", etc.\n * }\n * ```\n */\n async verifyAttachment(\n attachmentId: string,\n citations: CitationInput,\n options?: VerifyCitationsOptions\n ): Promise<VerifyCitationsResponse> {\n // Normalize citations to a map with citation keys\n const citationMap: Record<string, Citation> = {};\n\n if (Array.isArray(citations)) {\n // Array of citations - generate keys\n for (const citation of citations) {\n const key = generateCitationKey(citation);\n citationMap[key] = citation;\n }\n } else if (typeof citations === \"object\" && citations !== null) {\n // Check if it's a single citation or a map\n if (\"fullPhrase\" in citations || \"value\" in citations) {\n // Single citation\n const key = generateCitationKey(citations as Citation);\n citationMap[key] = citations as Citation;\n } else {\n // Already a map\n Object.assign(citationMap, citations);\n }\n } else {\n throw new Error(\"Invalid citations format\");\n }\n\n // If no citations to verify, return empty result\n if (Object.keys(citationMap).length === 0) {\n return { verifications: {} };\n }\n\n const requestUrl = `${this.apiUrl}/verifyCitations`;\n const requestBody = {\n data: {\n attachmentId,\n citations: citationMap,\n outputImageFormat: options?.outputImageFormat || \"avif\",\n },\n };\n\n const response = await fetch(requestUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n throw new Error(await extractErrorMessage(response, \"Verification\"));\n }\n\n const result = (await response.json()) as VerifyCitationsResponse;\n return result;\n }\n\n /**\n * Parse and verify all citations from LLM output.\n *\n * This is the recommended method for citation verification. It automatically:\n * 1. Parses citations from LLM output (no raw content sent to our servers)\n * 2. Groups citations by attachment ID\n * 3. Verifies each attachment in parallel\n *\n * For privacy-conscious users: we only receive the parsed citation metadata,\n * not your raw LLM output. This method is a convenience wrapper that parses\n * locally and makes per-attachment verification calls.\n *\n * @param input - Object containing llmOutput and optional outputImageFormat\n * @param citations - Optional pre-parsed citations (skips parsing if provided)\n * @returns Verification results with status and proof images\n *\n * @example\n * ```typescript\n * const result = await deepcitation.verify({\n * llmOutput: response.content,\n * });\n *\n * for (const [key, verification] of Object.entries(result.verifications)) {\n * console.log(key, verification.status);\n * }\n * ```\n */\n async verify(\n input: VerifyInput,\n citations?: { [key: string]: Citation }\n ): Promise<VerifyCitationsResponse> {\n const { llmOutput, outputImageFormat = \"avif\" } = input;\n\n // Parse citations from LLM output\n if (!citations) citations = getAllCitationsFromLlmOutput(llmOutput);\n\n // If no citations found, return empty result\n if (Object.keys(citations).length === 0) {\n return { verifications: {} };\n }\n\n // Group citations by attachmentId\n const citationsByAttachment = new Map<string, Record<string, Citation>>();\n for (const [key, citation] of Object.entries(citations)) {\n const attachmentId = citation.attachmentId || \"\";\n if (!citationsByAttachment.has(attachmentId)) {\n citationsByAttachment.set(attachmentId, {});\n }\n citationsByAttachment.get(attachmentId)![key] = citation;\n }\n\n const verificationPromises: Promise<VerifyCitationsResponse>[] = [];\n const skippedCitations: Record<string, Citation> = {};\n\n for (const [attachmentId, fileCitations] of citationsByAttachment) {\n if (attachmentId) {\n verificationPromises.push(\n this.verifyAttachment(attachmentId, fileCitations, { outputImageFormat })\n );\n } else {\n Object.assign(skippedCitations, fileCitations);\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n `[DeepCitation] ${Object.keys(fileCitations).length} citation(s) skipped: missing attachmentId`\n );\n }\n }\n }\n\n const results = await Promise.all(verificationPromises);\n const allVerifications: VerifyCitationsResponse[\"verifications\"] = {};\n for (const result of results) {\n Object.assign(allVerifications, result.verifications);\n }\n\n for (const key of Object.keys(skippedCitations)) {\n allVerifications[key] = { status: \"skipped\" };\n }\n\n return { verifications: allVerifications };\n }\n}\n"]}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
var g="<<<CITATION_DATA>>>",f="<<<END_CITATION_DATA>>>",d=`
|
|
2
|
+
<citation-instructions priority="critical">
|
|
3
|
+
## REQUIRED: Citation Format
|
|
4
|
+
|
|
5
|
+
### In-Text Markers
|
|
6
|
+
For every claim, value, or fact from attachments, place a sequential integer marker like [1], [2], [3] at the end of the claim.
|
|
7
|
+
|
|
8
|
+
### Citation Data Block
|
|
9
|
+
At the END of your response, append a citation block. Group citations by attachment_id to avoid repetition.
|
|
10
|
+
|
|
11
|
+
### Format
|
|
12
|
+
\`\`\`
|
|
13
|
+
<<<CITATION_DATA>>>
|
|
14
|
+
{
|
|
15
|
+
"attachment_id_here": [
|
|
16
|
+
{"id": 1, "reasoning": "why", "full_phrase": "quote", "anchor_text": "key", "page_id": "2_1", "line_ids": [12]}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
<<<END_CITATION_DATA>>>
|
|
20
|
+
\`\`\`
|
|
21
|
+
|
|
22
|
+
### Shorthand (Optional)
|
|
23
|
+
To save tokens: n=id, r=reasoning, f=full_phrase, k=anchor_text, p=page_id, l=line_ids
|
|
24
|
+
|
|
25
|
+
### JSON Field Rules
|
|
26
|
+
|
|
27
|
+
1. **Group key**: The attachment_id (exact ID from source document)
|
|
28
|
+
2. **id** (or n): Must match the [N] marker in your text (integer)
|
|
29
|
+
3. **reasoning** (or r): Brief explanation connecting the citation to your claim (think first!)
|
|
30
|
+
4. **full_phrase** (or f): Copy text VERBATIM from source. Use proper JSON escaping for quotes.
|
|
31
|
+
5. **anchor_text** (or k): The 1-3 most important words from full_phrase
|
|
32
|
+
6. **page_id** (or p): Format "N_I" where N=page number, I=index (from \`<page_number_N_index_I>\` tags)
|
|
33
|
+
7. **line_ids** (or l): Array of line numbers. Infer intermediate lines since only every 5th is shown.
|
|
34
|
+
|
|
35
|
+
### Placement Rules
|
|
36
|
+
|
|
37
|
+
- Place [N] markers inline, typically at the end of a claim
|
|
38
|
+
- One marker per distinct idea, concept, or value
|
|
39
|
+
- Use sequential numbering starting from [1]
|
|
40
|
+
- The JSON block MUST appear at the very end of your response
|
|
41
|
+
|
|
42
|
+
### Example Response
|
|
43
|
+
|
|
44
|
+
The company reported strong growth [1]. Revenue increased significantly in Q4 [2]. The competitor also grew [3].
|
|
45
|
+
|
|
46
|
+
<<<CITATION_DATA>>>
|
|
47
|
+
{
|
|
48
|
+
"abc123": [
|
|
49
|
+
{"id": 1, "reasoning": "directly states growth metrics", "full_phrase": "The company achieved 45% year-over-year growth", "anchor_text": "45% year-over-year growth", "page_id": "2_1", "line_ids": [12, 13]},
|
|
50
|
+
{"id": 2, "reasoning": "states Q4 revenue figure", "full_phrase": "Q4 revenue reached $2.3 billion, up from $1.8 billion", "anchor_text": "$2.3 billion", "page_id": "3_2", "line_ids": [5, 6, 7]}
|
|
51
|
+
],
|
|
52
|
+
"def456": [
|
|
53
|
+
{"id": 3, "reasoning": "competitor data", "full_phrase": "Competitor X reported 20% growth", "anchor_text": "20% growth", "page_id": "1_0", "line_ids": [8]}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
<<<END_CITATION_DATA>>>
|
|
57
|
+
</citation-instructions>
|
|
58
|
+
|
|
59
|
+
`,l=`
|
|
60
|
+
<citation-instructions priority="critical">
|
|
61
|
+
## REQUIRED: Audio/Video Citation Format
|
|
62
|
+
|
|
63
|
+
### In-Text Markers
|
|
64
|
+
For every claim, value, or fact from media content, place a sequential integer marker like [1], [2], [3] at the end of the claim.
|
|
65
|
+
|
|
66
|
+
### Citation Data Block
|
|
67
|
+
At the END of your response, append a citation block. Group citations by attachment_id to avoid repetition.
|
|
68
|
+
|
|
69
|
+
### Format
|
|
70
|
+
\`\`\`
|
|
71
|
+
<<<CITATION_DATA>>>
|
|
72
|
+
{
|
|
73
|
+
"attachment_id_here": [
|
|
74
|
+
{"id": 1, "reasoning": "why", "full_phrase": "quote", "anchor_text": "key", "timestamps": {"start_time": "HH:MM:SS.SSS", "end_time": "HH:MM:SS.SSS"}}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
<<<END_CITATION_DATA>>>
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
### Shorthand (Optional)
|
|
81
|
+
To save tokens: n=id, r=reasoning, f=full_phrase, k=anchor_text, t=timestamps (with s=start_time, e=end_time)
|
|
82
|
+
|
|
83
|
+
### JSON Field Rules
|
|
84
|
+
|
|
85
|
+
1. **Group key**: The attachment_id (exact ID from source media)
|
|
86
|
+
2. **id** (or n): Must match the [N] marker in your text (integer)
|
|
87
|
+
3. **reasoning** (or r): Brief explanation connecting the citation to your claim (think first!)
|
|
88
|
+
4. **full_phrase** (or f): Copy transcript text VERBATIM. Use proper JSON escaping.
|
|
89
|
+
5. **anchor_text** (or k): The 1-3 most important words from full_phrase
|
|
90
|
+
6. **timestamps** (or t): Object with start_time/s and end_time/e in HH:MM:SS.SSS format
|
|
91
|
+
|
|
92
|
+
### Placement Rules
|
|
93
|
+
|
|
94
|
+
- Place [N] markers inline, typically at the end of a claim
|
|
95
|
+
- One marker per distinct idea, concept, or value
|
|
96
|
+
- Use sequential numbering starting from [1]
|
|
97
|
+
- The JSON block MUST appear at the very end of your response
|
|
98
|
+
|
|
99
|
+
### Example Response
|
|
100
|
+
|
|
101
|
+
The speaker discussed exercise benefits [1]. They recommended specific techniques [2].
|
|
102
|
+
|
|
103
|
+
<<<CITATION_DATA>>>
|
|
104
|
+
{
|
|
105
|
+
"video123": [
|
|
106
|
+
{"id": 1, "reasoning": "speaker directly states health benefits", "full_phrase": "Regular exercise improves cardiovascular health by 30%", "anchor_text": "cardiovascular health", "timestamps": {"start_time": "00:05:23.000", "end_time": "00:05:45.500"}},
|
|
107
|
+
{"id": 2, "reasoning": "demonstrates proper form", "full_phrase": "Keep your back straight and engage your core", "anchor_text": "engage your core", "timestamps": {"start_time": "00:12:10.200", "end_time": "00:12:25.800"}}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
<<<END_CITATION_DATA>>>
|
|
111
|
+
</citation-instructions>
|
|
112
|
+
|
|
113
|
+
`,a="<citation-reminder>STOP and CHECK: Did you use [N] markers for every claim and include the <<<CITATION_DATA>>> JSON block at the end?</citation-reminder>",s="<citation-reminder>STOP and CHECK: Did you use [N] markers for every claim and include the <<<CITATION_DATA>>> JSON block with timestamps at the end?</citation-reminder>";function _(i){let{systemPrompt:n,isAudioVideo:t=false}=i,e=t?l:d,r=t?s:a;return `${e.trim()}
|
|
114
|
+
|
|
115
|
+
${n.trim()}
|
|
116
|
+
|
|
117
|
+
${r}`}function T(i){let{systemPrompt:n,userPrompt:t,deepTextPromptPortion:e,isAudioVideo:r=false}=i,p=_({systemPrompt:n,isAudioVideo:r}),c=r?s:a,o=t;return e&&(o=`${(Array.isArray(e)?e:[e]).map(m=>`
|
|
118
|
+
${m}`).join(`
|
|
119
|
+
|
|
120
|
+
`)}
|
|
121
|
+
|
|
122
|
+
${c}
|
|
123
|
+
|
|
124
|
+
${t}`),{enhancedSystemPrompt:p,enhancedUserPrompt:o}}var y={type:"object",properties:{id:{type:"integer",description:"Citation marker number matching [N] in text"},attachment_id:{type:"string",description:"Exact attachment ID from source document"},reasoning:{type:"string",description:"Brief explanation of why this supports the claim"},full_phrase:{type:"string",description:"Verbatim quote from source document"},anchor_text:{type:"string",description:"1-3 key words from full_phrase"},page_id:{type:"string",description:"Page ID in format 'N_I' (pageNumber_index)"},line_ids:{type:"array",items:{type:"integer"},description:"Array of line numbers for the citation"}},required:["id","attachment_id","full_phrase","anchor_text"]},A={type:"object",properties:{id:{type:"integer",description:"Citation marker number matching [N] in text"},attachment_id:{type:"string",description:"Exact attachment ID from source media"},reasoning:{type:"string",description:"Brief explanation of why this supports the claim"},full_phrase:{type:"string",description:"Verbatim transcript quote"},anchor_text:{type:"string",description:"1-3 key words from full_phrase"},timestamps:{type:"object",properties:{start_time:{type:"string",description:"Start time in HH:MM:SS.SSS format"},end_time:{type:"string",description:"End time in HH:MM:SS.SSS format"}},required:["start_time","end_time"]}},required:["id","attachment_id","full_phrase","anchor_text","timestamps"]};export{g as a,f as b,d as c,l as d,a as e,s as f,_ as g,T as h,y as i,A as j};//# sourceMappingURL=chunk-BDSA6VGC.js.map
|
|
125
|
+
//# sourceMappingURL=chunk-BDSA6VGC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prompts/citationPrompts.ts"],"names":["CITATION_DATA_START_DELIMITER","CITATION_DATA_END_DELIMITER","CITATION_PROMPT","AV_CITATION_PROMPT","CITATION_REMINDER","CITATION_AV_REMINDER","wrapSystemCitationPrompt","options","systemPrompt","isAudioVideo","citationPrompt","reminder","wrapCitationPrompt","userPrompt","deepTextPromptPortion","enhancedSystemPrompt","enhancedUserPrompt","text","CITATION_JSON_OUTPUT_FORMAT","CITATION_AV_JSON_OUTPUT_FORMAT"],"mappings":"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","file":"chunk-BDSA6VGC.js","sourcesContent":["/**\n * Citation Prompts\n *\n * This module provides the \"Deferred JSON Pattern\" for citation output.\n * The LLM uses lightweight markers (e.g., [1], [2]) in the text and outputs\n * a structured JSON block at the end of the response.\n *\n * Benefits:\n * - **Robustness**: JSON.parse handles escaping naturally, avoiding quote-escaping issues\n * - **Streaming Latency**: No mid-sentence pausing for hidden metadata generation\n * - **Token Efficiency**: ~40% reduction in tokens per citation\n */\n\n/** Start delimiter for the citation data block */\nexport const CITATION_DATA_START_DELIMITER = \"<<<CITATION_DATA>>>\";\n\n/** End delimiter for the citation data block */\nexport const CITATION_DATA_END_DELIMITER = \"<<<END_CITATION_DATA>>>\";\n\n/**\n * Citation prompt for document-based citations.\n * Uses [N] markers in text with JSON metadata at the end.\n * Citations are grouped by attachment_id to avoid repetition.\n *\n * Shorthand key mapping (optional):\n * - n: id, r: reasoning, f: full_phrase\n * - k: anchor_text, p: page_id, l: line_ids\n */\nexport const CITATION_PROMPT = `\n<citation-instructions priority=\"critical\">\n## REQUIRED: Citation Format\n\n### In-Text Markers\nFor every claim, value, or fact from attachments, place a sequential integer marker like [1], [2], [3] at the end of the claim.\n\n### Citation Data Block\nAt the END of your response, append a citation block. Group citations by attachment_id to avoid repetition.\n\n### Format\n\\`\\`\\`\n<<<CITATION_DATA>>>\n{\n \"attachment_id_here\": [\n {\"id\": 1, \"reasoning\": \"why\", \"full_phrase\": \"quote\", \"anchor_text\": \"key\", \"page_id\": \"2_1\", \"line_ids\": [12]}\n ]\n}\n<<<END_CITATION_DATA>>>\n\\`\\`\\`\n\n### Shorthand (Optional)\nTo save tokens: n=id, r=reasoning, f=full_phrase, k=anchor_text, p=page_id, l=line_ids\n\n### JSON Field Rules\n\n1. **Group key**: The attachment_id (exact ID from source document)\n2. **id** (or n): Must match the [N] marker in your text (integer)\n3. **reasoning** (or r): Brief explanation connecting the citation to your claim (think first!)\n4. **full_phrase** (or f): Copy text VERBATIM from source. Use proper JSON escaping for quotes.\n5. **anchor_text** (or k): The 1-3 most important words from full_phrase\n6. **page_id** (or p): Format \"N_I\" where N=page number, I=index (from \\`<page_number_N_index_I>\\` tags)\n7. **line_ids** (or l): Array of line numbers. Infer intermediate lines since only every 5th is shown.\n\n### Placement Rules\n\n- Place [N] markers inline, typically at the end of a claim\n- One marker per distinct idea, concept, or value\n- Use sequential numbering starting from [1]\n- The JSON block MUST appear at the very end of your response\n\n### Example Response\n\nThe company reported strong growth [1]. Revenue increased significantly in Q4 [2]. The competitor also grew [3].\n\n<<<CITATION_DATA>>>\n{\n \"abc123\": [\n {\"id\": 1, \"reasoning\": \"directly states growth metrics\", \"full_phrase\": \"The company achieved 45% year-over-year growth\", \"anchor_text\": \"45% year-over-year growth\", \"page_id\": \"2_1\", \"line_ids\": [12, 13]},\n {\"id\": 2, \"reasoning\": \"states Q4 revenue figure\", \"full_phrase\": \"Q4 revenue reached $2.3 billion, up from $1.8 billion\", \"anchor_text\": \"$2.3 billion\", \"page_id\": \"3_2\", \"line_ids\": [5, 6, 7]}\n ],\n \"def456\": [\n {\"id\": 3, \"reasoning\": \"competitor data\", \"full_phrase\": \"Competitor X reported 20% growth\", \"anchor_text\": \"20% growth\", \"page_id\": \"1_0\", \"line_ids\": [8]}\n ]\n}\n<<<END_CITATION_DATA>>>\n</citation-instructions>\n\n`;\n\n/**\n * Citation prompt for audio/video content.\n * Uses timestamps instead of page/line references.\n * Citations are grouped by attachment_id to avoid repetition.\n *\n * Shorthand key mapping (optional):\n * - n: id, r: reasoning, f: full_phrase\n * - k: anchor_text, t: timestamps (with s: start_time, e: end_time)\n */\nexport const AV_CITATION_PROMPT = `\n<citation-instructions priority=\"critical\">\n## REQUIRED: Audio/Video Citation Format\n\n### In-Text Markers\nFor every claim, value, or fact from media content, place a sequential integer marker like [1], [2], [3] at the end of the claim.\n\n### Citation Data Block\nAt the END of your response, append a citation block. Group citations by attachment_id to avoid repetition.\n\n### Format\n\\`\\`\\`\n<<<CITATION_DATA>>>\n{\n \"attachment_id_here\": [\n {\"id\": 1, \"reasoning\": \"why\", \"full_phrase\": \"quote\", \"anchor_text\": \"key\", \"timestamps\": {\"start_time\": \"HH:MM:SS.SSS\", \"end_time\": \"HH:MM:SS.SSS\"}}\n ]\n}\n<<<END_CITATION_DATA>>>\n\\`\\`\\`\n\n### Shorthand (Optional)\nTo save tokens: n=id, r=reasoning, f=full_phrase, k=anchor_text, t=timestamps (with s=start_time, e=end_time)\n\n### JSON Field Rules\n\n1. **Group key**: The attachment_id (exact ID from source media)\n2. **id** (or n): Must match the [N] marker in your text (integer)\n3. **reasoning** (or r): Brief explanation connecting the citation to your claim (think first!)\n4. **full_phrase** (or f): Copy transcript text VERBATIM. Use proper JSON escaping.\n5. **anchor_text** (or k): The 1-3 most important words from full_phrase\n6. **timestamps** (or t): Object with start_time/s and end_time/e in HH:MM:SS.SSS format\n\n### Placement Rules\n\n- Place [N] markers inline, typically at the end of a claim\n- One marker per distinct idea, concept, or value\n- Use sequential numbering starting from [1]\n- The JSON block MUST appear at the very end of your response\n\n### Example Response\n\nThe speaker discussed exercise benefits [1]. They recommended specific techniques [2].\n\n<<<CITATION_DATA>>>\n{\n \"video123\": [\n {\"id\": 1, \"reasoning\": \"speaker directly states health benefits\", \"full_phrase\": \"Regular exercise improves cardiovascular health by 30%\", \"anchor_text\": \"cardiovascular health\", \"timestamps\": {\"start_time\": \"00:05:23.000\", \"end_time\": \"00:05:45.500\"}},\n {\"id\": 2, \"reasoning\": \"demonstrates proper form\", \"full_phrase\": \"Keep your back straight and engage your core\", \"anchor_text\": \"engage your core\", \"timestamps\": {\"start_time\": \"00:12:10.200\", \"end_time\": \"00:12:25.800\"}}\n ]\n}\n<<<END_CITATION_DATA>>>\n</citation-instructions>\n\n`;\n\n/**\n * A brief reminder to reinforce citation requirements in user messages.\n * Use this when you want to add emphasis without repeating full instructions.\n */\nexport const CITATION_REMINDER = `<citation-reminder>STOP and CHECK: Did you use [N] markers for every claim and include the <<<CITATION_DATA>>> JSON block at the end?</citation-reminder>`;\n\n/**\n * Audio/video version of the citation reminder.\n */\nexport const CITATION_AV_REMINDER = `<citation-reminder>STOP and CHECK: Did you use [N] markers for every claim and include the <<<CITATION_DATA>>> JSON block with timestamps at the end?</citation-reminder>`;\n\nexport interface WrapSystemPromptOptions {\n /** The original system prompt to wrap with citation instructions */\n systemPrompt: string;\n /** Whether to use audio/video citation format (with timestamps) instead of text-based (with line IDs) */\n isAudioVideo?: boolean;\n}\n\nexport interface WrapCitationPromptOptions {\n /** The original system prompt to wrap with citation instructions */\n systemPrompt: string;\n /** The original user prompt */\n userPrompt: string;\n /** The extracted file text with metadata (from uploadFile response). Can be a single string or array for multiple files. */\n deepTextPromptPortion?: string | string[];\n /** Whether to use audio/video citation format (with timestamps) instead of text-based (with line IDs) */\n isAudioVideo?: boolean;\n}\n\nexport interface WrapCitationPromptResult {\n /** Enhanced system prompt with citation instructions */\n enhancedSystemPrompt: string;\n /** Enhanced user prompt (currently passed through unchanged) */\n enhancedUserPrompt: string;\n}\n\n/**\n * Wraps your existing system prompt with DeepCitation's citation syntax instructions.\n * This enables LLMs to output verifiable citations that can be checked against attachments.\n *\n * ## Why We Wrap (Instructions at Start + Reminder at End)\n *\n * This function places full citation instructions at the **start** of your system prompt\n * and a brief reminder at the **end**. This \"wrap\" strategy is intentional and based on\n * two key principles:\n *\n * ### 1. Recency Effect (RE2)\n * LLMs exhibit a \"recency bias\" where instructions closer to the end of the context\n * window have stronger influence on output. The reminder at the end reinforces citation\n * requirements right before generation begins.\n *\n * ### 2. Chain-of-Thought (CoT) Attribute Ordering\n * The citation attributes are ordered to encourage the model to \"think first\":\n * `attachment_id` → `reasoning` → `full_phrase` → `anchor_text` → `page_id` → `line_ids`\n *\n * By placing `reasoning` early, the model must articulate WHY it's citing before\n * specifying WHAT it's citing. Then `full_phrase` comes before `anchor_text` so the model\n * first produces the complete verbatim quote, then extracts the anchor text from it,\n * ensuring `anchor_text` is always a valid substring of `full_phrase`.\n *\n * ### Why Not Just Append?\n * In large system prompts, appended instructions can get \"lost\" in the middle of the\n * effective context. Prepending ensures citation instructions have high priority,\n * while the reminder leverages recency for reinforcement.\n *\n * @example\n * ```typescript\n * import { wrapSystemCitationPrompt } from '@deepcitation/deepcitation-js';\n *\n * const systemPrompt = \"You are a helpful assistant that analyzes documents.\";\n * const enhanced = wrapSystemCitationPrompt({ systemPrompt });\n *\n * // Use enhanced prompt with your LLM\n * const response = await openai.chat.completions.create({\n * messages: [{ role: \"system\", content: enhanced }],\n * // ...\n * });\n * ```\n */\nexport function wrapSystemCitationPrompt(\n options: WrapSystemPromptOptions\n): string {\n const { systemPrompt, isAudioVideo = false } = options;\n\n const citationPrompt = isAudioVideo ? AV_CITATION_PROMPT : CITATION_PROMPT;\n const reminder = isAudioVideo ? CITATION_AV_REMINDER : CITATION_REMINDER;\n\n // Full instructions at start (high priority), brief reminder at end (recency effect)\n return `${citationPrompt.trim()}\\n\\n${systemPrompt.trim()}\\n\\n${reminder}`;\n}\n\n/**\n * Wraps both system and user prompts with DeepCitation's citation syntax instructions.\n * This is the recommended way to prepare prompts for citation verification.\n *\n * @example\n * ```typescript\n * import { wrapCitationPrompt } from '@deepcitation/deepcitation-js';\n *\n * // Single file\n * const { enhancedSystemPrompt, enhancedUserPrompt } = wrapCitationPrompt({\n * systemPrompt: \"You are a helpful assistant.\",\n * userPrompt: \"Analyze this document and summarize it.\",\n * deepTextPromptPortion, // from uploadFile response\n * });\n *\n * // Multiple files\n * const { enhancedSystemPrompt, enhancedUserPrompt } = wrapCitationPrompt({\n * systemPrompt: \"You are a helpful assistant.\",\n * userPrompt: \"Compare these documents.\",\n * deepTextPromptPortion: [deepTextPromptPortion1, deepTextPromptPortion2], // array of file texts\n * });\n *\n * // Use enhanced prompts with your LLM\n * const response = await llm.chat({\n * messages: [\n * { role: \"system\", content: enhancedSystemPrompt },\n * { role: \"user\", content: enhancedUserPrompt },\n * ],\n * });\n * ```\n */\nexport function wrapCitationPrompt(\n options: WrapCitationPromptOptions\n): WrapCitationPromptResult {\n const {\n systemPrompt,\n userPrompt,\n deepTextPromptPortion,\n isAudioVideo = false,\n } = options;\n\n const enhancedSystemPrompt = wrapSystemCitationPrompt({\n systemPrompt,\n isAudioVideo,\n });\n\n const reminder = isAudioVideo ? CITATION_AV_REMINDER : CITATION_REMINDER;\n\n // Build enhanced user prompt with file content if provided\n let enhancedUserPrompt = userPrompt;\n\n if (deepTextPromptPortion) {\n const fileTexts = Array.isArray(deepTextPromptPortion)\n ? deepTextPromptPortion\n : [deepTextPromptPortion];\n const fileContent = fileTexts\n .map((text) => {\n return `\\n${text}`;\n })\n .join(\"\\n\\n\");\n\n enhancedUserPrompt = `${fileContent}\\n\\n${reminder}\\n\\n${userPrompt}`;\n }\n\n return {\n enhancedSystemPrompt,\n enhancedUserPrompt,\n };\n}\n\n/**\n * JSON schema for citation data (for structured output LLMs).\n * This can be used with OpenAI's response_format or similar features.\n */\nexport const CITATION_JSON_OUTPUT_FORMAT = {\n type: \"object\",\n properties: {\n id: {\n type: \"integer\",\n description: \"Citation marker number matching [N] in text\",\n },\n attachment_id: {\n type: \"string\",\n description: \"Exact attachment ID from source document\",\n },\n reasoning: {\n type: \"string\",\n description: \"Brief explanation of why this supports the claim\",\n },\n full_phrase: {\n type: \"string\",\n description: \"Verbatim quote from source document\",\n },\n anchor_text: {\n type: \"string\",\n description: \"1-3 key words from full_phrase\",\n },\n page_id: {\n type: \"string\",\n description: \"Page ID in format 'N_I' (pageNumber_index)\",\n },\n line_ids: {\n type: \"array\",\n items: { type: \"integer\" },\n description: \"Array of line numbers for the citation\",\n },\n },\n required: [\"id\", \"attachment_id\", \"full_phrase\", \"anchor_text\"],\n} as const;\n\n/**\n * JSON schema for AV citation data.\n */\nexport const CITATION_AV_JSON_OUTPUT_FORMAT = {\n type: \"object\",\n properties: {\n id: {\n type: \"integer\",\n description: \"Citation marker number matching [N] in text\",\n },\n attachment_id: {\n type: \"string\",\n description: \"Exact attachment ID from source media\",\n },\n reasoning: {\n type: \"string\",\n description: \"Brief explanation of why this supports the claim\",\n },\n full_phrase: {\n type: \"string\",\n description: \"Verbatim transcript quote\",\n },\n anchor_text: {\n type: \"string\",\n description: \"1-3 key words from full_phrase\",\n },\n timestamps: {\n type: \"object\",\n properties: {\n start_time: {\n type: \"string\",\n description: \"Start time in HH:MM:SS.SSS format\",\n },\n end_time: {\n type: \"string\",\n description: \"End time in HH:MM:SS.SSS format\",\n },\n },\n required: [\"start_time\", \"end_time\"],\n },\n },\n required: [\"id\", \"attachment_id\", \"full_phrase\", \"anchor_text\", \"timestamps\"],\n} as const;\n\n/**\n * Compact citation data format from LLM output.\n * Uses single-character keys for token efficiency.\n */\nexport interface CompactCitationData {\n /** Citation number (n) - matches [N] marker */\n n: number;\n /** Attachment ID (a) */\n a?: string;\n /** Reasoning (r) */\n r?: string;\n /** Full phrase (f) - verbatim quote */\n f?: string;\n /** Key phrase (k) - anchor text */\n k?: string;\n /** Page ID (p) - format \"N_I\" */\n p?: string;\n /** Line IDs (l) */\n l?: number[];\n /** Timestamps (t) for AV citations */\n t?: {\n /** Start time (s) */\n s?: string;\n /** End time (e) */\n e?: string;\n };\n}\n\n/**\n * Interface for citation data from JSON block.\n * This is the normalized/expanded format used internally after parsing.\n * The parser expands compact keys (n,a,r,f,k,p,l,t) to these full names.\n */\nexport interface CitationData {\n /** Citation marker number (matches [N] in text). Compact key: n */\n id: number;\n /** Attachment ID from source document. Compact key: a */\n attachment_id?: string;\n /** Reasoning for the citation. Compact key: r */\n reasoning?: string;\n /** Verbatim quote from source. Compact key: f */\n full_phrase?: string;\n /** Anchor text (1-3 words). Compact key: k */\n anchor_text?: string;\n /** Page ID in format \"N_I\" or legacy \"page_number_N_index_I\". Compact key: p */\n page_id?: string;\n /** Line IDs array. Compact key: l */\n line_ids?: number[];\n /** Timestamps for AV citations. Compact key: t */\n timestamps?: {\n /** Start time. Compact key: s */\n start_time?: string;\n /** End time. Compact key: e */\n end_time?: string;\n };\n}\n\n/**\n * Result of parsing a citation response.\n */\nexport interface ParsedCitationResponse {\n /** The clean text meant for display (content before the delimiter) */\n visibleText: string;\n /** The structured citation data from the JSON block */\n citations: CitationData[];\n /** Helper map for O(1) lookups by ID */\n citationMap: Map<number, CitationData>;\n /** Whether parsing was successful */\n success: boolean;\n /** Error message if parsing failed */\n error?: string;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/citation.ts","../src/types/verification.ts"],"names":["DEFAULT_OUTPUT_IMAGE_FORMAT","NOT_FOUND_VERIFICATION_INDEX","PENDING_VERIFICATION_INDEX","BLANK_VERIFICATION"],"mappings":"AAKO,IAAMA,CAAAA,CAA8B,OCApC,IAAMC,CAAAA,CAA+B,GAC/BC,CAAAA,CAA6B,EAAA,CAE7BC,EAAmC,CAC9C,YAAA,CAAc,KACd,kBAAA,CAAoBF,CAAAA,CACpB,qBAAsB,IAAA,CACtB,QAAA,CAAU,CACR,UAAA,CAAYA,CACd,CAAA,CACA,MAAA,CAAQ,WACV","file":"chunk-BEYJEW3Y.js","sourcesContent":["import { type ScreenBox } from \"./boxes.js\";\nimport { type Verification } from \"./verification.js\";\n\nexport type OutputImageFormat = \"jpeg\" | \"png\" | \"avif\" | undefined | null;\n\nexport const DEFAULT_OUTPUT_IMAGE_FORMAT = \"avif\" as const;\nexport interface VerifyCitationResponse {\n verifications: { [key: string]: Verification };\n}\n\nexport interface VerifyCitationRequest {\n attachmentId: string;\n citations: { [key: string]: Citation };\n outputImageFormat?: OutputImageFormat;\n apiKey?: string; // Optional API key for authentication\n}\n\n/**\n * Citation type discriminator.\n * - `\"document\"`: PDF or uploaded document citation (uses attachmentId, pageNumber, lineIds)\n * - `\"url\"`: URL/web citation (uses url, domain, title, etc.)\n */\nexport type CitationType = \"document\" | \"url\";\n\n/**\n * Source/platform type for categorization and display.\n * Used for icon selection and grouping in sources lists.\n */\nexport type SourceType =\n | \"web\" // Generic web page\n | \"pdf\" // PDF document\n | \"document\" // Uploaded document\n | \"social\" // Social media (X/Twitter, Facebook, etc.)\n | \"video\" // Video platforms (YouTube, Twitch, etc.)\n | \"news\" // News articles\n | \"academic\" // Academic papers/journals\n | \"code\" // Code repositories (GitHub, etc.)\n | \"forum\" // Forums/discussion boards (Reddit, etc.)\n | \"commerce\" // E-commerce sites\n | \"reference\" // Reference sites (Wikipedia, etc.)\n | \"unknown\"; // Unknown/other\n\n/**\n * Unified citation interface for both document and URL-based citations.\n *\n * Use `type` to discriminate:\n * - `type: \"document\"` - Uses attachmentId, pageNumber, lineIds for document citations\n * - `type: \"url\"` - Uses url, domain, title, etc. for web citations\n *\n * Common fields (used by both types):\n * - `fullPhrase`: The full context/excerpt containing the cited information\n * - `anchorText`: The specific key phrase being cited (must be substring of fullPhrase)\n * - `citationNumber`: Citation number for display (e.g., [1], [2])\n *\n * @example Document citation\n * ```typescript\n * const docCitation: Citation = {\n * type: \"document\",\n * attachmentId: \"abc123\",\n * pageNumber: 5,\n * lineIds: [12, 13],\n * fullPhrase: \"Revenue increased by 15% in Q4.\",\n * anchorText: \"increased by 15%\",\n * citationNumber: 1,\n * };\n * ```\n *\n * @example URL citation\n * ```typescript\n * const urlCitation: Citation = {\n * type: \"url\",\n * url: \"https://example.com/article\",\n * domain: \"example.com\",\n * title: \"Q4 Financial Report\",\n * fullPhrase: \"The TGU transitions require control, not brute strength.\",\n * anchorText: \"require control, not brute strength\",\n * citationNumber: 1,\n * };\n * ```\n */\nexport interface Citation {\n /**\n * Citation type discriminator.\n * - `\"document\"`: PDF/uploaded document (default if not specified)\n * - `\"url\"`: Web URL citation\n */\n type?: CitationType;\n\n // ==========================================================================\n // Common fields (used by both document and URL citations)\n // ==========================================================================\n\n /** The full context/excerpt containing the cited information */\n fullPhrase?: string | null;\n\n /** The specific key phrase being cited (should be substring of fullPhrase) */\n anchorText?: string | null;\n\n /** Citation number for display (e.g., [1], [2], [3]) */\n citationNumber?: number;\n\n /** Reasoning for why this citation was included */\n reasoning?: string | null;\n\n /** Text that appears before the citation marker */\n beforeCite?: string;\n\n // ==========================================================================\n // Document citation fields (type: \"document\")\n // ==========================================================================\n\n /** Attachment ID for document citations */\n attachmentId?: string;\n\n /** Page number in the document */\n pageNumber?: number | null;\n\n /** Line IDs within the page */\n lineIds?: number[] | null;\n\n /** Start page ID for multi-page citations */\n startPageId?: string | null;\n\n /** Selection box coordinates in the document */\n selection?: ScreenBox | null;\n\n // ==========================================================================\n // URL citation fields (type: \"url\")\n // ==========================================================================\n\n /** The source URL */\n url?: string;\n\n /** Display domain (e.g., \"example.com\", \"fitandwell.com\") */\n domain?: string;\n\n /** Page/article title */\n title?: string;\n\n /** Brief description or snippet from the page */\n description?: string;\n\n /** Favicon URL for the source */\n faviconUrl?: string;\n\n /** Platform/source type for categorization (e.g., \"video\", \"news\", \"social\") */\n sourceType?: SourceType;\n\n /** Platform name (e.g., \"Twitch\", \"YouTube\", \"Reddit\") */\n platform?: string;\n\n /** Site name (e.g., \"Fit&Well\", \"Garage Gym Reviews\") */\n siteName?: string;\n\n /** Author name if available */\n author?: string;\n\n /** Publication date */\n publishedAt?: Date | string;\n\n /** Open Graph or social media image URL */\n imageUrl?: string;\n\n /** When the source was accessed/verified */\n accessedAt?: Date | string;\n\n // ==========================================================================\n // Audio/Video citation fields (can be used with both types)\n // ==========================================================================\n\n /** Timestamps for audio/video citations */\n timestamps?: {\n startTime?: string;\n endTime?: string;\n };\n}\n\nexport interface CitationStatus {\n isVerified: boolean;\n isMiss: boolean;\n isPartialMatch: boolean;\n isPending: boolean;\n}\n\n/**\n * Metadata for a source in an aggregated sources list.\n * Used by SourcesListComponent to display collected citations.\n */\nexport interface SourceMeta {\n /** Unique identifier for this source */\n id: string;\n /** The source URL */\n url: string;\n /** Page/document title */\n title: string;\n /** Display domain without www prefix */\n domain: string;\n /** Platform/source type */\n sourceType?: SourceType;\n /** Favicon URL */\n faviconUrl?: string;\n /** Citation numbers that reference this source */\n citationNumbers?: number[];\n /** Number of times this source is cited */\n citationCount?: number;\n /** Relevant excerpts/quotes from this source */\n excerpts?: string[];\n /** Verification status if verified */\n verificationStatus?: \"verified\" | \"partial\" | \"pending\" | \"failed\" | \"unknown\";\n /** When the source was accessed */\n accessedAt?: Date | string;\n}\n","import { sha1Hash } from \"../utils/sha.js\";\nimport { type Citation } from \"./citation.js\";\nimport { type SearchStatus, type SearchAttempt } from \"./search.js\";\nimport { type DeepTextItem } from \"./boxes.js\";\n\nexport const NOT_FOUND_VERIFICATION_INDEX = -1;\nexport const PENDING_VERIFICATION_INDEX = -2;\n\nexport const BLANK_VERIFICATION: Verification = {\n attachmentId: null,\n verifiedPageNumber: NOT_FOUND_VERIFICATION_INDEX,\n verifiedMatchSnippet: null,\n citation: {\n pageNumber: NOT_FOUND_VERIFICATION_INDEX,\n },\n status: \"not_found\",\n};\n\n/**\n * Content match status for URL/web content verification.\n * Used when verifying that a URL contains what the AI claimed.\n */\nexport type ContentMatchStatus =\n | \"exact\" // Content exactly matches AI's claim\n | \"partial\" // Content partially matches (paraphrase, summary)\n | \"mismatch\" // URL exists but content doesn't match claim\n | \"not_found\" // Claimed content not found on page\n | \"not_checked\" // Content not yet verified (URL inaccessible or pending)\n | \"inconclusive\"; // Could not determine match (e.g., dynamic content)\n\n/**\n * URL access status for web content verification.\n */\nexport type UrlAccessStatus =\n | \"accessible\" // URL returned 200 OK\n | \"redirected\" // URL redirected to different domain\n | \"redirected_same_domain\" // URL redirected within same domain\n | \"not_found\" // 404 error\n | \"forbidden\" // 403 error\n | \"server_error\" // 5xx error\n | \"timeout\" // Request timed out\n | \"blocked\" // Blocked by paywall/login/antibot\n | \"network_error\" // DNS/connection error\n | \"pending\" // Not yet checked\n | \"unknown\"; // Unknown status\n\nexport interface Verification {\n attachmentId?: string | null;\n\n label?: string | null; //e.g. \"Invoice\"\n\n citation?: Citation;\n\n // Search status\n status?: SearchStatus | null;\n\n // Search attempts\n searchAttempts?: SearchAttempt[];\n\n highlightColor?: string | null;\n\n // Verified results (actual values found - expected values are in citation)\n verifiedPageNumber?: number | null;\n\n verifiedLineIds?: number[] | null;\n\n verifiedTimestamps?: { startTime?: string; endTime?: string } | null;\n\n verifiedFullPhrase?: string | null;\n\n verifiedAnchorText?: string | null;\n\n verifiedMatchSnippet?: string | null;\n\n hitIndexWithinPage?: number | null;\n\n phraseMatchDeepItem?: DeepTextItem;\n\n /** Multiple boxes for anchorText highlighting when the anchorText spans multiple PDF items/words */\n anchorTextMatchDeepItems?: DeepTextItem[];\n\n verificationImageBase64?: string | null;\n\n /** Dimensions of the verification image (for coordinate mapping) */\n verificationImageDimensions?: { width: number; height: number } | null;\n\n verifiedAt?: Date;\n\n // ==========================================================================\n // URL/Web Content Verification Fields\n // Used when verifying AI-generated URL claims (e.g., \"According to example.com...\")\n // ==========================================================================\n\n /** The URL that was verified (from Citation.url when type: \"url\") */\n verifiedUrl?: string | null;\n\n /** The actual URL after following redirects */\n resolvedUrl?: string | null;\n\n /** HTTP status code returned */\n httpStatus?: number | null;\n\n /** URL accessibility status */\n urlAccessStatus?: UrlAccessStatus | null;\n\n /** Whether the page content matches what the AI claimed */\n contentMatchStatus?: ContentMatchStatus | null;\n\n /** Similarity score between expected and actual content (0-1) */\n contentSimilarity?: number | null;\n\n /** The page title found at the URL */\n verifiedTitle?: string | null;\n\n /** Snippet of actual content found on the page */\n actualContentSnippet?: string | null;\n\n /** Screenshot of the web page as verification proof */\n webPageScreenshotBase64?: string | null;\n\n /** When the URL was crawled/fetched */\n crawledAt?: Date | string | null;\n\n /** Error message if URL verification failed */\n urlVerificationError?: string | null;\n\n // ==========================================================================\n // Verified URL metadata (fetched from the actual page)\n // ==========================================================================\n\n /** Verified domain from the URL */\n verifiedDomain?: string | null;\n\n /** Verified description/meta description from the page */\n verifiedDescription?: string | null;\n\n /** Verified favicon URL */\n verifiedFaviconUrl?: string | null;\n\n /** Verified site name (from og:site_name or similar) */\n verifiedSiteName?: string | null;\n\n /** Verified author (from meta tags) */\n verifiedAuthor?: string | null;\n\n /** Verified publication date */\n verifiedPublishedAt?: Date | string | null;\n\n /** Verified OG image URL */\n verifiedImageUrl?: string | null;\n\n /** Content type of the fetched URL (e.g., \"text/html\", \"application/pdf\") */\n contentType?: string | null;\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var u=4,m=3,I=5;function $(n,r){let c={};for(let e of n){for(let s=u;s<=e.length;s++){let t=e.slice(0,s),l=(t.match(/\d/g)||[]).length,o=(t.match(/[a-zA-Z]/g)||[]).length;if(t.length<u||l>0&&o<m||l===0&&o<I||n.some(g=>g!==e&&g.startsWith(t)))continue;let f=g=>g.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),i=(r.match(new RegExp(f(t),"g"))||[]).length,a=(r.match(new RegExp(f(e),"g"))||[]).length;if(i===a){c[t]=e;break}}if(!Object.values(c).includes(e))throw new Error(`Cannot find a safe unique prefix for ID "${e}" that meets the minimum requirements (length: ${u})`)}return c}function x(n,r){if(!r||r.length===0)return {compressed:n,prefixMap:{}};let c=Array.from(new Set(r)),e=JSON.stringify(n),s=$(c,e),t=Object.keys(s).sort((o,f)=>f.length-o.length),l=e;for(let o of t){let i=s[o].replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");l=l.replace(new RegExp(i,"g"),o);}return {compressed:JSON.parse(l),prefixMap:s}}function _(n,r){if(!r||Object.keys(r).length===0)return n;let c=Object.entries(r).sort((i,a)=>a[0].length-i[0].length),e,s=false;typeof n=="string"?e=n:(e=JSON.stringify(n),s=true);let t=e?.length;for(let[i,a]of c){let g=i.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");e=e.replace(new RegExp(g,"g"),a);}let l=["attachmentId","attachment_id","attachment_ID","attachmentID","fileId","file_id","file_ID","fileID","fileid"];for(let[i,a]of c){let g=i.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),p=l.join("|"),h="([\"'`])",d=new RegExp(`(${p})(\\s*=\\s*)${h}${g}\\3`,"g");e=e.replace(d,`$1$2$3${a}$3`);}let o=e?.length,f=t-o;if(f>0)throw new Error(`[decompressedPromptIds] diff ${f} originalLength ${t} newLength ${o}`);return s?JSON.parse(e):e}export{x as a,_ as b};//# sourceMappingURL=chunk-BWQLFMTV.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-BWQLFMTV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prompts/promptCompression.ts"],"names":["MIN_PREFIX_LENGTH","MIN_CHARACTERS_PER_PREFIX_WITH_AT_LEAST_ONE_DIGIT","MIN_CHARACTERS_PER_PREFIX_WITH_NO_DIGITS","buildSafePrefixMap","ids","prompt","map","id","len","prefix","digitCount","letterCount","other","esc","s","prefixCount","fullCount","compressPromptIds","obj","uniqueIds","text","prefixMap","prefixes","a","b","compressedText","escFull","decompressPromptIds","compressed","entries","shouldParseBack","originalLength","full","escPrefix","idAttributeKeys","keyPattern","quotePattern","re","newLength","diff"],"mappings":"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","file":"chunk-BWQLFMTV.js","sourcesContent":["import { CompressedResult } from \"./types.js\";\n\nconst MIN_PREFIX_LENGTH = 4;\nconst MIN_CHARACTERS_PER_PREFIX_WITH_AT_LEAST_ONE_DIGIT = 3;\nconst MIN_CHARACTERS_PER_PREFIX_WITH_NO_DIGITS = 5;\n\n/**\n * Build a map from each ID's minimal unique prefix to the full ID,\n * such that the prefix only ever appears in the prompt where the full ID appears.\n */\nfunction buildSafePrefixMap(\n ids: string[],\n prompt: string\n): Record<string, string> {\n const map: Record<string, string> = {};\n\n for (const id of ids) {\n for (let len = MIN_PREFIX_LENGTH; len <= id.length; len++) {\n const prefix = id.slice(0, len);\n\n // Check minimum requirements\n const digitCount = (prefix.match(/\\d/g) || []).length;\n const letterCount = (prefix.match(/[a-zA-Z]/g) || []).length;\n\n if (\n prefix.length < MIN_PREFIX_LENGTH ||\n (digitCount > 0 &&\n letterCount < MIN_CHARACTERS_PER_PREFIX_WITH_AT_LEAST_ONE_DIGIT) ||\n (digitCount === 0 &&\n letterCount < MIN_CHARACTERS_PER_PREFIX_WITH_NO_DIGITS)\n ) {\n continue;\n }\n\n // 1) Unique among IDs\n if (ids.some((other) => other !== id && other.startsWith(prefix))) {\n continue;\n }\n\n // 2) Only appears in prompt as part of the full ID\n const esc = (s: string) => s.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n const prefixCount = (prompt.match(new RegExp(esc(prefix), \"g\")) || [])\n .length;\n const fullCount = (prompt.match(new RegExp(esc(id), \"g\")) || []).length;\n if (prefixCount !== fullCount) {\n continue;\n }\n\n map[prefix] = id;\n break;\n }\n\n if (!Object.values(map).includes(id)) {\n throw new Error(\n `Cannot find a safe unique prefix for ID \"${id}\" that meets the minimum requirements (length: ${MIN_PREFIX_LENGTH})`\n );\n }\n }\n\n return map;\n}\n\n/**\n * Compress all occurrences of `ids` inside `obj`, returning a new object\n * plus the `prefixMap` needed to decompress.\n */\nexport function compressPromptIds<T>(\n obj: T,\n ids: string[] | undefined\n): CompressedResult<T> {\n if (!ids || ids.length === 0) {\n return { compressed: obj, prefixMap: {} };\n }\n\n const uniqueIds = Array.from(new Set(ids));\n const text = JSON.stringify(obj);\n const prefixMap = buildSafePrefixMap(uniqueIds, text);\n\n // Sort prefixes by descending length to avoid partial matches\n const prefixes = Object.keys(prefixMap).sort((a, b) => b.length - a.length);\n\n let compressedText = text;\n for (const prefix of prefixes) {\n const full = prefixMap[prefix];\n const escFull = full.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n compressedText = compressedText.replace(new RegExp(escFull, \"g\"), prefix);\n }\n\n return {\n compressed: JSON.parse(compressedText) as T,\n prefixMap,\n };\n}\n\n/**\n * Decompress all minimal prefixes back into their full IDs,\n * using the `prefixMap` returned from `compressPromptIds`.\n *\n * If you pass in a string, it will return a string.\n * If you pass in an object, it will JSON‑serialize and parse it back.\n */\nexport function decompressPromptIds<T>(\n compressed: T | string,\n prefixMap: Record<string, string>\n): T | string {\n if (!prefixMap || Object.keys(prefixMap).length === 0) {\n return compressed;\n }\n\n // Prepare sorted [prefix, full] entries (longest prefix first)\n const entries = Object.entries(prefixMap).sort(\n (a, b) => b[0].length - a[0].length\n );\n\n // Decide whether we're working on a string or an object\n let text: string;\n let shouldParseBack = false;\n\n if (typeof compressed === \"string\") {\n text = compressed;\n } else {\n text = JSON.stringify(compressed);\n shouldParseBack = true;\n }\n\n const originalLength = text?.length;\n\n // Perform all prefix → full-ID replacements\n for (const [prefix, full] of entries) {\n const escPrefix = prefix.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n text = text.replace(new RegExp(escPrefix, \"g\"), full);\n }\n\n // Handle cases where the LLM may output ID in a different attribute format\n // We look for common ID attribute patterns and replace compressed prefixes within them\n // Note: fileId variants are supported for backwards compatibility with legacy citations\n const idAttributeKeys = [\n \"attachmentId\",\n \"attachment_id\",\n \"attachment_ID\",\n \"attachmentID\",\n \"fileId\",\n \"file_id\",\n \"file_ID\",\n \"fileID\",\n \"fileid\",\n ];\n\n // For each prefix, look for it within ID attribute values and replace with full ID\n for (const [prefix, full] of entries) {\n const escPrefix = prefix.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n const keyPattern = idAttributeKeys.join(\"|\");\n const quotePattern = \"([\\\"'`])\";\n\n // Match: attributeName = 'prefix' or attributeName=\"prefix\" etc.\n // Only replace the prefix part, preserving the attribute name and quotes\n const re = new RegExp(\n `(${keyPattern})(\\\\s*=\\\\s*)${quotePattern}${escPrefix}\\\\3`,\n \"g\"\n );\n text = text.replace(re, `$1$2$3${full}$3`);\n }\n const newLength = text?.length;\n\n const diff = originalLength - newLength;\n if (diff > 0) {\n throw new Error(\n `[decompressedPromptIds] diff ${diff} originalLength ${originalLength} newLength ${newLength}`\n );\n }\n\n return shouldParseBack ? (JSON.parse(text) as T) : text;\n}\n"]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
'use strict';var d=Object.defineProperty;var e=(b,a,c)=>a in b?d(b,a,{enumerable:true,configurable:true,writable:true,value:c}):b[a]=c;var f=(b,a,c)=>e(b,typeof a!="symbol"?a+"":a,c);exports.a=f
|
|
1
|
+
'use strict';var d=Object.defineProperty;var e=(b,a,c)=>a in b?d(b,a,{enumerable:true,configurable:true,writable:true,value:c}):b[a]=c;var f=(b,a,c)=>e(b,typeof a!="symbol"?a+"":a,c);exports.a=f;//# sourceMappingURL=chunk-BYLIBOAU.cjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-BYLIBOAU.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-BYLIBOAU.cjs"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var u=4,m=3,I=5;function $(n,r){let c={};for(let e of n){for(let s=u;s<=e.length;s++){let t=e.slice(0,s),l=(t.match(/\d/g)||[]).length,o=(t.match(/[a-zA-Z]/g)||[]).length;if(t.length<u||l>0&&o<m||l===0&&o<I||n.some(g=>g!==e&&g.startsWith(t)))continue;let f=g=>g.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),i=(r.match(new RegExp(f(t),"g"))||[]).length,a=(r.match(new RegExp(f(e),"g"))||[]).length;if(i===a){c[t]=e;break}}if(!Object.values(c).includes(e))throw new Error(`Cannot find a safe unique prefix for ID "${e}" that meets the minimum requirements (length: ${u})`)}return c}function x(n,r){if(!r||r.length===0)return {compressed:n,prefixMap:{}};let c=Array.from(new Set(r)),e=JSON.stringify(n),s=$(c,e),t=Object.keys(s).sort((o,f)=>f.length-o.length),l=e;for(let o of t){let i=s[o].replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");l=l.replace(new RegExp(i,"g"),o);}return {compressed:JSON.parse(l),prefixMap:s}}function _(n,r){if(!r||Object.keys(r).length===0)return n;let c=Object.entries(r).sort((i,a)=>a[0].length-i[0].length),e,s=false;typeof n=="string"?e=n:(e=JSON.stringify(n),s=true);let t=e?.length;for(let[i,a]of c){let g=i.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");e=e.replace(new RegExp(g,"g"),a);}let l=["attachmentId","attachment_id","attachment_ID","attachmentID","fileId","file_id","file_ID","fileID","fileid"];for(let[i,a]of c){let g=i.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),p=l.join("|"),h="([\"'`])",d=new RegExp(`(${p})(\\s*=\\s*)${h}${g}\\3`,"g");e=e.replace(d,`$1$2$3${a}$3`);}let o=e?.length,f=t-o;if(f>0)throw new Error(`[decompressedPromptIds] diff ${f} originalLength ${t} newLength ${o}`);return s?JSON.parse(e):e}exports.a=x;exports.b=_;//# sourceMappingURL=chunk-DS6SOU4L.cjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-DS6SOU4L.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prompts/promptCompression.ts"],"names":["MIN_PREFIX_LENGTH","MIN_CHARACTERS_PER_PREFIX_WITH_AT_LEAST_ONE_DIGIT","MIN_CHARACTERS_PER_PREFIX_WITH_NO_DIGITS","buildSafePrefixMap","ids","prompt","map","id","len","prefix","digitCount","letterCount","other","esc","s","prefixCount","fullCount","compressPromptIds","obj","uniqueIds","text","prefixMap","prefixes","a","b","compressedText","escFull","decompressPromptIds","compressed","entries","shouldParseBack","originalLength","full","escPrefix","idAttributeKeys","keyPattern","quotePattern","re","newLength","diff"],"mappings":"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","file":"chunk-DS6SOU4L.cjs","sourcesContent":["import { CompressedResult } from \"./types.js\";\n\nconst MIN_PREFIX_LENGTH = 4;\nconst MIN_CHARACTERS_PER_PREFIX_WITH_AT_LEAST_ONE_DIGIT = 3;\nconst MIN_CHARACTERS_PER_PREFIX_WITH_NO_DIGITS = 5;\n\n/**\n * Build a map from each ID's minimal unique prefix to the full ID,\n * such that the prefix only ever appears in the prompt where the full ID appears.\n */\nfunction buildSafePrefixMap(\n ids: string[],\n prompt: string\n): Record<string, string> {\n const map: Record<string, string> = {};\n\n for (const id of ids) {\n for (let len = MIN_PREFIX_LENGTH; len <= id.length; len++) {\n const prefix = id.slice(0, len);\n\n // Check minimum requirements\n const digitCount = (prefix.match(/\\d/g) || []).length;\n const letterCount = (prefix.match(/[a-zA-Z]/g) || []).length;\n\n if (\n prefix.length < MIN_PREFIX_LENGTH ||\n (digitCount > 0 &&\n letterCount < MIN_CHARACTERS_PER_PREFIX_WITH_AT_LEAST_ONE_DIGIT) ||\n (digitCount === 0 &&\n letterCount < MIN_CHARACTERS_PER_PREFIX_WITH_NO_DIGITS)\n ) {\n continue;\n }\n\n // 1) Unique among IDs\n if (ids.some((other) => other !== id && other.startsWith(prefix))) {\n continue;\n }\n\n // 2) Only appears in prompt as part of the full ID\n const esc = (s: string) => s.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n const prefixCount = (prompt.match(new RegExp(esc(prefix), \"g\")) || [])\n .length;\n const fullCount = (prompt.match(new RegExp(esc(id), \"g\")) || []).length;\n if (prefixCount !== fullCount) {\n continue;\n }\n\n map[prefix] = id;\n break;\n }\n\n if (!Object.values(map).includes(id)) {\n throw new Error(\n `Cannot find a safe unique prefix for ID \"${id}\" that meets the minimum requirements (length: ${MIN_PREFIX_LENGTH})`\n );\n }\n }\n\n return map;\n}\n\n/**\n * Compress all occurrences of `ids` inside `obj`, returning a new object\n * plus the `prefixMap` needed to decompress.\n */\nexport function compressPromptIds<T>(\n obj: T,\n ids: string[] | undefined\n): CompressedResult<T> {\n if (!ids || ids.length === 0) {\n return { compressed: obj, prefixMap: {} };\n }\n\n const uniqueIds = Array.from(new Set(ids));\n const text = JSON.stringify(obj);\n const prefixMap = buildSafePrefixMap(uniqueIds, text);\n\n // Sort prefixes by descending length to avoid partial matches\n const prefixes = Object.keys(prefixMap).sort((a, b) => b.length - a.length);\n\n let compressedText = text;\n for (const prefix of prefixes) {\n const full = prefixMap[prefix];\n const escFull = full.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n compressedText = compressedText.replace(new RegExp(escFull, \"g\"), prefix);\n }\n\n return {\n compressed: JSON.parse(compressedText) as T,\n prefixMap,\n };\n}\n\n/**\n * Decompress all minimal prefixes back into their full IDs,\n * using the `prefixMap` returned from `compressPromptIds`.\n *\n * If you pass in a string, it will return a string.\n * If you pass in an object, it will JSON‑serialize and parse it back.\n */\nexport function decompressPromptIds<T>(\n compressed: T | string,\n prefixMap: Record<string, string>\n): T | string {\n if (!prefixMap || Object.keys(prefixMap).length === 0) {\n return compressed;\n }\n\n // Prepare sorted [prefix, full] entries (longest prefix first)\n const entries = Object.entries(prefixMap).sort(\n (a, b) => b[0].length - a[0].length\n );\n\n // Decide whether we're working on a string or an object\n let text: string;\n let shouldParseBack = false;\n\n if (typeof compressed === \"string\") {\n text = compressed;\n } else {\n text = JSON.stringify(compressed);\n shouldParseBack = true;\n }\n\n const originalLength = text?.length;\n\n // Perform all prefix → full-ID replacements\n for (const [prefix, full] of entries) {\n const escPrefix = prefix.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n text = text.replace(new RegExp(escPrefix, \"g\"), full);\n }\n\n // Handle cases where the LLM may output ID in a different attribute format\n // We look for common ID attribute patterns and replace compressed prefixes within them\n // Note: fileId variants are supported for backwards compatibility with legacy citations\n const idAttributeKeys = [\n \"attachmentId\",\n \"attachment_id\",\n \"attachment_ID\",\n \"attachmentID\",\n \"fileId\",\n \"file_id\",\n \"file_ID\",\n \"fileID\",\n \"fileid\",\n ];\n\n // For each prefix, look for it within ID attribute values and replace with full ID\n for (const [prefix, full] of entries) {\n const escPrefix = prefix.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n const keyPattern = idAttributeKeys.join(\"|\");\n const quotePattern = \"([\\\"'`])\";\n\n // Match: attributeName = 'prefix' or attributeName=\"prefix\" etc.\n // Only replace the prefix part, preserving the attribute name and quotes\n const re = new RegExp(\n `(${keyPattern})(\\\\s*=\\\\s*)${quotePattern}${escPrefix}\\\\3`,\n \"g\"\n );\n text = text.replace(re, `$1$2$3${full}$3`);\n }\n const newLength = text?.length;\n\n const diff = originalLength - newLength;\n if (diff > 0) {\n throw new Error(\n `[decompressedPromptIds] diff ${diff} originalLength ${originalLength} newLength ${newLength}`\n );\n }\n\n return shouldParseBack ? (JSON.parse(text) as T) : text;\n}\n"]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
'use strict';var t="avif";var e=-1,n=-2,r={attachmentId:null,verifiedPageNumber:e,verifiedMatchSnippet:null,citation:{pageNumber:e},status:"not_found"};exports.a=t;exports.b=e;exports.c=n;exports.d=r
|
|
1
|
+
'use strict';var t="avif";var e=-1,n=-2,r={attachmentId:null,verifiedPageNumber:e,verifiedMatchSnippet:null,citation:{pageNumber:e},status:"not_found"};exports.a=t;exports.b=e;exports.c=n;exports.d=r;//# sourceMappingURL=chunk-HL3AXCDL.cjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-HL3AXCDL.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/citation.ts","../src/types/verification.ts"],"names":["DEFAULT_OUTPUT_IMAGE_FORMAT","NOT_FOUND_VERIFICATION_INDEX","PENDING_VERIFICATION_INDEX","BLANK_VERIFICATION"],"mappings":"aAKO,IAAMA,CAAAA,CAA8B,OCApC,IAAMC,CAAAA,CAA+B,GAC/BC,CAAAA,CAA6B,EAAA,CAE7BC,EAAmC,CAC9C,YAAA,CAAc,KACd,kBAAA,CAAoBF,CAAAA,CACpB,qBAAsB,IAAA,CACtB,QAAA,CAAU,CACR,UAAA,CAAYA,CACd,CAAA,CACA,MAAA,CAAQ,WACV","file":"chunk-HL3AXCDL.cjs","sourcesContent":["import { type ScreenBox } from \"./boxes.js\";\nimport { type Verification } from \"./verification.js\";\n\nexport type OutputImageFormat = \"jpeg\" | \"png\" | \"avif\" | undefined | null;\n\nexport const DEFAULT_OUTPUT_IMAGE_FORMAT = \"avif\" as const;\nexport interface VerifyCitationResponse {\n verifications: { [key: string]: Verification };\n}\n\nexport interface VerifyCitationRequest {\n attachmentId: string;\n citations: { [key: string]: Citation };\n outputImageFormat?: OutputImageFormat;\n apiKey?: string; // Optional API key for authentication\n}\n\n/**\n * Citation type discriminator.\n * - `\"document\"`: PDF or uploaded document citation (uses attachmentId, pageNumber, lineIds)\n * - `\"url\"`: URL/web citation (uses url, domain, title, etc.)\n */\nexport type CitationType = \"document\" | \"url\";\n\n/**\n * Source/platform type for categorization and display.\n * Used for icon selection and grouping in sources lists.\n */\nexport type SourceType =\n | \"web\" // Generic web page\n | \"pdf\" // PDF document\n | \"document\" // Uploaded document\n | \"social\" // Social media (X/Twitter, Facebook, etc.)\n | \"video\" // Video platforms (YouTube, Twitch, etc.)\n | \"news\" // News articles\n | \"academic\" // Academic papers/journals\n | \"code\" // Code repositories (GitHub, etc.)\n | \"forum\" // Forums/discussion boards (Reddit, etc.)\n | \"commerce\" // E-commerce sites\n | \"reference\" // Reference sites (Wikipedia, etc.)\n | \"unknown\"; // Unknown/other\n\n/**\n * Unified citation interface for both document and URL-based citations.\n *\n * Use `type` to discriminate:\n * - `type: \"document\"` - Uses attachmentId, pageNumber, lineIds for document citations\n * - `type: \"url\"` - Uses url, domain, title, etc. for web citations\n *\n * Common fields (used by both types):\n * - `fullPhrase`: The full context/excerpt containing the cited information\n * - `anchorText`: The specific key phrase being cited (must be substring of fullPhrase)\n * - `citationNumber`: Citation number for display (e.g., [1], [2])\n *\n * @example Document citation\n * ```typescript\n * const docCitation: Citation = {\n * type: \"document\",\n * attachmentId: \"abc123\",\n * pageNumber: 5,\n * lineIds: [12, 13],\n * fullPhrase: \"Revenue increased by 15% in Q4.\",\n * anchorText: \"increased by 15%\",\n * citationNumber: 1,\n * };\n * ```\n *\n * @example URL citation\n * ```typescript\n * const urlCitation: Citation = {\n * type: \"url\",\n * url: \"https://example.com/article\",\n * domain: \"example.com\",\n * title: \"Q4 Financial Report\",\n * fullPhrase: \"The TGU transitions require control, not brute strength.\",\n * anchorText: \"require control, not brute strength\",\n * citationNumber: 1,\n * };\n * ```\n */\nexport interface Citation {\n /**\n * Citation type discriminator.\n * - `\"document\"`: PDF/uploaded document (default if not specified)\n * - `\"url\"`: Web URL citation\n */\n type?: CitationType;\n\n // ==========================================================================\n // Common fields (used by both document and URL citations)\n // ==========================================================================\n\n /** The full context/excerpt containing the cited information */\n fullPhrase?: string | null;\n\n /** The specific key phrase being cited (should be substring of fullPhrase) */\n anchorText?: string | null;\n\n /** Citation number for display (e.g., [1], [2], [3]) */\n citationNumber?: number;\n\n /** Reasoning for why this citation was included */\n reasoning?: string | null;\n\n /** Text that appears before the citation marker */\n beforeCite?: string;\n\n // ==========================================================================\n // Document citation fields (type: \"document\")\n // ==========================================================================\n\n /** Attachment ID for document citations */\n attachmentId?: string;\n\n /** Page number in the document */\n pageNumber?: number | null;\n\n /** Line IDs within the page */\n lineIds?: number[] | null;\n\n /** Start page ID for multi-page citations */\n startPageId?: string | null;\n\n /** Selection box coordinates in the document */\n selection?: ScreenBox | null;\n\n // ==========================================================================\n // URL citation fields (type: \"url\")\n // ==========================================================================\n\n /** The source URL */\n url?: string;\n\n /** Display domain (e.g., \"example.com\", \"fitandwell.com\") */\n domain?: string;\n\n /** Page/article title */\n title?: string;\n\n /** Brief description or snippet from the page */\n description?: string;\n\n /** Favicon URL for the source */\n faviconUrl?: string;\n\n /** Platform/source type for categorization (e.g., \"video\", \"news\", \"social\") */\n sourceType?: SourceType;\n\n /** Platform name (e.g., \"Twitch\", \"YouTube\", \"Reddit\") */\n platform?: string;\n\n /** Site name (e.g., \"Fit&Well\", \"Garage Gym Reviews\") */\n siteName?: string;\n\n /** Author name if available */\n author?: string;\n\n /** Publication date */\n publishedAt?: Date | string;\n\n /** Open Graph or social media image URL */\n imageUrl?: string;\n\n /** When the source was accessed/verified */\n accessedAt?: Date | string;\n\n // ==========================================================================\n // Audio/Video citation fields (can be used with both types)\n // ==========================================================================\n\n /** Timestamps for audio/video citations */\n timestamps?: {\n startTime?: string;\n endTime?: string;\n };\n}\n\nexport interface CitationStatus {\n isVerified: boolean;\n isMiss: boolean;\n isPartialMatch: boolean;\n isPending: boolean;\n}\n\n/**\n * Metadata for a source in an aggregated sources list.\n * Used by SourcesListComponent to display collected citations.\n */\nexport interface SourceMeta {\n /** Unique identifier for this source */\n id: string;\n /** The source URL */\n url: string;\n /** Page/document title */\n title: string;\n /** Display domain without www prefix */\n domain: string;\n /** Platform/source type */\n sourceType?: SourceType;\n /** Favicon URL */\n faviconUrl?: string;\n /** Citation numbers that reference this source */\n citationNumbers?: number[];\n /** Number of times this source is cited */\n citationCount?: number;\n /** Relevant excerpts/quotes from this source */\n excerpts?: string[];\n /** Verification status if verified */\n verificationStatus?: \"verified\" | \"partial\" | \"pending\" | \"failed\" | \"unknown\";\n /** When the source was accessed */\n accessedAt?: Date | string;\n}\n","import { sha1Hash } from \"../utils/sha.js\";\nimport { type Citation } from \"./citation.js\";\nimport { type SearchStatus, type SearchAttempt } from \"./search.js\";\nimport { type DeepTextItem } from \"./boxes.js\";\n\nexport const NOT_FOUND_VERIFICATION_INDEX = -1;\nexport const PENDING_VERIFICATION_INDEX = -2;\n\nexport const BLANK_VERIFICATION: Verification = {\n attachmentId: null,\n verifiedPageNumber: NOT_FOUND_VERIFICATION_INDEX,\n verifiedMatchSnippet: null,\n citation: {\n pageNumber: NOT_FOUND_VERIFICATION_INDEX,\n },\n status: \"not_found\",\n};\n\n/**\n * Content match status for URL/web content verification.\n * Used when verifying that a URL contains what the AI claimed.\n */\nexport type ContentMatchStatus =\n | \"exact\" // Content exactly matches AI's claim\n | \"partial\" // Content partially matches (paraphrase, summary)\n | \"mismatch\" // URL exists but content doesn't match claim\n | \"not_found\" // Claimed content not found on page\n | \"not_checked\" // Content not yet verified (URL inaccessible or pending)\n | \"inconclusive\"; // Could not determine match (e.g., dynamic content)\n\n/**\n * URL access status for web content verification.\n */\nexport type UrlAccessStatus =\n | \"accessible\" // URL returned 200 OK\n | \"redirected\" // URL redirected to different domain\n | \"redirected_same_domain\" // URL redirected within same domain\n | \"not_found\" // 404 error\n | \"forbidden\" // 403 error\n | \"server_error\" // 5xx error\n | \"timeout\" // Request timed out\n | \"blocked\" // Blocked by paywall/login/antibot\n | \"network_error\" // DNS/connection error\n | \"pending\" // Not yet checked\n | \"unknown\"; // Unknown status\n\nexport interface Verification {\n attachmentId?: string | null;\n\n label?: string | null; //e.g. \"Invoice\"\n\n citation?: Citation;\n\n // Search status\n status?: SearchStatus | null;\n\n // Search attempts\n searchAttempts?: SearchAttempt[];\n\n highlightColor?: string | null;\n\n // Verified results (actual values found - expected values are in citation)\n verifiedPageNumber?: number | null;\n\n verifiedLineIds?: number[] | null;\n\n verifiedTimestamps?: { startTime?: string; endTime?: string } | null;\n\n verifiedFullPhrase?: string | null;\n\n verifiedAnchorText?: string | null;\n\n verifiedMatchSnippet?: string | null;\n\n hitIndexWithinPage?: number | null;\n\n phraseMatchDeepItem?: DeepTextItem;\n\n /** Multiple boxes for anchorText highlighting when the anchorText spans multiple PDF items/words */\n anchorTextMatchDeepItems?: DeepTextItem[];\n\n verificationImageBase64?: string | null;\n\n /** Dimensions of the verification image (for coordinate mapping) */\n verificationImageDimensions?: { width: number; height: number } | null;\n\n verifiedAt?: Date;\n\n // ==========================================================================\n // URL/Web Content Verification Fields\n // Used when verifying AI-generated URL claims (e.g., \"According to example.com...\")\n // ==========================================================================\n\n /** The URL that was verified (from Citation.url when type: \"url\") */\n verifiedUrl?: string | null;\n\n /** The actual URL after following redirects */\n resolvedUrl?: string | null;\n\n /** HTTP status code returned */\n httpStatus?: number | null;\n\n /** URL accessibility status */\n urlAccessStatus?: UrlAccessStatus | null;\n\n /** Whether the page content matches what the AI claimed */\n contentMatchStatus?: ContentMatchStatus | null;\n\n /** Similarity score between expected and actual content (0-1) */\n contentSimilarity?: number | null;\n\n /** The page title found at the URL */\n verifiedTitle?: string | null;\n\n /** Snippet of actual content found on the page */\n actualContentSnippet?: string | null;\n\n /** Screenshot of the web page as verification proof */\n webPageScreenshotBase64?: string | null;\n\n /** When the URL was crawled/fetched */\n crawledAt?: Date | string | null;\n\n /** Error message if URL verification failed */\n urlVerificationError?: string | null;\n\n // ==========================================================================\n // Verified URL metadata (fetched from the actual page)\n // ==========================================================================\n\n /** Verified domain from the URL */\n verifiedDomain?: string | null;\n\n /** Verified description/meta description from the page */\n verifiedDescription?: string | null;\n\n /** Verified favicon URL */\n verifiedFaviconUrl?: string | null;\n\n /** Verified site name (from og:site_name or similar) */\n verifiedSiteName?: string | null;\n\n /** Verified author (from meta tags) */\n verifiedAuthor?: string | null;\n\n /** Verified publication date */\n verifiedPublishedAt?: Date | string | null;\n\n /** Verified OG image URL */\n verifiedImageUrl?: string | null;\n\n /** Content type of the fetched URL (e.g., \"text/html\", \"application/pdf\") */\n contentType?: string | null;\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import {a,b}from'./chunk-BDSA6VGC.js';function F(t){return new TextEncoder().encode(t)}function G(t){let e=1732584193,i=4023233417,r=2562383102,n=271733878,a=3285377520,l=t.length,c=l*8,o=l+1+8,s=Math.ceil(o/64)*64,u=new ArrayBuffer(s),C=new Uint8Array(u),d=new DataView(u);C.set(t),C[l]=128,d.setUint32(s-8,Math.floor(c/4294967296),false),d.setUint32(s-4,c>>>0,false);let h=new Uint32Array(80);for(let f=0;f<s;f+=64){for(let _=0;_<16;_++)h[_]=d.getUint32(f+_*4,false);for(let _=16;_<80;_++){let A=h[_-3]^h[_-8]^h[_-14]^h[_-16];h[_]=A<<1|A>>>31;}let I=e,m=i,p=r,x=n,k=a;for(let _=0;_<80;_++){let A,y;_<20?(A=m&p|~m&x,y=1518500249):_<40?(A=m^p^x,y=1859775393):_<60?(A=m&p|m&x|p&x,y=2400959708):(A=m^p^x,y=3395469782);let g=(I<<5|I>>>27)+A+k+y+h[_]>>>0;k=x,x=p,p=(m<<30|m>>>2)>>>0,m=I,I=g;}e=e+I>>>0,i=i+m>>>0,r=r+p>>>0,n=n+x>>>0,a=a+k>>>0;}let b=f=>f.toString(16).padStart(8,"0");return b(e)+b(i)+b(r)+b(n)+b(a)}function M(t){try{if(!t)return "";let e=typeof t=="string"?t:JSON.stringify(t);return G(F(e))}catch(e){console.error("Error in making the hash:",e);}return ""}var H={n:"id",a:"attachment_id",r:"reasoning",f:"full_phrase",k:"anchor_text",p:"page_id",l:"line_ids",t:"timestamps"};function Y(t){return typeof t=="object"&&t!==null&&"id"in t&&typeof t.id=="number"}function O(t,e){let i={};for(let[r,n]of Object.entries(t)){let a=H[r]||r;if((r==="t"||r==="timestamps")&&n&&typeof n=="object"){let l=n;i.timestamps={start_time:l.s??l.start_time,end_time:l.e??l.end_time};}else i[a]=n;}if(e&&!i.attachment_id&&(i.attachment_id=e),!Y(i))throw new Error("Invalid citation data: missing or invalid 'id' field");return i}function q(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 X(t){let e=[];for(let[i,r]of Object.entries(t))for(let n of r)typeof n=="object"&&n!==null&&e.push(O(n,i));return e}function E(t){return q(t)?X(t):(Array.isArray(t)?t:[t]).map(i=>O(i))}function Q(t){let e=t.trim(),i=[],r=e;e=e.replace(/^```(?:json)?\s*/i,"").replace(/\s*```$/,""),e!==r&&i.push("removed markdown code block markers");let n=e;if(e=e.replace(/,(\s*[\]\}])/g,"$1"),e!==n&&i.push("removed trailing commas"),e.startsWith("[")&&!e.endsWith("]")){let a=(e.match(/\[/g)||[]).length,l=(e.match(/\]/g)||[]).length;if(a>l){let c=a-l;e=e+"]".repeat(c),i.push(`added ${c} closing bracket(s)`);}}if(e.includes("{")){let a=(e.match(/\{/g)||[]).length,l=(e.match(/\}/g)||[]).length;if(a>l){let c=a-l;e=e+"}".repeat(c),i.push(`added ${c} closing brace(s)`);}}return {repaired:e,repairs:i}}function K(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 i=t.substring(0,e).trim(),r=t.indexOf(b,e),n=e+a.length,a$1=r!==-1?r:t.length,l=t.substring(n,a$1).trim(),c=[],o=new Map;if(l)try{let s=JSON.parse(l);c=E(s);}catch(s){try{let{repaired:u,repairs:C}=Q(l),d=JSON.parse(u);c=E(d),C.length>0&&console.warn("[DeepCitation] JSON repair was triggered for citation data.",`Repairs applied: ${C.join(", ")}.`,`Initial parse error: ${s instanceof Error?s.message:"Unknown error"}`);}catch(u){return {visibleText:i,citations:[],citationMap:new Map,success:false,error:`Failed to parse citation JSON. Initial error: ${s instanceof Error?s.message:"Unknown error"}. Repair error: ${u instanceof Error?u.message:"Unknown error"}`}}}for(let s of c)typeof s.id=="number"&&o.set(s.id,s);return {visibleText:i,citations:c,citationMap:o,success:true}}function tt(t){let e=t.match(/^(\d+)_(\d+)$/);if(e){let r=parseInt(e[1],10),n=parseInt(e[2],10);return {pageNumber:r,startPageId:`page_number_${r}_index_${n}`}}let i=t.match(/page[_a-zA-Z]*(\d+)_index_(\d+)/i);if(i){let r=parseInt(i[1],10),n=parseInt(i[2],10);return {pageNumber:r,startPageId:`page_number_${r}_index_${n}`}}return {pageNumber:void 0,startPageId:void 0}}function et(t,e){let i,r,n=t.page_id;if(n){let c=tt(n);i=c.pageNumber,r=c.startPageId;}let a;t.timestamps&&(a={startTime:t.timestamps.start_time,endTime:t.timestamps.end_time});let l=t.line_ids?.length?[...t.line_ids].sort((c,o)=>c-o):void 0;return {attachmentId:t.attachment_id,pageNumber:i,startPageId:r,fullPhrase:t.full_phrase,anchorText:t.anchor_text,citationNumber:e??t.id,lineIds:l,reasoning:t.reasoning,timestamps:a}}function z(t){let e=K(t);if(!e.success||e.citations.length===0)return {};let i={};for(let r of e.citations){let n=et(r);if(n.fullPhrase){let a=T(n);i[a]=n;}}return i}function V(t){return typeof t=="string"&&t.includes(a)}function gt(t){return K(t).visibleText}function ft(t,e){let{citationMap:i,showAnchorText:r,replacer:n}=e||{};return t.replace(/\[(\d+)\]/g,(a,l)=>{let c=parseInt(l,10),o=i?.get(c);return n?n(c,o):r&&o?.anchor_text?o.anchor_text:""})}function mt(t){let e=[],i=/\[(\d+)\]/g,r;for(;(r=i.exec(t))!==null;)e.push(parseInt(r[1],10));return e}var L=new Map;function nt(t){let e=L.get(t);return e||(e=new RegExp(`${t}='((?:[^'\\\\]|\\\\.)*)'`),L.set(t,e)),e}function it(t){if(!t)return;let e=[],i=t.split(",");for(let r of i){let n=r.trim();if(n)if(n.includes("-")){let[a,l]=n.split("-"),c=parseInt(a,10),o=parseInt(l,10);if(!isNaN(c)&&!isNaN(o)&&c<=o)for(let s=c;s<=o;s++)e.push(s);else isNaN(c)||e.push(c);}else {let a=parseInt(n,10);isNaN(a)||e.push(a);}}if(e.length!==0)return [...new Set(e)].sort((r,n)=>r-n)}function B(t){let e=t?.status,i=["not_found"].includes(e||""),r=["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||"")||r,a=["pending","loading",null,void 0].includes(e);return {isVerified:n,isMiss:i,isPartialMatch:r,isPending:a}}var rt=(t,e,i,r)=>{let n=y=>{if(!y)return;let g=y;return (g.startsWith("'")||g.startsWith('"'))&&(g=g.slice(1)),(g.endsWith("'")||g.endsWith('"'))&&!g.endsWith("\\'")&&!g.endsWith('\\"')&&(g=g.slice(0,-1)),g=g.replace(/\\"/g,'"'),g=g.replace(/\\'/g,"'"),g=g.replace(/\\n/g," "),g=g.replace(/\\\\/g,"\\"),g},a=i?.current?i.current++:void 0,l=t.substring(0,t.indexOf("<cite")),c=t.includes("/>")?t.slice(t.indexOf("/>")+2):"",o=t.substring(t.indexOf("<cite"),t.indexOf("/>")+2),s=(y,g)=>{for(let P of g){let N=nt(P),D=y.match(N);if(D)return D[1]}},u=s(o,["attachment_id","attachmentId","file_id","fileId"]),C=u?.length===20?u:e||u,d=s(o,["start_page_id","startPageId","start_page_key","startPageKey","start_page"]),h,b;if(d){let y=d.match(/page[\_a-zA-Z]*(\d+)_index_(\d+)/);y&&(h=parseInt(y[1]),b=parseInt(y[2]));}let f=n(s(o,["full_phrase","fullPhrase"])),I=n(s(o,["anchor_text","anchorText","key_span","keySpan"])),m=n(s(o,["reasoning"])),p=n(s(o,["value"])),x;try{let g=s(o,["line_ids","lineIds"])?.replace(/[A-Za-z_[\](){}:]/g,"");x=g?it(g):void 0;}catch(y){r&&console.error("Error parsing lineIds",y);}let k=s(o,["timestamps"]),_;if(k){let[y,g]=k.split("-")||[];_={startTime:y,endTime:g};}let A={attachmentId:C,pageNumber:h,startPageId:`page_number_${h||1}_index_${b||0}`,fullPhrase:f,anchorText:I||p,citationNumber:a,lineIds:x,beforeCite:l,timestamps:_,reasoning:m};return {beforeCite:l,afterCite:c,citation:A}},st=(t,e)=>{if(!t)return null;let i=t.fullPhrase??t.full_phrase,r=t.startPageId??t.start_page_id??t.startPageKey??t.start_page_key,n=t.anchorText??t.anchor_text??t.keySpan??t.key_span,a=t.lineIds??t.line_ids,l=t.attachmentId??t.attachment_id??t.fileId??t.file_id,c=t.reasoning,o=t.value;if(!i)return null;let s;if(r){let d=r.match(/page[_a-zA-Z]*(\d+)_index_(\d+)/i);if(d)s=parseInt(d[1],10);else {let h=r.match(/^(\d+)_(\d+)$/);h&&(s=parseInt(h[1],10));}}let u=a?.length?[...a].sort((d,h)=>d-h):void 0;return {attachmentId:l,pageNumber:s,fullPhrase:i,citationNumber:e,lineIds:u,anchorText:n||o,reasoning:c}},J=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),R=t=>Array.isArray(t)?t.length>0&&t.some(J):typeof t=="object"&&t!==null?J(t):false,Z=t=>{let e={},i=Array.isArray(t)?t:[t],r=1;for(let n of i){let a=st(n,r++);if(a&&a.fullPhrase){let l=T(a);e[l]=a;}}return e},$=(t,e)=>{if(!(!t||typeof t!="object")){if(t.citation&&R(t.citation)){let i=Array.isArray(t.citation)?t.citation:[t.citation];e.push(...i);}if(t.citations&&R(t.citations)){let i=Array.isArray(t.citations)?t.citations:[t.citations];e.push(...i);}if(Array.isArray(t))for(let i of t)$(i,e);else for(let i of Object.keys(t))i!=="citation"&&i!=="citations"&&$(t[i],e);}},U=t=>{let e=W(t),i=/<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*\/>/g,r=e.match(i);if(!r||r.length===0)return {};let n={},a={current:1};for(let l of r){let{citation:c}=rt(l,void 0,a);if(c&&c.fullPhrase){let o=T(c);n[o]=c;}}return n},Ct=t=>{if(!t)return {};let e={};if(typeof t=="object"){if(R(t)){let n=Z(t);Object.assign(e,n);}else {let n=[];if($(t,n),n.length>0){let a=Z(n);Object.assign(e,a);}}let i=JSON.stringify(t),r=U(i);Object.assign(e,r);}else if(typeof t=="string"){if(V(t)){let r=z(t);Object.assign(e,r);}let i=U(t);Object.assign(e,i);}return e};function It(t){let e=new Map,i=Array.isArray(t)?t.map((r,n)=>[T(r)||String(n+1),r]):Object.entries(t);for(let[r,n]of i){let a=n.attachmentId||"";e.has(a)||e.set(a,{}),e.get(a)[r]=n;}return e}function bt(t){let e={},i=Array.isArray(t)?t.map((r,n)=>[T(r)||String(n+1),r]):Object.entries(t);for(let[r,n]of i){let a=n.attachmentId||"";e[a]||(e[a]={}),e[a][r]=n;}return e}var at=t=>{let e={},i=/([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(['"])((?:[^'"\\]|\\.)*)\2/g,r;for(;(r=i.exec(t))!==null;){let n=r[1].toLowerCase().replace(/([a-z])([A-Z])/g,"$1_$2").toLowerCase(),a=r[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]=a;}return e},ot=t=>{let e=B(t);return e.isMiss?"\u274C":e.isVerified&&!e.isPartialMatch?"\u2611\uFE0F":e.isPartialMatch?"\u2705":e.isPending?"\u231B":"\u25CC"},wt=(t,e={})=>{let{leaveAnchorTextBehind:i=false,verifications:r,showVerificationStatus:n=false}=e,a=0,l=/<cite\s+[^>]*?\/>/g;return t.replace(l,c=>{a++;let o=at(c),s="";if(i&&o.anchor_text&&(s=o.anchor_text.replace(/\\'/g,"'").replace(/\\"/g,'"')),n&&r){let u,C=m=>{if(!m)return;let p=m.match(/page[_a-zA-Z]*(\d+)/);return p?parseInt(p[1],10):void 0},d=m=>{if(!m)return;let x=m.replace(/(\d+)-(\d+)/g,(k,_,A)=>{let y=parseInt(_,10),g=parseInt(A,10);if(y<=g){let P=[];for(let N=y;N<=g;N++)P.push(N);return P.join(",")}return _}).split(",").map(k=>parseInt(k.trim(),10)).filter(k=>!isNaN(k));return x.length>0?x:void 0},h=m=>m?.replace(/\\'/g,"'").replace(/\\"/g,'"'),b={attachmentId:o.attachment_id,pageNumber:C(o.start_page_id),fullPhrase:h(o.full_phrase),anchorText:h(o.anchor_text),lineIds:d(o.line_ids)},f=T(b);if(u=r[f],!u){let m=String(a);u=r[m];}let I=ot(u);s=s?`${s}${I}`:I;}return s})},Nt=t=>t.replace(/<page_number_\d+_index_\d+>/g,"").replace(/<\/page_number_\d+_index_\d+>/g,"").trim(),Pt=t=>{let e=/<line id="[^"]*">|<\/line>/g;return t.replace(e,"")},j=t=>{if(!t)return null;let e=t.match(/\d+/)?.[0];return e?parseInt(e):null},ct=t=>{let e=t.match(/^(<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>)([\s\S]*?)<\/cite>$/);if(!e){let c=t.match(/^(<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>)$/);if(c){let o=c[1].replace(/>$/," />");return w(o)}return w(t)}let[,i,r]=e;if(!r||!r.trim())return w(t);let n=i.replace(/>$/," />"),a=r.trim(),l=w(n);return a+l},W=t=>{let e=t?.trim()||"";e=e.replace(/(?<![<a-zA-Z])cite\s+(attachment_id|file_id|fileId|attachmentId)\s*=/gi,"<cite $1=");let i=e.split(/(<cite[\s\S]*?(?:\/>|<\/cite>|>(?=\s*$|[\r\n])(?![\s\S]*<\/cite>)))/gm);if(i.length<=1){let r=e.match(/<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>/g);if(r&&r.length>0){let n=e.replace(/<cite\s+(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|[^'">/])*>/g,a=>a.replace(/>$/," />"));return w(n)}return w(e)}return e=i.map(r=>r.startsWith("<cite")?ct(r):r).join(""),e},w=t=>{let e=t;e=e.replace(/\\_/g,"_"),e=e.replace(/><\/cite>/g,"/>");let i=o=>{let s=o.toLowerCase();return s==="fullphrase"||s==="full_phrase"?"full_phrase":s==="lineids"||s==="line_ids"?"line_ids":s==="startpageid"||s==="start_pageid"||s==="start_page_id"||s==="startpagekey"||s==="start_pagekey"||s==="start_page_key"?"start_page_id":s==="fileid"||s==="file_id"||s==="attachmentid"||s==="attachment_id"?"attachment_id":s==="anchortext"||s==="anchor_text"||s==="keyspan"||s==="key_span"?"anchor_text":s==="reasoning"||s==="value"?s:s==="timestamps"||s==="timestamp"||s==="timestamps"?"timestamps":s},r={""":'"',"'":"'","<":"<",">":">","&":"&"},n=/&(?:quot|apos|lt|gt|amp);/g,a=o=>o.replace(n,s=>r[s]||s),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,(o,s,u,C)=>{let d=C;return d.endsWith(u)&&(d=d.slice(0,-1)),d=d.replace(/(\r?\n)+|(\*|_){2,}|\*/g,h=>h.includes(`
|
|
2
|
+
`)||h.includes("\r")?" ":""),d=a(d),d=d.replace(/\\\\'/g,"'").replace(/\\'/g,"'").replace(/'/g,"\\'"),d=d.replace(/\\\\"/g,'"').replace(/\\"/g,'"').replace(/"/g,'\\"'),`${i(s)}='${d}'`}),e=e.replace(/(line_ids|lineIds|timestamps)=['"]?([\[\]\(\){}A-Za-z0-9_\-, ]+)['"]?(\s*\/?>|\s+)/gm,(o,s,u,C)=>{let d=u.replace(/[A-Za-z\[\]\(\){}]/g,"");return d=d.replace(/(\d+)-(\d+)/g,(h,b,f)=>{let I=parseInt(b,10),m=parseInt(f,10),p=[];if(I<=m)for(let x=I;x<=m;x++)p.push(x);else p.push(I);return p.join(",")}),d=d.replace(/,+/g,",").replace(/^,|,$/g,""),`${i(s)}='${d}'${C}`});let c=o=>{let s=/([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(['"])((?:[^'"\\\n]|\\.)*)(?:\2)/g,u={},C;for(;C=s.exec(o);){let p=C[1],x=C[3],k=i(p);u[k]=x;}let d=Object.keys(u);if(d.length===0)return o;let h=typeof u.timestamps=="string"&&u.timestamps.length>0,b=d.filter(p=>p.startsWith("start_page")),f=[];u.attachment_id&&f.push("attachment_id"),h?(u.full_phrase&&f.push("full_phrase"),u.anchor_text&&f.push("anchor_text"),f.push("timestamps")):(b.includes("start_page_id")&&f.push("start_page_id"),b.filter(p=>p!=="start_page_id").sort().forEach(p=>f.push(p)),u.full_phrase&&f.push("full_phrase"),u.anchor_text&&f.push("anchor_text"),u.line_ids&&f.push("line_ids")),u.reasoning&&f.push("reasoning"),u.value&&f.push("value");let I=new Set(f);return d.filter(p=>!I.has(p)).sort().forEach(p=>f.push(p)),`<cite ${f.map(p=>`${p}='${u[p]}'`).join(" ")} />`};return e=e.replace(/<cite\b[\s\S]*?\/>/gm,o=>c(o)),e};function $t(...t){return t.filter(Boolean).join(" ")}function lt(t){return t.type==="url"||typeof t.url=="string"&&t.url.length>0}function T(t){let e=t.pageNumber||j(t.startPageId),i=[t.attachmentId||"",e?.toString()||"",t.fullPhrase||"",t.anchorText?.toString()||"",t.lineIds?.join(",")||"",t.timestamps?.startTime||"",t.timestamps?.endTime||""];return lt(t)&&i.push(t.url||"",t.title||"",t.domain||""),M(i.join("|")).slice(0,16)}function Dt(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 M(e.join("|")).slice(0,16)}function vt(t){let e=Math.random().toString(36).slice(2,11);return `${t}-${e}`}function Et(t,e={}){let{fallbackDisplay:i}=e;return t.anchorText?.toString()||t.citationNumber?.toString()||i||"1"}function Ot(t){return t.citationNumber?.toString()||"1"}function Kt(t){return t.anchorText?.toString()||""}function zt(...t){return t.filter(Boolean).join(" ")}var Vt=4,Lt=1;export{rt as A,Ct as B,It as C,bt as D,M as a,$t as b,lt as c,T as d,Dt as e,vt as f,Et as g,Ot as h,Kt as i,zt as j,Vt as k,Lt as l,ot as m,wt as n,Nt as o,Pt as p,j as q,W as r,K as s,et as t,z as u,V as v,gt as w,ft as x,mt as y,B as z};//# sourceMappingURL=chunk-N7FTXSGM.js.map
|
|
3
|
+
//# sourceMappingURL=chunk-N7FTXSGM.js.map
|