aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorA.J. Shulman <Shulman.aj@gmail.com>2024-09-07 11:10:33 -0400
committerA.J. Shulman <Shulman.aj@gmail.com>2024-09-07 11:10:33 -0400
commit6c7e67810419ddc0e59f548509b4066fbd2ca90f (patch)
treee3c175dd4722748e29298fd47d74578749fadf63 /src
parentc1053475810a1b1b3a9963c3f1ef0b1a9509d222 (diff)
Fixed web document rendering by changing cors
Diffstat (limited to 'src')
-rw-r--r--src/client/util/Scripting.ts8
-rw-r--r--src/client/views/nodes/ChatBox/ChatBox.scss8
-rw-r--r--src/client/views/nodes/ChatBox/ChatBox.tsx59
-rw-r--r--src/client/views/nodes/ChatBox/prompts.ts1
-rw-r--r--src/client/views/nodes/ChatBox/tools/RAGTool.ts22
-rw-r--r--src/client/views/nodes/ChatBox/types.ts2
-rw-r--r--src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts7
-rw-r--r--src/client/views/nodes/PDFBox.tsx16
-rw-r--r--src/client/views/pdf/PDFViewer.tsx20
-rw-r--r--src/server/ApiManagers/AssistantManager.ts21
10 files changed, 118 insertions, 46 deletions
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index c63d3d7cb..3e7a2df02 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -1,7 +1,7 @@
// export const ts = (window as any).ts;
// import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts'
// import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
-import typescriptlib from 'type_decls.d';
+// import typescriptlib from 'type_decls.d';
import * as ts from 'typescript';
import { Doc, FieldType } from '../../fields/Doc';
import { RefField } from '../../fields/RefField';
@@ -29,7 +29,7 @@ export interface CompiledScript {
readonly compiled: true;
readonly originalScript: string;
// eslint-disable-next-line no-use-before-define
- readonly options: Readonly<ScriptOptions>;
+ readonly options: Readonly;
run(args?: { [name: string]: unknown }, onError?: (res: string) => void, errorVal?: unknown): ScriptResult;
}
@@ -154,7 +154,7 @@ class ScriptingCompilerHost {
export type Traverser = (node: ts.Node, indentation: string) => boolean | void;
export type TraverserParam = Traverser | { onEnter: Traverser; onLeave: Traverser };
export type Transformer = {
- transformer: ts.TransformerFactory<ts.Node>;
+ transformer: ts.TransformerFactory;
getVars?: () => { [name: string]: FieldType };
};
export interface ScriptOptions {
@@ -248,7 +248,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
const funcScript = `(function(${paramString})${reqTypes} { ${body} })`;
host.writeFile('file.ts', funcScript);
- if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
+ // if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
const program = ts.createProgram(['file.ts'], {}, host);
const testResult = program.emit();
const outputText = host.readFile('file.js');
diff --git a/src/client/views/nodes/ChatBox/ChatBox.scss b/src/client/views/nodes/ChatBox/ChatBox.scss
index 76fa05ce8..adb0663c3 100644
--- a/src/client/views/nodes/ChatBox/ChatBox.scss
+++ b/src/client/views/nodes/ChatBox/ChatBox.scss
@@ -7,7 +7,6 @@ $light-text-color: #777;
$border-color: #e1e8ed;
$shadow-color: rgba(0, 0, 0, 0.1);
$transition: all 0.3s ease;
-
.chat-box {
display: flex;
flex-direction: column;
@@ -25,6 +24,7 @@ $transition: all 0.3s ease;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px $shadow-color;
+ position: relative;
.chat-header {
background-color: $primary-color;
@@ -33,6 +33,7 @@ $transition: all 0.3s ease;
text-align: center;
box-shadow: 0 2px 4px $shadow-color;
height: fit-content;
+
h2 {
margin: 0;
font-size: 1.3em;
@@ -46,6 +47,7 @@ $transition: all 0.3s ease;
padding: 20px;
display: flex;
flex-direction: column;
+ gap: 10px; // Added to give space between elements
&::-webkit-scrollbar {
width: 6px;
@@ -108,6 +110,9 @@ $transition: all 0.3s ease;
border-top: 3px solid #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
}
}
@@ -121,6 +126,7 @@ $transition: all 0.3s ease;
font-size: 15px;
line-height: 1.5;
box-shadow: 0 2px 4px $shadow-color;
+ word-wrap: break-word; // To handle long words
&.user {
align-self: flex-end;
diff --git a/src/client/views/nodes/ChatBox/ChatBox.tsx b/src/client/views/nodes/ChatBox/ChatBox.tsx
index 383be0bb7..32ccbc35e 100644
--- a/src/client/views/nodes/ChatBox/ChatBox.tsx
+++ b/src/client/views/nodes/ChatBox/ChatBox.tsx
@@ -24,6 +24,8 @@ import { DocUtils } from '../../../documents/DocUtils';
import { createRef } from 'react';
import { ClientUtils } from '../../../../ClientUtils';
import { ProgressBar } from './ProgressBar';
+import { DocumentView } from '../DocumentView';
+import { Networking } from '../../../Network';
dotenv.config();
@@ -37,7 +39,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable currentStep: string = ''; // Track current step name
@observable expandedScratchpadIndex: number | null = null;
@observable inputValue: string = '';
- @observable private linked_docs_to_add: ObservableSet<Doc> = observable.set();
+ @observable private linked_docs_to_add: ObservableSet = observable.set();
@observable private linked_csv_files: { filename: string; id: string; text: string }[] = [];
@observable private isUploadingDocs: boolean = false;
private openai: OpenAI;
@@ -45,7 +47,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
private vectorstore: Vectorstore;
private agent: Agent; // Add the ChatBot instance
private _oldWheel: HTMLDivElement | null = null;
- private messagesRef: React.RefObject<HTMLDivElement>;
+ private messagesRef: React.RefObject;
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(ChatBox, fieldKey);
@@ -184,7 +186,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
@action
- askGPT = async (event: React.FormEvent<HTMLFormElement>): Promise<void> => {
+ askGPT = async (event: React.FormEvent): Promise => {
event.preventDefault();
this.inputValue = '';
@@ -244,14 +246,43 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action
addLinkedUrlDoc = async (url: string, id: string) => {
- const doc = Docs.Create.WebDocument(url);
+ const doc = Docs.Create.WebDocument(url, { data_useCors: true });
+
+ // const scriptsKey = Doc.LayoutFieldKey(doc) + '_allowScripts';
+ // doc[DocData][scriptsKey] = true;
+
+ console.log('Adding URL:', url);
+
+ //console.log('Layout Field Key:', doc[DocData][scriptsKey]);
const linkDoc = Docs.Create.LinkDocument(this.Document, doc);
LinkManager.Instance.addLink(linkDoc);
+ let canDisplay;
+
+ try {
+ // Fetch the URL content through the proxy
+ const { data } = await Networking.PostToServer('/proxyFetch', { url });
+
+ // Simulating header behavior as you can't fetch headers via the proxy
+ const xFrameOptions = data.headers?.['x-frame-options'];
+
+ if (xFrameOptions && xFrameOptions.toUpperCase() === 'SAMEORIGIN') {
+ console.log('URL cannot be displayed in an iframe:', url);
+ canDisplay = false;
+ } else {
+ console.log('URL can be displayed in an iframe:', url);
+ console.log(StrCast(linkDoc.canDisplay));
+ canDisplay = true;
+ }
+ } catch (error) {
+ console.error('Error fetching the URL from the server:', error);
+ }
const chunkToAdd = {
chunkId: id,
chunkType: CHUNK_TYPE.URL,
+ url: url,
+ canDisplay: canDisplay,
};
doc.chunk_simpl = JSON.stringify({ chunks: [chunkToAdd] });
@@ -315,18 +346,26 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
break;
case CHUNK_TYPE.TEXT:
DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {
- const firstView = Array.from(doc[DocViews])[0];
- firstView.ComponentView?.search?.(citation.direct_text);
+ const firstView = Array.from(doc[DocViews])[0] as DocumentView;
+ firstView.ComponentView?.search?.(citation.direct_text ?? '');
});
break;
case CHUNK_TYPE.URL:
- DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {
- const firstView = Array.from(doc[DocViews])[0];
- });
+ console.log('Opening URL:', foundChunk.url);
+ console.log('Can display:', foundChunk.canDisplay);
+ if (!foundChunk.canDisplay) {
+ console.log('Opening URL in new tab:', doc.displayUrl);
+ window.open(StrCast(doc.displayUrl), '_blank');
+ } else if (foundChunk.canDisplay) {
+ console.log('Opening URL in Dash:', doc.displayUrl);
+ DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {
+ const firstView = Array.from(doc[DocViews])[0] as DocumentView;
+ });
+ }
break;
case CHUNK_TYPE.CSV:
DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {
- const firstView = Array.from(doc[DocViews])[0];
+ const firstView = Array.from(doc[DocViews])[0] as DocumentView;
});
break;
default:
diff --git a/src/client/views/nodes/ChatBox/prompts.ts b/src/client/views/nodes/ChatBox/prompts.ts
index 9ea86dbf4..0a356189b 100644
--- a/src/client/views/nodes/ChatBox/prompts.ts
+++ b/src/client/views/nodes/ChatBox/prompts.ts
@@ -30,6 +30,7 @@ export function getReactPrompt(tools: Tool[], summaries: () => string, chatHisto
<point>Ensure at the end of every final answer, you provide exactly three follow-up questions from the user's perspective—from the perspective that they are asking the question.</point>
<point>Always follow the response structure provided in the instructions.</point>
<point>If a tool doesn't work—or yield helpful results—after two tries, EITHER use another tool or proceed with the response and ask the user for more information or clarification or let them know you cannot answer their question and why. DO NOT CONTINUE WITH THE SAME TOOL 3 TIMES.</point>
+ <point>Use multiple tools in conjunction with each other to provide a comprehensive answer to the user's query, if needed (i.e. for the prompt "create a CSV showing historical bird migration trends", you could use the search tool and the webscraper tool to get the info, and then use the create CSV tool to create the CSV)</point>
</critical_points>
<response_structure>
diff --git a/src/client/views/nodes/ChatBox/tools/RAGTool.ts b/src/client/views/nodes/ChatBox/tools/RAGTool.ts
index fe8deae6b..544b9daba 100644
--- a/src/client/views/nodes/ChatBox/tools/RAGTool.ts
+++ b/src/client/views/nodes/ChatBox/tools/RAGTool.ts
@@ -6,7 +6,7 @@ import { Networking } from '../../../../Network';
import { file } from 'jszip';
import { ChatCompletion, ChatCompletionContentPart, ChatCompletionMessageParam } from 'openai/resources';
-export class RAGTool extends BaseTool<{ hypothetical_document_chunk: string }> {
+export class RAGTool extends BaseTool {
constructor(private vectorstore: Vectorstore) {
super(
'rag',
@@ -55,13 +55,15 @@ export class RAGTool extends BaseTool<{ hypothetical_document_chunk: string }> {
5. Detailed Citation Guidelines:
a. Create a unique citation for each distinct piece of information from the chunks that is used to support grounded_text.
- b. ALL TEXT CITATIONS must have direct text in its element content (e.g. <citation ...>DIRECT TEXT HERE</citation>) that is a relevant subset of the original text chunk that is being cited specifically.
- b. Ensure each citation has a unique index number.
- c. Specify the correct type: "text", "image", or "table".
- d. For text chunks, the content of the citation should ALWAYS have the relevant subset of the original text that the grounded_text is based on.
- e. For image/table chunks, leave the citation content empty.
- f. One citation can be used for multiple grounded_text tags if they are based on the same chunk information.
- g. !!!DO NOT OVERCITE - only include citations for information that is directly relevant to the grounded_text.
+ b. ALL TEXT CITATIONS must have direct text in its element content (e.g. <citation ...>DIRECT TEXT HERE</citation>) that is a relevant SUBSET of the original text chunk that is being cited specifically.
+ c. DO NOT paraphrase or summarize the text; use the original text as much as possible.
+ d. DO NOT USE THE FULL TEXT CHUNK as the citation content; only use the relevant subset of the text that the grounded_text is base. AS SHORT AS POSSIBLE WHILE PROVIDING INFORMATION (ONE TO TWO SENTENCES USUALLY)!
+ e. Ensure each citation has a unique index number.
+ f. Specify the correct type: "text", "image", or "table".
+ g. For text chunks, the content of the citation should ALWAYS have the relevant subset of the original text that the grounded_text is based on.
+ h. For image/table chunks, leave the citation content empty.
+ i. One citation can be used for multiple grounded_text tags if they are based on the same chunk information.
+ j. !!!DO NOT OVERCITE - only include citations for information that is directly relevant to the grounded_text.
6. Structural Integrity Checks:
a. Ensure all opening tags have corresponding closing tags.
@@ -113,13 +115,13 @@ export class RAGTool extends BaseTool<{ hypothetical_document_chunk: string }> {
);
}
- async execute(args: { hypothetical_document_chunk: string }): Promise<any> {
+ async execute(args: { hypothetical_document_chunk: string }): Promise {
const relevantChunks = await this.vectorstore.retrieve(args.hypothetical_document_chunk);
const formatted_chunks = await this.getFormattedChunks(relevantChunks);
return formatted_chunks;
}
- async getFormattedChunks(relevantChunks: RAGChunk[]): Promise<ChatCompletionContentPart[]> {
+ async getFormattedChunks(relevantChunks: RAGChunk[]): Promise {
try {
const { formattedChunks } = await Networking.PostToServer('/formatChunks', { relevantChunks });
diff --git a/src/client/views/nodes/ChatBox/types.ts b/src/client/views/nodes/ChatBox/types.ts
index a59ead067..a12c52592 100644
--- a/src/client/views/nodes/ChatBox/types.ts
+++ b/src/client/views/nodes/ChatBox/types.ts
@@ -106,6 +106,8 @@ export interface SimplifiedChunk {
endPage: number;
location?: string;
chunkType: CHUNK_TYPE;
+ url?: string;
+ canDisplay?: boolean;
}
export interface AI_Document {
diff --git a/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts b/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts
index 408274703..b5145c1f7 100644
--- a/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts
+++ b/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts
@@ -135,6 +135,7 @@ export class Vectorstore {
endPage: chunk.metadata.end_page,
location: chunk.metadata.location,
chunkType: chunk.metadata.type as CHUNK_TYPE,
+ text: chunk.metadata.text,
};
const new_chunk_simpl = JSON.parse(StrCast(doc.chunk_simpl));
new_chunk_simpl.chunks = new_chunk_simpl.chunks.concat(chunkToAdd);
@@ -148,7 +149,7 @@ export class Vectorstore {
private async indexDocument(document: any) {
console.log('Uploading vectors to content namespace...');
- const pineconeRecords: PineconeRecord<RecordMetadata>[] = (document.chunks as RAGChunk[]).map(
+ const pineconeRecords: PineconeRecord[] = (document.chunks as RAGChunk[]).map(
chunk =>
({
id: chunk.id,
@@ -159,7 +160,7 @@ export class Vectorstore {
await this.index.upsert(pineconeRecords);
}
- async retrieve(query: string, topK: number = 10): Promise<RAGChunk[]> {
+ async retrieve(query: string, topK: number = 10): Promise {
console.log(`Retrieving chunks for query: ${query}`);
try {
const queryEmbeddingResponse: EmbedResponse = await this.cohere.embed({
@@ -182,7 +183,7 @@ export class Vectorstore {
throw new Error('Query embedding is not an array');
}
- const queryResponse: QueryResponse<RecordMetadata> = await this.index.query({
+ const queryResponse: QueryResponse = await this.index.query({
vector: queryEmbedding,
filter: {
doc_id: { $in: this._doc_ids },
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index cb0b0d71f..4616ec057 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -43,14 +43,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
public static openSidebarWidth = 250;
public static sidebarResizerWidth = 5;
private _searchString: string = '';
- private _initialScrollTarget: Opt<Doc>;
+ private _initialScrollTarget: Opt;
private _pdfViewer: PDFViewer | undefined;
private _searchRef = React.createRef<HTMLInputElement>();
private _disposers: { [name: string]: IReactionDisposer } = {};
private _sidebarRef = React.createRef<SidebarAnnos>();
@observable private _searching: boolean = false;
- @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy> = undefined;
+ @observable private _pdf: Opt = undefined;
@observable private _pageControls = false;
@computed get pdfUrl() {
@@ -242,13 +242,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
options.didMove = true;
this.toggleSidebar(false);
}
- return new Promise<Opt<DocumentView>>(res => {
+ return new Promise<Opt>(res => {
DocumentView.addViewRenderedCb(doc, dv => res(dv));
});
};
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
- let ele: Opt<HTMLDivElement>;
+ let ele: Opt;
if (this._pdfViewer?.selectionContent()) {
ele = document.createElement('div');
ele.append(this._pdfViewer.selectionContent()!);
@@ -327,7 +327,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._initialScrollTarget = undefined;
}
};
- searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
+ searchStringChanged = (e: React.ChangeEvent) => {
this._searchString = e.currentTarget.value;
};
@@ -365,8 +365,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
);
};
- @observable _previewNativeWidth: Opt<number> = undefined;
- @observable _previewWidth: Opt<number> = undefined;
+ @observable _previewNativeWidth: Opt = undefined;
+ @observable _previewWidth: Opt = undefined;
toggleSidebar = action((preview: boolean = false) => {
const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']);
const sideratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth;
@@ -637,7 +637,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
static pdfcache = new Map<string, Pdfjs.PDFDocumentProxy>();
- static pdfpromise = new Map<string, Promise<Pdfjs.PDFDocumentProxy>>();
+ static pdfpromise = new Map<string, Promise>();
render() {
TraceMobx();
const pdfView = !this._pdf ? null : this.renderPdfView;
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index b9d5ce857..7543b3fb1 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -51,7 +51,7 @@ interface IViewerProps extends FieldViewProps {
* Handles rendering and virtualization of the pdf
*/
@observer
-export class PDFViewer extends ObservableReactComponent<IViewerProps> {
+export class PDFViewer extends ObservableReactComponent {
static _annotationStyle = addStyleSheet();
constructor(props: IViewerProps) {
@@ -68,12 +68,12 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
private _pdfViewer!: PDFJSViewer.PDFViewer;
private _styleRule: number | undefined; // stylesheet rule for making hyperlinks clickable
private _retries = 0; // number of times tried to create the PDF viewer
- private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void);
+ private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt) => void);
private _marqueeref = React.createRef<MarqueeAnnotator>();
- private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
+ private _annotationLayer: React.RefObject = React.createRef();
private _disposers: { [name: string]: IReactionDisposer } = {};
- private _viewer: React.RefObject<HTMLDivElement> = React.createRef();
- _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
+ private _viewer: React.RefObject = React.createRef();
+ _mainCont: React.RefObject = React.createRef();
private _selectionText: string = '';
private _selectionContent: DocumentFragment | undefined;
private _downX: number = 0;
@@ -81,9 +81,9 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
private _lastSearch = false;
private _viewerIsSetup = false;
private _ignoreScroll = false;
- private _initialScroll: { loc: Opt<number>; easeFunc: 'linear' | 'ease' | undefined } | undefined;
+ private _initialScroll: { loc: Opt; easeFunc: 'linear' | 'ease' | undefined } | undefined;
private _forcedScroll = true;
- _getAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = () => undefined;
+ _getAnchor: (savedAnnotations: Opt, addAsAnnotation: boolean) => Opt = () => undefined;
selectionText = () => this._selectionText;
selectionContent = () => this._selectionContent;
@@ -179,7 +179,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
// otherwise it will scroll smoothly.
scrollFocus = (doc: Doc, scrollTop: number, options: FocusViewOptions) => {
const mainCont = this._mainCont.current;
- let focusSpeed: Opt<number>;
+ let focusSpeed: Opt;
if (doc !== this._props.Document && mainCont) {
const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
const scrollTo = ClientUtils.scrollIntoView(scrollTop, doc[Height](), NumCast(this._props.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, this._scrollHeight);
@@ -495,7 +495,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
// e.stopPropagation(); // bcz: not sure why this was here. We need to allow the DocumentView to get clicks to process doubleClicks
};
- setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => {
+ setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt) => void) => {
this._setPreviewCursor = func;
};
@@ -534,7 +534,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
transparentFilter = () => [...this._props.childFilters(), ClientUtils.TransparentBackgroundFilter];
opaqueFilter = () => [...this._props.childFilters(), ClientUtils.noDragDocsFilter, ...(SnappingManager.CanEmbed && this._props.isContentActive() ? [] : [ClientUtils.OpaqueBackgroundFilter])];
- childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => {
+ childStyleProvider = (doc: Doc | undefined, props: Opt, property: string) => {
if (doc instanceof Doc && property === StyleProp.PointerEvents) {
if (this.inlineTextAnnotations.includes(doc) || this._props.isContentActive() === false) return 'none';
const isInk = doc.layout_isSvg && !props?.LayoutTemplateString;
diff --git a/src/server/ApiManagers/AssistantManager.ts b/src/server/ApiManagers/AssistantManager.ts
index 2ffc99e58..58d35ce64 100644
--- a/src/server/ApiManagers/AssistantManager.ts
+++ b/src/server/ApiManagers/AssistantManager.ts
@@ -140,6 +140,27 @@ export default class AssistantManager extends ApiManager {
register({
method: Method.POST,
+ subscription: '/proxyFetch',
+ secureHandler: async ({ req, res }) => {
+ const { url } = req.body;
+
+ if (!url) {
+ res.status(400).send({ error: 'No URL provided' });
+ return;
+ }
+
+ try {
+ const data = await fetchWithRetry(url);
+ res.send({ data });
+ } catch (error: any) {
+ console.error('Error fetching the URL:', error);
+ res.status(500).send({ error: 'Failed to fetch the URL', details: error.message });
+ }
+ },
+ });
+
+ register({
+ method: Method.POST,
subscription: '/scrapeWebsite',
secureHandler: async ({ req, res }) => {
const { url } = req.body;