@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":["../src/utils/sha.ts","../src/parsing/citationParser.ts","../src/parsing/parseCitation.ts","../src/parsing/normalizeCitation.ts","../src/react/utils.ts"],"names":["utf8Encode","str","sha1","message","h0","h1","h2","h3","h4","msgLen","bitLen","totalLen","paddedLen","padded","paddedView","dataView","w","offset","i","val","a","b","c","d","e","f","k","temp","hex","n","sha1Hash","data","error","COMPACT_KEY_MAP","isValidCitationData","obj","expandCompactKeys","attachmentId","result","key","value","fullKey","ts","isGroupedFormat","parsed","values","flattenGroupedCitations","grouped","citations","citationArray","citation","parseCitationsFromJson","repairJson","jsonString","repaired","repairs","beforeMarkdownRemoval","beforeTrailingCommas","openBrackets","closeBrackets","addedCount","openBraces","closeBraces","parseDeferredCitationResponse","llmResponse","startIndex","CITATION_DATA_START_DELIMITER","visibleText","endIndex","CITATION_DATA_END_DELIMITER","jsonStartIndex","jsonEndIndex","citationMap","initialError","repairError","parsePageId","pageId","compactMatch","pageNum","index","legacyMatch","deferredCitationToCitation","citationNumber","pageNumber","startPageId","timestamps","lineIds","getAllCitationsFromDeferredResponse","citationKey","generateCitationKey","hasDeferredCitations","response","extractVisibleText","replaceDeferredMarkers","text","options","showAnchorText","replacer","match","idStr","id","getCitationMarkerIds","ids","regex","attributeRegexCache","getAttributeRegex","name","parseLineIds","lineIdsString","parts","part","trimmed","startStr","endStr","start","end","num","getCitationStatus","verification","status","isMiss","isPartialMatch","isVerified","isPending","parseCitation","fragment","mdAttachmentId","citationCounterRef","isVerbose","cleanAndUnescape","beforeCite","afterCite","middleCite","extractAttribute","tag","attrNames","rawAttachmentId","startPageIdRaw","pageIndex","pageMatch","fullPhrase","anchorText","reasoning","timestampsRaw","startTime","endTime","parseJsonCitation","jsonCitation","rawLineIds","simpleMatch","hasCitationProperties","item","isJsonCitationFormat","extractJsonCitations","items","findJsonCitationsInObject","found","extractXmlCitations","normalizedText","normalizeCitations","citeRegex","matches","getAllCitationsFromLlmOutput","llmOutput","jsonCitations","foundJsonCitations","xmlCitations","deferredCitations","groupCitationsByAttachmentId","entries","idx","groupCitationsByAttachmentIdObject","parseCiteAttributes","citeTag","attrs","attrRegex","normalizedKey","getVerificationTextIndicator","replaceCitations","markdownWithCitations","leaveAnchorTextBehind","verifications","showVerificationStatus","citationIndex","citationRegex","output","parsePageNumber","lineIdsStr","nums","_match","startNum","endNum","range","s","unescapeQuotes","numericKey","indicator","removePageNumberMetadata","pageText","removeLineIdMetadata","lineIdRegex","getCitationPageNumber","extractAndRelocateCitationContent","citePart","nonSelfClosingMatch","unclosedMatch","selfClosingTag","normalizeCitationContent","openingTag","innerContent","relocatedContent","normalizedCitation","trimmedResponse","citationParts","input","normalized","canonicalizeCiteAttributeKey","lowerKey","htmlEntityMap","htmlEntityRegex","decodeHtmlEntities","textAttributeRegex","openQuote","rawContent","content","rawValue","trailingChars","cleanedValue","_rangeMatch","reorderCiteTagAttributes","rawKey","keys","hasTimestamps","startPageIds","ordered","used","cn","classes","isUrlCitation","keyParts","generateVerificationKey","generateCitationInstanceId","randomSuffix","getCitationDisplayText","fallbackDisplay","getCitationNumber","getCitationAnchorText","classNames","CITATION_X_PADDING","CITATION_Y_PADDING"],"mappings":"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","file":"chunk-N7FTXSGM.js","sourcesContent":["/**\n * Pure JavaScript SHA-1 implementation.\n * Based on the FIPS 180-4 specification.\n * No external dependencies.\n */\n\nfunction utf8Encode(str: string): Uint8Array {\n const encoder = new TextEncoder();\n return encoder.encode(str);\n}\n\nfunction sha1(message: Uint8Array): string {\n // Initial hash values\n let h0 = 0x67452301;\n let h1 = 0xefcdab89;\n let h2 = 0x98badcfe;\n let h3 = 0x10325476;\n let h4 = 0xc3d2e1f0;\n\n // Pre-processing: adding padding bits\n const msgLen = message.length;\n const bitLen = msgLen * 8;\n\n // Calculate padded length: message + 1 (0x80) + padding + 8 (length)\n // Total must be multiple of 64 bytes (512 bits)\n const totalLen = msgLen + 1 + 8; // minimum: msg + 0x80 + 64-bit length\n const paddedLen = Math.ceil(totalLen / 64) * 64;\n\n // Create padded buffer\n const padded = new ArrayBuffer(paddedLen);\n const paddedView = new Uint8Array(padded);\n const dataView = new DataView(padded);\n\n // Copy message\n paddedView.set(message);\n\n // Append bit '1' (0x80)\n paddedView[msgLen] = 0x80;\n\n // Append length as 64-bit big-endian (in bits)\n // High 32 bits (for messages > 512MB, which we don't support)\n dataView.setUint32(paddedLen - 8, Math.floor(bitLen / 0x100000000), false);\n // Low 32 bits\n dataView.setUint32(paddedLen - 4, bitLen >>> 0, false);\n\n // Process each 512-bit (64-byte) chunk\n const w = new Uint32Array(80);\n\n for (let offset = 0; offset < paddedLen; offset += 64) {\n // Break chunk into sixteen 32-bit big-endian words\n for (let i = 0; i < 16; i++) {\n w[i] = dataView.getUint32(offset + i * 4, false);\n }\n\n // Extend the sixteen 32-bit words into eighty 32-bit words\n for (let i = 16; i < 80; i++) {\n const val = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];\n w[i] = (val << 1) | (val >>> 31);\n }\n\n // Initialize working variables\n let a = h0;\n let b = h1;\n let c = h2;\n let d = h3;\n let e = h4;\n\n // Main loop\n for (let i = 0; i < 80; i++) {\n let f: number;\n let k: number;\n\n if (i < 20) {\n f = (b & c) | (~b & d);\n k = 0x5a827999;\n } else if (i < 40) {\n f = b ^ c ^ d;\n k = 0x6ed9eba1;\n } else if (i < 60) {\n f = (b & c) | (b & d) | (c & d);\n k = 0x8f1bbcdc;\n } else {\n f = b ^ c ^ d;\n k = 0xca62c1d6;\n }\n\n const temp = (((a << 5) | (a >>> 27)) + f + e + k + w[i]) >>> 0;\n e = d;\n d = c;\n c = ((b << 30) | (b >>> 2)) >>> 0;\n b = a;\n a = temp;\n }\n\n // Add this chunk's hash to result\n h0 = (h0 + a) >>> 0;\n h1 = (h1 + b) >>> 0;\n h2 = (h2 + c) >>> 0;\n h3 = (h3 + d) >>> 0;\n h4 = (h4 + e) >>> 0;\n }\n\n // Produce the final hash value (160-bit) as hex string\n const hex = (n: number) => n.toString(16).padStart(8, \"0\");\n return hex(h0) + hex(h1) + hex(h2) + hex(h3) + hex(h4);\n}\n\n/**\n * Computes a SHA-1 hash of the provided data.\n * Used internally by generateCitationKey in react/utils.ts\n */\nexport function sha1Hash(data: string | any): string {\n try {\n if (!data) return \"\";\n const str = typeof data === \"string\" ? data : JSON.stringify(data);\n return sha1(utf8Encode(str));\n } catch (error) {\n console.error(\"Error in making the hash:\", error);\n }\n return \"\";\n}\n","/**\n * Citation Parser\n *\n * Implements the \"Split & Parse\" strategy for the deferred JSON citation pattern.\n * This parser extracts citations from LLM responses that use [N] markers in text\n * and include a JSON data block at the end.\n *\n * Algorithm:\n * 1. Detection: Look for the start delimiter <<<CITATION_DATA>>>\n * 2. Splitting: Separate visible content from the citation data block\n * 3. Data Extraction: Extract the JSON string between delimiters\n * 4. Sanitization: Parse with JSON.parse, with fallback repair for common issues\n * 5. Hydration: Map the JSON objects to a usable format\n */\n\nimport { type Citation } from \"../types/citation.js\";\nimport { generateCitationKey } from \"../react/utils.js\";\nimport {\n CITATION_DATA_START_DELIMITER,\n CITATION_DATA_END_DELIMITER,\n type CitationData,\n type CompactCitationData,\n type ParsedCitationResponse,\n} from \"../prompts/citationPrompts.js\";\n\n/**\n * Map of compact keys to their full CitationData equivalents.\n */\nconst COMPACT_KEY_MAP: Record<string, keyof CitationData> = {\n n: \"id\",\n a: \"attachment_id\",\n r: \"reasoning\",\n f: \"full_phrase\",\n k: \"anchor_text\",\n p: \"page_id\",\n l: \"line_ids\",\n t: \"timestamps\",\n} as const;\n\n/**\n * Map for timestamp sub-keys.\n */\nconst TIMESTAMP_KEY_MAP: Record<string, string> = {\n s: \"start_time\",\n e: \"end_time\",\n} as const;\n\n/**\n * Type guard to validate that an object has the required CitationData structure.\n * Ensures at minimum the id field is present and is a number.\n */\nfunction isValidCitationData(obj: unknown): obj is CitationData {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"id\" in obj &&\n typeof (obj as Record<string, unknown>).id === \"number\"\n );\n}\n\n/**\n * Expands compact citation data to the full CitationData format.\n * Handles both compact keys (n, a, r, f, k, p, l, t) and full keys.\n *\n * @param data - Raw citation object (may have compact or full keys)\n * @param attachmentId - Optional attachment_id to inject (for grouped format)\n * @returns Normalized CitationData with full keys\n * @throws Error if the resulting data doesn't have a valid id field\n */\nfunction expandCompactKeys(\n data: CompactCitationData | CitationData | Record<string, unknown>,\n attachmentId?: string\n): CitationData {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data)) {\n // Check if this is a compact key\n const fullKey = COMPACT_KEY_MAP[key] || key;\n\n // Handle timestamps specially (nested object with s/e keys)\n if ((key === \"t\" || key === \"timestamps\") && value && typeof value === \"object\") {\n const ts = value as Record<string, unknown>;\n result.timestamps = {\n start_time: ts.s ?? ts.start_time,\n end_time: ts.e ?? ts.end_time,\n };\n } else {\n result[fullKey] = value;\n }\n }\n\n // Inject attachment_id if provided (from grouped format)\n if (attachmentId && !result.attachment_id) {\n result.attachment_id = attachmentId;\n }\n\n // Runtime validation to ensure type safety\n if (!isValidCitationData(result)) {\n throw new Error(\"Invalid citation data: missing or invalid 'id' field\");\n }\n\n return result;\n}\n\n/**\n * Checks if the parsed JSON is in grouped format (object with attachment IDs as keys)\n * vs flat format (array of citations).\n */\nfunction isGroupedFormat(parsed: unknown): parsed is Record<string, unknown[]> {\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return false;\n }\n // Check if all values are arrays (grouped format)\n const values = Object.values(parsed);\n return values.length > 0 && values.every(Array.isArray);\n}\n\n/**\n * Flattens grouped citation format into a flat array.\n * Grouped format: { \"attachmentId\": [citations...], ... }\n * Flat format: [{ attachment_id: \"...\", ...citation }, ...]\n */\nfunction flattenGroupedCitations(\n grouped: Record<string, unknown[]>\n): CitationData[] {\n const citations: CitationData[] = [];\n\n for (const [attachmentId, citationArray] of Object.entries(grouped)) {\n for (const citation of citationArray) {\n if (typeof citation === \"object\" && citation !== null) {\n citations.push(expandCompactKeys(citation as Record<string, unknown>, attachmentId));\n }\n }\n }\n\n return citations;\n}\n\n/**\n * Helper to parse citations from JSON, handling both grouped and flat formats.\n */\nfunction parseCitationsFromJson(parsed: unknown): CitationData[] {\n // Check for grouped format: { \"attachmentId\": [citations...], ... }\n if (isGroupedFormat(parsed)) {\n return flattenGroupedCitations(parsed);\n }\n\n // Flat format: array of citations or single citation\n const rawCitations = Array.isArray(parsed) ? parsed : [parsed];\n return rawCitations.map((c) => expandCompactKeys(c as Record<string, unknown>));\n}\n\nexport type { CitationData, ParsedCitationResponse } from \"../prompts/citationPrompts.js\";\n\n/**\n * Attempts to repair malformed JSON.\n * Handles common LLM output issues like:\n * - Trailing commas\n * - Single quotes instead of double quotes (in JSON context)\n * - Missing closing brackets\n * - Unescaped newlines in strings\n *\n * @param jsonString - The potentially malformed JSON string\n * @returns The repaired JSON string\n */\nfunction repairJson(jsonString: string): { repaired: string; repairs: string[] } {\n let repaired = jsonString.trim();\n const repairs: string[] = [];\n\n // Remove any markdown code block markers that might be present\n const beforeMarkdownRemoval = repaired;\n repaired = repaired.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```$/, \"\");\n if (repaired !== beforeMarkdownRemoval) {\n repairs.push(\"removed markdown code block markers\");\n }\n\n // Fix trailing commas before ] or }\n const beforeTrailingCommas = repaired;\n repaired = repaired.replace(/,(\\s*[\\]\\}])/g, \"$1\");\n if (repaired !== beforeTrailingCommas) {\n repairs.push(\"removed trailing commas\");\n }\n\n // Fix missing closing bracket if we have an opening [\n if (repaired.startsWith(\"[\") && !repaired.endsWith(\"]\")) {\n // Check if we have unclosed array\n const openBrackets = (repaired.match(/\\[/g) || []).length;\n const closeBrackets = (repaired.match(/\\]/g) || []).length;\n if (openBrackets > closeBrackets) {\n const addedCount = openBrackets - closeBrackets;\n repaired = repaired + \"]\".repeat(addedCount);\n repairs.push(`added ${addedCount} closing bracket(s)`);\n }\n }\n\n // Fix missing closing brace if we have an opening {\n if (repaired.includes(\"{\")) {\n const openBraces = (repaired.match(/\\{/g) || []).length;\n const closeBraces = (repaired.match(/\\}/g) || []).length;\n if (openBraces > closeBraces) {\n const addedCount = openBraces - closeBraces;\n repaired = repaired + \"}\".repeat(addedCount);\n repairs.push(`added ${addedCount} closing brace(s)`);\n }\n }\n\n return { repaired, repairs };\n}\n\n\n/**\n * Parses a citation response from an LLM.\n *\n * This function:\n * 1. Finds the <<<CITATION_DATA>>> delimiter in the response\n * 2. Splits the response into visible text and citation data\n * 3. Parses the JSON citation data\n * 4. Returns a structured result with both\n *\n * @param llmResponse - The full LLM response text\n * @returns ParsedCitationResponse with visible text and parsed citations\n *\n * @example\n * ```typescript\n * const response = `\n * The company grew 45% [1].\n *\n * <<<CITATION_DATA>>>\n * [{\"id\": 1, \"attachment_id\": \"abc\", \"full_phrase\": \"grew 45%\", \"anchor_text\": \"45%\"}]\n * <<<END_CITATION_DATA>>>\n * `;\n *\n * const parsed = parseDeferredCitationResponse(response);\n * console.log(parsed.visibleText); // \"The company grew 45% [1].\"\n * console.log(parsed.citations); // [{id: 1, attachment_id: \"abc\", ...}]\n * ```\n */\nexport function parseDeferredCitationResponse(\n llmResponse: string\n): ParsedCitationResponse {\n if (!llmResponse || typeof llmResponse !== \"string\") {\n return {\n visibleText: \"\",\n citations: [],\n citationMap: new Map(),\n success: false,\n error: \"Invalid input: expected a string\",\n };\n }\n\n // Find the start delimiter\n const startIndex = llmResponse.indexOf(CITATION_DATA_START_DELIMITER);\n\n // No citation data block found - return full text as visible\n if (startIndex === -1) {\n return {\n visibleText: llmResponse.trim(),\n citations: [],\n citationMap: new Map(),\n success: true,\n };\n }\n\n // Extract visible text (everything before the delimiter)\n const visibleText = llmResponse.substring(0, startIndex).trim();\n\n // Find the end delimiter\n const endIndex = llmResponse.indexOf(\n CITATION_DATA_END_DELIMITER,\n startIndex\n );\n\n // Extract the JSON block\n const jsonStartIndex = startIndex + CITATION_DATA_START_DELIMITER.length;\n const jsonEndIndex =\n endIndex !== -1 ? endIndex : llmResponse.length;\n const jsonString = llmResponse.substring(jsonStartIndex, jsonEndIndex).trim();\n\n // Parse the JSON\n let citations: CitationData[] = [];\n const citationMap = new Map<number, CitationData>();\n\n if (jsonString) {\n try {\n // First attempt: direct JSON.parse\n const parsed = JSON.parse(jsonString);\n citations = parseCitationsFromJson(parsed);\n } catch (initialError) {\n // Second attempt: repair and retry\n try {\n const { repaired, repairs } = repairJson(jsonString);\n const parsed = JSON.parse(repaired);\n citations = parseCitationsFromJson(parsed);\n\n // Log warning when repair was necessary\n if (repairs.length > 0) {\n console.warn(\n \"[DeepCitation] JSON repair was triggered for citation data.\",\n `Repairs applied: ${repairs.join(\", \")}.`,\n `Initial parse error: ${initialError instanceof Error ? initialError.message : \"Unknown error\"}`\n );\n }\n } catch (repairError) {\n return {\n visibleText,\n citations: [],\n citationMap: new Map(),\n success: false,\n error: `Failed to parse citation JSON. Initial error: ${initialError instanceof Error ? initialError.message : \"Unknown error\"}. Repair error: ${repairError instanceof Error ? repairError.message : \"Unknown error\"}`,\n };\n }\n }\n }\n\n // Map citations by ID for O(1) lookups\n for (const citation of citations) {\n if (typeof citation.id === \"number\") {\n citationMap.set(citation.id, citation);\n }\n }\n\n return {\n visibleText,\n citations,\n citationMap,\n success: true,\n };\n}\n\n/**\n * Parses a page_id string to extract page number and index.\n * Supports both compact \"N_I\" format and legacy \"page_number_N_index_I\" format.\n *\n * @param pageId - The page ID string\n * @returns Object with pageNumber and normalized startPageId, or undefined values\n */\nfunction parsePageId(pageId: string): { pageNumber?: number; startPageId?: string } {\n // Try compact format first: \"N_I\" (e.g., \"2_1\")\n const compactMatch = pageId.match(/^(\\d+)_(\\d+)$/);\n if (compactMatch) {\n const pageNum = parseInt(compactMatch[1], 10);\n const index = parseInt(compactMatch[2], 10);\n return {\n pageNumber: pageNum,\n startPageId: `page_number_${pageNum}_index_${index}`,\n };\n }\n\n // Try legacy format: \"page_number_N_index_I\" or variations\n const legacyMatch = pageId.match(/page[_a-zA-Z]*(\\d+)_index_(\\d+)/i);\n if (legacyMatch) {\n const pageNum = parseInt(legacyMatch[1], 10);\n const index = parseInt(legacyMatch[2], 10);\n return {\n pageNumber: pageNum,\n startPageId: `page_number_${pageNum}_index_${index}`,\n };\n }\n\n return { pageNumber: undefined, startPageId: undefined };\n}\n\n/**\n * Converts a CitationData object to the standard Citation format.\n *\n * @param data - The citation data\n * @param citationNumber - Optional override for citation number (defaults to data.id)\n * @returns Standard Citation object\n */\nexport function deferredCitationToCitation(\n data: CitationData,\n citationNumber?: number\n): Citation {\n // Parse page number from page_id (supports both \"N_I\" and \"page_number_N_index_I\")\n let pageNumber: number | undefined;\n let startPageId: string | undefined;\n const pageId = data.page_id;\n if (pageId) {\n const parsed = parsePageId(pageId);\n pageNumber = parsed.pageNumber;\n startPageId = parsed.startPageId;\n }\n\n // Parse timestamps for AV citations\n let timestamps: { startTime?: string; endTime?: string } | undefined;\n if (data.timestamps) {\n timestamps = {\n startTime: data.timestamps.start_time,\n endTime: data.timestamps.end_time,\n };\n }\n\n // Sort lineIds if present\n const lineIds = data.line_ids?.length\n ? [...data.line_ids].sort((a, b) => a - b)\n : undefined;\n\n return {\n attachmentId: data.attachment_id,\n pageNumber,\n startPageId,\n fullPhrase: data.full_phrase,\n anchorText: data.anchor_text,\n citationNumber: citationNumber ?? data.id,\n lineIds,\n reasoning: data.reasoning,\n timestamps,\n };\n}\n\n/**\n * Extracts all citations from a citation response and returns them\n * in the standard dictionary format used by the verification API.\n *\n * This function parses the response, converts each citation to the standard\n * Citation format, and generates deterministic keys for each.\n *\n * @param llmResponse - The full LLM response with citation block\n * @returns Dictionary of parsed Citation objects keyed by citation key\n *\n * @example\n * ```typescript\n * const citations = getAllCitationsFromDeferredResponse(llmOutput);\n * // Returns: { \"abc123...\": { attachmentId: \"...\", fullPhrase: \"...\", ... }, ... }\n * ```\n */\nexport function getAllCitationsFromDeferredResponse(\n llmResponse: string\n): { [key: string]: Citation } {\n const parsed = parseDeferredCitationResponse(llmResponse);\n\n if (!parsed.success || parsed.citations.length === 0) {\n return {};\n }\n\n const citations: { [key: string]: Citation } = {};\n\n for (const data of parsed.citations) {\n const citation = deferredCitationToCitation(data);\n if (citation.fullPhrase) {\n const citationKey = generateCitationKey(citation);\n citations[citationKey] = citation;\n }\n }\n\n return citations;\n}\n\n/**\n * Checks if a response contains citation markers.\n *\n * @param response - The LLM response to check\n * @returns True if the response contains the citation data delimiter\n */\nexport function hasDeferredCitations(response: string): boolean {\n return (\n typeof response === \"string\" &&\n response.includes(CITATION_DATA_START_DELIMITER)\n );\n}\n\n/**\n * Extracts just the visible text from a response,\n * removing the citation data block.\n *\n * @param llmResponse - The full LLM response\n * @returns The visible text portion only\n */\nexport function extractVisibleText(llmResponse: string): string {\n const parsed = parseDeferredCitationResponse(llmResponse);\n return parsed.visibleText;\n}\n\n/**\n * Replaces [N] citation markers in text with optional content.\n *\n * @param text - The text containing [N] markers\n * @param options - Configuration for replacement\n * @returns The text with markers replaced\n *\n * @example\n * ```typescript\n * const text = \"Revenue grew 45% [1] in Q4 [2].\";\n *\n * // Remove markers entirely\n * replaceDeferredMarkers(text);\n * // Returns: \"Revenue grew 45% in Q4.\"\n *\n * // Replace with anchor texts\n * replaceDeferredMarkers(text, {\n * citationMap: new Map([[1, { anchor_text: \"45%\" }], [2, { anchor_text: \"Q4\" }]]),\n * showAnchorText: true,\n * });\n * // Returns: \"Revenue grew 45% 45% in Q4 Q4.\"\n * ```\n */\nexport function replaceDeferredMarkers(\n text: string,\n options?: {\n /** Map of citation IDs to their data */\n citationMap?: Map<number, CitationData>;\n /** Whether to show the anchor text after the marker */\n showAnchorText?: boolean;\n /** Custom replacement function */\n replacer?: (id: number, data?: CitationData) => string;\n }\n): string {\n const { citationMap, showAnchorText, replacer } = options || {};\n\n // Match [N] patterns where N is one or more digits\n return text.replace(/\\[(\\d+)\\]/g, (match, idStr) => {\n const id = parseInt(idStr, 10);\n const data = citationMap?.get(id);\n\n // Custom replacer takes precedence\n if (replacer) {\n return replacer(id, data);\n }\n\n // Show anchor text if requested\n if (showAnchorText && data?.anchor_text) {\n return data.anchor_text;\n }\n\n // Default: remove marker\n return \"\";\n });\n}\n\n/**\n * Gets all citation marker IDs found in a text.\n *\n * @param text - The text to scan for [N] markers\n * @returns Array of citation IDs in order of appearance\n */\nexport function getCitationMarkerIds(text: string): number[] {\n const ids: number[] = [];\n const regex = /\\[(\\d+)\\]/g;\n let match;\n\n while ((match = regex.exec(text)) !== null) {\n ids.push(parseInt(match[1], 10));\n }\n\n return ids;\n}\n","import { type Verification } from \"../types/verification.js\";\nimport { type Citation, type CitationStatus } from \"../types/citation.js\";\nimport { normalizeCitations } from \"./normalizeCitation.js\";\nimport { generateCitationKey } from \"../react/utils.js\";\nimport {\n hasDeferredCitations,\n getAllCitationsFromDeferredResponse,\n} from \"./citationParser.js\";\n\nconst attributeRegexCache = new Map<string, RegExp>();\n\nfunction getAttributeRegex(name: string): RegExp {\n let regex = attributeRegexCache.get(name);\n if (!regex) {\n regex = new RegExp(`${name}='((?:[^'\\\\\\\\]|\\\\\\\\.)*)'`);\n attributeRegexCache.set(name, regex);\n }\n return regex;\n}\n\n/**\n * Parses a line_ids string that may contain individual numbers, ranges, or both.\n * Examples: \"1,2,3\", \"5-10\", \"1,5-7,10\", \"20-20\"\n *\n * @param lineIdsString - The raw line_ids string (e.g., \"1,5-7,10\")\n * @returns Sorted array of unique line IDs, or undefined if empty/invalid\n */\nfunction parseLineIds(lineIdsString: string): number[] | undefined {\n if (!lineIdsString) return undefined;\n\n const lineIds: number[] = [];\n const parts = lineIdsString.split(\",\");\n\n for (const part of parts) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n\n // Check if this part is a range (e.g., \"5-10\")\n if (trimmed.includes(\"-\")) {\n const [startStr, endStr] = trimmed.split(\"-\");\n const start = parseInt(startStr, 10);\n const end = parseInt(endStr, 10);\n\n if (!isNaN(start) && !isNaN(end) && start <= end) {\n // Expand the range\n for (let i = start; i <= end; i++) {\n lineIds.push(i);\n }\n } else if (!isNaN(start)) {\n // If only start is valid, just use it\n lineIds.push(start);\n }\n } else {\n // Single number\n const num = parseInt(trimmed, 10);\n if (!isNaN(num)) {\n lineIds.push(num);\n }\n }\n }\n\n if (lineIds.length === 0) return undefined;\n\n // Sort and deduplicate\n return [...new Set(lineIds)].sort((a, b) => a - b);\n}\n\n/**\n * Calculates the verification status of a citation based on the found highlight and search state.\n *\n * @param verification - The found highlight location, or null/undefined if not found\n * @returns An object containing boolean flags for verification status\n */\nexport function getCitationStatus(\n verification: Verification | null | undefined\n): CitationStatus {\n const status = verification?.status;\n\n const isMiss = [\"not_found\"].includes(status || \"\");\n\n // Partial matches: something found but not ideal (amber indicator)\n const isPartialMatch = [\n \"found_anchor_text_only\", // Only anchor text found, not full phrase\n \"partial_text_found\",\n \"found_on_other_page\",\n \"found_on_other_line\",\n \"first_word_found\"\n ].includes(status || \"\");\n\n // Verified: exact match or partial match (green or amber indicator)\n const isVerified = [\"found\", \"found_phrase_missed_anchor_text\"].includes(status || \"\") || isPartialMatch;\n\n const isPending = [\"pending\", \"loading\", null, undefined].includes(status);\n\n return { isVerified, isMiss, isPartialMatch, isPending };\n}\n\nexport const parseCitation = (\n fragment: string,\n mdAttachmentId?: string | null,\n citationCounterRef?: any | null,\n isVerbose?: boolean\n) => {\n // Helper: Remove wrapper quotes and fully unescape content\n // Handles: \\' -> ', \\\" -> \", \\n -> space, \\\\ -> \\\n const cleanAndUnescape = (str?: string) => {\n if (!str) return undefined;\n let result = str;\n // Remove surrounding quotes if present, but only if not escaped\n // Check start: remove leading quote only if it exists\n if (result.startsWith(\"'\") || result.startsWith('\"')) {\n result = result.slice(1);\n }\n // Check end: remove trailing quote only if it's not escaped (not preceded by \\)\n if ((result.endsWith(\"'\") || result.endsWith('\"')) && !result.endsWith(\"\\\\'\") && !result.endsWith('\\\\\"')) {\n result = result.slice(0, -1);\n }\n // Replace escaped double quotes with actual double quotes\n result = result.replace(/\\\\\"/g, '\"');\n // Replace escaped single quotes with actual single quotes\n result = result.replace(/\\\\'/g, \"'\");\n // Replace literal \\n sequences with spaces (newlines in attribute values)\n result = result.replace(/\\\\n/g, \" \");\n // Replace double backslashes with single backslash\n result = result.replace(/\\\\\\\\/g, \"\\\\\");\n return result;\n };\n\n const citationNumber = citationCounterRef?.current\n ? citationCounterRef.current++\n : undefined;\n\n const beforeCite = fragment.substring(0, fragment.indexOf(\"<cite\"));\n const afterCite = fragment.includes(\"/>\")\n ? fragment.slice(fragment.indexOf(\"/>\") + 2)\n : \"\";\n const middleCite = fragment.substring(\n fragment.indexOf(\"<cite\"),\n fragment.indexOf(\"/>\") + 2\n );\n\n const extractAttribute = (tag: string, attrNames: string[]): string | undefined => {\n for (const name of attrNames) {\n const regex = getAttributeRegex(name);\n const match = tag.match(regex);\n if (match) {\n return match[1];\n }\n }\n return undefined;\n };\n\n // Extract all attributes by name (order-independent)\n let rawAttachmentId = extractAttribute(middleCite, ['attachment_id', 'attachmentId', 'file_id', 'fileId']);\n let attachmentId = rawAttachmentId?.length === 20 ? rawAttachmentId : mdAttachmentId || rawAttachmentId;\n\n const startPageIdRaw = extractAttribute(middleCite, ['start_page_id', 'startPageId', 'start_page_key', 'startPageKey', 'start_page']);\n let pageNumber: number | undefined;\n let pageIndex: number | undefined;\n if (startPageIdRaw) {\n const pageMatch = startPageIdRaw.match(/page[\\_a-zA-Z]*(\\d+)_index_(\\d+)/);\n if (pageMatch) {\n pageNumber = parseInt(pageMatch[1]);\n pageIndex = parseInt(pageMatch[2]);\n }\n }\n\n // Use helper to handle escaped quotes inside the phrase\n let fullPhrase = cleanAndUnescape(extractAttribute(middleCite, ['full_phrase', 'fullPhrase']));\n let anchorText = cleanAndUnescape(extractAttribute(middleCite, ['anchor_text', 'anchorText', 'key_span', 'keySpan']));\n let reasoning = cleanAndUnescape(extractAttribute(middleCite, ['reasoning']));\n let value = cleanAndUnescape(extractAttribute(middleCite, ['value']));\n\n let lineIds: number[] | undefined;\n try {\n const lineIdsRaw = extractAttribute(middleCite, ['line_ids', 'lineIds']);\n const lineIdsString = lineIdsRaw?.replace(/[A-Za-z_[\\](){}:]/g, \"\");\n lineIds = lineIdsString ? parseLineIds(lineIdsString) : undefined;\n } catch (e) {\n if (isVerbose) console.error(\"Error parsing lineIds\", e);\n }\n\n // Check for AV citation (has timestamps instead of line_ids)\n const timestampsRaw = extractAttribute(middleCite, ['timestamps']);\n let timestamps: { startTime?: string; endTime?: string } | undefined;\n\n if (timestampsRaw) {\n const [startTime, endTime] = timestampsRaw.split(\"-\") || [];\n timestamps = { startTime, endTime };\n }\n\n const citation: Citation = {\n attachmentId: attachmentId,\n pageNumber,\n startPageId: `page_number_${pageNumber || 1}_index_${pageIndex || 0}`,\n fullPhrase,\n anchorText: anchorText || value,\n citationNumber,\n lineIds,\n beforeCite,\n timestamps,\n reasoning,\n };\n\n return {\n beforeCite,\n afterCite,\n citation,\n };\n};\n\n/**\n * Parses a JSON-based citation object into a Citation.\n * Supports both camelCase and snake_case property names.\n *\n * @param jsonCitation - The JSON citation object (can have camelCase or snake_case properties)\n * @param citationNumber - Optional citation number for ordering\n * @returns Parsed Citation object\n */\nconst parseJsonCitation = (\n jsonCitation: any,\n citationNumber?: number\n): Citation | null => {\n if (!jsonCitation) {\n return null;\n }\n\n // Support both camelCase and snake_case property names (with backward compatibility)\n const fullPhrase = jsonCitation.fullPhrase ?? jsonCitation.full_phrase;\n const startPageId = jsonCitation.startPageId ?? jsonCitation.start_page_id ?? jsonCitation.startPageKey ?? jsonCitation.start_page_key;\n const anchorText = jsonCitation.anchorText ?? jsonCitation.anchor_text ?? jsonCitation.keySpan ?? jsonCitation.key_span;\n const rawLineIds = jsonCitation.lineIds ?? jsonCitation.line_ids;\n const attachmentId = jsonCitation.attachmentId ?? jsonCitation.attachment_id ?? jsonCitation.fileId ?? jsonCitation.file_id;\n const reasoning = jsonCitation.reasoning;\n const value = jsonCitation.value;\n\n if (!fullPhrase) {\n return null;\n }\n\n // Parse startPageId format: \"page_number_PAGE_index_INDEX\" or simple \"PAGE_INDEX\"\n let pageNumber: number | undefined;\n if (startPageId) {\n // Try full format first: page_number_5_index_2 or pageId_5_index_2\n const pageMatch = startPageId.match(/page[_a-zA-Z]*(\\d+)_index_(\\d+)/i);\n if (pageMatch) {\n pageNumber = parseInt(pageMatch[1], 10);\n } else {\n // Try simple n_m format: 5_4 (page 5, index 4)\n const simpleMatch = startPageId.match(/^(\\d+)_(\\d+)$/);\n if (simpleMatch) {\n pageNumber = parseInt(simpleMatch[1], 10);\n }\n }\n }\n\n // Sort lineIds if present\n const lineIds = rawLineIds?.length\n ? [...rawLineIds].sort((a: number, b: number) => a - b)\n : undefined;\n\n const citation: Citation = {\n attachmentId,\n pageNumber,\n fullPhrase,\n citationNumber,\n lineIds,\n anchorText: anchorText || value,\n reasoning,\n };\n\n return citation;\n};\n\n/**\n * Checks if an object has citation-like properties (camelCase or snake_case).\n */\nconst hasCitationProperties = (item: any): boolean =>\n typeof item === \"object\" &&\n item !== null &&\n (\"fullPhrase\" in item ||\n \"full_phrase\" in item ||\n \"startPageId\" in item ||\n \"start_page_id\" in item ||\n \"startPageKey\" in item ||\n \"start_page_key\" in item ||\n \"anchorText\" in item ||\n \"anchor_text\" in item ||\n \"keySpan\" in item ||\n \"key_span\" in item ||\n \"lineIds\" in item ||\n \"line_ids\" in item);\n\n/**\n * Checks if the input appears to be JSON-based citations.\n * Looks for array of objects with citation-like properties (supports both camelCase and snake_case).\n */\nconst isJsonCitationFormat = (data: any): data is Citation[] | Citation => {\n if (Array.isArray(data)) {\n return data.length > 0 && data.some(hasCitationProperties);\n }\n if (typeof data === \"object\" && data !== null) {\n return hasCitationProperties(data);\n }\n return false;\n};\n\n/**\n * Extracts citations from JSON format (array or single object).\n */\nconst extractJsonCitations = (\n data: Citation[] | Citation\n): { [key: string]: Citation } => {\n const citations: { [key: string]: Citation } = {};\n const items = Array.isArray(data) ? data : [data];\n\n let citationNumber = 1;\n for (const item of items) {\n const citation = parseJsonCitation(item, citationNumber++);\n if (citation && citation.fullPhrase) {\n const citationKey = generateCitationKey(citation);\n citations[citationKey] = citation;\n }\n }\n\n return citations;\n};\n\n/**\n * Recursively traverses an object looking for `citation` or `citations` properties\n * that match our JSON citation format.\n */\nconst findJsonCitationsInObject = (obj: any, found: Citation[]): void => {\n if (!obj || typeof obj !== \"object\") return;\n\n // Check for citation/citations properties\n if (obj.citation && isJsonCitationFormat(obj.citation)) {\n const items = Array.isArray(obj.citation) ? obj.citation : [obj.citation];\n found.push(...items);\n }\n if (obj.citations && isJsonCitationFormat(obj.citations)) {\n const items = Array.isArray(obj.citations)\n ? obj.citations\n : [obj.citations];\n found.push(...items);\n }\n\n // Recurse into object properties\n if (Array.isArray(obj)) {\n for (const item of obj) {\n findJsonCitationsInObject(item, found);\n }\n } else {\n for (const key of Object.keys(obj)) {\n if (key !== \"citation\" && key !== \"citations\") {\n findJsonCitationsInObject(obj[key], found);\n }\n }\n }\n};\n\n/**\n * Extracts XML citations from text using <cite ... /> tags.\n */\nconst extractXmlCitations = (text: string): { [key: string]: Citation } => {\n const normalizedText = normalizeCitations(text);\n\n // Find all <cite ... /> tags\n // This regex handles > characters inside quoted attribute values and escaped quotes:\n // - '(?:[^'\\\\]|\\\\.)*' matches single-quoted strings with escaped chars\n // - \"(?:[^\"\\\\]|\\\\.)*\" matches double-quoted strings with escaped chars\n // - [^'\">/] matches any char that's not a quote, >, or /\n // - The whole pattern repeats until we hit />\n const citeRegex = /<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*\\/>/g;\n const matches = normalizedText.match(citeRegex);\n\n if (!matches || matches.length === 0) return {};\n\n const citations: { [key: string]: Citation } = {};\n const citationCounterRef = { current: 1 };\n\n for (const match of matches) {\n const { citation } = parseCitation(match, undefined, citationCounterRef);\n if (citation && citation.fullPhrase) {\n const citationKey = generateCitationKey(citation);\n citations[citationKey] = citation;\n }\n }\n\n return citations;\n};\n\n/**\n * Extracts all citations from LLM output.\n * Supports both XML <cite ... /> tags (embedded in strings/markdown) and JSON-based citation formats.\n *\n * For object input:\n * - Traverses the object looking for `citation` or `citations` properties matching JSON format\n * - Also stringifies the object to find embedded XML citations in markdown content\n *\n * @param llmOutput - The LLM output (string or object)\n * @returns Dictionary of parsed Citation objects keyed by citation key\n */\nexport const getAllCitationsFromLlmOutput = (\n llmOutput: any\n): { [key: string]: Citation } => {\n if (!llmOutput) return {};\n\n const citations: { [key: string]: Citation } = {};\n\n if (typeof llmOutput === \"object\") {\n // Check if the root object itself is JSON citation format\n if (isJsonCitationFormat(llmOutput)) {\n const jsonCitations = extractJsonCitations(llmOutput);\n Object.assign(citations, jsonCitations);\n } else {\n // Traverse object for nested citation/citations properties\n const foundJsonCitations: Citation[] = [];\n findJsonCitationsInObject(llmOutput, foundJsonCitations);\n\n if (foundJsonCitations.length > 0) {\n const jsonCitations = extractJsonCitations(foundJsonCitations);\n Object.assign(citations, jsonCitations);\n }\n }\n\n // Also stringify and parse for embedded XML citations in markdown\n const text = JSON.stringify(llmOutput);\n const xmlCitations = extractXmlCitations(text);\n Object.assign(citations, xmlCitations);\n } else if (typeof llmOutput === \"string\") {\n // Check for deferred JSON format (<<<CITATION_DATA>>>)\n if (hasDeferredCitations(llmOutput)) {\n const deferredCitations = getAllCitationsFromDeferredResponse(llmOutput);\n Object.assign(citations, deferredCitations);\n }\n // Also parse for XML citations (both formats can coexist)\n const xmlCitations = extractXmlCitations(llmOutput);\n Object.assign(citations, xmlCitations);\n }\n\n return citations;\n};\n\n/**\n * Groups citations by their attachmentId for multi-file verification scenarios.\n * This is useful when you have citations from multiple files and need to\n * verify them against their respective attachments.\n *\n * @param citations - Array of Citation objects or a dictionary of citations\n * @returns Map of attachmentId to dictionary of citations from that file\n *\n * @example\n * ```typescript\n * const citations = getAllCitationsFromLlmOutput(response.content);\n * const citationsByAttachment = groupCitationsByAttachmentId(citations);\n *\n * // Verify citations for each file\n * for (const [attachmentId, fileCitations] of citationsByAttachment) {\n * const verified = await deepcitation.verifyCitations(attachmentId, fileCitations);\n * // Process verification results...\n * }\n * ```\n */\nexport function groupCitationsByAttachmentId(\n citations: Citation[] | { [key: string]: Citation }\n): Map<string, { [key: string]: Citation }> {\n const grouped = new Map<string, { [key: string]: Citation }>();\n\n // Normalize input to entries\n const entries: [string, Citation][] = Array.isArray(citations)\n ? citations.map((c, idx) => [generateCitationKey(c) || String(idx + 1), c])\n : Object.entries(citations);\n\n for (const [key, citation] of entries) {\n const attachmentId = citation.attachmentId || \"\";\n\n if (!grouped.has(attachmentId)) {\n grouped.set(attachmentId, {});\n }\n\n grouped.get(attachmentId)![key] = citation;\n }\n\n return grouped;\n}\n\n/**\n * Groups citations by their attachmentId and returns as a plain object.\n * Alternative to groupCitationsByAttachmentId that returns a plain object instead of a Map.\n *\n * @param citations - Array of Citation objects or a dictionary of citations\n * @returns Object with attachmentId keys mapping to citation dictionaries\n *\n * @example\n * ```typescript\n * const citations = getAllCitationsFromLlmOutput(response.content);\n * const citationsByAttachment = groupCitationsByAttachmentIdObject(citations);\n *\n * // Verify citations for each file using Promise.all\n * const verificationPromises = Object.entries(citationsByAttachment).map(\n * ([attachmentId, fileCitations]) => deepcitation.verifyCitations(attachmentId, fileCitations)\n * );\n * const results = await Promise.all(verificationPromises);\n * ```\n */\nexport function groupCitationsByAttachmentIdObject(\n citations: Citation[] | { [key: string]: Citation }\n): { [attachmentId: string]: { [key: string]: Citation } } {\n const grouped: { [attachmentId: string]: { [key: string]: Citation } } = {};\n\n // Normalize input to entries\n const entries: [string, Citation][] = Array.isArray(citations)\n ? citations.map((c, idx) => [generateCitationKey(c) || String(idx + 1), c])\n : Object.entries(citations);\n\n for (const [key, citation] of entries) {\n const attachmentId = citation.attachmentId || \"\";\n\n if (!grouped[attachmentId]) {\n grouped[attachmentId] = {};\n }\n\n grouped[attachmentId][key] = citation;\n }\n\n return grouped;\n}\n","import type { Verification } from \"../types/verification.js\";\nimport type { Citation } from \"../types/citation.js\";\nimport { getCitationStatus } from \"./parseCitation.js\";\nimport { generateCitationKey } from \"../react/utils.js\";\n\nexport interface ReplaceCitationsOptions {\n /**\n * If true, leaves the anchor_text text behind when removing citations.\n * @default false\n */\n leaveAnchorTextBehind?: boolean;\n\n /**\n * Map of citation keys to verification results.\n * Used to determine verification status for each citation.\n */\n verifications?: Record<string, Verification>;\n\n /**\n * If true and verifications are provided, appends a verification status indicator.\n * Uses: ✓ (verified), ⚠ (partial), ✗ (not found), ◌ (pending)\n * @default false\n */\n showVerificationStatus?: boolean;\n}\n\n/**\n * Parse attributes from a cite tag in any order.\n * Returns an object with all found attributes.\n */\nconst parseCiteAttributes = (\n citeTag: string\n): Record<string, string | undefined> => {\n const attrs: Record<string, string | undefined> = {};\n\n // Match attribute patterns: key='value' or key=\"value\"\n const attrRegex =\n /([a-zA-Z_][a-zA-Z0-9_]*)\\s*=\\s*(['\"])((?:[^'\"\\\\]|\\\\.)*)\\2/g;\n let match;\n\n while ((match = attrRegex.exec(citeTag)) !== null) {\n const key = match[1]\n .toLowerCase()\n .replace(/([a-z])([A-Z])/g, \"$1_$2\")\n .toLowerCase();\n const value = match[3];\n\n // Normalize key names\n const normalizedKey =\n key === \"fileid\" || key === \"file_id\" || key === \"attachmentid\"\n ? \"attachment_id\"\n : key === \"anchortext\" || key === \"anchor_text\" || key === \"keyspan\" || key === \"key_span\"\n ? \"anchor_text\"\n : key === \"fullphrase\"\n ? \"full_phrase\"\n : key === \"lineids\"\n ? \"line_ids\"\n : key === \"pageid\" || key === \"page_id\" || key === \"startpageid\" || key === \"start_pageid\" || key === \"start_page_id\" || key === \"startpagekey\" || key === \"start_pagekey\" || key === \"start_page_key\" || key === \"pagekey\" || key === \"page_key\"\n ? \"start_page_id\"\n : key;\n\n attrs[normalizedKey] = value;\n }\n\n return attrs;\n};\n\n/**\n * Get verification status indicator character for plain text/terminal output.\n * Returns: ☑️ (fully verified), ✅ (partial match), ❌ (not found), ⌛ (pending/null), ◌ (unknown)\n *\n * For web UI, use the React CitationComponent instead which provides\n * proper styled indicators with colors and accessibility.\n */\nexport const getVerificationTextIndicator = (\n verification: Verification | null | undefined\n): string => {\n const status = getCitationStatus(verification);\n\n if (status.isMiss) return \"❌\";\n // Check for fully verified (not partial) first\n if (status.isVerified && !status.isPartialMatch) return \"☑️\";\n // Then check for partial match\n if (status.isPartialMatch) return \"✅\";\n\n if (status.isPending) return \"⌛\";\n\n return \"◌\";\n};\n\n/**\n * Replaces citation tags in markdown text with optional replacement content.\n *\n * @param markdownWithCitations - The text containing <cite /> tags\n * @param options - Configuration options\n * @returns The text with citations replaced\n *\n * @example\n * ```typescript\n * // Remove all citations\n * const clean = replaceCitations(llmOutput);\n *\n * // Leave anchor_text text behind\n * const withAnchorTexts = replaceCitations(llmOutput, { leaveAnchorTextBehind: true });\n *\n * // Show verification status indicators\n * const withStatus = replaceCitations(llmOutput, {\n * leaveAnchorTextBehind: true,\n * verifications: verificationMap,\n * showVerificationStatus: true,\n * });\n * // Output: \"Revenue grew 45% year-over-year Revenue Growth✓\"\n * ```\n */\nexport const replaceCitations = (\n markdownWithCitations: string,\n options: ReplaceCitationsOptions = {}\n): string => {\n const {\n leaveAnchorTextBehind = false,\n verifications,\n showVerificationStatus = false,\n } = options;\n\n // Track citation index for matching with numbered verification keys\n let citationIndex = 0;\n\n // Flexible regex that matches any <cite ... /> tag\n const citationRegex = /<cite\\s+[^>]*?\\/>/g;\n\n return markdownWithCitations.replace(citationRegex, (match) => {\n citationIndex++;\n const attrs = parseCiteAttributes(match);\n\n // Determine what to output\n let output = \"\";\n\n if (leaveAnchorTextBehind && attrs.anchor_text) {\n // Unescape the anchor_text value\n output = attrs.anchor_text.replace(/\\\\'/g, \"'\").replace(/\\\\\"/g, '\"');\n }\n\n // Add verification status if requested\n if (showVerificationStatus && verifications) {\n // Try to find verification by various key strategies\n let verification: Verification | undefined;\n\n // Build a Citation object from parsed attributes to generate the key\n const parsePageNumber = (startPageId?: string): number | undefined => {\n if (!startPageId) return undefined;\n const match = startPageId.match(/page[_a-zA-Z]*(\\d+)/);\n return match ? parseInt(match[1], 10) : undefined;\n };\n\n const parseLineIds = (lineIdsStr?: string): number[] | undefined => {\n if (!lineIdsStr) return undefined;\n\n // First expand ranges (e.g., \"62-63\" -> \"62,63\")\n let expanded = lineIdsStr.replace(\n /(\\d+)-(\\d+)/g,\n (_match, start, end) => {\n const startNum = parseInt(start, 10);\n const endNum = parseInt(end, 10);\n if (startNum <= endNum) {\n const range = [];\n for (let i = startNum; i <= endNum; i++) {\n range.push(i);\n }\n return range.join(\",\");\n }\n return start;\n }\n );\n\n const nums = expanded.split(\",\").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n));\n return nums.length > 0 ? nums : undefined;\n };\n\n // Unescape quotes in fullPhrase and anchorText to match how citations are parsed\n // by getAllCitationsFromLlmOutput (which returns unescaped values)\n const unescapeQuotes = (str: string | undefined): string | undefined =>\n str?.replace(/\\\\'/g, \"'\").replace(/\\\\\"/g, '\"');\n\n const citation: Citation = {\n attachmentId: attrs.attachment_id,\n pageNumber: parsePageNumber(attrs.start_page_id),\n fullPhrase: unescapeQuotes(attrs.full_phrase),\n anchorText: unescapeQuotes(attrs.anchor_text),\n lineIds: parseLineIds(attrs.line_ids),\n };\n\n // Strategy 1: Match by citationKey (hash) - most reliable\n const citationKey = generateCitationKey(citation);\n verification = verifications[citationKey];\n\n // Strategy 2: Fall back to numbered keys (1, 2, 3, etc.)\n if (!verification) {\n const numericKey = String(citationIndex);\n verification = verifications[numericKey];\n }\n\n const indicator = getVerificationTextIndicator(verification);\n output = output ? `${output}${indicator}` : indicator;\n }\n\n return output;\n });\n};\n\nexport const removePageNumberMetadata = (pageText: string): string => {\n return pageText\n .replace(/<page_number_\\d+_index_\\d+>/g, \"\")\n .replace(/<\\/page_number_\\d+_index_\\d+>/g, \"\")\n .trim();\n};\n\nexport const removeLineIdMetadata = (pageText: string): string => {\n const lineIdRegex = /<line id=\"[^\"]*\">|<\\/line>/g;\n return pageText.replace(lineIdRegex, \"\");\n};\n\nexport const getCitationPageNumber = (\n startPageId?: string | null\n): number | null => {\n //page_number_{page_number}_index_{page_index} or page_number_{page_number} or page_id_{page_number}_index_{page_index}\n if (!startPageId) return null;\n\n //regex first \\d+ is the page number\n const pageNumber = startPageId.match(/\\d+/)?.[0];\n return pageNumber ? parseInt(pageNumber) : null;\n};\n\n/**\n * Extracts content from a non-self-closing citation tag and moves it before the citation.\n * Converts <cite ...>content</cite> to: content<cite ... />\n *\n * @param citePart - The citation part that may contain inner content\n * @returns The normalized citation with content moved before it\n */\nconst extractAndRelocateCitationContent = (citePart: string): string => {\n // Check if this is a non-self-closing citation: <cite ...>content</cite>\n // Match: <cite with attributes> then content then </cite>\n // The attribute regex handles escaped quotes: (?:[^'\\\\]|\\\\.)* matches non-quote/non-backslash OR backslash+any\n const nonSelfClosingMatch = citePart.match(\n /^(<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>)([\\s\\S]*?)<\\/cite>$/\n );\n\n if (!nonSelfClosingMatch) {\n // Check if this is an unclosed citation ending with just >\n // Pattern: <cite attributes> (no closing tag)\n const unclosedMatch = citePart.match(\n /^(<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>)$/\n );\n if (unclosedMatch) {\n // Convert <cite ... > to self-closing <cite ... />\n const selfClosingTag = unclosedMatch[1].replace(/>$/, \" />\");\n return normalizeCitationContent(selfClosingTag);\n }\n // Already self-closing or doesn't match pattern, normalize as-is\n return normalizeCitationContent(citePart);\n }\n\n const [, openingTag, innerContent] = nonSelfClosingMatch;\n\n // If there's no inner content, just normalize the citation\n if (!innerContent || !innerContent.trim()) {\n return normalizeCitationContent(citePart);\n }\n\n // Extract the attributes from the opening tag\n // Convert <cite attributes> to <cite attributes />\n const selfClosingTag = openingTag.replace(/>$/, \" />\");\n\n // Move inner content before the citation and normalize\n // The inner content is trimmed to avoid extra whitespace issues\n const relocatedContent = innerContent.trim();\n\n // Normalize the self-closing citation tag\n const normalizedCitation = normalizeCitationContent(selfClosingTag);\n\n // Return content followed by the citation\n return relocatedContent + normalizedCitation;\n};\n\nexport const normalizeCitations = (response: string): string => {\n let trimmedResponse = response?.trim() || \"\";\n\n // Fix missing < before cite tags\n // LLMs sometimes output 'cite' without the leading '<'\n // Match 'cite' followed by a space and attribute pattern, but NOT preceded by '<' or a letter\n // This avoids matching words like \"excite\" or \"recite\"\n trimmedResponse = trimmedResponse.replace(\n /(?<![<a-zA-Z])cite\\s+(attachment_id|file_id|fileId|attachmentId)\\s*=/gi,\n \"<cite $1=\"\n );\n\n // Split on citation tags - captures three patterns:\n // 1. Self-closing: <cite ... />\n // 2. With closing tag: <cite ...>content</cite>\n // 3. Unclosed (ends with >): <cite ...> (no closing tag, no </cite> anywhere after)\n // Pattern 3 uses negative lookahead to avoid matching when </cite> follows\n const citationParts = trimmedResponse.split(\n /(<cite[\\s\\S]*?(?:\\/>|<\\/cite>|>(?=\\s*$|[\\r\\n])(?![\\s\\S]*<\\/cite>)))/gm\n );\n if (citationParts.length <= 1) {\n // Handle unclosed citations by converting to self-closing\n const unclosedMatch = trimmedResponse.match(/<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>/g);\n if (unclosedMatch && unclosedMatch.length > 0) {\n const result = trimmedResponse.replace(\n /<cite\\s+(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|[^'\">/])*>/g,\n (match) => match.replace(/>$/, ' />')\n );\n return normalizeCitationContent(result);\n }\n return normalizeCitationContent(trimmedResponse);\n }\n\n trimmedResponse = citationParts\n .map((part) =>\n part.startsWith(\"<cite\")\n ? extractAndRelocateCitationContent(part)\n : part\n )\n .join(\"\");\n\n return trimmedResponse;\n};\n\nconst normalizeCitationContent = (input: string): string => {\n let normalized = input;\n\n // 0. Unescape all backslash-escaped underscores\n // This handles Markdown-processed output where underscores get escaped (e.g., attachment\\_id -> attachment_id, page\\_number\\_1 -> page_number_1)\n normalized = normalized.replace(/\\\\_/g, \"_\");\n\n // 1. Standardize self-closing tags\n // Replace ></cite> with /> for consistency\n normalized = normalized.replace(/><\\/cite>/g, \"/>\");\n\n const canonicalizeCiteAttributeKey = (key: string): string => {\n const lowerKey = key.toLowerCase();\n if (lowerKey === \"fullphrase\" || lowerKey === \"full_phrase\")\n return \"full_phrase\";\n if (lowerKey === \"lineids\" || lowerKey === \"line_ids\") return \"line_ids\";\n if (\n lowerKey === \"startpageid\" ||\n lowerKey === \"start_pageid\" ||\n lowerKey === \"start_page_id\" ||\n lowerKey === \"startpagekey\" ||\n lowerKey === \"start_pagekey\" ||\n lowerKey === \"start_page_key\"\n )\n return \"start_page_id\";\n if (\n lowerKey === \"fileid\" ||\n lowerKey === \"file_id\" ||\n lowerKey === \"attachmentid\" ||\n lowerKey === \"attachment_id\"\n )\n return \"attachment_id\";\n if (lowerKey === \"anchortext\" || lowerKey === \"anchor_text\" || lowerKey === \"keyspan\" || lowerKey === \"key_span\") return \"anchor_text\";\n if (lowerKey === \"reasoning\" || lowerKey === \"value\") return lowerKey;\n if (\n lowerKey === \"timestamps\" ||\n lowerKey === \"timestamp\" ||\n lowerKey === \"timestamps\"\n )\n return \"timestamps\";\n\n return lowerKey;\n };\n\n const htmlEntityMap: Record<string, string> = {\n '"': '\"',\n ''': \"'\",\n '<': '<',\n '>': '>',\n '&': '&',\n };\n const htmlEntityRegex = /&(?:quot|apos|lt|gt|amp);/g;\n const decodeHtmlEntities = (str: string) => {\n return str.replace(htmlEntityRegex, (match) => htmlEntityMap[match] || match);\n };\n\n const textAttributeRegex =\n /(fullPhrase|full_phrase|anchorText|anchor_text|keySpan|key_span|reasoning|value)\\s*=\\s*(['\"])([\\s\\S]*?)(?=\\s+(?:line_ids|lineIds|timestamps|fileId|file_id|attachmentId|attachment_id|start_page_id|start_pageId|startPageId|start_page_key|start_pageKey|startPageKey|anchorText|anchor_text|keySpan|key_span|reasoning|value|full_phrase)\\s*=|\\s*\\/>|['\"]>)/gm;\n\n normalized = normalized.replace(\n textAttributeRegex,\n (_match, key, openQuote, rawContent) => {\n let content = rawContent;\n\n if (content.endsWith(openQuote)) {\n content = content.slice(0, -1);\n }\n\n // Flatten newlines and remove markdown markers\n content = content.replace(/(\\r?\\n)+|(\\*|_){2,}|\\*/g, (match: string) => {\n if (match.includes('\\n') || match.includes('\\r')) return ' ';\n return '';\n });\n\n content = decodeHtmlEntities(content);\n\n // Normalize quotes\n content = content.replace(/\\\\\\\\'/g, \"'\").replace(/\\\\'/g, \"'\").replace(/'/g, \"\\\\'\");\n content = content.replace(/\\\\\\\\\"/g, '\"').replace(/\\\\\"/g, '\"').replace(/\"/g, '\\\\\"');\n\n return `${canonicalizeCiteAttributeKey(key)}='${content}'`;\n }\n );\n normalized = normalized.replace(\n /(line_ids|lineIds|timestamps)=['\"]?([\\[\\]\\(\\){}A-Za-z0-9_\\-, ]+)['\"]?(\\s*\\/?>|\\s+)/gm,\n (_match, key, rawValue, trailingChars) => {\n // Clean up the value (remove generic text, keep numbers/separators)\n let cleanedValue = rawValue.replace(/[A-Za-z\\[\\]\\(\\){}]/g, \"\");\n\n // Expand ranges (e.g., \"1-3\" -> \"1,2,3\")\n cleanedValue = cleanedValue.replace(\n /(\\d+)-(\\d+)/g,\n (_rangeMatch: string, start: string, end: string) => {\n const startNum = parseInt(start, 10);\n const endNum = parseInt(end, 10);\n const range = [];\n\n // Handle ascending range\n if (startNum <= endNum) {\n for (let i = startNum; i <= endNum; i++) {\n range.push(i);\n }\n } else {\n // Fallback for weird descending ranges or just return start\n range.push(startNum);\n }\n return range.join(\",\");\n }\n );\n\n // Normalize commas\n cleanedValue = cleanedValue.replace(/,+/g, \",\").replace(/^,|,$/g, \"\");\n\n // Return standardized format: key='value' + preserved trailing characters (space or />)\n return `${canonicalizeCiteAttributeKey(\n key\n )}='${cleanedValue}'${trailingChars}`;\n }\n );\n\n // 4. Re-order <cite ... /> attributes to match the strict parsing expectations in `citationParser.ts`\n // (the parser uses regexes that assume a canonical attribute order).\n const reorderCiteTagAttributes = (tag: string): string => {\n // Match both single-quoted and double-quoted attributes\n const attrRegex =\n /([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(['\"])((?:[^'\"\\\\\\n]|\\\\.)*)(?:\\2)/g;\n const attrs: Record<string, string> = {};\n let match: RegExpExecArray | null;\n\n while ((match = attrRegex.exec(tag))) {\n const rawKey = match[1];\n const value = match[3]; // match[2] is the quote character\n const key = canonicalizeCiteAttributeKey(rawKey);\n attrs[key] = value;\n }\n\n // If we didn't find any parsable attrs, don't touch the tag.\n const keys = Object.keys(attrs);\n if (keys.length === 0) return tag;\n\n const hasTimestamps =\n typeof attrs.timestamps === \"string\" && attrs.timestamps.length > 0;\n const startPageIds = keys.filter((k) => k.startsWith(\"start_page\"));\n\n const ordered: string[] = [];\n\n // Shared first\n if (attrs.attachment_id) ordered.push(\"attachment_id\");\n\n if (hasTimestamps) {\n // AV citations: attachment_id, full_phrase, anchor_text, timestamps, (optional reasoning/value), then any extras\n if (attrs.full_phrase) ordered.push(\"full_phrase\");\n if (attrs.anchor_text) ordered.push(\"anchor_text\");\n ordered.push(\"timestamps\");\n } else {\n // Document citations: attachment_id, start_page*, full_phrase, anchor_text, line_ids, (optional reasoning/value), then any extras\n if (startPageIds.includes(\"start_page_id\"))\n ordered.push(\"start_page_id\");\n startPageIds\n .filter((k) => k !== \"start_page_id\")\n .sort()\n .forEach((k) => ordered.push(k));\n\n if (attrs.full_phrase) ordered.push(\"full_phrase\");\n if (attrs.anchor_text) ordered.push(\"anchor_text\");\n if (attrs.line_ids) ordered.push(\"line_ids\");\n }\n\n // Optional attrs supported by the parser (but not required)\n if (attrs.reasoning) ordered.push(\"reasoning\");\n if (attrs.value) ordered.push(\"value\");\n\n // Any remaining attributes, stable + deterministic (alpha)\n const used = new Set(ordered);\n keys\n .filter((k) => !used.has(k))\n .sort()\n .forEach((k) => ordered.push(k));\n\n const rebuiltAttrs = ordered.map((k) => `${k}='${attrs[k]}'`).join(\" \");\n return `<cite ${rebuiltAttrs} />`;\n };\n\n normalized = normalized.replace(/<cite\\b[\\s\\S]*?\\/>/gm, (tag) =>\n reorderCiteTagAttributes(tag)\n );\n\n return normalized;\n};\n","import type { Citation } from \"../types/citation.js\";\nimport type { Verification } from \"../types/verification.js\";\nimport { sha1Hash } from \"../utils/sha.js\";\nimport { getCitationPageNumber } from \"../parsing/normalizeCitation.js\";\n\n// =============================================================================\n// UTILITY FUNCTIONS\n// =============================================================================\n\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n\n/**\n * Type guard to check if a citation is a URL citation (type: \"url\" or has url field).\n */\nexport function isUrlCitation(citation: Citation): boolean {\n return citation.type === \"url\" || (typeof citation.url === \"string\" && citation.url.length > 0);\n}\n\n/**\n * Generates a unique, deterministic key for a citation based on its content.\n * Works with both document and URL citation types.\n *\n * For URL citations, the URL is included in the key generation for uniqueness.\n *\n * @param citation - The citation to generate a key for\n * @returns A unique, deterministic key for the citation\n */\nexport function generateCitationKey(citation: Citation): string {\n const pageNumber =\n citation.pageNumber || getCitationPageNumber(citation.startPageId);\n\n // Base key parts for all citations\n const keyParts = [\n citation.attachmentId || \"\",\n pageNumber?.toString() || \"\",\n citation.fullPhrase || \"\",\n citation.anchorText?.toString() || \"\",\n citation.lineIds?.join(\",\") || \"\",\n citation.timestamps?.startTime || \"\",\n citation.timestamps?.endTime || \"\",\n ];\n\n // Add URL-specific fields if present\n if (isUrlCitation(citation)) {\n keyParts.push(\n citation.url || \"\",\n citation.title || \"\",\n citation.domain || \"\",\n );\n }\n\n return sha1Hash(keyParts.join(\"|\")).slice(0, 16);\n}\n\n/**\n * Generates a unique, deterministic key for a verification based on its content.\n * @param verification - The verification to generate a key for\n * @returns\n */\nexport function generateVerificationKey(verification: Verification): string {\n const keyParts = [\n verification.attachmentId || \"\",\n verification.label || \"\",\n verification.verifiedFullPhrase || \"\",\n verification.verifiedAnchorText || \"\",\n verification.verifiedLineIds?.join(\",\") || \"\",\n verification.verifiedPageNumber?.toString() || \"\",\n\n verification.verifiedTimestamps?.startTime || \"\",\n verification.verifiedTimestamps?.endTime || \"\",\n\n verification.verifiedMatchSnippet || \"\",\n verification.hitIndexWithinPage?.toString() || \"\",\n ];\n\n return sha1Hash(keyParts.join(\"|\")).slice(0, 16);\n}\n\n/**\n * Generates a unique instance ID for a citation component render.\n * Combines the citation key with a random suffix for uniqueness.\n */\nexport function generateCitationInstanceId(citationKey: string): string {\n const randomSuffix = Math.random().toString(36).slice(2, 11);\n return `${citationKey}-${randomSuffix}`;\n}\n\n/**\n * Gets the display text for a citation (anchorText with fallback to number).\n */\nexport function getCitationDisplayText(\n citation: Citation,\n options: {\n fallbackDisplay?: string | null;\n } = {}\n): string {\n const { fallbackDisplay } = options;\n return (\n citation.anchorText?.toString() ||\n citation.citationNumber?.toString() ||\n fallbackDisplay ||\n \"1\"\n );\n}\n\n/**\n * Gets the citation number as a string.\n */\nexport function getCitationNumber(citation: Citation): string {\n return citation.citationNumber?.toString() || \"1\";\n}\n\n/**\n * Gets the anchorText text from a citation.\n */\nexport function getCitationAnchorText(citation: Citation): string {\n return citation.anchorText?.toString() || \"\";\n}\n\n/**\n * Joins class names, filtering out falsy values.\n * This is a minimal implementation for the base component.\n */\nexport function classNames(\n ...classes: (string | undefined | null | false)[]\n): string {\n return classes.filter(Boolean).join(\" \");\n}\n\n/**\n * Default padding values for citation styling.\n */\nexport const CITATION_X_PADDING = 4;\nexport const CITATION_Y_PADDING = 1;\n"]}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use strict';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"]};exports.a=g;exports.b=f;exports.c=d;exports.d=l;exports.e=a;exports.f=s;exports.g=_;exports.h=T;exports.i=y;exports.j=A;//# sourceMappingURL=chunk-WS4CQVDI.cjs.map
|
|
125
|
+
//# sourceMappingURL=chunk-WS4CQVDI.cjs.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-WS4CQVDI.cjs","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"]}
|
package/lib/client/index.cjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var chunk7TORYXU4_cjs=require('../chunk-7TORYXU4.cjs');require('../chunk-4UWAUWYL.cjs'),require('../chunk-WS4CQVDI.cjs'),require('../chunk-BYLIBOAU.cjs');Object.defineProperty(exports,"DeepCitation",{enumerable:true,get:function(){return chunk7TORYXU4_cjs.a}});//# sourceMappingURL=index.cjs.map
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
package/lib/client/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Citation, V as Verification } from '../index-
|
|
1
|
+
import { C as Citation, V as Verification } from '../index-BHjI8Bh1.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for the DeepCitation client
|
|
@@ -47,6 +47,30 @@ interface UploadFileOptions {
|
|
|
47
47
|
/** Optional custom filename (uses File.name if not provided) */
|
|
48
48
|
filename?: string;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Options for preparing a URL for citation verification.
|
|
52
|
+
* URLs and Office files take ~30s to process vs. <1s for images/PDFs.
|
|
53
|
+
*/
|
|
54
|
+
interface PrepareUrlOptions {
|
|
55
|
+
/** The URL to convert and prepare for citation verification */
|
|
56
|
+
url: string;
|
|
57
|
+
/** Optional custom attachment ID to use instead of auto-generated one */
|
|
58
|
+
attachmentId?: string;
|
|
59
|
+
/** Optional custom filename for the converted document */
|
|
60
|
+
filename?: string;
|
|
61
|
+
/**
|
|
62
|
+
* UNSAFE: Skip PDF conversion and extract text directly from HTML.
|
|
63
|
+
*
|
|
64
|
+
* This is much faster (<1s vs ~30s) but VULNERABLE to:
|
|
65
|
+
* - Hidden text (CSS display:none, tiny fonts, etc.)
|
|
66
|
+
* - Fine print that users can't see
|
|
67
|
+
* - Prompt injection attacks embedded in the page
|
|
68
|
+
*
|
|
69
|
+
* Only use this for trusted URLs where you control the content.
|
|
70
|
+
* Default: false (uses safe PDF conversion)
|
|
71
|
+
*/
|
|
72
|
+
unsafeFastUrlOutput?: boolean;
|
|
73
|
+
}
|
|
50
74
|
/**
|
|
51
75
|
* Response from verifying citations
|
|
52
76
|
*/
|
|
@@ -93,12 +117,6 @@ interface FileDataPart {
|
|
|
93
117
|
interface PrepareFilesResult {
|
|
94
118
|
/** Array of file references for verification (includes deepTextPromptPortion for each file) */
|
|
95
119
|
fileDataParts: FileDataPart[];
|
|
96
|
-
/**
|
|
97
|
-
* Array of formatted text content for LLM prompts (with page markers and line IDs).
|
|
98
|
-
* @deprecated Use fileDataParts[].deepTextPromptPortion instead for single source of truth.
|
|
99
|
-
* This is kept for backwards compatibility but will be removed in a future version.
|
|
100
|
-
*/
|
|
101
|
-
deepTextPromptPortion: string[];
|
|
102
120
|
}
|
|
103
121
|
/**
|
|
104
122
|
* Input for verify method
|
|
@@ -111,10 +129,6 @@ interface VerifyInput {
|
|
|
111
129
|
/** Output image format for verification screenshots */
|
|
112
130
|
outputImageFormat?: "jpeg" | "png" | "avif";
|
|
113
131
|
}
|
|
114
|
-
/**
|
|
115
|
-
* @deprecated Use VerifyInput instead. This alias is kept for backwards compatibility.
|
|
116
|
-
*/
|
|
117
|
-
type verifyAll = VerifyInput;
|
|
118
132
|
/**
|
|
119
133
|
* Input for convertFile - convert URL or Office file to PDF
|
|
120
134
|
*/
|
|
@@ -271,6 +285,37 @@ declare class DeepCitation {
|
|
|
271
285
|
* ```
|
|
272
286
|
*/
|
|
273
287
|
prepareConvertedFile(options: PrepareConvertedFileOptions): Promise<UploadFileResponse>;
|
|
288
|
+
/**
|
|
289
|
+
* Prepare a URL for citation verification.
|
|
290
|
+
*
|
|
291
|
+
* This is a convenience method that handles URL conversion and text extraction
|
|
292
|
+
* in a single call. The API will convert the URL to PDF and extract text content
|
|
293
|
+
* for citation verification.
|
|
294
|
+
*
|
|
295
|
+
* Note: URLs and Office files take ~30s to process vs. <1s for images/PDFs.
|
|
296
|
+
*
|
|
297
|
+
* @param options - URL and optional settings
|
|
298
|
+
* @returns Upload response with attachmentId and extracted text for LLM prompts
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* ```typescript
|
|
302
|
+
* // Prepare a URL for citation verification
|
|
303
|
+
* const { attachmentId, deepTextPromptPortion } = await deepcitation.prepareUrl({
|
|
304
|
+
* url: "https://example.com/article"
|
|
305
|
+
* });
|
|
306
|
+
*
|
|
307
|
+
* // Use deepTextPromptPortion in your LLM prompt
|
|
308
|
+
* const { enhancedSystemPrompt, enhancedUserPrompt } = wrapCitationPrompt({
|
|
309
|
+
* systemPrompt,
|
|
310
|
+
* userPrompt: question,
|
|
311
|
+
* deepTextPromptPortion,
|
|
312
|
+
* });
|
|
313
|
+
*
|
|
314
|
+
* // Verify citations
|
|
315
|
+
* const verified = await deepcitation.verifyAttachment(attachmentId, citations);
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
prepareUrl(options: PrepareUrlOptions): Promise<UploadFileResponse>;
|
|
274
319
|
/**
|
|
275
320
|
* Upload multiple files for citation verification and get structured content.
|
|
276
321
|
* This is the recommended way to prepare files for LLM prompts.
|
|
@@ -293,7 +338,7 @@ declare class DeepCitation {
|
|
|
293
338
|
* });
|
|
294
339
|
*
|
|
295
340
|
* // Use fileDataParts later for verification
|
|
296
|
-
* const result = await deepcitation.
|
|
341
|
+
* const result = await deepcitation.verify({ llmOutput, fileDataParts });
|
|
297
342
|
* ```
|
|
298
343
|
*/
|
|
299
344
|
prepareFiles(files: FileInput[]): Promise<PrepareFilesResult>;
|
|
@@ -355,4 +400,4 @@ declare class DeepCitation {
|
|
|
355
400
|
}): Promise<VerifyCitationsResponse>;
|
|
356
401
|
}
|
|
357
402
|
|
|
358
|
-
export { type CitationInput, type ConvertFileInput, type ConvertFileResponse, DeepCitation, type DeepCitationConfig, type FileDataPart, type FileInput, type PrepareConvertedFileOptions, type PrepareFilesResult, type UploadFileOptions, type UploadFileResponse, type VerifyCitationsOptions, type VerifyCitationsResponse, type VerifyInput
|
|
403
|
+
export { type CitationInput, type ConvertFileInput, type ConvertFileResponse, DeepCitation, type DeepCitationConfig, type FileDataPart, type FileInput, type PrepareConvertedFileOptions, type PrepareFilesResult, type PrepareUrlOptions, type UploadFileOptions, type UploadFileResponse, type VerifyCitationsOptions, type VerifyCitationsResponse, type VerifyInput };
|