@e-llm-studio/citation 0.0.252 → 0.0.254
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/features/ChatDrawer/ChatDrawer.js +1 -1
- package/dist/cjs/features/ChatDrawer/ChatDrawer.js.map +1 -1
- package/dist/cjs/features/IngestionStatus/IngestionStatusComponent.js +1 -1
- package/dist/cjs/features/IngestionStatus/IngestionStatusComponent.js.map +1 -1
- package/dist/cjs/features/IngestionStatus/useIngestionStatus.js +1 -1
- package/dist/cjs/features/IngestionStatus/useIngestionStatus.js.map +1 -1
- package/dist/cjs/features/PdfViewer/PdfContainer.js +1 -1
- package/dist/cjs/features/PdfViewer/PdfContainer.js.map +1 -1
- package/dist/cjs/features/PdfViewer/PdfViewer.js +1 -1
- package/dist/cjs/features/PdfViewer/PdfViewer.js.map +1 -1
- package/dist/cjs/features/PdfViewer/usePdfHighlight.js +1 -1
- package/dist/cjs/features/PdfViewer/usePdfHighlight.js.map +1 -1
- package/dist/cjs/features/SegmentReviewComponents/ApprovalDescriptionBanner.js +2 -0
- package/dist/cjs/features/SegmentReviewComponents/ApprovalDescriptionBanner.js.map +1 -0
- package/dist/cjs/features/SegmentReviewComponents/CognitiveIntegrity.js +1 -1
- package/dist/cjs/features/SegmentReviewComponents/CognitiveIntegrity.js.map +1 -1
- package/dist/cjs/features/SegmentReviewComponents/RevertCard.js +1 -1
- package/dist/cjs/features/SegmentReviewComponents/RevertCard.js.map +1 -1
- package/dist/cjs/features/SegmentReviewComponents/SaveAsLearningCard.js +2 -0
- package/dist/cjs/features/SegmentReviewComponents/SaveAsLearningCard.js.map +1 -0
- package/dist/cjs/features/SegmentReviewComponents/SegmentReviewPdfWrapper.js +1 -1
- package/dist/cjs/features/SegmentReviewComponents/SegmentReviewPdfWrapper.js.map +1 -1
- package/dist/cjs/hooks/useOnDemandCitationFetch.js +1 -1
- package/dist/cjs/hooks/useOnDemandCitationFetch.js.map +1 -1
- package/dist/cjs/service/onDemandApi.js +1 -1
- package/dist/cjs/service/onDemandApi.js.map +1 -1
- package/dist/features/ChatDrawer/ChatDrawer.js +1 -1
- package/dist/features/ChatDrawer/ChatDrawer.js.map +1 -1
- package/dist/features/IngestionStatus/IngestionStatusComponent.js +1 -1
- package/dist/features/IngestionStatus/IngestionStatusComponent.js.map +1 -1
- package/dist/features/IngestionStatus/useIngestionStatus.js +1 -1
- package/dist/features/IngestionStatus/useIngestionStatus.js.map +1 -1
- package/dist/features/PdfViewer/PdfContainer.js +1 -1
- package/dist/features/PdfViewer/PdfContainer.js.map +1 -1
- package/dist/features/PdfViewer/PdfViewer.js +1 -1
- package/dist/features/PdfViewer/PdfViewer.js.map +1 -1
- package/dist/features/PdfViewer/usePdfHighlight.js +1 -1
- package/dist/features/PdfViewer/usePdfHighlight.js.map +1 -1
- package/dist/features/SegmentReviewComponents/ApprovalDescriptionBanner.js +2 -0
- package/dist/features/SegmentReviewComponents/ApprovalDescriptionBanner.js.map +1 -0
- package/dist/features/SegmentReviewComponents/CognitiveIntegrity.js +1 -1
- package/dist/features/SegmentReviewComponents/CognitiveIntegrity.js.map +1 -1
- package/dist/features/SegmentReviewComponents/RevertCard.js +1 -1
- package/dist/features/SegmentReviewComponents/RevertCard.js.map +1 -1
- package/dist/features/SegmentReviewComponents/SaveAsLearningCard.js +2 -0
- package/dist/features/SegmentReviewComponents/SaveAsLearningCard.js.map +1 -0
- package/dist/features/SegmentReviewComponents/SegmentReviewPdfWrapper.js +1 -1
- package/dist/features/SegmentReviewComponents/SegmentReviewPdfWrapper.js.map +1 -1
- package/dist/hooks/useOnDemandCitationFetch.js +1 -1
- package/dist/hooks/useOnDemandCitationFetch.js.map +1 -1
- package/dist/service/onDemandApi.js +1 -1
- package/dist/service/onDemandApi.js.map +1 -1
- package/dist/types/features/ChatDrawer/ChatDrawer.d.ts.map +1 -1
- package/dist/types/features/IngestionStatus/IngestionStatusComponent.d.ts +1 -0
- package/dist/types/features/IngestionStatus/IngestionStatusComponent.d.ts.map +1 -1
- package/dist/types/features/IngestionStatus/useIngestionStatus.d.ts +1 -1
- package/dist/types/features/IngestionStatus/useIngestionStatus.d.ts.map +1 -1
- package/dist/types/features/PdfViewer/PdfContainer.d.ts +3 -2
- package/dist/types/features/PdfViewer/PdfContainer.d.ts.map +1 -1
- package/dist/types/features/PdfViewer/PdfViewer.d.ts +3 -2
- package/dist/types/features/PdfViewer/PdfViewer.d.ts.map +1 -1
- package/dist/types/features/PdfViewer/usePdfHighlight.d.ts +1 -0
- package/dist/types/features/PdfViewer/usePdfHighlight.d.ts.map +1 -1
- package/dist/types/features/SegmentReviewComponents/ApprovalDescriptionBanner.d.ts +11 -0
- package/dist/types/features/SegmentReviewComponents/ApprovalDescriptionBanner.d.ts.map +1 -0
- package/dist/types/features/SegmentReviewComponents/CognitiveIntegrity.d.ts +6 -1
- package/dist/types/features/SegmentReviewComponents/CognitiveIntegrity.d.ts.map +1 -1
- package/dist/types/features/SegmentReviewComponents/RevertCard.d.ts +9 -1
- package/dist/types/features/SegmentReviewComponents/RevertCard.d.ts.map +1 -1
- package/dist/types/features/SegmentReviewComponents/SaveAsLearningCard.d.ts +16 -0
- package/dist/types/features/SegmentReviewComponents/SaveAsLearningCard.d.ts.map +1 -0
- package/dist/types/features/SegmentReviewComponents/SegmentReviewPdfWrapper.d.ts +19 -1
- package/dist/types/features/SegmentReviewComponents/SegmentReviewPdfWrapper.d.ts.map +1 -1
- package/dist/types/hooks/useOnDemandCitationFetch.d.ts.map +1 -1
- package/dist/types/service/onDemandApi.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),e=require("@tanstack/react-query"),n=require("../service/onDemandApi.js");const i=(t,e,n)=>Array.isArray(t)?Array.isArray(e)&&0!==e.length?Number.isNaN(n)?(console.warn("[findCitation] citationNumber is NaN"),null):t.find(t=>{const i=(t=>{if(null==t)return console.warn("[getCitationType] received null or undefined citation"),"";const e=t?.customMetaData?.type??t?.customMetadata?.type??t?.type??"";return e||console.warn("[getCitationType] citation has no resolvable type field",t),e})(t);return(t=>null==t?(console.warn("[getCitationNumber] received null or undefined citation"),""):(null==t.citation_number&&console.warn("[getCitationNumber] citation is missing citation_number field",t),t?.citation_number??""))(t)?.toString()===n.toString()&&e.some(t=>i?.includes(t))})??null:(console.warn("[findCitation] citationTypes is empty or falsy",e),null):(console.warn("[findCitation] citations is not an array",t),null);exports.useOnDemandCitationFetch=({msg:a,citationType:o,citationNumber:c,enabled:s=!1,accessToken:r,baseUrl:u,orgName:d,citationAssistantProcessingName:l,citationAgentName:_})=>{const m=a?.requestId||a?.id||"",y=t.useMemo(()=>(t=>{switch(t){case"artifact_chunks":return["artifact_chunks","scanned_doc_citation","scanned_doc_citations"];case"rai_artifact_citation":return["rai_artifact_citation","rai_artifact_citations"];case"json_chunks":return["json_chunks"];case"scanned_doc_citation":return["scanned_doc_citation","scanned_doc_citations","artifact_chunks"];case"scanned_doc_citations":return["scanned_doc_citations","scanned_doc_citation","artifact_chunks"];default:return[t]}})(o),[o]),f=(()=>{switch(o){case"artifact_chunks":case"scanned_doc_citations":return"scanned_doc_citation";case"rai_artifact_citation":return"rai_artifact_citation";default:return o}})(),g=a?.isEcgPayloadActive?t.useMemo(()=>["onDemandCitationFetch",m,f,a?.customCitationId,a?.ecg_agent_name],[m,f,a?.customCitationId,a?.ecg_agent_name]):t.useMemo(()=>["onDemandCitationFetch",m,f,"gpt_citation"===o?a?.id:c],[m,f,c]),h=t.useMemo(()=>i(a?.citations,y,c),[a?.citations,y,c]),p=Boolean(s&&m&&f&&u&&d&&!Number.isNaN(c)&&!h),C=r,b=!0===a?.isStreamEnd,A=e.useQuery({queryKey:g,queryFn:async()=>{const t=await n.fetchOnDemandCitation(m,f,c,a?.content??"",C,u,l??"",d,_??"",a?.isEcgPayloadActive??!1,"boolean"==typeof a?.isReqPayloadActive&&a.isReqPayloadActive,a?.ecg_agent_name??"",a?.customCitationId??"",a?.plan_id??"",a?.ui_chat_history??void 0,a?.mmvf_list??void 0,Array.isArray(a?.files)?a.files:[],"string"==typeof a?.metadata&&a.metadata.trim()?a.metadata:"",a?.checkPossibleCitationPayload,a?.ui_request_body);if(t.error||!t.responseData)throw new Error(t.error?.errorMessage||"Failed to fetch on-demand citation");return t.responseData},enabled:p&&b&&Boolean(a?.content),staleTime:1/0,gcTime:1/0,refetchOnMount:!1,refetchOnWindowFocus:!1,retry:!1}),N=t.useMemo(()=>{const t=A.data?.result?.citations??[];return Array.isArray(t)&&0!==t.length?a?.customCitationId?t.find(t=>{const e=t?.title??t?.display_name??"";return"string"==typeof e&&e.includes(a.customCitationId)})??t[0]??null:i(t,y,c)??t[0]??null:null},[a?.customCitationId,c,y,A.data]);return{citation:h??N,isFetching:A.isFetching,isLoading:A.isLoading,isComplete:A.isSuccess,status:A.status,refetch:A.refetch}};
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),e=require("@tanstack/react-query"),n=require("../service/onDemandApi.js");const i=(t,e,n)=>Array.isArray(t)?Array.isArray(e)&&0!==e.length?Number.isNaN(n)?(console.warn("[findCitation] citationNumber is NaN"),null):t.find(t=>{const i=(t=>{if(null==t)return console.warn("[getCitationType] received null or undefined citation"),"";const e=t?.customMetaData?.type??t?.customMetadata?.type??t?.type??"";return e||console.warn("[getCitationType] citation has no resolvable type field",t),e})(t);return(t=>null==t?(console.warn("[getCitationNumber] received null or undefined citation"),""):(null==t.citation_number&&console.warn("[getCitationNumber] citation is missing citation_number field",t),t?.citation_number??""))(t)?.toString()===n.toString()&&e.some(t=>i?.includes(t))})??null:(console.warn("[findCitation] citationTypes is empty or falsy",e),null):(console.warn("[findCitation] citations is not an array",t),null);exports.useOnDemandCitationFetch=({msg:a,citationType:o,citationNumber:c,enabled:s=!1,accessToken:r,baseUrl:u,orgName:d,citationAssistantProcessingName:l,citationAgentName:_})=>{const m=a?.requestId||a?.id||"",y=t.useMemo(()=>(t=>{switch(t){case"artifact_chunks":return["artifact_chunks","scanned_doc_citation","scanned_doc_citations"];case"rai_artifact_citation":return["rai_artifact_citation","rai_artifact_citations"];case"json_chunks":return["json_chunks"];case"scanned_doc_citation":return["scanned_doc_citation","scanned_doc_citations","artifact_chunks"];case"scanned_doc_citations":return["scanned_doc_citations","scanned_doc_citation","artifact_chunks"];default:return[t]}})(o),[o]),f=(()=>{switch(o){case"artifact_chunks":case"scanned_doc_citations":return"scanned_doc_citation";case"rai_artifact_citation":return"rai_artifact_citation";default:return o}})(),g=a?.isEcgPayloadActive?t.useMemo(()=>["onDemandCitationFetch",m,f,a?.customCitationId,a?.ecg_agent_name],[m,f,a?.customCitationId,a?.ecg_agent_name]):t.useMemo(()=>["onDemandCitationFetch",m,f,"gpt_citation"===o?a?.id:c],[m,f,c]),h=t.useMemo(()=>i(a?.citations,y,c),[a?.citations,y,c]),p=Boolean(s&&m&&f&&u&&d&&!Number.isNaN(c)&&!h),C=r,b=!0===a?.isStreamEnd,A=e.useQuery({queryKey:g,queryFn:async()=>{C&&C.trim()||console.warn("[useOnDemandCitationFetch] no accessToken passed in props");const t=await n.fetchOnDemandCitation(m,f,c,a?.content??"",C,u,l??"",d,_??"",a?.isEcgPayloadActive??!1,"boolean"==typeof a?.isReqPayloadActive&&a.isReqPayloadActive,a?.ecg_agent_name??"",a?.customCitationId??"",a?.plan_id??"",a?.ui_chat_history??void 0,a?.mmvf_list??void 0,Array.isArray(a?.files)?a.files:[],"string"==typeof a?.metadata&&a.metadata.trim()?a.metadata:"",a?.checkPossibleCitationPayload,a?.ui_request_body);if(t.error||!t.responseData)throw new Error(t.error?.errorMessage||"Failed to fetch on-demand citation");return t.responseData},enabled:p&&b&&Boolean(a?.content),staleTime:1/0,gcTime:1/0,refetchOnMount:!1,refetchOnWindowFocus:!1,retry:!1}),N=t.useMemo(()=>{const t=A.data?.result?.citations??[];return Array.isArray(t)&&0!==t.length?a?.customCitationId?t.find(t=>{const e=t?.title??t?.display_name??"";return"string"==typeof e&&e.includes(a.customCitationId)})??t[0]??null:i(t,y,c)??t[0]??null:null},[a?.customCitationId,c,y,A.data]);return{citation:h??N,isFetching:A.isFetching,isLoading:A.isLoading,isComplete:A.isSuccess,status:A.status,refetch:A.refetch}};
|
|
2
2
|
//# sourceMappingURL=useOnDemandCitationFetch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOnDemandCitationFetch.js","sources":["../../../src/hooks/useOnDemandCitationFetch.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { fetchOnDemandCitation } from '../service/onDemandApi';\nimport type {\n OnDemandCitationPayload,\n UseOnDemandCitationFetchParams,\n} from '../types/useOnDemandCitationFetch.types';\n\nexport type {\n OnDemandCitationPayload,\n ShareChatToMode,\n IntermediateStep,\n ShareChat,\n ArtifactData,\n PowerActionMetadata,\n UseOnDemandCitationFetchParams,\n} from '../types/useOnDemandCitationFetch.types';\n\nconst getCitationType = (citation: any) => {\n if (citation == null) {\n console.warn('[getCitationType] received null or undefined citation');\n return '';\n }\n const type =\n citation?.customMetaData?.type ??\n citation?.customMetadata?.type ??\n citation?.type ??\n '';\n if (!type) {\n console.warn('[getCitationType] citation has no resolvable type field', citation);\n }\n return type;\n};\n\nconst getCitationNumber = (citation: any) => {\n if (citation == null) {\n console.warn('[getCitationNumber] received null or undefined citation');\n return '';\n }\n if (citation.citation_number == null) {\n console.warn('[getCitationNumber] citation is missing citation_number field', citation);\n }\n return citation?.citation_number ?? '';\n};\n\nconst getCitationTypeCandidates = (citationType: string) => {\n switch (citationType) {\n case 'artifact_chunks':\n return ['artifact_chunks', 'scanned_doc_citation', 'scanned_doc_citations'];\n case 'rai_artifact_citation':\n return ['rai_artifact_citation', 'rai_artifact_citations'];\n case 'json_chunks':\n return ['json_chunks'];\n case 'scanned_doc_citation':\n return ['scanned_doc_citation', 'scanned_doc_citations', 'artifact_chunks'];\n case 'scanned_doc_citations':\n return ['scanned_doc_citations', 'scanned_doc_citation', 'artifact_chunks'];\n default:\n return [citationType];\n }\n};\n\nconst findCitation = (\n citations: any[] | undefined,\n citationTypes: string[],\n citationNumber: number\n) => {\n if (!Array.isArray(citations)) {\n console.warn('[findCitation] citations is not an array', citations);\n return null;\n }\n if (!Array.isArray(citationTypes) || citationTypes.length === 0) {\n console.warn('[findCitation] citationTypes is empty or falsy', citationTypes);\n return null;\n }\n if (Number.isNaN(citationNumber)) {\n console.warn('[findCitation] citationNumber is NaN');\n return null;\n }\n\n return (\n citations.find((citation: any) => {\n const type = getCitationType(citation);\n return (\n getCitationNumber(citation)?.toString() === citationNumber.toString() &&\n citationTypes.some((citationType) => type?.includes(citationType))\n );\n }) ?? null\n );\n};\n\nexport const useOnDemandCitationFetch = ({\n msg,\n citationType,\n citationNumber,\n enabled = false,\n accessToken,\n baseUrl,\n orgName,\n citationAssistantProcessingName,\n citationAgentName,\n}: UseOnDemandCitationFetchParams) => {\n const requestId = msg?.requestId || msg?.id || '';\n const citationTypesForMatching = useMemo(() => getCitationTypeCandidates(citationType), [citationType]);\n const citationTypeForRequest = (() => {\n switch (citationType) {\n case 'artifact_chunks': return 'scanned_doc_citation';\n case 'rai_artifact_citation': return 'rai_artifact_citation';\n case 'scanned_doc_citations': return 'scanned_doc_citation';\n default: return citationType;\n }\n })();\n\n\t// Each (requestId, citationType, citationNumber) triple gets its own cache entry\n\tconst queryKey =msg?.isEcgPayloadActive ? useMemo(\n\t () => ['onDemandCitationFetch', requestId, citationTypeForRequest, msg?.customCitationId, msg?.ecg_agent_name],\n\t [requestId, citationTypeForRequest, msg?.customCitationId, msg?.ecg_agent_name]) \n\t : useMemo(\n\t () => ['onDemandCitationFetch', requestId, citationTypeForRequest, citationType === 'gpt_citation' ? msg?.id : citationNumber],\n\t [requestId, citationTypeForRequest, citationNumber]\n\t);\n\n // If the citation already exists on the message, no need to fetch\n const existingCitation = useMemo(\n () => findCitation(msg?.citations, citationTypesForMatching, citationNumber),\n [msg?.citations, citationTypesForMatching, citationNumber]\n );\n\n const shouldFetch = Boolean(enabled && requestId && citationTypeForRequest && baseUrl && orgName && !Number.isNaN(citationNumber) && !existingCitation);\n const token = accessToken;\n const isMessageComplete = msg?.isStreamEnd === true;\n\n const query = useQuery<OnDemandCitationPayload>({\n queryKey,\n queryFn: async () => {\n // if(!token) {\n // console.error('[useOnDemandCitationFetch] No auth token available, cannot fetch citation');\n // throw new Error('No auth token available, cannot fetch citation');\n // }\n const response = await fetchOnDemandCitation(\n requestId,\n citationTypeForRequest,\n citationNumber,\n msg?.content ?? '',\n token,\n baseUrl,\n citationAssistantProcessingName ?? '',\n orgName,\n citationAgentName ?? '',\n msg?.isEcgPayloadActive ?? false,\n (typeof msg?.isReqPayloadActive === 'boolean' ? msg.isReqPayloadActive : false),\n msg?.ecg_agent_name ?? '',\n msg?.customCitationId ?? '',\n msg?.plan_id ?? '',\n msg?.ui_chat_history ?? undefined,\n msg?.mmvf_list ?? undefined,\n Array.isArray(msg?.files) ? msg.files : [],\n (typeof msg?.metadata === 'string' && msg.metadata.trim()) ? msg.metadata : '',\n msg?.checkPossibleCitationPayload,\n msg?.ui_request_body\n );\n\n if (response.error || !response.responseData) {\n throw new Error(response.error?.errorMessage || 'Failed to fetch on-demand citation');\n }\n\n return response.responseData;\n },\n enabled: shouldFetch && isMessageComplete && Boolean(msg?.content),\n staleTime: Infinity,\n gcTime: Infinity,\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n retry: false,\n });\n const fetchedCitation = useMemo(() => {\n const citations = query.data?.result?.citations ?? [];\n if (!Array.isArray(citations) || citations.length === 0) return null;\n\n if (msg?.customCitationId) {\n return (\n citations.find((c: any) => {\n const title = c?.title ?? c?.display_name ?? '';\n return typeof title === 'string' && title.includes(msg.customCitationId);\n }) ?? citations[0] ?? null\n );\n }\n\n return (\n findCitation(citations, citationTypesForMatching, citationNumber) ??\n citations[0] ??\n null\n );\n}, [msg?.customCitationId, citationNumber, citationTypesForMatching, query.data]);\n const resolvedCitation = existingCitation ?? fetchedCitation;\n\n return {\n citation: resolvedCitation,\n isFetching: query.isFetching,\n isLoading: query.isLoading,\n isComplete: query.isSuccess,\n status: query.status,\n refetch: query.refetch,\n };\n};\n"],"names":["findCitation","citations","citationTypes","citationNumber","Array","isArray","length","Number","isNaN","console","warn","find","citation","type","customMetaData","customMetadata","getCitationType","citation_number","getCitationNumber","toString","some","citationType","includes","msg","enabled","accessToken","baseUrl","orgName","citationAssistantProcessingName","citationAgentName","requestId","id","citationTypesForMatching","useMemo","getCitationTypeCandidates","citationTypeForRequest","queryKey","isEcgPayloadActive","customCitationId","ecg_agent_name","existingCitation","shouldFetch","Boolean","token","isMessageComplete","isStreamEnd","query","useQuery","queryFn","async","response","fetchOnDemandCitation","content","isReqPayloadActive","plan_id","ui_chat_history","mmvf_list","files","metadata","trim","checkPossibleCitationPayload","ui_request_body","error","responseData","Error","errorMessage","staleTime","Infinity","gcTime","refetchOnMount","refetchOnWindowFocus","retry","fetchedCitation","data","result","c","title","display_name","isFetching","isLoading","isComplete","isSuccess","status","refetch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useOnDemandCitationFetch.js","sources":["../../../src/hooks/useOnDemandCitationFetch.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { fetchOnDemandCitation } from '../service/onDemandApi';\nimport type {\n OnDemandCitationPayload,\n UseOnDemandCitationFetchParams,\n} from '../types/useOnDemandCitationFetch.types';\n\nexport type {\n OnDemandCitationPayload,\n ShareChatToMode,\n IntermediateStep,\n ShareChat,\n ArtifactData,\n PowerActionMetadata,\n UseOnDemandCitationFetchParams,\n} from '../types/useOnDemandCitationFetch.types';\n\nconst getCitationType = (citation: any) => {\n if (citation == null) {\n console.warn('[getCitationType] received null or undefined citation');\n return '';\n }\n const type =\n citation?.customMetaData?.type ??\n citation?.customMetadata?.type ??\n citation?.type ??\n '';\n if (!type) {\n console.warn('[getCitationType] citation has no resolvable type field', citation);\n }\n return type;\n};\n\nconst getCitationNumber = (citation: any) => {\n if (citation == null) {\n console.warn('[getCitationNumber] received null or undefined citation');\n return '';\n }\n if (citation.citation_number == null) {\n console.warn('[getCitationNumber] citation is missing citation_number field', citation);\n }\n return citation?.citation_number ?? '';\n};\n\nconst getCitationTypeCandidates = (citationType: string) => {\n switch (citationType) {\n case 'artifact_chunks':\n return ['artifact_chunks', 'scanned_doc_citation', 'scanned_doc_citations'];\n case 'rai_artifact_citation':\n return ['rai_artifact_citation', 'rai_artifact_citations'];\n case 'json_chunks':\n return ['json_chunks'];\n case 'scanned_doc_citation':\n return ['scanned_doc_citation', 'scanned_doc_citations', 'artifact_chunks'];\n case 'scanned_doc_citations':\n return ['scanned_doc_citations', 'scanned_doc_citation', 'artifact_chunks'];\n default:\n return [citationType];\n }\n};\n\nconst findCitation = (\n citations: any[] | undefined,\n citationTypes: string[],\n citationNumber: number\n) => {\n if (!Array.isArray(citations)) {\n console.warn('[findCitation] citations is not an array', citations);\n return null;\n }\n if (!Array.isArray(citationTypes) || citationTypes.length === 0) {\n console.warn('[findCitation] citationTypes is empty or falsy', citationTypes);\n return null;\n }\n if (Number.isNaN(citationNumber)) {\n console.warn('[findCitation] citationNumber is NaN');\n return null;\n }\n\n return (\n citations.find((citation: any) => {\n const type = getCitationType(citation);\n return (\n getCitationNumber(citation)?.toString() === citationNumber.toString() &&\n citationTypes.some((citationType) => type?.includes(citationType))\n );\n }) ?? null\n );\n};\n\nexport const useOnDemandCitationFetch = ({\n msg,\n citationType,\n citationNumber,\n enabled = false,\n accessToken,\n baseUrl,\n orgName,\n citationAssistantProcessingName,\n citationAgentName,\n}: UseOnDemandCitationFetchParams) => {\n const requestId = msg?.requestId || msg?.id || '';\n const citationTypesForMatching = useMemo(() => getCitationTypeCandidates(citationType), [citationType]);\n const citationTypeForRequest = (() => {\n switch (citationType) {\n case 'artifact_chunks': return 'scanned_doc_citation';\n case 'rai_artifact_citation': return 'rai_artifact_citation';\n case 'scanned_doc_citations': return 'scanned_doc_citation';\n default: return citationType;\n }\n })();\n\n\t// Each (requestId, citationType, citationNumber) triple gets its own cache entry\n\tconst queryKey =msg?.isEcgPayloadActive ? useMemo(\n\t () => ['onDemandCitationFetch', requestId, citationTypeForRequest, msg?.customCitationId, msg?.ecg_agent_name],\n\t [requestId, citationTypeForRequest, msg?.customCitationId, msg?.ecg_agent_name]) \n\t : useMemo(\n\t () => ['onDemandCitationFetch', requestId, citationTypeForRequest, citationType === 'gpt_citation' ? msg?.id : citationNumber],\n\t [requestId, citationTypeForRequest, citationNumber]\n\t);\n\n // If the citation already exists on the message, no need to fetch\n const existingCitation = useMemo(\n () => findCitation(msg?.citations, citationTypesForMatching, citationNumber),\n [msg?.citations, citationTypesForMatching, citationNumber]\n );\n\n const shouldFetch = Boolean(enabled && requestId && citationTypeForRequest && baseUrl && orgName && !Number.isNaN(citationNumber) && !existingCitation);\n const token = accessToken;\n const isMessageComplete = msg?.isStreamEnd === true;\n\n const query = useQuery<OnDemandCitationPayload>({\n queryKey,\n queryFn: async () => {\n if (!token || !token.trim()) {\n console.warn('[useOnDemandCitationFetch] no accessToken passed in props');\n }\n const response = await fetchOnDemandCitation(\n requestId,\n citationTypeForRequest,\n citationNumber,\n msg?.content ?? '',\n token,\n baseUrl,\n citationAssistantProcessingName ?? '',\n orgName,\n citationAgentName ?? '',\n msg?.isEcgPayloadActive ?? false,\n (typeof msg?.isReqPayloadActive === 'boolean' ? msg.isReqPayloadActive : false),\n msg?.ecg_agent_name ?? '',\n msg?.customCitationId ?? '',\n msg?.plan_id ?? '',\n msg?.ui_chat_history ?? undefined,\n msg?.mmvf_list ?? undefined,\n Array.isArray(msg?.files) ? msg.files : [],\n (typeof msg?.metadata === 'string' && msg.metadata.trim()) ? msg.metadata : '',\n msg?.checkPossibleCitationPayload,\n msg?.ui_request_body\n );\n\n if (response.error || !response.responseData) {\n throw new Error(response.error?.errorMessage || 'Failed to fetch on-demand citation');\n }\n\n return response.responseData;\n },\n enabled: shouldFetch && isMessageComplete && Boolean(msg?.content),\n staleTime: Infinity,\n gcTime: Infinity,\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n retry: false,\n });\n const fetchedCitation = useMemo(() => {\n const citations = query.data?.result?.citations ?? [];\n if (!Array.isArray(citations) || citations.length === 0) return null;\n\n if (msg?.customCitationId) {\n return (\n citations.find((c: any) => {\n const title = c?.title ?? c?.display_name ?? '';\n return typeof title === 'string' && title.includes(msg.customCitationId);\n }) ?? citations[0] ?? null\n );\n }\n\n return (\n findCitation(citations, citationTypesForMatching, citationNumber) ??\n citations[0] ??\n null\n );\n}, [msg?.customCitationId, citationNumber, citationTypesForMatching, query.data]);\n const resolvedCitation = existingCitation ?? fetchedCitation;\n\n return {\n citation: resolvedCitation,\n isFetching: query.isFetching,\n isLoading: query.isLoading,\n isComplete: query.isSuccess,\n status: query.status,\n refetch: query.refetch,\n };\n};\n"],"names":["findCitation","citations","citationTypes","citationNumber","Array","isArray","length","Number","isNaN","console","warn","find","citation","type","customMetaData","customMetadata","getCitationType","citation_number","getCitationNumber","toString","some","citationType","includes","msg","enabled","accessToken","baseUrl","orgName","citationAssistantProcessingName","citationAgentName","requestId","id","citationTypesForMatching","useMemo","getCitationTypeCandidates","citationTypeForRequest","queryKey","isEcgPayloadActive","customCitationId","ecg_agent_name","existingCitation","shouldFetch","Boolean","token","isMessageComplete","isStreamEnd","query","useQuery","queryFn","async","trim","response","fetchOnDemandCitation","content","isReqPayloadActive","plan_id","ui_chat_history","mmvf_list","files","metadata","checkPossibleCitationPayload","ui_request_body","error","responseData","Error","errorMessage","staleTime","Infinity","gcTime","refetchOnMount","refetchOnWindowFocus","retry","fetchedCitation","data","result","c","title","display_name","isFetching","isLoading","isComplete","isSuccess","status","refetch"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("axios"),r=require("./apicache.service.js"),t=require("../types/onDemandApi.types.js");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=a(e);const o=72e5,n=e=>{if(!e||"object"!=typeof e)return;const r=e;return"string"==typeof r.message?r.message:"string"==typeof r.errorMessage?r.errorMessage:"string"==typeof r.error?r.error:r.error&&"object"==typeof r.error&&"string"==typeof r.error.message?r.error.message:"string"==typeof r.details?r.details:r},i=async e=>{if(s.default.isAxiosError(e)){const r=e;if("ECONNABORTED"===r.code)return{type:t.NetworkErrorType.TIMEOUT,message:"The request took too long to complete. Please try again.",originalError:e};if(r.message.includes("net::ERR_NETWORK_CHANGED")||r.message.includes("net::ERR_INTERNET_DISCONNECTED")||r.message.includes("net::ERR_NAME_NOT_RESOLVED"))return{type:t.NetworkErrorType.INTERNET_DISCONNECTED,message:"Internet connection issue detected. Please check your network.",originalError:e};if(r.message.includes("Network Error")||"ERR_NETWORK"===r.code||r.message.includes("net::ERR_CONNECTION_REFUSED")||r.message.includes("net::ERR_EMPTY_RESPONSE"))return{type:t.NetworkErrorType.SERVER_UNREACHABLE,message:"Unable to connect to server. The service may be down or unreachable.",originalError:e};if(r.response&&r.response.status>=500)return{type:t.NetworkErrorType.SERVER_ERROR,message:`Service Unavailable. Server error (${r.response.status}).`,status:r.response.status,originalError:e};if(r.response&&r.response.status>=400&&r.response.status<500)return{type:t.NetworkErrorType.SERVER_ERROR,message:n(r.response.data)||`Request failed with status code ${r.response.status}`,status:r.response.status,originalError:e}}return{type:t.NetworkErrorType.UNKNOWN_ERROR,message:"An unexpected error occurred. Please try again later.",originalError:e}},c=(e,r=18e4)=>{const t=s.default.create({baseURL:e,timeout:r});return t.interceptors.request.use(async e=>e,async e=>{const r=await i(e);return Promise.reject(r)}),t.interceptors.response.use(e=>e,async e=>{const r=await i(e);return console.error("API Request Failed:",r),Promise.reject(r)}),t},p=(e,r,t)=>`${e}:${r}:${JSON.stringify(t||{})}`,u=c(),l=async(e,r,a)=>{try{const t=a?.baseURL?c(a.baseURL):u,{data:s,config:o}=a||{};let n;switch(e.toLowerCase()){case"get":n=await t.get(r,o);break;case"post":n=await t.post(r,s,o);break;case"put":n=await t.put(r,s,o);break;case"patch":n=await t.patch(r,s,o);break;case"delete":const a={...o,data:s};n=await t.delete(r,a);break;default:throw new Error(`Unsupported method: ${e}`)}return{responseData:n.data,error:null}}catch(e){if(e.type&&Object.values(t.NetworkErrorType).includes(e.type))return{responseData:null,error:e};return{responseData:null,error:await i(e)}}},E=async(e,a,s)=>{const{data:n,params:i,config:c,errorMessage:u,baseURL:E,cacheOption:y,shouldCache:d}=s||{},g=y?.ttl??o,_=y?.key||p(e,a,i);if(!y?.forceRefresh&&!y?.skipCache){const e=await r.apiCache.get(_);if(e)return{responseData:e.data,error:null,cacheMeta:{isFromCache:!0,timestamp:e.timestamp,ttl:e.ttl,cacheKey:_}}}const m={...c,...i&&{params:i}},R=await l(e,a,{data:n,config:m,baseURL:E});return!y?.skipCache&&null!=R.responseData&&(!d||d(R.responseData))&&await r.apiCache.set(_,R.responseData,g),{responseData:R.responseData,error:R.error?{errorMessage:R.error.type===t.NetworkErrorType.INTERNET_DISCONNECTED||R.error.type===t.NetworkErrorType.SLOW_CONNECTION||R.error.type===t.NetworkErrorType.TIMEOUT?R.error.message:R.error.type===t.NetworkErrorType.SERVER_UNREACHABLE?"Unable to connect to server. Please try again later.":u||R.error.message,errorObjData:R.error}:null,cacheMeta:{isFromCache:!1,timestamp:Date.now(),ttl:g,cacheKey:_}}};exports.NetworkErrorType=t.NetworkErrorType,exports.DEFAULT_CACHE_TTL=o,exports.createApiInstance=c,exports.fetchOnDemandCitation=async(e,r,t,a,s,o,n,i,c,p,u,l,y,d,g,_,m,R,N,h)=>{const f="artifact_chunks"===r||"scanned_doc_citation"===r?"artifact_chunks":r,T="gpt_citation"===r?"string"==typeof h?.citationId?h.citationId:"":p?y:`${f}_${t}`,w="post",k="/api/chat/chatResponse";return E(w,k,{baseURL:o,data:{name:n||"citationsprocessing",organizationName:i,prompt:"",useAgent:{agent_name:c||"ProcessCitationsAgent",metadata:u?R:void 0,arguments:{citation_type:r,is_primary_agent_request:!1,...p&&{check_possible_citation_payload:!1},..."boolean"==typeof N&&{check_possible_citation_payload:N},ui_request_body:{llm_formatted_response:a,request_id:e,max_concurrent_citations:10,citation_id:T,...p&&l&&{ecg_agent_name:l},...p&&d&&{plan_id:d},...p&&g&&{ui_chat_history:g},...u&&_&&{mmvf_list:_},...u&&m&&{files:m},...h&&"object"==typeof h&&!Array.isArray(h)&&h}}}},config:{headers:{"Content-Type":"application/json"},withCredentials:!0},errorMessage:"Failed to fetch on-demand citation",cacheOption:{key:`${w}:${k}:onDemandCitation:${e}:${r}:${p?y:t}:${p?l:""}:${"gpt_citation"===r?T:""}`},shouldCache:e=>Array.isArray(e?.result?.citations)&&Boolean(e.result.citations[0])})},exports.generateCacheKey=p,exports.makeApiRequest=l,exports.makeApiRequestWithTTLCache=E;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("axios"),r=require("./apicache.service.js"),t=require("../types/onDemandApi.types.js");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=a(e);const o=72e5,n=e=>{if(!e||"object"!=typeof e)return;const r=e;return"string"==typeof r.message?r.message:"string"==typeof r.errorMessage?r.errorMessage:"string"==typeof r.error?r.error:r.error&&"object"==typeof r.error&&"string"==typeof r.error.message?r.error.message:"string"==typeof r.details?r.details:r},i=async e=>{if(s.default.isAxiosError(e)){const r=e;if("ECONNABORTED"===r.code)return{type:t.NetworkErrorType.TIMEOUT,message:"The request took too long to complete. Please try again.",originalError:e};if(r.message.includes("net::ERR_NETWORK_CHANGED")||r.message.includes("net::ERR_INTERNET_DISCONNECTED")||r.message.includes("net::ERR_NAME_NOT_RESOLVED"))return{type:t.NetworkErrorType.INTERNET_DISCONNECTED,message:"Internet connection issue detected. Please check your network.",originalError:e};if(r.message.includes("Network Error")||"ERR_NETWORK"===r.code||r.message.includes("net::ERR_CONNECTION_REFUSED")||r.message.includes("net::ERR_EMPTY_RESPONSE"))return{type:t.NetworkErrorType.SERVER_UNREACHABLE,message:"Unable to connect to server. The service may be down or unreachable.",originalError:e};if(r.response&&r.response.status>=500)return{type:t.NetworkErrorType.SERVER_ERROR,message:`Service Unavailable. Server error (${r.response.status}).`,status:r.response.status,originalError:e};if(r.response&&r.response.status>=400&&r.response.status<500)return{type:t.NetworkErrorType.SERVER_ERROR,message:n(r.response.data)||`Request failed with status code ${r.response.status}`,status:r.response.status,originalError:e}}return{type:t.NetworkErrorType.UNKNOWN_ERROR,message:"An unexpected error occurred. Please try again later.",originalError:e}},c=(e,r=18e4)=>{const t=s.default.create({baseURL:e,timeout:r});return t.interceptors.request.use(async e=>e,async e=>{const r=await i(e);return Promise.reject(r)}),t.interceptors.response.use(e=>e,async e=>{const r=await i(e);return console.error("API Request Failed:",r),Promise.reject(r)}),t},p=(e,r,t)=>`${e}:${r}:${JSON.stringify(t||{})}`,u=c(),l=async(e,r,a)=>{try{const t=a?.baseURL?c(a.baseURL):u,{data:s,config:o}=a||{};let n;switch(e.toLowerCase()){case"get":n=await t.get(r,o);break;case"post":n=await t.post(r,s,o);break;case"put":n=await t.put(r,s,o);break;case"patch":n=await t.patch(r,s,o);break;case"delete":const a={...o,data:s};n=await t.delete(r,a);break;default:throw new Error(`Unsupported method: ${e}`)}return{responseData:n.data,error:null}}catch(e){if(e.type&&Object.values(t.NetworkErrorType).includes(e.type))return{responseData:null,error:e};return{responseData:null,error:await i(e)}}},E=async(e,a,s)=>{const{data:n,params:i,config:c,errorMessage:u,baseURL:E,cacheOption:y,shouldCache:d}=s||{},g=y?.ttl??o,_=y?.key||p(e,a,i);if(!y?.forceRefresh&&!y?.skipCache){const e=await r.apiCache.get(_);if(e)return{responseData:e.data,error:null,cacheMeta:{isFromCache:!0,timestamp:e.timestamp,ttl:e.ttl,cacheKey:_}}}const m={...c,...i&&{params:i}},R=await l(e,a,{data:n,config:m,baseURL:E});return!y?.skipCache&&null!=R.responseData&&(!d||d(R.responseData))&&await r.apiCache.set(_,R.responseData,g),{responseData:R.responseData,error:R.error?{errorMessage:R.error.type===t.NetworkErrorType.INTERNET_DISCONNECTED||R.error.type===t.NetworkErrorType.SLOW_CONNECTION||R.error.type===t.NetworkErrorType.TIMEOUT?R.error.message:R.error.type===t.NetworkErrorType.SERVER_UNREACHABLE?"Unable to connect to server. Please try again later.":u||R.error.message,errorObjData:R.error}:null,cacheMeta:{isFromCache:!1,timestamp:Date.now(),ttl:g,cacheKey:_}}};exports.NetworkErrorType=t.NetworkErrorType,exports.DEFAULT_CACHE_TTL=o,exports.createApiInstance=c,exports.fetchOnDemandCitation=async(e,r,t,a,s,o,n,i,c,p,u,l,y,d,g,_,m,R,N,h)=>{const f="artifact_chunks"===r||"scanned_doc_citation"===r?"artifact_chunks":r,T="gpt_citation"===r?"string"==typeof h?.citationId?h.citationId:"":p?y:`${f}_${t}`,w="post",k="/api/chat/chatResponse";return E(w,k,{baseURL:o,data:{name:n||"citationsprocessing",organizationName:i,prompt:"",useAgent:{agent_name:c||"ProcessCitationsAgent",metadata:u?R:void 0,arguments:{citation_type:r,is_primary_agent_request:!1,...p&&{check_possible_citation_payload:!1},..."boolean"==typeof N&&{check_possible_citation_payload:N},ui_request_body:{llm_formatted_response:a,request_id:e,max_concurrent_citations:10,citation_id:T,...p&&l&&{ecg_agent_name:l},...p&&d&&{plan_id:d},...p&&g&&{ui_chat_history:g},...u&&_&&{mmvf_list:_},...u&&m&&{files:m},...h&&"object"==typeof h&&!Array.isArray(h)&&h}}}},config:{headers:{"Content-Type":"application/json",...s&&s.trim()&&{Authorization:`Bearer ${s}`}},withCredentials:!0},errorMessage:"Failed to fetch on-demand citation",cacheOption:{key:`${w}:${k}:onDemandCitation:${e}:${r}:${p?y:t}:${p?l:""}:${"gpt_citation"===r?T:""}`},shouldCache:e=>Array.isArray(e?.result?.citations)&&Boolean(e.result.citations[0])})},exports.generateCacheKey=p,exports.makeApiRequest=l,exports.makeApiRequestWithTTLCache=E;
|
|
2
2
|
//# sourceMappingURL=onDemandApi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onDemandApi.js","sources":["../../../src/service/onDemandApi.ts"],"sourcesContent":["\nimport axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from \"axios\";\nimport { apiCache } from \"./apicache.service\";\nimport { NetworkErrorType } from \"../types/onDemandApi.types\";\nimport type {\n NetworkError,\n CachedAPIResponse,\n CacheOptions,\n OnDemandCitationFetchApiResponse,\n UIMediaValidationFeedbackItem,\n} from \"../types/onDemandApi.types\";\n\nexport { NetworkErrorType } from \"../types/onDemandApi.types\";\nexport type {\n NetworkError,\n ApiError,\n StandardAPIResponse,\n CachedAPIResponse,\n OnDemandCitationFetchResponse,\n OnDemandCitationFetchApiResponse,\n CacheOptions,\n} from \"../types/onDemandApi.types\";\n\nexport const DEFAULT_CACHE_TTL = 1000 * 60 * 60 * 2;\n\n\n// on-demand citation fetch — single-shot request that returns the final citations directly\nexport const fetchOnDemandCitation = async (\n requestId: string,\n citationType: string,\n citationNumber: number,\n llmFormattedResponse: string,\n token: string,\n baseUrl:string,\n citationAssistantProcessingName:string,\n orgName:string,\n citationAgentName:string,\n isEcgPayloadActive:boolean,\n isReqPayloadActive:boolean,\n ecg_agent_name:string,\n customCitationId:string, \n plan_id:string,\n ui_chat_history?: any,\n mmvf_list?:UIMediaValidationFeedbackItem[],\n files?: string[],\n metadata?:string,\n checkPossibleCitationPayload?: boolean,\n uiRequestBody?: Record<string, unknown>\n): Promise<CachedAPIResponse<any>> => {\n\n // if(!token || !token.trim()) {\n // throw new Error('Authorization token is required to fetch on-demand citation');\n // }\n\n const normalizedCitationType = citationType === \"artifact_chunks\" || citationType === \"scanned_doc_citation\" ? \"artifact_chunks\" : citationType;\n const citationId =\n citationType === 'gpt_citation'\n ? (typeof uiRequestBody?.citationId === 'string' ? uiRequestBody.citationId : '')\n : isEcgPayloadActive\n ? customCitationId\n : `${normalizedCitationType}_${citationNumber}`;\n \n const method = 'post';\n const endpoint = '/api/chat/chatResponse';\n\n\n return makeApiRequestWithTTLCache<CachedAPIResponse<any>>(\n method,\n endpoint,\n {\n baseURL: baseUrl,\n data: {\n name: citationAssistantProcessingName || 'citationsprocessing',\n organizationName: orgName,\n prompt: '',\n useAgent: {\n agent_name: citationAgentName || 'ProcessCitationsAgent',\n metadata: isReqPayloadActive ? metadata : undefined,\n arguments: {\n citation_type: citationType,\n is_primary_agent_request: false,\n ...(isEcgPayloadActive && {check_possible_citation_payload : false}),\n ...(typeof checkPossibleCitationPayload === 'boolean' && {check_possible_citation_payload: checkPossibleCitationPayload,}),\n ui_request_body: {\n llm_formatted_response: llmFormattedResponse,\n request_id: requestId,\n max_concurrent_citations: 10,\n citation_id: citationId,\n ...(isEcgPayloadActive && ecg_agent_name && {ecg_agent_name}),\n ...(isEcgPayloadActive && plan_id && {plan_id}),\n ...(isEcgPayloadActive && ui_chat_history && {ui_chat_history}),\n ...(isReqPayloadActive && mmvf_list && {mmvf_list}),\n ...(isReqPayloadActive && files && {files}),\n ...(uiRequestBody && typeof uiRequestBody === 'object' && !Array.isArray(uiRequestBody) && uiRequestBody),\n },\n },\n },\n },\n config: {\n headers: {\n 'Content-Type': 'application/json',\n },\n withCredentials: true,\n },\n errorMessage: 'Failed to fetch on-demand citation',\n cacheOption: {\n key: `${method}:${endpoint}:onDemandCitation:${requestId}:${citationType}:${\n isEcgPayloadActive ? customCitationId : citationNumber\n }:${\n isEcgPayloadActive ? ecg_agent_name : ''\n }:${citationType === \"gpt_citation\" ? citationId : ''}`,\n },\n shouldCache: (responseData) => Array.isArray(responseData?.result?.citations) && Boolean(responseData.result.citations[0]),\n }\n );\n};\n\n// legacy on-demand citation fetch — kept for older polling flows that still read from Redis\nexport const getOnDemandCitation = async (\n requestId: string,\n citationType: string,\n citationNumber: number,\n token:string,\n baseUrl:string\n): Promise<OnDemandCitationFetchApiResponse> => {\n return makeApiRequestWithTTLCache<OnDemandCitationFetchApiResponse>(\n 'get',\n '/api/redis/get-single-citations-data',\n {\n baseURL:baseUrl,\n config: {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n },\n params: { request_id: `CitationAgent_${requestId}`, citation_type: citationType, citation_number: citationNumber },\n errorMessage: 'Failed to fetch on-demand citation',\n cacheOption: { ttl: Infinity },\n shouldCache: (data) => data.status === 'ready',\n }\n );\n};\n\nconst extractErrorMessage = (data: unknown): string | undefined => {\n if (!data || typeof data !== 'object') {\n return undefined;\n }\n // Cast to any to avoid TypeScript errors while checking properties\n const errorData = data as any;\n \n // Check for common error message patterns\n if (typeof errorData.message === 'string') {\n return errorData.message;\n }\n \n if (typeof errorData.errorMessage === 'string') {\n return errorData.errorMessage;\n }\n \n if (typeof errorData.error === 'string') {\n return errorData.error;\n }\n \n if (errorData.error && typeof errorData.error === 'object' && typeof errorData.error.message === 'string') {\n return errorData.error.message;\n }\n \n if (typeof errorData.details === 'string') {\n return errorData.details;\n }\n \n return errorData;\n};\n\n\n\n// Helper function to determine error type\nconst determineNetworkErrorType = async (error: any): Promise<NetworkError> => {\n // Check if there's an internet connection first\n // commented out\n // const isConnected = await checkInternetConnection();\n \n // if (!isConnected) {\n // return {\n // type: NetworkErrorType.INTERNET_DISCONNECTED,\n // message: 'No internet connection. Please check your network.',\n // originalError: error,\n // };\n // }\n\n // Axios specific error handling\n if (axios.isAxiosError(error)) {\n const axiosError = error as AxiosError;\n \n // Check for timeout\n if (axiosError.code === 'ECONNABORTED') {\n return {\n type: NetworkErrorType.TIMEOUT,\n message: 'The request took too long to complete. Please try again.',\n originalError: error,\n };\n }\n \n // Client connectivity issues - internet problems detected via error message\n if (axiosError.message.includes('net::ERR_NETWORK_CHANGED') ||\n axiosError.message.includes('net::ERR_INTERNET_DISCONNECTED') ||\n axiosError.message.includes('net::ERR_NAME_NOT_RESOLVED')) {\n return {\n type: NetworkErrorType.INTERNET_DISCONNECTED,\n message: 'Internet connection issue detected. Please check your network.',\n originalError: error,\n };\n }\n \n // Server connectivity issues - server is likely down\n if (axiosError.message.includes('Network Error') || \n axiosError.code === 'ERR_NETWORK' ||\n axiosError.message.includes('net::ERR_CONNECTION_REFUSED') ||\n axiosError.message.includes('net::ERR_EMPTY_RESPONSE')) {\n return {\n type: NetworkErrorType.SERVER_UNREACHABLE,\n message: 'Unable to connect to server. The service may be down or unreachable.',\n originalError: error,\n };\n }\n \n // Server errors (500 range)\n if (axiosError.response && axiosError.response.status >= 500) {\n return {\n type: NetworkErrorType.SERVER_ERROR,\n message: `Service Unavailable. Server error (${axiosError.response.status}).`,\n status: axiosError.response.status,\n originalError: error,\n };\n }\n \n // Client errors (400 range) - these are expected errors\n if (axiosError.response && axiosError.response.status >= 400 && axiosError.response.status < 500) {\n return {\n type: NetworkErrorType.SERVER_ERROR,\n message: extractErrorMessage(axiosError.response.data) || \n `Request failed with status code ${axiosError.response.status}`,\n status: axiosError.response.status,\n originalError: error,\n };\n }\n }\n \n // Default case - unknown error\n return {\n type: NetworkErrorType.UNKNOWN_ERROR,\n message: 'An unexpected error occurred. Please try again later.',\n originalError: error,\n };\n};\n\nexport const createApiInstance = (baseURL?: string, timeout: number = 180000): AxiosInstance => { // 3 mins timeout\n // Create a custom axios instance with interceptors and timeout\n const apiInstance = axios.create({\n baseURL: baseURL,\n timeout: timeout, // Default to 3 mins timeout\n });\n\n // Set up request interceptor for adding headers, etc.\n apiInstance.interceptors.request.use(\n async (config) => {\n \n return config;\n },\n async (error) => {\n const networkError = await determineNetworkErrorType(error);\n return Promise.reject(networkError);\n }\n );\n\n // Set up response interceptor for handling errors\n apiInstance.interceptors.response.use(\n (response: AxiosResponse) => {\n return response;\n },\n async (error: any) => {\n const networkError = await determineNetworkErrorType(error);\n \n // Log errors (you might want to send them to a monitoring service)\n console.error('API Request Failed:', networkError);\n \n // You can also dispatch actions to a global state manager (Redux, etc.)\n // store.dispatch(setNetworkError(networkError));\n \n return Promise.reject(networkError);\n }\n );\n\n return apiInstance;\n};\n\nexport const generateCacheKey = (\n method: string,\n url: string,\n params?: any\n) => `${method}:${url}:${JSON.stringify(params || {})}`;\n\nconst defaultApi = createApiInstance();\n\n\nexport const makeApiRequest = async <T>(\n method: string,\n url: string,\n options?: {\n data?: any,\n config?: AxiosRequestConfig,\n baseURL?: string\n }\n): Promise<{ \n responseData: T | null;\n error: NetworkError | null;\n}> => {\n try {\n // Determine which API instance to use\n const apiInstance = options?.baseURL \n ? createApiInstance(options.baseURL)\n : defaultApi;\n \n const { data, config } = options || {};\n \n let response;\n switch (method.toLowerCase()) {\n case 'get':\n response = await apiInstance.get<T>(url, config);\n break;\n case 'post':\n response = await apiInstance.post<T>(url, data, config);\n break;\n case 'put':\n response = await apiInstance.put<T>(url, data, config);\n break;\n case 'patch':\n response = await apiInstance.patch<T>(url, data, config);\n break;\n case 'delete':\n const deleteConfig = {\n ...config,\n data: data\n };\n response = await apiInstance.delete<T>(url, deleteConfig);\n break;\n default:\n throw new Error(`Unsupported method: ${method}`);\n }\n \n return {\n responseData: response.data,\n error: null,\n };\n } catch (error: any) {\n // The error should already be processed by our interceptor\n if (error.type && Object.values(NetworkErrorType).includes(error.type)) {\n return {\n responseData: null,\n error: error as NetworkError,\n };\n }\n \n // Fallback for unhandled errors\n const networkError = await determineNetworkErrorType(error);\n return {\n responseData: null,\n error: networkError,\n };\n }\n};\n\nexport const makeApiRequestWithTTLCache = async <\n ResponseType extends CachedAPIResponse<any>\n>(\n method: string,\n url: string,\n options?: {\n data?: any;\n params?: any;\n config?: AxiosRequestConfig;\n errorMessage?: string;\n baseURL?: string;\n cacheOption?: CacheOptions;\n // return false to skip writing to cache for this response; defaults to caching all successful responses\n shouldCache?: (responseData: NonNullable<ResponseType['responseData']>) => boolean;\n }\n): Promise<ResponseType> => {\n type ExpectedDataType = NonNullable<ResponseType['responseData']>;\n\n const { data, params, config, errorMessage, baseURL, cacheOption, shouldCache } =\n options || {};\n\n const ttl = cacheOption?.ttl ?? DEFAULT_CACHE_TTL;\n const cacheKey =\n cacheOption?.key || generateCacheKey(method, url, params);\n\n // 1. Try cache\n if (!cacheOption?.forceRefresh && !cacheOption?.skipCache) {\n const cached = await apiCache.get<ExpectedDataType>(cacheKey);\n\n if (cached) {\n return {\n responseData: cached.data,\n error: null,\n cacheMeta: {\n isFromCache: true,\n timestamp: cached.timestamp,\n ttl: cached.ttl,\n cacheKey,\n },\n } as ResponseType;\n }\n }\n\n // 2. Prepare config\n const mergedConfig: AxiosRequestConfig = {\n ...config,\n ...(params && { params }),\n };\n\n // 3. Call API\n const result = await makeApiRequest<ExpectedDataType>(method, url, {\n data,\n config: mergedConfig,\n baseURL,\n });\n\n // 4. Store in cache — skipped if cacheOption.skipCache is set, or if shouldCache returns false\n const allowWrite =\n !cacheOption?.skipCache &&\n result.responseData != null &&\n (shouldCache ? shouldCache(result.responseData) : true);\n\n if (allowWrite) {\n await apiCache.set(cacheKey, result.responseData, ttl);\n }\n\n // 5. Return SAME structure as before + cacheMeta\n return {\n responseData: result.responseData,\n error: result.error\n ? {\n errorMessage:\n result.error.type === NetworkErrorType.INTERNET_DISCONNECTED ||\n result.error.type === NetworkErrorType.SLOW_CONNECTION ||\n result.error.type === NetworkErrorType.TIMEOUT\n ? result.error.message\n : result.error.type === NetworkErrorType.SERVER_UNREACHABLE\n ? \"Unable to connect to server. Please try again later.\"\n : errorMessage || result.error.message,\n errorObjData: result.error,\n }\n : null,\n cacheMeta: {\n isFromCache: false,\n timestamp: Date.now(),\n ttl,\n cacheKey,\n },\n } as ResponseType;\n};\n"],"names":["DEFAULT_CACHE_TTL","extractErrorMessage","data","errorData","message","errorMessage","error","details","determineNetworkErrorType","async","axios","isAxiosError","axiosError","code","type","NetworkErrorType","TIMEOUT","originalError","includes","INTERNET_DISCONNECTED","SERVER_UNREACHABLE","response","status","SERVER_ERROR","UNKNOWN_ERROR","createApiInstance","baseURL","timeout","apiInstance","create","interceptors","request","use","config","networkError","Promise","reject","console","generateCacheKey","method","url","params","JSON","stringify","defaultApi","makeApiRequest","options","toLowerCase","get","post","put","patch","deleteConfig","delete","Error","responseData","Object","values","makeApiRequestWithTTLCache","cacheOption","shouldCache","ttl","cacheKey","key","forceRefresh","skipCache","cached","apiCache","cacheMeta","isFromCache","timestamp","mergedConfig","result","set","SLOW_CONNECTION","errorObjData","Date","now","requestId","citationType","citationNumber","llmFormattedResponse","token","baseUrl","citationAssistantProcessingName","orgName","citationAgentName","isEcgPayloadActive","isReqPayloadActive","ecg_agent_name","customCitationId","plan_id","ui_chat_history","mmvf_list","files","metadata","checkPossibleCitationPayload","uiRequestBody","normalizedCitationType","citationId","endpoint","name","organizationName","prompt","useAgent","agent_name","arguments","citation_type","is_primary_agent_request","check_possible_citation_payload","ui_request_body","llm_formatted_response","request_id","max_concurrent_citations","citation_id","Array","isArray","headers","withCredentials","citations","Boolean"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"onDemandApi.js","sources":["../../../src/service/onDemandApi.ts"],"sourcesContent":["\nimport axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from \"axios\";\nimport { apiCache } from \"./apicache.service\";\nimport { NetworkErrorType } from \"../types/onDemandApi.types\";\nimport type {\n NetworkError,\n CachedAPIResponse,\n CacheOptions,\n OnDemandCitationFetchApiResponse,\n UIMediaValidationFeedbackItem,\n} from \"../types/onDemandApi.types\";\n\nexport { NetworkErrorType } from \"../types/onDemandApi.types\";\nexport type {\n NetworkError,\n ApiError,\n StandardAPIResponse,\n CachedAPIResponse,\n OnDemandCitationFetchResponse,\n OnDemandCitationFetchApiResponse,\n CacheOptions,\n} from \"../types/onDemandApi.types\";\n\nexport const DEFAULT_CACHE_TTL = 1000 * 60 * 60 * 2;\n\n\n// on-demand citation fetch — single-shot request that returns the final citations directly\nexport const fetchOnDemandCitation = async (\n requestId: string,\n citationType: string,\n citationNumber: number,\n llmFormattedResponse: string,\n token: string,\n baseUrl:string,\n citationAssistantProcessingName:string,\n orgName:string,\n citationAgentName:string,\n isEcgPayloadActive:boolean,\n isReqPayloadActive:boolean,\n ecg_agent_name:string,\n customCitationId:string, \n plan_id:string,\n ui_chat_history?: any,\n mmvf_list?:UIMediaValidationFeedbackItem[],\n files?: string[],\n metadata?:string,\n checkPossibleCitationPayload?: boolean,\n uiRequestBody?: Record<string, unknown>\n): Promise<CachedAPIResponse<any>> => {\n\n // if(!token || !token.trim()) {\n // throw new Error('Authorization token is required to fetch on-demand citation');\n // }\n\n const normalizedCitationType = citationType === \"artifact_chunks\" || citationType === \"scanned_doc_citation\" ? \"artifact_chunks\" : citationType;\n const citationId =\n citationType === 'gpt_citation'\n ? (typeof uiRequestBody?.citationId === 'string' ? uiRequestBody.citationId : '')\n : isEcgPayloadActive\n ? customCitationId\n : `${normalizedCitationType}_${citationNumber}`;\n \n const method = 'post';\n const endpoint = '/api/chat/chatResponse';\n\n\n return makeApiRequestWithTTLCache<CachedAPIResponse<any>>(\n method,\n endpoint,\n {\n baseURL: baseUrl,\n data: {\n name: citationAssistantProcessingName || 'citationsprocessing',\n organizationName: orgName,\n prompt: '',\n useAgent: {\n agent_name: citationAgentName || 'ProcessCitationsAgent',\n metadata: isReqPayloadActive ? metadata : undefined,\n arguments: {\n citation_type: citationType,\n is_primary_agent_request: false,\n ...(isEcgPayloadActive && {check_possible_citation_payload : false}),\n ...(typeof checkPossibleCitationPayload === 'boolean' && {check_possible_citation_payload: checkPossibleCitationPayload,}),\n ui_request_body: {\n llm_formatted_response: llmFormattedResponse,\n request_id: requestId,\n max_concurrent_citations: 10,\n citation_id: citationId,\n ...(isEcgPayloadActive && ecg_agent_name && {ecg_agent_name}),\n ...(isEcgPayloadActive && plan_id && {plan_id}),\n ...(isEcgPayloadActive && ui_chat_history && {ui_chat_history}),\n ...(isReqPayloadActive && mmvf_list && {mmvf_list}),\n ...(isReqPayloadActive && files && {files}),\n ...(uiRequestBody && typeof uiRequestBody === 'object' && !Array.isArray(uiRequestBody) && uiRequestBody),\n },\n },\n },\n },\n config: {\n headers: {\n 'Content-Type': 'application/json',\n ...(token && token.trim() && { Authorization: `Bearer ${token}` }),\n },\n withCredentials: true,\n },\n errorMessage: 'Failed to fetch on-demand citation',\n cacheOption: {\n key: `${method}:${endpoint}:onDemandCitation:${requestId}:${citationType}:${\n isEcgPayloadActive ? customCitationId : citationNumber\n }:${\n isEcgPayloadActive ? ecg_agent_name : ''\n }:${citationType === \"gpt_citation\" ? citationId : ''}`,\n },\n shouldCache: (responseData) => Array.isArray(responseData?.result?.citations) && Boolean(responseData.result.citations[0]),\n }\n );\n};\n\n// legacy on-demand citation fetch — kept for older polling flows that still read from Redis\nexport const getOnDemandCitation = async (\n requestId: string,\n citationType: string,\n citationNumber: number,\n token:string,\n baseUrl:string\n): Promise<OnDemandCitationFetchApiResponse> => {\n return makeApiRequestWithTTLCache<OnDemandCitationFetchApiResponse>(\n 'get',\n '/api/redis/get-single-citations-data',\n {\n baseURL:baseUrl,\n config: {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n },\n params: { request_id: `CitationAgent_${requestId}`, citation_type: citationType, citation_number: citationNumber },\n errorMessage: 'Failed to fetch on-demand citation',\n cacheOption: { ttl: Infinity },\n shouldCache: (data) => data.status === 'ready',\n }\n );\n};\n\nconst extractErrorMessage = (data: unknown): string | undefined => {\n if (!data || typeof data !== 'object') {\n return undefined;\n }\n // Cast to any to avoid TypeScript errors while checking properties\n const errorData = data as any;\n \n // Check for common error message patterns\n if (typeof errorData.message === 'string') {\n return errorData.message;\n }\n \n if (typeof errorData.errorMessage === 'string') {\n return errorData.errorMessage;\n }\n \n if (typeof errorData.error === 'string') {\n return errorData.error;\n }\n \n if (errorData.error && typeof errorData.error === 'object' && typeof errorData.error.message === 'string') {\n return errorData.error.message;\n }\n \n if (typeof errorData.details === 'string') {\n return errorData.details;\n }\n \n return errorData;\n};\n\n\n\n// Helper function to determine error type\nconst determineNetworkErrorType = async (error: any): Promise<NetworkError> => {\n // Check if there's an internet connection first\n // commented out\n // const isConnected = await checkInternetConnection();\n \n // if (!isConnected) {\n // return {\n // type: NetworkErrorType.INTERNET_DISCONNECTED,\n // message: 'No internet connection. Please check your network.',\n // originalError: error,\n // };\n // }\n\n // Axios specific error handling\n if (axios.isAxiosError(error)) {\n const axiosError = error as AxiosError;\n \n // Check for timeout\n if (axiosError.code === 'ECONNABORTED') {\n return {\n type: NetworkErrorType.TIMEOUT,\n message: 'The request took too long to complete. Please try again.',\n originalError: error,\n };\n }\n \n // Client connectivity issues - internet problems detected via error message\n if (axiosError.message.includes('net::ERR_NETWORK_CHANGED') ||\n axiosError.message.includes('net::ERR_INTERNET_DISCONNECTED') ||\n axiosError.message.includes('net::ERR_NAME_NOT_RESOLVED')) {\n return {\n type: NetworkErrorType.INTERNET_DISCONNECTED,\n message: 'Internet connection issue detected. Please check your network.',\n originalError: error,\n };\n }\n \n // Server connectivity issues - server is likely down\n if (axiosError.message.includes('Network Error') || \n axiosError.code === 'ERR_NETWORK' ||\n axiosError.message.includes('net::ERR_CONNECTION_REFUSED') ||\n axiosError.message.includes('net::ERR_EMPTY_RESPONSE')) {\n return {\n type: NetworkErrorType.SERVER_UNREACHABLE,\n message: 'Unable to connect to server. The service may be down or unreachable.',\n originalError: error,\n };\n }\n \n // Server errors (500 range)\n if (axiosError.response && axiosError.response.status >= 500) {\n return {\n type: NetworkErrorType.SERVER_ERROR,\n message: `Service Unavailable. Server error (${axiosError.response.status}).`,\n status: axiosError.response.status,\n originalError: error,\n };\n }\n \n // Client errors (400 range) - these are expected errors\n if (axiosError.response && axiosError.response.status >= 400 && axiosError.response.status < 500) {\n return {\n type: NetworkErrorType.SERVER_ERROR,\n message: extractErrorMessage(axiosError.response.data) || \n `Request failed with status code ${axiosError.response.status}`,\n status: axiosError.response.status,\n originalError: error,\n };\n }\n }\n \n // Default case - unknown error\n return {\n type: NetworkErrorType.UNKNOWN_ERROR,\n message: 'An unexpected error occurred. Please try again later.',\n originalError: error,\n };\n};\n\nexport const createApiInstance = (baseURL?: string, timeout: number = 180000): AxiosInstance => { // 3 mins timeout\n // Create a custom axios instance with interceptors and timeout\n const apiInstance = axios.create({\n baseURL: baseURL,\n timeout: timeout, // Default to 3 mins timeout\n });\n\n // Set up request interceptor for adding headers, etc.\n apiInstance.interceptors.request.use(\n async (config) => {\n \n return config;\n },\n async (error) => {\n const networkError = await determineNetworkErrorType(error);\n return Promise.reject(networkError);\n }\n );\n\n // Set up response interceptor for handling errors\n apiInstance.interceptors.response.use(\n (response: AxiosResponse) => {\n return response;\n },\n async (error: any) => {\n const networkError = await determineNetworkErrorType(error);\n \n // Log errors (you might want to send them to a monitoring service)\n console.error('API Request Failed:', networkError);\n \n // You can also dispatch actions to a global state manager (Redux, etc.)\n // store.dispatch(setNetworkError(networkError));\n \n return Promise.reject(networkError);\n }\n );\n\n return apiInstance;\n};\n\nexport const generateCacheKey = (\n method: string,\n url: string,\n params?: any\n) => `${method}:${url}:${JSON.stringify(params || {})}`;\n\nconst defaultApi = createApiInstance();\n\n\nexport const makeApiRequest = async <T>(\n method: string,\n url: string,\n options?: {\n data?: any,\n config?: AxiosRequestConfig,\n baseURL?: string\n }\n): Promise<{ \n responseData: T | null;\n error: NetworkError | null;\n}> => {\n try {\n // Determine which API instance to use\n const apiInstance = options?.baseURL \n ? createApiInstance(options.baseURL)\n : defaultApi;\n \n const { data, config } = options || {};\n \n let response;\n switch (method.toLowerCase()) {\n case 'get':\n response = await apiInstance.get<T>(url, config);\n break;\n case 'post':\n response = await apiInstance.post<T>(url, data, config);\n break;\n case 'put':\n response = await apiInstance.put<T>(url, data, config);\n break;\n case 'patch':\n response = await apiInstance.patch<T>(url, data, config);\n break;\n case 'delete':\n const deleteConfig = {\n ...config,\n data: data\n };\n response = await apiInstance.delete<T>(url, deleteConfig);\n break;\n default:\n throw new Error(`Unsupported method: ${method}`);\n }\n \n return {\n responseData: response.data,\n error: null,\n };\n } catch (error: any) {\n // The error should already be processed by our interceptor\n if (error.type && Object.values(NetworkErrorType).includes(error.type)) {\n return {\n responseData: null,\n error: error as NetworkError,\n };\n }\n \n // Fallback for unhandled errors\n const networkError = await determineNetworkErrorType(error);\n return {\n responseData: null,\n error: networkError,\n };\n }\n};\n\nexport const makeApiRequestWithTTLCache = async <\n ResponseType extends CachedAPIResponse<any>\n>(\n method: string,\n url: string,\n options?: {\n data?: any;\n params?: any;\n config?: AxiosRequestConfig;\n errorMessage?: string;\n baseURL?: string;\n cacheOption?: CacheOptions;\n // return false to skip writing to cache for this response; defaults to caching all successful responses\n shouldCache?: (responseData: NonNullable<ResponseType['responseData']>) => boolean;\n }\n): Promise<ResponseType> => {\n type ExpectedDataType = NonNullable<ResponseType['responseData']>;\n\n const { data, params, config, errorMessage, baseURL, cacheOption, shouldCache } =\n options || {};\n\n const ttl = cacheOption?.ttl ?? DEFAULT_CACHE_TTL;\n const cacheKey =\n cacheOption?.key || generateCacheKey(method, url, params);\n\n // 1. Try cache\n if (!cacheOption?.forceRefresh && !cacheOption?.skipCache) {\n const cached = await apiCache.get<ExpectedDataType>(cacheKey);\n\n if (cached) {\n return {\n responseData: cached.data,\n error: null,\n cacheMeta: {\n isFromCache: true,\n timestamp: cached.timestamp,\n ttl: cached.ttl,\n cacheKey,\n },\n } as ResponseType;\n }\n }\n\n // 2. Prepare config\n const mergedConfig: AxiosRequestConfig = {\n ...config,\n ...(params && { params }),\n };\n\n // 3. Call API\n const result = await makeApiRequest<ExpectedDataType>(method, url, {\n data,\n config: mergedConfig,\n baseURL,\n });\n\n // 4. Store in cache — skipped if cacheOption.skipCache is set, or if shouldCache returns false\n const allowWrite =\n !cacheOption?.skipCache &&\n result.responseData != null &&\n (shouldCache ? shouldCache(result.responseData) : true);\n\n if (allowWrite) {\n await apiCache.set(cacheKey, result.responseData, ttl);\n }\n\n // 5. Return SAME structure as before + cacheMeta\n return {\n responseData: result.responseData,\n error: result.error\n ? {\n errorMessage:\n result.error.type === NetworkErrorType.INTERNET_DISCONNECTED ||\n result.error.type === NetworkErrorType.SLOW_CONNECTION ||\n result.error.type === NetworkErrorType.TIMEOUT\n ? result.error.message\n : result.error.type === NetworkErrorType.SERVER_UNREACHABLE\n ? \"Unable to connect to server. Please try again later.\"\n : errorMessage || result.error.message,\n errorObjData: result.error,\n }\n : null,\n cacheMeta: {\n isFromCache: false,\n timestamp: Date.now(),\n ttl,\n cacheKey,\n },\n } as ResponseType;\n};\n"],"names":["DEFAULT_CACHE_TTL","extractErrorMessage","data","errorData","message","errorMessage","error","details","determineNetworkErrorType","async","axios","isAxiosError","axiosError","code","type","NetworkErrorType","TIMEOUT","originalError","includes","INTERNET_DISCONNECTED","SERVER_UNREACHABLE","response","status","SERVER_ERROR","UNKNOWN_ERROR","createApiInstance","baseURL","timeout","apiInstance","create","interceptors","request","use","config","networkError","Promise","reject","console","generateCacheKey","method","url","params","JSON","stringify","defaultApi","makeApiRequest","options","toLowerCase","get","post","put","patch","deleteConfig","delete","Error","responseData","Object","values","makeApiRequestWithTTLCache","cacheOption","shouldCache","ttl","cacheKey","key","forceRefresh","skipCache","cached","apiCache","cacheMeta","isFromCache","timestamp","mergedConfig","result","set","SLOW_CONNECTION","errorObjData","Date","now","requestId","citationType","citationNumber","llmFormattedResponse","token","baseUrl","citationAssistantProcessingName","orgName","citationAgentName","isEcgPayloadActive","isReqPayloadActive","ecg_agent_name","customCitationId","plan_id","ui_chat_history","mmvf_list","files","metadata","checkPossibleCitationPayload","uiRequestBody","normalizedCitationType","citationId","endpoint","name","organizationName","prompt","useAgent","agent_name","arguments","citation_type","is_primary_agent_request","check_possible_citation_payload","ui_request_body","llm_formatted_response","request_id","max_concurrent_citations","citation_id","Array","isArray","headers","trim","Authorization","withCredentials","citations","Boolean"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as o,useRef as n,useEffect as
|
|
1
|
+
import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as o,useRef as n,useEffect as i}from"react";import{ChevronDown as r}from"lucide-react";const d=({children:d,uploadListTopContent:l,defaultHeight:s=300,minHeight:a=150,maxHeight:u,isExpanded:p=!1,onToggle:c,onHeightChange:h,styles:m={},drawerSummaryComponent:f,totalCountsBadge:g,headerComponent:x})=>{const[v,w]=o(!1),[b,y]=o(s),C=n(0),E=n(s),z=n(null),H=n(0),L=()=>"string"==typeof u?parseFloat(u)/100*(window.visualViewport?.height??window.innerHeight):u??.4*window.innerHeight;i(()=>{const e=()=>{const e=Math.max(a,Math.min(L(),b));e!==b&&(y(e),h?.(e))};window.addEventListener("resize",e),window.visualViewport?.addEventListener("resize",e);const t="undefined"!=typeof ResizeObserver?new ResizeObserver(e):null;return t?.observe(document.documentElement),()=>{window.removeEventListener("resize",e),window.visualViewport?.removeEventListener("resize",e),t?.disconnect()}},[b,u,a,h]),i(()=>{!p&&z.current&&(H.current=z.current.getBoundingClientRect().height)},[p]);return i(()=>{if(!v)return;const e=e=>{e.preventDefault();const t=e.clientY-C.current,o=Math.max(a,Math.min(L(),E.current+t));y(o),h?.(o)},t=()=>{w(!1),document.body.style.userSelect=""};return document.addEventListener("mousemove",e),document.addEventListener("mouseup",t),()=>{document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",t)}},[v,u,a,h]),e("div",{ref:z,style:{position:"relative",width:"100%",minHeight:p?H.current:"auto"},children:[e("div",{style:{position:p?"absolute":"relative",zIndex:p?10:"auto",left:0,right:0,top:0,display:"flex",flexDirection:"column",backgroundColor:"#fff",borderRadius:20,border:"1px solid #BDB4FE",boxShadow:"0 4px 8px -2px rgba(16, 24, 40, 0.05), 0 2px 4px -2px rgba(16, 24, 40, 0.06)",height:p?`${b}px`:"auto",minHeight:p?`${a}px`:"auto",maxHeight:p?`${b}px`:"auto",overflow:"hidden",width:"100%",...m.container},children:[e("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",marginBottom:12,flexShrink:0,padding:"12px 20px 0 20px",gap:"16px",...m.header},children:[t("span",{style:{display:"inline-block",flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",fontSize:16,fontWeight:500,lineHeight:"24px",color:"#101828",fontFamily:"Inter, sans-serif",...m.title},children:x||(l?.trim()?l:"Data uploaded for your context")}),g]}),f,p&&t("div",{style:{flex:1,overflowY:"auto",overflowX:"hidden",minHeight:0,padding:"0 20px",paddingBottom:"36px",...m.body},children:d}),p&&t("div",{onMouseDown:e=>{e.preventDefault(),w(!0),C.current=e.clientY,E.current=b,document.body.style.userSelect="none"},style:{position:"absolute",bottom:0,left:0,right:0,backgroundColor:m.body?.backgroundColor??"#fff",display:"flex",justifyContent:"center",alignItems:"center",padding:"8px 20px",cursor:"ns-resize",userSelect:"none",flexShrink:0},children:t("div",{style:{width:48,height:4,borderRadius:4,background:v?m.dragPillActiveColor??"#a78bfa":"#d1d5db",...m.dragPill}})})]}),t("div",{style:{position:p?"absolute":"relative",top:p?`${b}px`:"auto",width:"100%",display:"flex",justifyContent:"center",height:18,zIndex:p?10:"auto"},children:t("button",{onClick:c,"aria-label":p?"Collapse":"Expand",style:{position:"absolute",width:"52px",height:"18px",borderBottomLeftRadius:"10px",borderBottomRightRadius:"10px",border:"1px solid rgb(189, 180, 254)",borderTop:"none",backgroundColor:"#fff",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0,...m.notch},children:t(r,{size:14,color:m.notchArrowColor??"#6d28d9",style:{transform:p?"rotate(180deg)":"rotate(0deg)",transition:"transform 0.2s ease"}})})})]})};export{d as default};
|
|
2
2
|
//# sourceMappingURL=ChatDrawer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatDrawer.js","sources":["../../../src/features/ChatDrawer/ChatDrawer.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { ChatDrawerProps } from './types/ChatDrawer.types';\n\nconst ChatDrawer: React.FC<ChatDrawerProps> = ({\n children,\n uploadListTopContent,\n defaultHeight = 300,\n minHeight = 150,\n maxHeight,\n isExpanded = false,\n onToggle,\n onHeightChange,\n styles = {},\n drawerSummaryComponent,\n totalCountsBadge, \n headerComponent\n}) => {\n const [isDragging, setIsDragging] = useState(false);\n const [height, setHeight] = useState<number>(defaultHeight);\n\n const startYRef = useRef<number>(0);\n const startHeightRef = useRef<number>(defaultHeight);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const collapsedHeightRef = useRef<number>(0);\n\n const resolvedMaxHeight =\n typeof maxHeight === 'string'\n ? (parseFloat(maxHeight) / 100) * window.innerHeight\n : maxHeight ?? window.innerHeight * 0.4;\n\n useEffect(() => {\n if (!isExpanded && wrapperRef.current) {\n collapsedHeightRef.current = wrapperRef.current.getBoundingClientRect().height;\n }\n }, [isExpanded]);\n\n const handleDragStart = (e: React.MouseEvent) => {\n e.preventDefault();\n setIsDragging(true);\n startYRef.current = e.clientY;\n startHeightRef.current = height;\n document.body.style.userSelect = 'none';\n };\n\n useEffect(() => {\n if (!isDragging) return;\n\n const onMove = (e: MouseEvent) => {\n e.preventDefault();\n const deltaY = e.clientY - startYRef.current;\n const newHeight = Math.max(\n minHeight,\n Math.min(resolvedMaxHeight, startHeightRef.current + deltaY)\n );\n setHeight(newHeight);\n onHeightChange?.(newHeight);\n };\n\n const onUp = () => {\n setIsDragging(false);\n document.body.style.userSelect = '';\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n return () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n }, [isDragging]);\n\n return (\n <div\n ref={wrapperRef}\n style={{\n position: 'relative',\n width: '100%',\n minHeight: isExpanded ? collapsedHeightRef.current : 'auto',\n }}\n >\n {/* Main drawer container */}\n <div\n style={{\n position: isExpanded ? 'absolute' : 'relative',\n zIndex: isExpanded ? 10 : 'auto',\n left: 0,\n right: 0,\n top: 0,\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: '#fff',\n borderRadius: 20,\n border: '1px solid #BDB4FE',\n boxShadow: '0 4px 8px -2px rgba(16, 24, 40, 0.05), 0 2px 4px -2px rgba(16, 24, 40, 0.06)',\n height: isExpanded ? `${height}px` : 'auto',\n minHeight: isExpanded ? `${minHeight}px` : 'auto',\n maxHeight: isExpanded ? `${height}px` : 'auto',\n overflow: 'hidden',\n width: '100%',\n ...styles.container,\n }}\n >\n {/* Header */}\n <div style={{ \n display: 'flex', \n alignItems: 'center', \n justifyContent: 'space-between', \n width: '100%', \n marginBottom: 12, \n flexShrink: 0, \n padding: '12px 20px 0 20px', \n gap: '16px',\n ...styles.header \n }}>\n <span\n style={{\n display: 'inline-block',\n flex: 1, \n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n fontSize: 16,\n fontWeight: 500,\n lineHeight: '24px',\n color: '#101828',\n fontFamily: 'Inter, sans-serif',\n ...styles.title,\n }}\n >\n {headerComponent ? headerComponent : (uploadListTopContent?.trim() ? uploadListTopContent : 'Data uploaded for your context')}\n </span>\n \n {totalCountsBadge}\n </div>\n {/* Summary of drawer */}\n {drawerSummaryComponent}\n\n {/* Body */}\n {isExpanded && (\n <div style={{ \n flex: 1, \n overflowY: 'auto', \n overflowX: 'hidden', \n minHeight: 0, \n padding: '0 20px', \n paddingBottom: '36px', // ADDED: Prevents content from hiding behind the floating drag handle\n ...styles.body \n }}>\n {children}\n </div>\n )}\n\n {/* Drag handle */}\n {isExpanded && (\n <div\n onMouseDown={handleDragStart}\n style={{ \n position: 'absolute', // Pin it to the bottom of the container\n bottom: 0, \n left: 0, \n right: 0,\n backgroundColor: styles.body?.backgroundColor ?? '#fff', // Use themed background\n display: 'flex', \n justifyContent: 'center', \n alignItems: 'center', \n padding: '8px 20px', \n cursor: 'ns-resize', \n userSelect: 'none', \n flexShrink: 0,\n }}\n >\n <div style={{ width: 48, height: 4, borderRadius: 4, background: isDragging ? (styles.dragPillActiveColor ?? '#a78bfa') : '#d1d5db', ...styles.dragPill }} />\n </div>\n )}\n </div>\n\n {/* Notch */}\n <div\n style={{\n position: isExpanded ? 'absolute' : 'relative',\n top: isExpanded ? `${height}px` : 'auto',\n width: '100%',\n display: 'flex',\n justifyContent: 'center',\n height: 18,\n zIndex: isExpanded ? 10 : 'auto',\n }}\n >\n <button\n onClick={onToggle}\n aria-label={isExpanded ? 'Collapse' : 'Expand'}\n style={{\n position: 'absolute',\n width: '52px',\n height: '18px',\n borderBottomLeftRadius: '10px',\n borderBottomRightRadius: '10px',\n border: '1px solid rgb(189, 180, 254)',\n borderTop: 'none',\n backgroundColor: '#fff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n padding: 0,\n ...styles.notch,\n }}\n >\n <ChevronDown\n size={14}\n color={styles.notchArrowColor ?? \"#6d28d9\"}\n style={{\n transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 0.2s ease',\n }}\n />\n </button>\n </div>\n </div>\n );\n};\n\nexport default ChatDrawer;"],"names":["ChatDrawer","children","uploadListTopContent","defaultHeight","minHeight","maxHeight","isExpanded","onToggle","onHeightChange","styles","drawerSummaryComponent","totalCountsBadge","headerComponent","isDragging","setIsDragging","useState","height","setHeight","startYRef","useRef","startHeightRef","wrapperRef","collapsedHeightRef","resolvedMaxHeight","parseFloat","window","innerHeight","useEffect","current","getBoundingClientRect","onMove","e","preventDefault","deltaY","clientY","newHeight","Math","max","min","onUp","document","body","style","userSelect","addEventListener","removeEventListener","jsxs","ref","position","width","zIndex","left","right","top","display","flexDirection","backgroundColor","borderRadius","border","boxShadow","overflow","container","alignItems","justifyContent","marginBottom","flexShrink","padding","gap","header","jsx","flex","textOverflow","whiteSpace","fontSize","fontWeight","lineHeight","color","fontFamily","title","trim","overflowY","overflowX","paddingBottom","onMouseDown","bottom","cursor","background","dragPillActiveColor","dragPill","onClick","borderBottomLeftRadius","borderBottomRightRadius","borderTop","notch","ChevronDown","size","notchArrowColor","transform","transition"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChatDrawer.js","sources":["../../../src/features/ChatDrawer/ChatDrawer.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { ChatDrawerProps } from './types/ChatDrawer.types';\n\nconst ChatDrawer: React.FC<ChatDrawerProps> = ({\n children,\n uploadListTopContent,\n defaultHeight = 300,\n minHeight = 150,\n maxHeight,\n isExpanded = false,\n onToggle,\n onHeightChange,\n styles = {},\n drawerSummaryComponent,\n totalCountsBadge, \n headerComponent\n}) => {\n const [isDragging, setIsDragging] = useState(false);\n const [height, setHeight] = useState<number>(defaultHeight);\n\n const startYRef = useRef<number>(0);\n const startHeightRef = useRef<number>(defaultHeight);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const collapsedHeightRef = useRef<number>(0);\n\n const getResolvedMaxHeight = () =>\n typeof maxHeight === 'string'\n ? (parseFloat(maxHeight) / 100) * (window.visualViewport?.height ?? window.innerHeight)\n : maxHeight ?? window.innerHeight * 0.4;\n\n useEffect(() => {\n const clampHeightToViewport = () => {\n const nextHeight = Math.max(minHeight, Math.min(getResolvedMaxHeight(), height));\n\n if (nextHeight !== height) {\n setHeight(nextHeight);\n onHeightChange?.(nextHeight);\n }\n };\n\n window.addEventListener('resize', clampHeightToViewport);\n window.visualViewport?.addEventListener('resize', clampHeightToViewport);\n\n const resizeObserver = typeof ResizeObserver !== 'undefined'\n ? new ResizeObserver(clampHeightToViewport)\n : null;\n resizeObserver?.observe(document.documentElement);\n\n return () => {\n window.removeEventListener('resize', clampHeightToViewport);\n window.visualViewport?.removeEventListener('resize', clampHeightToViewport);\n resizeObserver?.disconnect();\n };\n }, [height, maxHeight, minHeight, onHeightChange]);\n\n useEffect(() => {\n if (!isExpanded && wrapperRef.current) {\n collapsedHeightRef.current = wrapperRef.current.getBoundingClientRect().height;\n }\n }, [isExpanded]);\n\n const handleDragStart = (e: React.MouseEvent) => {\n e.preventDefault();\n setIsDragging(true);\n startYRef.current = e.clientY;\n startHeightRef.current = height;\n document.body.style.userSelect = 'none';\n };\n\n useEffect(() => {\n if (!isDragging) return;\n\n const onMove = (e: MouseEvent) => {\n e.preventDefault();\n const deltaY = e.clientY - startYRef.current;\n const newHeight = Math.max(\n minHeight,\n Math.min(getResolvedMaxHeight(), startHeightRef.current + deltaY)\n );\n setHeight(newHeight);\n onHeightChange?.(newHeight);\n };\n\n const onUp = () => {\n setIsDragging(false);\n document.body.style.userSelect = '';\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n return () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n }, [isDragging, maxHeight, minHeight, onHeightChange]);\n\n return (\n <div\n ref={wrapperRef}\n style={{\n position: 'relative',\n width: '100%',\n minHeight: isExpanded ? collapsedHeightRef.current : 'auto',\n }}\n >\n {/* Main drawer container */}\n <div\n style={{\n position: isExpanded ? 'absolute' : 'relative',\n zIndex: isExpanded ? 10 : 'auto',\n left: 0,\n right: 0,\n top: 0,\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: '#fff',\n borderRadius: 20,\n border: '1px solid #BDB4FE',\n boxShadow: '0 4px 8px -2px rgba(16, 24, 40, 0.05), 0 2px 4px -2px rgba(16, 24, 40, 0.06)',\n height: isExpanded ? `${height}px` : 'auto',\n minHeight: isExpanded ? `${minHeight}px` : 'auto',\n maxHeight: isExpanded ? `${height}px` : 'auto',\n overflow: 'hidden',\n width: '100%',\n ...styles.container,\n }}\n >\n {/* Header */}\n <div style={{ \n display: 'flex', \n alignItems: 'center', \n justifyContent: 'space-between', \n width: '100%', \n marginBottom: 12, \n flexShrink: 0, \n padding: '12px 20px 0 20px', \n gap: '16px',\n ...styles.header \n }}>\n <span\n style={{\n display: 'inline-block',\n flex: 1, \n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n fontSize: 16,\n fontWeight: 500,\n lineHeight: '24px',\n color: '#101828',\n fontFamily: 'Inter, sans-serif',\n ...styles.title,\n }}\n >\n {headerComponent ? headerComponent : (uploadListTopContent?.trim() ? uploadListTopContent : 'Data uploaded for your context')}\n </span>\n \n {totalCountsBadge}\n </div>\n {/* Summary of drawer */}\n {drawerSummaryComponent}\n\n {/* Body */}\n {isExpanded && (\n <div style={{ \n flex: 1, \n overflowY: 'auto', \n overflowX: 'hidden', \n minHeight: 0, \n padding: '0 20px', \n paddingBottom: '36px', // ADDED: Prevents content from hiding behind the floating drag handle\n ...styles.body \n }}>\n {children}\n </div>\n )}\n\n {/* Drag handle */}\n {isExpanded && (\n <div\n onMouseDown={handleDragStart}\n style={{ \n position: 'absolute', // Pin it to the bottom of the container\n bottom: 0, \n left: 0, \n right: 0,\n backgroundColor: styles.body?.backgroundColor ?? '#fff', // Use themed background\n display: 'flex', \n justifyContent: 'center', \n alignItems: 'center', \n padding: '8px 20px', \n cursor: 'ns-resize', \n userSelect: 'none', \n flexShrink: 0,\n }}\n >\n <div style={{ width: 48, height: 4, borderRadius: 4, background: isDragging ? (styles.dragPillActiveColor ?? '#a78bfa') : '#d1d5db', ...styles.dragPill }} />\n </div>\n )}\n </div>\n\n {/* Notch */}\n <div\n style={{\n position: isExpanded ? 'absolute' : 'relative',\n top: isExpanded ? `${height}px` : 'auto',\n width: '100%',\n display: 'flex',\n justifyContent: 'center',\n height: 18,\n zIndex: isExpanded ? 10 : 'auto',\n }}\n >\n <button\n onClick={onToggle}\n aria-label={isExpanded ? 'Collapse' : 'Expand'}\n style={{\n position: 'absolute',\n width: '52px',\n height: '18px',\n borderBottomLeftRadius: '10px',\n borderBottomRightRadius: '10px',\n border: '1px solid rgb(189, 180, 254)',\n borderTop: 'none',\n backgroundColor: '#fff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n padding: 0,\n ...styles.notch,\n }}\n >\n <ChevronDown\n size={14}\n color={styles.notchArrowColor ?? \"#6d28d9\"}\n style={{\n transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 0.2s ease',\n }}\n />\n </button>\n </div>\n </div>\n );\n};\n\nexport default ChatDrawer;"],"names":["ChatDrawer","children","uploadListTopContent","defaultHeight","minHeight","maxHeight","isExpanded","onToggle","onHeightChange","styles","drawerSummaryComponent","totalCountsBadge","headerComponent","isDragging","setIsDragging","useState","height","setHeight","startYRef","useRef","startHeightRef","wrapperRef","collapsedHeightRef","getResolvedMaxHeight","parseFloat","window","visualViewport","innerHeight","useEffect","clampHeightToViewport","nextHeight","Math","max","min","addEventListener","resizeObserver","ResizeObserver","observe","document","documentElement","removeEventListener","disconnect","current","getBoundingClientRect","onMove","e","preventDefault","deltaY","clientY","newHeight","onUp","body","style","userSelect","jsxs","ref","position","width","zIndex","left","right","top","display","flexDirection","backgroundColor","borderRadius","border","boxShadow","overflow","container","alignItems","justifyContent","marginBottom","flexShrink","padding","gap","header","jsx","flex","textOverflow","whiteSpace","fontSize","fontWeight","lineHeight","color","fontFamily","title","trim","overflowY","overflowX","paddingBottom","onMouseDown","bottom","cursor","background","dragPillActiveColor","dragPill","onClick","borderBottomLeftRadius","borderBottomRightRadius","borderTop","notch","ChevronDown","size","notchArrowColor","transform","transition"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as n,Fragment as s}from"react/jsx-runtime";import r from"./ingestion.module.css.js";import{useIngestionWebSocket as t}from"./useIngestionStatus.js";import{ExternalLink as o}from"lucide-react";const i={ingested:{label:"Ingested",className:r.ingested},failed:{label:"Ingestion Failed",className:r.failed},in_progress:{label:"Ingesting...",className:r.inProgress},pending:{label:"Pending",className:r.pending}};const a=({status:t,label:a,percentage:l,customConfig:c,redirectionLink:u})=>{if(c)return e("span",{className:r.chip,style:{border:`1px solid ${c.borderColor}`,background:c.background,color:c.color},children:a??c.label});if("custom"===t)return null;const d=i[t];if(!d)return null;const g="in_progress"===t&&void 0!==l;return n("span",{className:`${r.chip} ${d.className}`,style:{display:"inline-flex",alignItems:"center",gap:6},children:[g?n(s,{children:[a??"Ingesting",e("span",{className:r.dot}),`${l}%`]}):a??d.label,u&&e(o,{size:14,style:{cursor:"pointer",flexShrink:0},onClick:e=>{e.stopPropagation(),window.open(u,"_blank","noopener,noreferrer")}})]})},l=new Set(["DONE","COMPLETED","FAILED"]),c=({ingestionId:n,status:s,wsBaseUrl:r,showPercentage:o=!0,statusMap:i,customStatusConfigs:c,redirectionLink:u})=>{console.log("Component:",u);const
|
|
1
|
+
import{jsx as e,jsxs as n,Fragment as s}from"react/jsx-runtime";import r from"./ingestion.module.css.js";import{useIngestionWebSocket as t}from"./useIngestionStatus.js";import{ExternalLink as o}from"lucide-react";const i={ingested:{label:"Ingested",className:r.ingested},failed:{label:"Ingestion Failed",className:r.failed},in_progress:{label:"Ingesting...",className:r.inProgress},pending:{label:"Pending",className:r.pending}};const a=({status:t,label:a,percentage:l,customConfig:c,redirectionLink:u})=>{if(c)return e("span",{className:r.chip,style:{border:`1px solid ${c.borderColor}`,background:c.background,color:c.color},children:a??c.label});if("custom"===t)return null;const d=i[t];if(!d)return null;const g="in_progress"===t&&void 0!==l;return n("span",{className:`${r.chip} ${d.className}`,style:{display:"inline-flex",alignItems:"center",gap:6},children:[g?n(s,{children:[a??"Ingesting",e("span",{className:r.dot}),`${l}%`]}):a??d.label,u&&e(o,{size:14,style:{cursor:"pointer",flexShrink:0},onClick:e=>{e.stopPropagation(),window.open(u,"_blank","noopener,noreferrer")}})]})},l=new Set(["DONE","COMPLETED","FAILED"]),c=({ingestionId:n,status:s,wsBaseUrl:r,showPercentage:o=!0,statusMap:i,customStatusConfigs:c,redirectionLink:u,authToken:d})=>{console.log("Component:",u);const g=!!s&&l.has(s.toUpperCase()),{data:p}=t(!g&&n?n:null,r,d),m=g?s:p?.ingestionStatus??s??"",f=m?function(e,n){if(!e)return"custom";if(n){if(void 0!==n[e])return n[e];const s=e.toUpperCase();if(void 0!==n[s])return n[s]}return"custom"}(m,i):"pending",b=c?c[f]??c[m]??c[m.toUpperCase()]:void 0,h=(()=>{if(!g&&o)return void 0!==p?.currentProgress?Math.max(5,p.currentProgress):"in_progress"===f?5:void 0})();return e(a,{status:f,percentage:h,customConfig:b,redirectionLink:u})};export{a as IngestionStatusChip,c as IngestionStatusComponent};
|
|
2
2
|
//# sourceMappingURL=IngestionStatusComponent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IngestionStatusComponent.js","sources":["../../../src/features/IngestionStatus/IngestionStatusComponent.tsx"],"sourcesContent":["import React from \"react\";\nimport styles from \"./ingestion.module.css\";\nimport { useIngestionWebSocket } from \"./useIngestionStatus\";\nimport { ExternalLink } from \"lucide-react\";\n\n\nconst STATUS_CONFIG: Record<\n Exclude<string, \"custom\">,\n { label: string; className: string }\n> = {\n ingested: { label: \"Ingested\", className: styles.ingested },\n failed: { label: \"Ingestion Failed\", className: styles.failed },\n in_progress: { label: \"Ingesting...\", className: styles.inProgress },\n pending: { label: \"Pending\", className: styles.pending },\n};\n\nexport interface CustomChipConfig {\n label: string;\n borderColor: string;\n background: string;\n color: string;\n dotColor?: string;\n}\n\nfunction mapStatus(rawStatus: string, statusMap?: Record<string, string>): string {\n if (!rawStatus) return \"custom\";\n if (statusMap) {\n if (statusMap[rawStatus] !== undefined) return statusMap[rawStatus];\n const upper = rawStatus.toUpperCase();\n if (statusMap[upper] !== undefined) return statusMap[upper];\n }\n return \"custom\";\n}\n\ninterface IngestionStatusChipProps {\n status: string;\n label?: string;\n percentage?: number;\n customConfig?: CustomChipConfig;\n redirectionLink?: string;\n\n}\n\nexport const IngestionStatusChip: React.FC<IngestionStatusChipProps> = ({\n status,\n label,\n percentage,\n customConfig,\n redirectionLink,\n}) => {\n if (customConfig) {\n return (\n <span\n className={styles.chip}\n style={{\n border: `1px solid ${customConfig.borderColor}`,\n background: customConfig.background,\n color: customConfig.color,\n }}\n >\n {label ?? customConfig.label}\n </span>\n );\n }\n\n if (status === \"custom\") return null;\n\n const config = STATUS_CONFIG[status];\n if (!config) return null;\n const showPercentage = status === \"in_progress\" && percentage !== undefined;\n\n return (\n <span className={`${styles.chip} ${config.className}`}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n }}>\n {showPercentage ? (\n <>\n {label ?? \"Ingesting\"}\n <span className={styles.dot} />\n {`${percentage}%`}\n </>\n ) : (\n label ?? config.label\n )}\n \n {redirectionLink && (\n <ExternalLink\n size={14}\n style={{ cursor: \"pointer\", flexShrink: 0 }}\n onClick={(e) => {\n e.stopPropagation();\n window.open(redirectionLink, \"_blank\", \"noopener,noreferrer\");\n }}\n />\n )}\n </span>\n );\n};\n\nconst TERMINAL_STATUSES = new Set([\"DONE\", \"COMPLETED\", \"FAILED\"]);\n\n\ninterface IngestionStatusComponentProps {\n ingestionId?: string;\n status?: string;\n wsBaseUrl?: string;\n showPercentage?: boolean;\n statusMap?: Record<string, string>;\n customStatusConfigs?: Record<string, CustomChipConfig>;\n redirectionLink?: string;\n\n}\n\nexport const IngestionStatusComponent: React.FC<IngestionStatusComponentProps> = ({\n ingestionId,\n status,\n wsBaseUrl,\n showPercentage = true,\n statusMap,\n customStatusConfigs,\n redirectionLink\n}) => {\n console.log(\"Component:\", redirectionLink);\n\n const isTerminal = status ? TERMINAL_STATUSES.has(status.toUpperCase()) : false;\n\n const { data } = useIngestionWebSocket(\n !isTerminal && ingestionId ? ingestionId : null,\n wsBaseUrl\n );\n\n const rawForMapping: string = isTerminal\n ? status!\n : data?.ingestionStatus ?? status ?? \"\";\n\n const resolvedStatus: string = rawForMapping\n ? mapStatus(rawForMapping, statusMap)\n : \"pending\";\n\n const customConfig: CustomChipConfig | undefined = customStatusConfigs\n ? customStatusConfigs[resolvedStatus] ??\n customStatusConfigs[rawForMapping] ??\n customStatusConfigs[rawForMapping.toUpperCase()]\n : undefined;\n\n const percentage = (() => {\n if (isTerminal || !showPercentage) return undefined;\n if (data?.currentProgress !== undefined) return Math.max(5, data.currentProgress);\n if (resolvedStatus === \"in_progress\") return 5;\n return undefined;\n })();\n\n return <IngestionStatusChip status={resolvedStatus} percentage={percentage} customConfig={customConfig} redirectionLink={redirectionLink}\n />;\n};\n\n"],"names":["STATUS_CONFIG","ingested","label","className","styles","failed","in_progress","inProgress","pending","IngestionStatusChip","status","percentage","customConfig","redirectionLink","jsx","chip","style","border","borderColor","background","color","children","config","showPercentage","jsxs","display","alignItems","gap","Fragment","dot","ExternalLink","size","cursor","flexShrink","onClick","e","stopPropagation","window","open","TERMINAL_STATUSES","Set","IngestionStatusComponent","ingestionId","wsBaseUrl","statusMap","customStatusConfigs","console","log","isTerminal","has","toUpperCase","data","useIngestionWebSocket","rawForMapping","ingestionStatus","resolvedStatus","rawStatus","upper","mapStatus","currentProgress","Math","max"],"mappings":"qNAMA,MAAMA,EAGF,CACFC,SAAU,CAAEC,MAAO,WAAYC,UAAWC,EAAOH,UACjDI,OAAQ,CAAEH,MAAO,mBAAoBC,UAAWC,EAAOC,QACvDC,YAAa,CAAEJ,MAAO,eAAgBC,UAAWC,EAAOG,YACxDC,QAAS,CAAEN,MAAO,UAAWC,UAAWC,EAAOI,UA8B1C,MAAMC,EAA0D,EACrEC,SACAR,QACAS,aACAC,eACAC,sBAEA,GAAID,EAEA,OAAAE,EAAC,OAAA,CACCX,UAAWC,EAAOW,KAClBC,MAAO,CACLC,OAAQ,aAAaL,EAAaM,cAClCC,WAAYP,EAAaO,WACzBC,MAAOR,EAAaQ,OAGrBC,YAAST,EAAaV,QAKzB,GAAW,WAAXQ,EAA4B,OAAA,KAE1B,MAAAY,EAAStB,EAAcU,GACzB,IAACY,EAAe,OAAA,KACd,MAAAC,EAA4B,gBAAXb,QAA2C,IAAfC,EAGjD,OAAAa,EAAC,OAAA,CAAKrB,UAAW,GAAGC,EAAOW,QAAQO,EAAOnB,YAC1Ca,MAAO,CACLS,QAAS,cACTC,WAAY,SACZC,IAAK,GAEJN,SAAA,CAAAE,EAEIC,EAAAI,EAAA,CAAAP,SAAA,CAASnB,GAAA,YACTY,EAAA,OAAA,CAAKX,UAAWC,EAAOyB,MACvB,GAAGlB,QAGNT,GAASoB,EAAOpB,MAGjBW,GACDC,EAACgB,EAAA,CACCC,KAAM,GACNf,MAAO,CAAEgB,OAAQ,UAAWC,WAAY,GACxCC,QAAUC,IACRA,EAAEC,kBACKC,OAAAC,KAAKzB,EAAiB,SAAU,8BAQ3C0B,EAAwB,IAAAC,IAAI,CAAC,OAAQ,YAAa,
|
|
1
|
+
{"version":3,"file":"IngestionStatusComponent.js","sources":["../../../src/features/IngestionStatus/IngestionStatusComponent.tsx"],"sourcesContent":["import React from \"react\";\nimport styles from \"./ingestion.module.css\";\nimport { useIngestionWebSocket } from \"./useIngestionStatus\";\nimport { ExternalLink } from \"lucide-react\";\n\n\nconst STATUS_CONFIG: Record<\n Exclude<string, \"custom\">,\n { label: string; className: string }\n> = {\n ingested: { label: \"Ingested\", className: styles.ingested },\n failed: { label: \"Ingestion Failed\", className: styles.failed },\n in_progress: { label: \"Ingesting...\", className: styles.inProgress },\n pending: { label: \"Pending\", className: styles.pending },\n};\n\nexport interface CustomChipConfig {\n label: string;\n borderColor: string;\n background: string;\n color: string;\n dotColor?: string;\n}\n\nfunction mapStatus(rawStatus: string, statusMap?: Record<string, string>): string {\n if (!rawStatus) return \"custom\";\n if (statusMap) {\n if (statusMap[rawStatus] !== undefined) return statusMap[rawStatus];\n const upper = rawStatus.toUpperCase();\n if (statusMap[upper] !== undefined) return statusMap[upper];\n }\n return \"custom\";\n}\n\ninterface IngestionStatusChipProps {\n status: string;\n label?: string;\n percentage?: number;\n customConfig?: CustomChipConfig;\n redirectionLink?: string;\n\n}\n\nexport const IngestionStatusChip: React.FC<IngestionStatusChipProps> = ({\n status,\n label,\n percentage,\n customConfig,\n redirectionLink,\n}) => {\n if (customConfig) {\n return (\n <span\n className={styles.chip}\n style={{\n border: `1px solid ${customConfig.borderColor}`,\n background: customConfig.background,\n color: customConfig.color,\n }}\n >\n {label ?? customConfig.label}\n </span>\n );\n }\n\n if (status === \"custom\") return null;\n\n const config = STATUS_CONFIG[status];\n if (!config) return null;\n const showPercentage = status === \"in_progress\" && percentage !== undefined;\n\n return (\n <span className={`${styles.chip} ${config.className}`}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n }}>\n {showPercentage ? (\n <>\n {label ?? \"Ingesting\"}\n <span className={styles.dot} />\n {`${percentage}%`}\n </>\n ) : (\n label ?? config.label\n )}\n \n {redirectionLink && (\n <ExternalLink\n size={14}\n style={{ cursor: \"pointer\", flexShrink: 0 }}\n onClick={(e) => {\n e.stopPropagation();\n window.open(redirectionLink, \"_blank\", \"noopener,noreferrer\");\n }}\n />\n )}\n </span>\n );\n};\n\nconst TERMINAL_STATUSES = new Set([\"DONE\", \"COMPLETED\", \"FAILED\"]);\n\n\ninterface IngestionStatusComponentProps {\n ingestionId?: string;\n status?: string;\n wsBaseUrl?: string;\n showPercentage?: boolean;\n statusMap?: Record<string, string>;\n customStatusConfigs?: Record<string, CustomChipConfig>;\n redirectionLink?: string;\n authToken?: string;\n\n}\n\nexport const IngestionStatusComponent: React.FC<IngestionStatusComponentProps> = ({\n ingestionId,\n status,\n wsBaseUrl,\n showPercentage = true,\n statusMap,\n customStatusConfigs,\n redirectionLink,\n authToken\n}) => {\n console.log(\"Component:\", redirectionLink);\n\n const isTerminal = status ? TERMINAL_STATUSES.has(status.toUpperCase()) : false;\n\n const { data } = useIngestionWebSocket(\n !isTerminal && ingestionId ? ingestionId : null,\n wsBaseUrl,\n authToken\n );\n\n const rawForMapping: string = isTerminal\n ? status!\n : data?.ingestionStatus ?? status ?? \"\";\n\n const resolvedStatus: string = rawForMapping\n ? mapStatus(rawForMapping, statusMap)\n : \"pending\";\n\n const customConfig: CustomChipConfig | undefined = customStatusConfigs\n ? customStatusConfigs[resolvedStatus] ??\n customStatusConfigs[rawForMapping] ??\n customStatusConfigs[rawForMapping.toUpperCase()]\n : undefined;\n\n const percentage = (() => {\n if (isTerminal || !showPercentage) return undefined;\n if (data?.currentProgress !== undefined) return Math.max(5, data.currentProgress);\n if (resolvedStatus === \"in_progress\") return 5;\n return undefined;\n })();\n\n return <IngestionStatusChip status={resolvedStatus} percentage={percentage} customConfig={customConfig} redirectionLink={redirectionLink}\n />;\n};\n\n"],"names":["STATUS_CONFIG","ingested","label","className","styles","failed","in_progress","inProgress","pending","IngestionStatusChip","status","percentage","customConfig","redirectionLink","jsx","chip","style","border","borderColor","background","color","children","config","showPercentage","jsxs","display","alignItems","gap","Fragment","dot","ExternalLink","size","cursor","flexShrink","onClick","e","stopPropagation","window","open","TERMINAL_STATUSES","Set","IngestionStatusComponent","ingestionId","wsBaseUrl","statusMap","customStatusConfigs","authToken","console","log","isTerminal","has","toUpperCase","data","useIngestionWebSocket","rawForMapping","ingestionStatus","resolvedStatus","rawStatus","upper","mapStatus","currentProgress","Math","max"],"mappings":"qNAMA,MAAMA,EAGF,CACFC,SAAU,CAAEC,MAAO,WAAYC,UAAWC,EAAOH,UACjDI,OAAQ,CAAEH,MAAO,mBAAoBC,UAAWC,EAAOC,QACvDC,YAAa,CAAEJ,MAAO,eAAgBC,UAAWC,EAAOG,YACxDC,QAAS,CAAEN,MAAO,UAAWC,UAAWC,EAAOI,UA8B1C,MAAMC,EAA0D,EACrEC,SACAR,QACAS,aACAC,eACAC,sBAEA,GAAID,EAEA,OAAAE,EAAC,OAAA,CACCX,UAAWC,EAAOW,KAClBC,MAAO,CACLC,OAAQ,aAAaL,EAAaM,cAClCC,WAAYP,EAAaO,WACzBC,MAAOR,EAAaQ,OAGrBC,YAAST,EAAaV,QAKzB,GAAW,WAAXQ,EAA4B,OAAA,KAE1B,MAAAY,EAAStB,EAAcU,GACzB,IAACY,EAAe,OAAA,KACd,MAAAC,EAA4B,gBAAXb,QAA2C,IAAfC,EAGjD,OAAAa,EAAC,OAAA,CAAKrB,UAAW,GAAGC,EAAOW,QAAQO,EAAOnB,YAC1Ca,MAAO,CACLS,QAAS,cACTC,WAAY,SACZC,IAAK,GAEJN,SAAA,CAAAE,EAEIC,EAAAI,EAAA,CAAAP,SAAA,CAASnB,GAAA,YACTY,EAAA,OAAA,CAAKX,UAAWC,EAAOyB,MACvB,GAAGlB,QAGNT,GAASoB,EAAOpB,MAGjBW,GACDC,EAACgB,EAAA,CACCC,KAAM,GACNf,MAAO,CAAEgB,OAAQ,UAAWC,WAAY,GACxCC,QAAUC,IACRA,EAAEC,kBACKC,OAAAC,KAAKzB,EAAiB,SAAU,8BAQ3C0B,EAAwB,IAAAC,IAAI,CAAC,OAAQ,YAAa,WAe3CC,EAAoE,EAC/EC,cACAhC,SACAiC,YACApB,kBAAiB,EACjBqB,YACAC,sBACAhC,kBACAiC,gBAEUC,QAAAC,IAAI,aAAcnC,GAE5B,MAAMoC,IAAavC,GAAS6B,EAAkBW,IAAIxC,EAAOyC,gBAEnDC,KAAEA,GAASC,GACdJ,GAAcP,EAAcA,EAAc,KAC3CC,EACAG,GAGIQ,EAAwBL,EAC1BvC,EACA0C,GAAMG,iBAAmB7C,GAAU,GAEjC8C,EAAyBF,EArHjC,SAAmBG,EAAmBb,GAChC,IAACa,EAAkB,MAAA,SACvB,GAAIb,EAAW,CACb,QAAwC,IAApCA,EAAUa,GAA0B,OAAOb,EAAUa,GACnD,MAAAC,EAAQD,EAAUN,cACxB,QAAoC,IAAhCP,EAAUc,GAAsB,OAAOd,EAAUc,EACvD,CACO,MAAA,QACT,CA8GMC,CAAUL,EAAeV,GACzB,UAEEhC,EAA6CiC,EAC/CA,EAAoBW,IACpBX,EAAoBS,IACpBT,EAAoBS,EAAcH,oBAClC,EAEExC,QACA,IAAAsC,GAAe1B,EACf,YAAqC,IAArC6B,GAAMQ,gBAAsCC,KAAKC,IAAI,EAAGV,EAAKQ,iBAC1C,gBAAnBJ,EAAyC,OAAzC,CAEH,KAEI,OAAA1C,EAACL,EAAA,CAAoBC,OAAQ8C,EAAgB7C,aAAwBC,eAA4BC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useState as e,useRef as t,useEffect as n,useCallback as r}from"react";const s=new Set(["DONE","COMPLETED","FAILED"]);const o=new Map;function l(e,t,n){t.listeners.delete(n),0===t.listeners.size&&o.get(e)===t&&(clearInterval(t.keepAliveInterval),t.ws.readyState!==WebSocket.OPEN&&t.ws.readyState!==WebSocket.CONNECTING||t.ws.close(),o.delete(e))}function c(c,a){const[
|
|
1
|
+
import{useState as e,useRef as t,useEffect as n,useCallback as r}from"react";const s=new Set(["DONE","COMPLETED","FAILED"]);const o=new Map;function l(e,t,n){t.listeners.delete(n),0===t.listeners.size&&o.get(e)===t&&(clearInterval(t.keepAliveInterval),t.ws.readyState!==WebSocket.OPEN&&t.ws.readyState!==WebSocket.CONNECTING||t.ws.close(),o.delete(e))}function c(c,a,i){const[u,d]=e(null),[v,S]=e(!1),[p,f]=e(null),g=t(null),k=t(null),E=t(c);n(()=>{E.current=c},[c]);const w=r(()=>{const e=E.current;e&&g.current&&k.current&&l(e,g.current,k.current),g.current=null,k.current=null,S(!1)},[]);return n(()=>{if(!c)return;f(null);const e=function(e,t,n){if(!t||"string"!=typeof t||!t.trim())return console.error("useIngestionWebSocket: wsBaseUrl is missing or invalid; skipping connection."),null;const r=o.get(e);if(r&&r.ws.readyState!==WebSocket.CLOSED)return r;let l=`${t.trim()}/${e}`;n&&(l+=`?token=${n}`);const c=new WebSocket(l),a={ws:c,listeners:new Set,lastData:null,keepAliveInterval:setInterval(()=>{c.readyState===WebSocket.OPEN&&c.send(JSON.stringify({type:"ping"}))},5e3)};return c.onmessage=t=>{let n;try{n=JSON.parse(t.data)}catch{return void a.listeners.forEach(e=>e(null,"Failed to parse WebSocket message"))}if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e;return"string"==typeof t.ingestionStatus&&"string"==typeof t.ingestionId}(n))return void a.listeners.forEach(e=>e(null,"Received malformed WebSocket payload"));const r=n;a.lastData=r,a.listeners.forEach(e=>e(r,null)),s.has(r.ingestionStatus.toUpperCase())&&(clearInterval(a.keepAliveInterval),c.close(),o.delete(e))},c.onerror=()=>{a.listeners.forEach(e=>e(null,"WebSocket connection error"))},c.onclose=()=>{clearInterval(a.keepAliveInterval),o.get(e)===a&&o.delete(e)},o.set(e,a),a}(c,a,i);if(!e)return f("Missing or invalid WebSocket base URL"),void S(!1);e.lastData&&d(e.lastData),S(e.ws.readyState===WebSocket.OPEN);const t=(e,t)=>{t?f(t):d(e)};e.listeners.add(t),g.current=e,k.current=t;const n=()=>S(!0),r=()=>S(!1);return e.ws.addEventListener("open",n),e.ws.addEventListener("close",r),()=>{e.ws.removeEventListener("open",n),e.ws.removeEventListener("close",r),l(c,e,t),g.current=null,k.current=null}},[c,a]),{data:u,connected:v,error:p,disconnect:w}}export{c as useIngestionWebSocket};
|
|
2
2
|
//# sourceMappingURL=useIngestionStatus.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIngestionStatus.js","sources":["../../../src/features/IngestionStatus/useIngestionStatus.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, useRef } from \"react\";\n\nexport interface ArtifactLayer {\n label: string;\n layerStatus: string;\n currentProgress: number;\n chunks: { total: number; completed: number; failed: number };\n}\n\nexport interface Artifact {\n artifactId: string;\n name: string;\n status: string;\n artifactSize: string;\n layers: ArtifactLayer[];\n}\n\nexport interface WebSocketIngestionData {\n ingestionStatus: string;\n ingestionId: string;\n currentProgress: number;\n createdAt: string;\n completedAt?: string | null;\n eta?: string | null;\n artifacts: Artifact[];\n total_artifacts?: number;\n layer_orchestration_count?: number;\n artifactStatus?: {\n \"in-progress\": number;\n completed: number;\n queued: number;\n };\n}\n\nconst TERMINAL_STATUSES = new Set([\"DONE\", \"COMPLETED\", \"FAILED\"]);\n\n// Minimal runtime shape check for incoming WS payloads. We don't pull in a\n// full schema library for one message type — just guard the fields we\n// actually branch on (ingestionStatus) and require an object shape overall.\nfunction isValidIngestionPayload(value: unknown): value is WebSocketIngestionData {\n if (!value || typeof value !== \"object\") return false;\n const candidate = value as Record<string, unknown>;\n return typeof candidate.ingestionStatus === \"string\" && typeof candidate.ingestionId === \"string\";\n}\n\n// --- Shared connection registry -------------------------------------------\n// One real WebSocket per ingestionId, fanned out to any number of subscribers.\n// This lets multiple TimelineItem/IngestionStatusComponent instances that\n// happen to share the same ingestionId (e.g. a batched multi-file upload)\n// observe the same socket instead of each opening (and closing) their own.\ntype Listener = (data: WebSocketIngestionData | null, error: string | null) => void;\n\ninterface SharedConnection {\n ws: WebSocket;\n keepAliveInterval: ReturnType<typeof setInterval>;\n listeners: Set<Listener>;\n lastData: WebSocketIngestionData | null;\n}\n\nconst sharedConnections = new Map<string, SharedConnection>();\n\nfunction releaseListener(ingestionId: string, conn: SharedConnection, listener: Listener) {\n conn.listeners.delete(listener);\n\n // Last subscriber leaving → actually tear down the socket.\n if (conn.listeners.size === 0 && sharedConnections.get(ingestionId) === conn) {\n clearInterval(conn.keepAliveInterval);\n if (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING) {\n conn.ws.close();\n }\n sharedConnections.delete(ingestionId);\n }\n}\n\nfunction getOrCreateConnection(ingestionId: string, wsBaseUrl?: string): SharedConnection | null {\n if (!wsBaseUrl || typeof wsBaseUrl !== \"string\" || !wsBaseUrl.trim()) {\n console.error(\"useIngestionWebSocket: wsBaseUrl is missing or invalid; skipping connection.\");\n return null;\n }\n\n const existing = sharedConnections.get(ingestionId);\n if (existing && existing.ws.readyState !== WebSocket.CLOSED) {\n return existing;\n }\n\n const ws = new WebSocket(`${wsBaseUrl.trim()}/${ingestionId}`);\n const conn: SharedConnection = {\n ws,\n listeners: new Set(),\n lastData: null,\n keepAliveInterval: setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"ping\" }));\n }\n }, 5000),\n };\n\n ws.onmessage = (event) => {\n let rawData: unknown;\n try {\n rawData = JSON.parse(event.data);\n } catch {\n conn.listeners.forEach((listener) => listener(null, \"Failed to parse WebSocket message\"));\n return;\n }\n\n if (!isValidIngestionPayload(rawData)) {\n conn.listeners.forEach((listener) => listener(null, \"Received malformed WebSocket payload\"));\n return;\n }\n\n // Bind to a const so the narrowed type survives inside the closures below —\n // `let` bindings get widened back to their declared type inside closures\n // since TS can't prove they won't be reassigned before the closure runs.\n const payload: WebSocketIngestionData = rawData;\n\n conn.lastData = payload;\n conn.listeners.forEach((listener) => listener(payload, null));\n\n if (TERMINAL_STATUSES.has(payload.ingestionStatus.toUpperCase())) {\n clearInterval(conn.keepAliveInterval);\n ws.close();\n sharedConnections.delete(ingestionId);\n }\n};\n\n ws.onerror = () => {\n conn.listeners.forEach((listener) => listener(null, \"WebSocket connection error\"));\n };\n\n ws.onclose = () => {\n clearInterval(conn.keepAliveInterval);\n // Only remove from the registry if this is still the active connection\n // for this id (avoids racing a newer reconnect attempt).\n if (sharedConnections.get(ingestionId) === conn) {\n sharedConnections.delete(ingestionId);\n }\n };\n\n sharedConnections.set(ingestionId, conn);\n return conn;\n}\n\nexport function useIngestionWebSocket(ingestionId: string | null, wsBaseUrl?: string) {\n const [data, setData] = useState<WebSocketIngestionData | null>(null);\n const [connected, setConnected] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Track the current connection + listener so the imperative disconnect()\n // below can unsubscribe/close outside of the effect's own cleanup.\n const connRef = useRef<SharedConnection | null>(null);\n const listenerRef = useRef<Listener | null>(null);\n const ingestionIdRef = useRef<string | null>(ingestionId);\n\n useEffect(() => {\n ingestionIdRef.current = ingestionId;\n }, [ingestionId]);\n\n const disconnect = useCallback(() => {\n const currentId = ingestionIdRef.current;\n if (currentId && connRef.current && listenerRef.current) {\n releaseListener(currentId, connRef.current, listenerRef.current);\n }\n connRef.current = null;\n listenerRef.current = null;\n setConnected(false);\n }, []);\n\n useEffect(() => {\n if (!ingestionId) return;\n\n setError(null);\n\n const conn = getOrCreateConnection(ingestionId, wsBaseUrl);\n if (!conn) {\n setError(\"Missing or invalid WebSocket base URL\");\n setConnected(false);\n return;\n }\n\n // Seed with whatever the shared connection already has, so a late\n // subscriber isn't stuck blank until the next message arrives.\n if (conn.lastData) setData(conn.lastData);\n setConnected(conn.ws.readyState === WebSocket.OPEN);\n\n const listener: Listener = (newData, newError) => {\n if (newError) {\n setError(newError);\n return;\n }\n setData(newData);\n };\n\n conn.listeners.add(listener);\n connRef.current = conn;\n listenerRef.current = listener;\n\n const handleOpen = () => setConnected(true);\n const handleClose = () => setConnected(false);\n conn.ws.addEventListener(\"open\", handleOpen);\n conn.ws.addEventListener(\"close\", handleClose);\n\n return () => {\n conn.ws.removeEventListener(\"open\", handleOpen);\n conn.ws.removeEventListener(\"close\", handleClose);\n releaseListener(ingestionId, conn, listener);\n connRef.current = null;\n listenerRef.current = null;\n };\n }, [ingestionId, wsBaseUrl]);\n\n return { data, connected, error, disconnect };\n}"],"names":["TERMINAL_STATUSES","Set","sharedConnections","Map","releaseListener","ingestionId","conn","listener","listeners","delete","size","get","clearInterval","keepAliveInterval","ws","readyState","WebSocket","OPEN","CONNECTING","close","useIngestionWebSocket","wsBaseUrl","data","setData","useState","connected","setConnected","error","setError","connRef","useRef","listenerRef","ingestionIdRef","useEffect","current","disconnect","useCallback","currentId","trim","console","existing","CLOSED","lastData","setInterval","send","JSON","stringify","type","onmessage","event","rawData","parse","forEach","value","candidate","ingestionStatus","isValidIngestionPayload","payload","has","toUpperCase","onerror","onclose","set","getOrCreateConnection","newData","newError","add","handleOpen","handleClose","addEventListener","removeEventListener"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useIngestionStatus.js","sources":["../../../src/features/IngestionStatus/useIngestionStatus.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, useRef } from \"react\";\n\nexport interface ArtifactLayer {\n label: string;\n layerStatus: string;\n currentProgress: number;\n chunks: { total: number; completed: number; failed: number };\n}\n\nexport interface Artifact {\n artifactId: string;\n name: string;\n status: string;\n artifactSize: string;\n layers: ArtifactLayer[];\n}\n\nexport interface WebSocketIngestionData {\n ingestionStatus: string;\n ingestionId: string;\n currentProgress: number;\n createdAt: string;\n completedAt?: string | null;\n eta?: string | null;\n artifacts: Artifact[];\n total_artifacts?: number;\n layer_orchestration_count?: number;\n artifactStatus?: {\n \"in-progress\": number;\n completed: number;\n queued: number;\n };\n}\n\nconst TERMINAL_STATUSES = new Set([\"DONE\", \"COMPLETED\", \"FAILED\"]);\n\n// Minimal runtime shape check for incoming WS payloads. We don't pull in a\n// full schema library for one message type — just guard the fields we\n// actually branch on (ingestionStatus) and require an object shape overall.\nfunction isValidIngestionPayload(value: unknown): value is WebSocketIngestionData {\n if (!value || typeof value !== \"object\") return false;\n const candidate = value as Record<string, unknown>;\n return typeof candidate.ingestionStatus === \"string\" && typeof candidate.ingestionId === \"string\";\n}\n\n// --- Shared connection registry -------------------------------------------\n// One real WebSocket per ingestionId, fanned out to any number of subscribers.\n// This lets multiple TimelineItem/IngestionStatusComponent instances that\n// happen to share the same ingestionId (e.g. a batched multi-file upload)\n// observe the same socket instead of each opening (and closing) their own.\ntype Listener = (data: WebSocketIngestionData | null, error: string | null) => void;\n\ninterface SharedConnection {\n ws: WebSocket;\n keepAliveInterval: ReturnType<typeof setInterval>;\n listeners: Set<Listener>;\n lastData: WebSocketIngestionData | null;\n}\n\nconst sharedConnections = new Map<string, SharedConnection>();\n\nfunction releaseListener(ingestionId: string, conn: SharedConnection, listener: Listener) {\n conn.listeners.delete(listener);\n\n // Last subscriber leaving → actually tear down the socket.\n if (conn.listeners.size === 0 && sharedConnections.get(ingestionId) === conn) {\n clearInterval(conn.keepAliveInterval);\n if (conn.ws.readyState === WebSocket.OPEN || conn.ws.readyState === WebSocket.CONNECTING) {\n conn.ws.close();\n }\n sharedConnections.delete(ingestionId);\n }\n}\n\nfunction getOrCreateConnection(ingestionId: string, wsBaseUrl?: string, authToken?: string): SharedConnection | null {\n if (!wsBaseUrl || typeof wsBaseUrl !== \"string\" || !wsBaseUrl.trim()) {\n console.error(\"useIngestionWebSocket: wsBaseUrl is missing or invalid; skipping connection.\");\n return null;\n }\n\n const existing = sharedConnections.get(ingestionId);\n if (existing && existing.ws.readyState !== WebSocket.CLOSED) {\n return existing;\n }\n let wsUrl = `${wsBaseUrl.trim()}/${ingestionId}`;\n if(authToken){\n wsUrl+=`?token=${authToken}`;\n }\n\n const ws = new WebSocket(wsUrl);\n const conn: SharedConnection = {\n ws,\n listeners: new Set(),\n lastData: null,\n keepAliveInterval: setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: \"ping\" }));\n }\n }, 5000),\n };\n\n ws.onmessage = (event) => {\n let rawData: unknown;\n try {\n rawData = JSON.parse(event.data);\n } catch {\n conn.listeners.forEach((listener) => listener(null, \"Failed to parse WebSocket message\"));\n return;\n }\n\n if (!isValidIngestionPayload(rawData)) {\n conn.listeners.forEach((listener) => listener(null, \"Received malformed WebSocket payload\"));\n return;\n }\n\n // Bind to a const so the narrowed type survives inside the closures below —\n // `let` bindings get widened back to their declared type inside closures\n // since TS can't prove they won't be reassigned before the closure runs.\n const payload: WebSocketIngestionData = rawData;\n\n conn.lastData = payload;\n conn.listeners.forEach((listener) => listener(payload, null));\n\n if (TERMINAL_STATUSES.has(payload.ingestionStatus.toUpperCase())) {\n clearInterval(conn.keepAliveInterval);\n ws.close();\n sharedConnections.delete(ingestionId);\n }\n};\n\n ws.onerror = () => {\n conn.listeners.forEach((listener) => listener(null, \"WebSocket connection error\"));\n };\n\n ws.onclose = () => {\n clearInterval(conn.keepAliveInterval);\n // Only remove from the registry if this is still the active connection\n // for this id (avoids racing a newer reconnect attempt).\n if (sharedConnections.get(ingestionId) === conn) {\n sharedConnections.delete(ingestionId);\n }\n };\n\n sharedConnections.set(ingestionId, conn);\n return conn;\n}\n\nexport function useIngestionWebSocket(ingestionId: string | null, wsBaseUrl?: string, authToken?: string) {\n const [data, setData] = useState<WebSocketIngestionData | null>(null);\n const [connected, setConnected] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Track the current connection + listener so the imperative disconnect()\n // below can unsubscribe/close outside of the effect's own cleanup.\n const connRef = useRef<SharedConnection | null>(null);\n const listenerRef = useRef<Listener | null>(null);\n const ingestionIdRef = useRef<string | null>(ingestionId);\n\n useEffect(() => {\n ingestionIdRef.current = ingestionId;\n }, [ingestionId]);\n\n const disconnect = useCallback(() => {\n const currentId = ingestionIdRef.current;\n if (currentId && connRef.current && listenerRef.current) {\n releaseListener(currentId, connRef.current, listenerRef.current);\n }\n connRef.current = null;\n listenerRef.current = null;\n setConnected(false);\n }, []);\n\n useEffect(() => {\n if (!ingestionId) return;\n\n setError(null);\n\n const conn = getOrCreateConnection(ingestionId, wsBaseUrl, authToken);\n if (!conn) {\n setError(\"Missing or invalid WebSocket base URL\");\n setConnected(false);\n return;\n }\n\n // Seed with whatever the shared connection already has, so a late\n // subscriber isn't stuck blank until the next message arrives.\n if (conn.lastData) setData(conn.lastData);\n setConnected(conn.ws.readyState === WebSocket.OPEN);\n\n const listener: Listener = (newData, newError) => {\n if (newError) {\n setError(newError);\n return;\n }\n setData(newData);\n };\n\n conn.listeners.add(listener);\n connRef.current = conn;\n listenerRef.current = listener;\n\n const handleOpen = () => setConnected(true);\n const handleClose = () => setConnected(false);\n conn.ws.addEventListener(\"open\", handleOpen);\n conn.ws.addEventListener(\"close\", handleClose);\n\n return () => {\n conn.ws.removeEventListener(\"open\", handleOpen);\n conn.ws.removeEventListener(\"close\", handleClose);\n releaseListener(ingestionId, conn, listener);\n connRef.current = null;\n listenerRef.current = null;\n };\n }, [ingestionId, wsBaseUrl]);\n\n return { data, connected, error, disconnect };\n}"],"names":["TERMINAL_STATUSES","Set","sharedConnections","Map","releaseListener","ingestionId","conn","listener","listeners","delete","size","get","clearInterval","keepAliveInterval","ws","readyState","WebSocket","OPEN","CONNECTING","close","useIngestionWebSocket","wsBaseUrl","authToken","data","setData","useState","connected","setConnected","error","setError","connRef","useRef","listenerRef","ingestionIdRef","useEffect","current","disconnect","useCallback","currentId","trim","console","existing","CLOSED","wsUrl","lastData","setInterval","send","JSON","stringify","type","onmessage","event","rawData","parse","forEach","value","candidate","ingestionStatus","isValidIngestionPayload","payload","has","toUpperCase","onerror","onclose","set","getOrCreateConnection","newData","newError","add","handleOpen","handleClose","addEventListener","removeEventListener"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e}from"react/jsx-runtime";import{Worker as r,Viewer as n}from"@react-pdf-viewer/core";import{pdfStyles as
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import{Worker as r,Viewer as n}from"@react-pdf-viewer/core";import{pdfStyles as o}from"./PdfStyle.js";import{useEffect as t}from"react";const d="https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js",a=({error:r,onError:n})=>(t(()=>{n?.(r)},[r,n]),e("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100%",color:"#ef4444"},children:e("span",{children:"Error loading PDF document. The link may have expired."})})),i=({pdfUrl:t,plugins:i,onLoad:l,customStyles:s,onPageChange:c,defaultScale:f,renderPage:p,setRenderRange:m,onError:g})=>e("div",{style:{...o.pdfConatiner,...s?.pdfContainer},children:e(r,{workerUrl:d,children:e(n,{fileUrl:t,defaultScale:f,plugins:i,onDocumentLoad:l,onPageChange:c,renderPage:p,setRenderRange:m,renderError:r=>e(a,{error:r,onError:g})})})});export{i as default,d as pdfWorker};
|
|
2
2
|
//# sourceMappingURL=PdfContainer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PdfContainer.js","sources":["../../../src/features/PdfViewer/PdfContainer.tsx"],"sourcesContent":["import { Worker, Viewer, SpecialZoomLevel, PageChangeEvent, DocumentLoadEvent, RenderPage, SetRenderRange } from \"@react-pdf-viewer/core\";\nimport { pdfStyles } from \"./PdfStyle\";\nimport { CustomStylesType } from \"./PdfViewer\";\nexport const pdfWorker: string = \"https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js\";\n\ntype Props = {\n pdfUrl: string;\n plugins: any[];\n onLoad: (e: DocumentLoadEvent) => void;\n customStyles?: CustomStylesType;\n onPageChange : (e : PageChangeEvent) => void;\n defaultScale?: SpecialZoomLevel | number | undefined;\n renderPage?: RenderPage;\n setRenderRange?: SetRenderRange;\n};\n\nconst PdfContainer = ({ pdfUrl, plugins, onLoad, customStyles,onPageChange, defaultScale, renderPage, setRenderRange }: Props) => {\n return (\n <div style={{ ...pdfStyles.pdfConatiner, ...customStyles?.pdfContainer }}>\n <Worker workerUrl={pdfWorker}>\n <Viewer\n fileUrl={pdfUrl}\n defaultScale={defaultScale}\n plugins={plugins}\n onDocumentLoad={onLoad}\n onPageChange={onPageChange}\n renderPage={renderPage}\n setRenderRange={setRenderRange}\n />\n </Worker>\n </div>\n );\n};\n\nexport default PdfContainer;\n"],"names":["pdfWorker","PdfContainer","pdfUrl","plugins","onLoad","customStyles","onPageChange","defaultScale","renderPage","setRenderRange","
|
|
1
|
+
{"version":3,"file":"PdfContainer.js","sources":["../../../src/features/PdfViewer/PdfContainer.tsx"],"sourcesContent":["import { Worker, Viewer, SpecialZoomLevel, PageChangeEvent, DocumentLoadEvent, RenderPage, SetRenderRange, type LoadError } from \"@react-pdf-viewer/core\";\nimport { pdfStyles } from \"./PdfStyle\";\nimport { CustomStylesType } from \"./PdfViewer\";\nimport { useEffect } from \"react\";\nexport const pdfWorker: string = \"https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js\";\n\ntype Props = {\n pdfUrl: string;\n plugins: any[];\n onLoad: (e: DocumentLoadEvent) => void;\n customStyles?: CustomStylesType;\n onPageChange : (e : PageChangeEvent) => void;\n defaultScale?: SpecialZoomLevel | number | undefined;\n renderPage?: RenderPage;\n setRenderRange?: SetRenderRange;\n onError?: (error: LoadError) => void;\n};\n\nconst PdfErrorHandler = ({ error, onError }: { error: LoadError; onError?: (error: LoadError) => void }) => {\n useEffect(() => {\n onError?.(error);\n }, [error, onError]);\n\n\n return (\n <div style={{ display: \"flex\", justifyContent: \"center\", alignItems: 'center', height: \"100%\", color: \"#ef4444\"}}>\n <span>Error loading PDF document. The link may have expired.</span>\n </div>\n );\n};\n\nconst PdfContainer = ({ pdfUrl, plugins, onLoad, customStyles,onPageChange, defaultScale, renderPage, setRenderRange, onError }: Props) => {\n return (\n <div style={{ ...pdfStyles.pdfConatiner, ...customStyles?.pdfContainer }}>\n <Worker workerUrl={pdfWorker}>\n <Viewer\n fileUrl={pdfUrl}\n defaultScale={defaultScale}\n plugins={plugins}\n onDocumentLoad={onLoad}\n onPageChange={onPageChange}\n renderPage={renderPage}\n setRenderRange={setRenderRange}\n renderError={(error)=> <PdfErrorHandler error={error} onError={onError} />}\n />\n </Worker>\n </div>\n );\n};\n\nexport default PdfContainer;\n"],"names":["pdfWorker","PdfErrorHandler","error","onError","useEffect","style","display","justifyContent","alignItems","height","color","children","jsx","PdfContainer","pdfUrl","plugins","onLoad","customStyles","onPageChange","defaultScale","renderPage","setRenderRange","pdfStyles","pdfConatiner","pdfContainer","Worker","workerUrl","Viewer","fileUrl","onDocumentLoad","renderError"],"mappings":"gLAIO,MAAMA,EAAoB,gEAc3BC,EAAkB,EAAGC,QAAOC,cAChCC,EAAU,KACRD,IAAUD,IACT,CAACA,EAAOC,MAIR,MAAI,CAAAE,MAAO,CAAEC,QAAS,OAAQC,eAAgB,SAAUC,WAAY,SAAUC,OAAQ,OAAQC,MAAO,WACpGC,SAACC,EAAA,OAAA,CAAKD,uEAKNE,EAAe,EAAGC,SAAQC,UAASC,SAAQC,eAAaC,eAAcC,eAAcC,aAAYC,iBAAgBlB,aAEjHS,EAAA,MAAA,CAAIP,MAAO,IAAKiB,EAAUC,gBAAiBN,GAAcO,cACxDb,SAACC,EAAAa,EAAA,CAAOC,UAAW1B,EACjBW,SAAAC,EAACe,EAAA,CACCC,QAASd,EACTK,eACAJ,UACAc,eAAgBb,EAChBE,eACAE,aACAC,iBACAS,YAAc5B,GAAUU,EAAAX,EAAA,CAAgBC,QAAcC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t,Fragment as
|
|
1
|
+
import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import{SpecialZoomLevel as r}from"@react-pdf-viewer/core";import o from"./PdfContainer.js";import i from"./PdfToolbar.js";import{pdfStyles as a}from"./PdfStyle.js";import{PdfHighlightControls as s}from"./usePdfHighlight.js";import{rotationManager as c}from"./rotationManager.js";import"@react-pdf-viewer/zoom/lib/styles/index.css";import"@react-pdf-viewer/page-navigation/lib/styles/index.css";import"@react-pdf-viewer/core/lib/styles/index.css";import"@react-pdf-viewer/search/lib/styles/index.css";import l,{useRef as u,useState as d,useMemo as g,useEffect as h}from"react";import p from"../ScannedDocCitation/ScannedDocCitation.js";import"./PdfViewer.css.js";const f=({pdfUrl:f,highlightText:m,highlightPages:v,highlightCordinatePages:w,highlightColor:x="yellow",activeHighlightColor:y="#f7dc51",jumpToPageValue:P,pdfName:b,onClose:T,customStyles:C,customClasses:I,customIcons:S,useCoordinates:A,fallbackPages:R,activeCitationIndex:_,onActiveCitationChange:F,headerAction:N,isZoomEnabled:j=!0,showHighlightsAction:q=!0,defaultScale:L=r.ActualSize,useRange:H=!1,rangeOfPages:B=null,showFullScreenAction:E=!0,showRotateButton:M=!1,segments:V=[{title:"Document 2",start_page:52,end_page:52,page_count:1}],segmentTooltipText:k,onCurrentPageChange:z,navigationRequest:D,onNavigationSettled:W,disablePdfAnnotations:O=!1,disablePdfTextLayer:U=!1,renderPage:$,setRenderRange:Z,onError:J})=>{const K=u(null),G=(e=>{switch(e){case"ActualSize":return r.ActualSize;case"PageFit":return r.PageFit;case"PageWidth":return r.PageWidth;default:return e??r.PageWidth}})(L),Q=P??(A&&w.length>0?1:0),[X,Y]=d(0),[ee,te]=d(0),[ne,re]=d(null),[oe,ie]=d(0),ae=u(null),se=u(null),ce=u(0),le=u(null),ue=u(null),de=g(()=>{if(!f)return"";try{return new URL(f,window.location.origin).pathname.split("/").pop()||"default"}catch{return"default"}},[f]);h(()=>{de&&c.setPdfIdentifier(de)},[de]);h(()=>c.onRotationChange((e,t)=>{e===X+1&&ie(t)}),[X]),h(()=>{const e=new MutationObserver(()=>{const e=K.current?.querySelectorAll('[data-testid^="core__page-layer-"]'),t=new Set;e?.forEach(e=>{const n=e.getAttribute("data-testid")?.match(/core__page-layer-(\d+)/);if(n&&n.length>=2){const r=parseInt(n[1],10)+1;t.has(r)||(c.registerPageElement(r,e),t.add(r))}})});return K.current&&(e.observe(K.current,{childList:!0,subtree:!0,attributes:!1}),le.current=e),()=>{e.disconnect(),le.current=null}},[]),h(()=>()=>{c.clearAll(),le.current&&le.current.disconnect()},[]),h(()=>{const e=X+1;ie(c.getRotation(e))},[X]);const ge=g(()=>O||U?r=>{const o=U?e("div",{"aria-hidden":"true",style:{display:"none"},children:r.textLayer.children}):r.textLayer.children,i={...r,annotationLayer:{...r.annotationLayer,children:O?null:r.annotationLayer.children},textLayer:{...r.textLayer,children:o}};return $?$(i):t(n,{children:[r.canvasLayer.children,o,!O&&r.annotationLayer.children]})}:$,[O,U,$]),he=g(()=>{if(A)return new Set(w.map(e=>e.pageIndex));{const e=new Set;return Object.values(v).forEach(t=>{t>0&&e.add(t-1)}),e}},[w,v,A]),pe=(fe=m)&&0!==fe.length?fe.filter(e=>!fe.some(t=>t!==e&&t.includes(e))):fe;var fe;const{highlightIndex:me,setHighlightIndex:ve,cursorIndex:we,setCursorIndex:xe,orderedKeys:ye,totalHighlights:Pe,getValidPosition:be,tryJump:Te,jumpToPage:Ce,zoomTo:Ie,plugins:Se,controls:Ae,hideNonTargetHighlights:Re,deduplicateHighlights:_e,scrollToCoordAfterNav:Fe}=s(pe,A?{}:v,K,he,A,A?w:[],x,y);h(()=>{if(!A||H||ee<=0||ne!==(f??null))return;const e=Q-1,t=w[e];if(!t||t.pageIndex<0||t.pageIndex>=ee)return;const n=[f,e,t.pageIndex,t.top,t.height].join(":");ue.current!==n&&(ue.current=n,xe(e),Ce(t.pageIndex),Fe(t.pageIndex,t.top,t.height))},[w,Ce,ne,f,Q,Fe,xe,ee,A,H]);const Ne=be(we),je=g(()=>{const e=X+1;return V.find(t=>e>=t.start_page&&e<=t.end_page)},[X,V]);h(()=>{void 0!==_&&_!==we&&xe(_)},[_]);const qe={...Ae,goToNext:()=>{if(we>=Pe-1)return;const e=we+1;if(A){const t=w[e];if(!t)return;xe(e),Ce(t.pageIndex),Fe(t.pageIndex,Number.isFinite(t.top)?t.top:0,Number.isFinite(t.height)?t.height:0)}else Ae.goToNext();F?.(e)},goToPrevious:()=>{if(we<=0)return;const e=we-1;if(A){const t=w[e];if(!t)return;xe(e),Ce(t.pageIndex),Fe(t.pageIndex,Number.isFinite(t.top)?t.top:0,Number.isFinite(t.height)?t.height:0)}else Ae.goToPrevious();F?.(e)}},Le=l.useCallback((e,t)=>{ce.current+=1;const n=ce.current;null!=se.current&&window.clearTimeout(se.current);let r=null,o=0,i=0;const a=()=>{if(ce.current!==n)return;i+=1;const s=K.current?.querySelector(".rpv-core__inner-pages"),c=K.current?.querySelector(`[data-testid="core__page-layer-${t-1}"]`);if(!s||!c)return i>=40?(se.current=null,void W?.({pageNumber:t,requestId:e.requestId})):void(se.current=window.setTimeout(a,50));r===s.scrollTop?o+=1:(r=s.scrollTop,o=0);const l=s.getBoundingClientRect(),u=c.getBoundingClientRect(),d=Boolean(l&&u&&u.bottom>l.top&&u.top<l.bottom);if(o>=2&&d||i>=40)return se.current=null,void W?.({pageNumber:t,requestId:e.requestId});se.current=window.setTimeout(a,50)};se.current=window.setTimeout(a,50)},[W]);if(h(()=>()=>{ce.current+=1,null!=se.current&&window.clearTimeout(se.current)},[]),h(()=>{if(!D||ee<=0)return;const e=Math.min(Math.max(Math.trunc(D.pageNumber),1),ee),t=`${D.requestId??e}:${e}`;ae.current!==t&&(ae.current=t,Y(e-1),Ce(e-1),Le(D,e))},[Ce,D,ee,Le]),!f)return e(p,{pages:R,activeCitationIndex:_,onActiveCitationChange:F,headerAction:N});return t("div",{ref:K,className:["citation-pdf-viewer",I?.pdfViewerWrapper].filter(Boolean).join(" "),"data-disable-pdf-annotations":O?"true":void 0,"data-pdf-page-fit":G===r.PageFit?"true":void 0,style:{height:"100%",minHeight:0,minWidth:0,overflow:"hidden",display:"flex",flexDirection:"column",...a.pdfViewer,display:"flex",flexDirection:"column",height:"100%",width:"100%",backgroundColor:"#FAFAFA",...C?.pdfViewer,backgroundColor:"#F1F5F9"},children:[e(i,{highlightIndex:me,totalHighlights:Pe,controls:qe,currentPosition:Ne,pdfName:b,onClose:T,pdfUrl:f,viewerRef:K,customStyles:C,customClasses:I,customIcons:S,headerAction:N,isZoomEnabled:j,showHighlightsAction:q,showFullScreenAction:E,currentSegment:je,segmentTooltipText:k,currentPage:X+1,totalPages:ee,onPageNavigate:e=>{const t=Math.min(Math.max(e,1),ee||e);Y(t-1),Ce(t-1)},onRotatePage:()=>{const e=X+1;c.rotatePageBy90(e),ie(c.getRotation(e))},currentPageRotation:oe,showRotateButton:M}),e(o,{defaultScale:G,pdfUrl:f,plugins:Se,customStyles:C,onError:J,onLoad:e=>{te(e.doc.numPages),re(f??null);const t=!A&&!H&&Q<=0;if(!A&&Q>0&&!H){const e=Q-1,t=ye[e],n=void 0!==t?v?.[t]:void 0;xe(e),n>0&&(setTimeout(()=>{Re(he),_e(n-1)},1e3),Ce(n-1))}else if(H&&B&&2===B.length){(async()=>{const[e,t]=B;for(let n=e;n<=t;n++){const e=n-1;Ce(e),await new Promise(e=>setTimeout(e,1e3)),Re(he);const t=_e(e);if(t&&t>0)break}})()}else if(!A&&v){const e=ye.find(e=>v[e]>0);if(void 0!==e){const t=v[e]-1;Ce(t),setTimeout(()=>{Re(he),_e(t)},1e3)}}requestAnimationFrame(()=>{t&&Te(),!A&&Q>0&&!H&&(()=>{if(!K.current)return;const e=Q-1,t=ye[e],n=v[t],r=n>0?n-1:0,o={};ye.forEach((e,t)=>{const n=v[e];n>0&&(o[n]||(o[n]=[]),o[n].push(t))});const i=(o[n]||[]).indexOf(e);let a=0;const s=()=>{if(a++,a>40)return;const e=K.current?.querySelector(".rpv-core__inner-pages");if(!e)return void setTimeout(s,100);const t=K.current?.querySelector(`[data-testid="core__page-layer-${r}"]`);if(!t)return void setTimeout(s,100);const n=e.getBoundingClientRect(),o=t.getBoundingClientRect();if(!(o.top<n.bottom&&o.bottom>n.top))return void setTimeout(s,100);const c=t.querySelectorAll(".rpv-search__highlight")[i];if(!c)return void setTimeout(s,100);const l=c.getBoundingClientRect(),u=e.scrollTop+(l.top-n.top)-e.clientHeight/2+l.height/2;e.scrollTo({top:u,behavior:"smooth"})};setTimeout(s,500)})()})},onPageChange:e=>{const t=e.currentPage;Y(t),z?.(t+1),he.has(t)?(_e(t),Re(he)):Re(he)},renderPage:ge,setRenderRange:Z})]})};export{f as default};
|
|
2
2
|
//# sourceMappingURL=PdfViewer.js.map
|