aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/ImageBox.tsx1
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss1
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx53
-rw-r--r--src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts15
-rw-r--r--src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts86
5 files changed, 75 insertions, 81 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 78bacdcac..fb2346bd1 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -49,7 +49,6 @@ import { gptImageLabel } from '../../apis/gpt/GPT';
const DefaultPath = '/assets/unknown-file-icon-hi.png';
export class ImageEditorData {
- // eslint-disable-next-line no-use-before-define
private static _instance: ImageEditorData;
private static get imageData() { return (ImageEditorData._instance ?? new ImageEditorData()).imageData; } // prettier-ignore
@observable imageData: { rootDoc: Doc | undefined; open: boolean; source: string; addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean> } = observable({ rootDoc: undefined, open: false, source: '', addDoc: undefined });
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss
index 4a916e86c..0bacc70c2 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss
@@ -183,7 +183,6 @@ $font-size-xlarge: 18px;
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.05);
position: relative;
align-items: center;
- gap: 12px;
z-index: 5;
transition: padding 0.2s ease;
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 19459b025..636b77b38 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -7,10 +7,12 @@
* with support for follow-up questions and citation management.
*/
+import { Button, Size, Type } from '@dash/components';
import { ObservableSet, action, computed, makeObservable, observable, observe, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import OpenAI, { ClientOptions } from 'openai';
import * as React from 'react';
+import { AiOutlineSend } from 'react-icons/ai';
import { v4 as uuidv4 } from 'uuid';
import { ClientUtils, OmitKeys } from '../../../../../ClientUtils';
import { Doc, DocListCast, Opt } from '../../../../../fields/Doc';
@@ -18,7 +20,9 @@ import { DocData, DocViews } from '../../../../../fields/DocSymbols';
import { Id } from '../../../../../fields/FieldSymbols';
import { RichTextField } from '../../../../../fields/RichTextField';
import { ScriptField } from '../../../../../fields/ScriptField';
-import { CsvCast, DocCast, PDFCast, RTFCast, StrCast, VideoCast, AudioCast } from '../../../../../fields/Types';
+import { AudioCast, CsvCast, DocCast, NumCast, PDFCast, RTFCast, StrCast, VideoCast } from '../../../../../fields/Types';
+import { Upload } from '../../../../../server/SharedMediaTypes';
+import { DocServer } from '../../../../DocServer';
import { DocUtils } from '../../../../documents/DocUtils';
import { CollectionViewType, DocumentType } from '../../../../documents/DocumentTypes';
import { Docs, DocumentOptions } from '../../../../documents/Documents';
@@ -26,23 +30,23 @@ import { DocumentManager } from '../../../../util/DocumentManager';
import { ImageUtils } from '../../../../util/Import & Export/ImageUtils';
import { LinkManager } from '../../../../util/LinkManager';
import { CompileError, CompileScript } from '../../../../util/Scripting';
+import { SnappingManager } from '../../../../util/SnappingManager';
import { DictationButton } from '../../../DictationButton';
import { ViewBoxAnnotatableComponent } from '../../../DocComponent';
import { AudioBox } from '../../AudioBox';
import { DocumentView, DocumentViewInternal } from '../../DocumentView';
import { FieldView, FieldViewProps } from '../../FieldView';
+import { OpenWhere } from '../../OpenWhere';
import { PDFBox } from '../../PDFBox';
import { ScriptingBox } from '../../ScriptingBox';
import { VideoBox } from '../../VideoBox';
import { Agent } from '../agentsystem/Agent';
import { supportedDocTypes } from '../types/tool_types';
import { ASSISTANT_ROLE, AssistantMessage, CHUNK_TYPE, Citation, ProcessingInfo, SimplifiedChunk, TEXT_TYPE } from '../types/types';
+import { AgentDocumentManager } from '../utils/AgentDocumentManager';
import { Vectorstore } from '../vectorstore/Vectorstore';
import './ChatBox.scss';
import MessageComponentBox from './MessageComponent';
-import { OpenWhere } from '../../OpenWhere';
-import { Upload } from '../../../../../server/SharedMediaTypes';
-import { AgentDocumentManager } from '../utils/AgentDocumentManager';
export type parsedDocData = {
doc_type: string;
@@ -555,8 +559,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
})();
if (ndoc) {
- ndoc.x = NumCast((options.x as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc.width)) + 100;
- ndoc.y = NumCast(options.y as number) + (insideCol ? 0 : NumCast(this.layoutDoc.y));
+ ndoc.x = ((options.x as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc.width)) + 100;
+ ndoc.y = ((options.y as number) ?? 0) + (insideCol ? 0 : NumCast(this.layoutDoc.y));
}
return ndoc;
};
@@ -655,8 +659,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
} else {
console.warn(`Chunk not found for chunk ID: ${chunkId}`);
}
- return;
- }
+ return;
+ }
console.log(`Found chunk in document:`, foundChunk);
@@ -665,7 +669,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const directMatchSegmentStart = this.getDirectMatchingSegmentStart(doc, citation.direct_text || '', foundChunk.indexes || []);
if (directMatchSegmentStart) {
await this.goToMediaTimestamp(doc, directMatchSegmentStart, foundChunk.chunkType);
- } else {
+ } else {
console.error('No direct matching segment found for the citation.');
}
} else if (foundChunk.chunkType === CHUNK_TYPE.TABLE || foundChunk.chunkType === CHUNK_TYPE.IMAGE) {
@@ -710,7 +714,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// If specific indexes are provided, filter segments by those indexes
if (indexesOfSegments && indexesOfSegments.length > 0) {
- segments = original_segments.filter((segment: any) => indexesOfSegments.includes(segment.index));
+ segments = original_segments.filter(segment => indexesOfSegments.includes(segment.index));
}
// If no segments match the indexes, use all segments
@@ -719,7 +723,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
// First try to find an exact match
- const exactMatch = segments.find((segment: any) => segment.text && segment.text.includes(citationText));
+ const exactMatch = segments.find(segment => segment.text && segment.text.includes(citationText));
if (exactMatch) {
return exactMatch.start;
@@ -828,7 +832,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
existingDoc._width = x2 - x1;
existingDoc._height = y2 - y1;
}
- const highlightDoc = existingDoc ?? this.createImageCitationHighlight(x1, y1, x2, y2, citation, annotationKey, doc);
+ // const highlightDoc =
+ existingDoc ?? this.createImageCitationHighlight(x1, y1, x2, y2, citation, annotationKey, doc);
//doc.layout_scroll = y1;
doc._layout_curPage = foundChunk.startPage + 1;
@@ -922,7 +927,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
console.error(`Maximum verification attempts (${attempt}) reached for document ${doc.id}`);
// Last resort: force re-creation of the document view
- if (isPDF) {
+ if (isPDF) {
console.log('Forcing document recreation as last resort');
DocumentManager.Instance.showDocument(doc, {
willZoomCentered: true,
@@ -950,7 +955,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return;
}
- this.processPDFDocumentView(doc, isPDF, citation, foundChunk);
+ this.processPDFDocumentView(doc, isPDF, citation, foundChunk);
} catch (error) {
console.error(`Error on verification attempt ${attempt}:`, error);
if (attempt < 5) {
@@ -1454,16 +1459,16 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
disabled={this._isLoading}
/>
</div>
- <button className="submit-button" onClick={() => this._dictation?.stopDictation()} type="submit" disabled={this._isLoading || !this._inputValue.trim()}>
- {this._isLoading ? (
- <div className="spinner"></div>
- ) : (
- <svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round">
- <line x1="22" y1="2" x2="11" y2="13"></line>
- <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
- </svg>
- )}
- </button>
+ <Button
+ // className="submit-button"
+ onClick={() => this._dictation?.stopDictation()}
+ type={Type.PRIM}
+ tooltip="Send to AI"
+ color={SnappingManager.userVariantColor}
+ inactive={this._isLoading || !this._inputValue.trim()}
+ icon={<AiOutlineSend />}
+ size={Size.LARGE}
+ />
<DictationButton ref={this.setDictationRef} setInput={this.setChatInput} inputRef={this._textInputRef} />
</form>
{/* Popup for citation */}
diff --git a/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts b/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts
index a55f901e1..da4a4ae29 100644
--- a/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts
+++ b/src/client/views/nodes/chatbot/tools/DocumentMetadataTool.ts
@@ -1,16 +1,7 @@
-import { Doc, FieldType } from '../../../../../fields/Doc';
-import { DocData } from '../../../../../fields/DocSymbols';
+import { Parameter, ParametersType, supportedDocTypes, ToolInfo } from '../types/tool_types';
import { Observation } from '../types/types';
-import { ParametersType, ToolInfo, Parameter } from '../types/tool_types';
-import { BaseTool } from './BaseTool';
-import { DocumentOptions } from '../../../../documents/Documents';
-import { CollectionFreeFormDocumentView } from '../../../nodes/CollectionFreeFormDocumentView';
-import { v4 as uuidv4 } from 'uuid';
-import { LinkManager } from '../../../../util/LinkManager';
-import { DocCast, StrCast } from '../../../../../fields/Types';
-import { supportedDocTypes } from '../types/tool_types';
-import { parsedDoc } from '../chatboxcomponents/ChatBox';
import { AgentDocumentManager } from '../utils/AgentDocumentManager';
+import { BaseTool } from './BaseTool';
// Define the parameters for the DocumentMetadataTool
const parameterDefinitions: ReadonlyArray<Parameter> = [
@@ -598,7 +589,7 @@ export class DocumentMetadataTool extends BaseTool<DocumentMetadataToolParamsTyp
message: string;
fieldName?: string;
originalFieldName?: string;
- newValue?: any;
+ newValue?: string | number | boolean | object;
warning?: string;
}[] = [];
diff --git a/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts b/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts
index 3c8b49f33..dcb708450 100644
--- a/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts
+++ b/src/client/views/nodes/chatbot/utils/AgentDocumentManager.ts
@@ -1,7 +1,5 @@
import { action, computed, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
-import { observer } from 'mobx-react';
-import { v4 as uuidv4 } from 'uuid';
-import { Doc, StrListCast } from '../../../../../fields/Doc';
+import { Doc, FieldResult, StrListCast } from '../../../../../fields/Doc';
import { DocData } from '../../../../../fields/DocSymbols';
import { Id } from '../../../../../fields/FieldSymbols';
import { List } from '../../../../../fields/List';
@@ -30,7 +28,7 @@ export class AgentDocumentManager {
@observable private documentsById: ObservableMap<string, AgentDocument>;
private chatBox: ChatBox;
private chatBoxDocument: Doc | null = null;
- private fieldMetadata: Record<string, any> = {};
+ private fieldMetadata: Record<string, any> = {}; // bcz: CHANGE any to a proper type!
@observable private simplifiedChunks: ObservableMap<string, SimplifiedChunk>;
/**
@@ -103,6 +101,7 @@ export class AgentDocumentManager {
for (const [fieldName, fieldInfo] of documentOptionsEntries) {
// Extract field information
const fieldData: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
name: fieldName,
withoutUnderscore: fieldName.startsWith('_') ? fieldName.substring(1) : fieldName,
description: '',
@@ -223,6 +222,7 @@ export class AgentDocumentManager {
const dataDoc = agentDoc.dataDoc;
const metadata: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
id: layoutDoc[Id] || dataDoc[Id] || '',
title: layoutDoc.title || '',
type: layoutDoc.type || '',
@@ -235,7 +235,7 @@ export class AgentDocumentManager {
// Process all known field definitions
Object.keys(this.fieldMetadata).forEach(fieldName => {
- const fieldDef = this.fieldMetadata[fieldName];
+ // const fieldDef = this.fieldMetadata[fieldName];
const strippedName = fieldName.startsWith('_') ? fieldName.substring(1) : fieldName;
// Check if field exists on layout document
@@ -307,7 +307,7 @@ export class AgentDocumentManager {
* @param value The field value to format
* @returns A JSON-friendly representation of the field value
*/
- private formatFieldValue(value: any): any {
+ private formatFieldValue(value: FieldResult | undefined) {
if (value === undefined || value === null) {
return null;
}
@@ -330,12 +330,12 @@ export class AgentDocumentManager {
if (rtfObj.doc && rtfObj.doc.content) {
// Recursively extract text from the content
let plainText = '';
- const extractText = (node: any) => {
+ const extractText = (node: { text: string; content?: unknown[] }) => {
if (node.text) {
plainText += node.text;
}
if (node.content && Array.isArray(node.content)) {
- node.content.forEach((child: any) => extractText(child));
+ node.content.forEach(child => extractText(child as { text: string; content?: unknown[] }));
}
};
@@ -351,7 +351,7 @@ export class AgentDocumentManager {
};
}
}
- } catch (e) {
+ } catch {
// If parsing fails, just treat as a regular string
}
}
@@ -366,7 +366,7 @@ export class AgentDocumentManager {
try {
// Try to convert to JSON string
return JSON.stringify(value);
- } catch (e) {
+ } catch {
return '[Complex Object]';
}
}
@@ -381,26 +381,24 @@ export class AgentDocumentManager {
* @param fieldValue The string value to convert
* @returns The converted value with the appropriate type
*/
- private convertFieldValue(fieldName: string, fieldValue: any): any {
+ private convertFieldValue(fieldName: string, fieldValueIn: string | number | boolean): FieldResult | undefined {
// If fieldValue is already a number or boolean, we don't need to convert it from string
- if (typeof fieldValue === 'number' || typeof fieldValue === 'boolean') {
- return fieldValue;
+ if (typeof fieldValueIn === 'number' || typeof fieldValueIn === 'boolean') {
+ return fieldValueIn;
}
// If fieldValue is a string "true" or "false", convert to boolean
- if (typeof fieldValue === 'string') {
- if (fieldValue.toLowerCase() === 'true') {
+ if (typeof fieldValueIn === 'string') {
+ if (fieldValueIn.toLowerCase() === 'true') {
return true;
}
- if (fieldValue.toLowerCase() === 'false') {
+ if (fieldValueIn.toLowerCase() === 'false') {
return false;
}
}
- // If fieldValue is not a string (and not a number or boolean), convert it to string
- if (typeof fieldValue !== 'string') {
- fieldValue = String(fieldValue);
- }
+ // coerce fieldvValue to a string
+ const fieldValue = typeof fieldValueIn !== 'string' ? String(fieldValueIn) : fieldValueIn;
// Special handling for text field - convert to proper RichTextField format
if (fieldName === 'text') {
@@ -408,7 +406,7 @@ export class AgentDocumentManager {
// Check if it's already a valid JSON RichTextField
JSON.parse(fieldValue);
return fieldValue;
- } catch (e) {
+ } catch {
// It's a plain text string, so convert it to RichTextField format
const rtf = {
doc: {
@@ -462,21 +460,21 @@ export class AgentDocumentManager {
// Try to convert to date (stored as number timestamp)
try {
return new Date(fieldValue).getTime();
- } catch (e) {
+ } catch {
return fieldValue;
}
} else if (fieldType.includes('list') || fieldType.includes('array')) {
// Try to parse as JSON array
try {
- return JSON.parse(fieldValue);
- } catch (e) {
+ return JSON.parse(fieldValue) as FieldResult; // bcz: this needs to be typed properly. Dash fields can't accept a generic 'objext'
+ } catch {
return fieldValue;
}
} else if (fieldType === 'json' || fieldType === 'object') {
// Try to parse as JSON object
try {
- return JSON.parse(fieldValue);
- } catch (e) {
+ return JSON.parse(fieldValue) as FieldResult; // bcz: this needs to be typed properly. Dash fields can't accept a generic 'objext'
+ } catch {
return fieldValue;
}
}
@@ -492,6 +490,7 @@ export class AgentDocumentManager {
public getAllFieldMetadata() {
// Start with our already populated fieldMetadata from the DocumentOptions class
const result: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
fieldCount: Object.keys(this.fieldMetadata).length,
fields: {},
fieldsByType: {
@@ -526,6 +525,7 @@ export class AgentDocumentManager {
// Create structured field metadata
const fieldData: Record<string, any> = {
+ // bcz: CHANGE any to a proper type!
name: fieldName,
displayName: strippedName,
description: fieldInfo.description || '',
@@ -618,12 +618,12 @@ export class AgentDocumentManager {
message: string;
fieldName?: string;
originalFieldName?: string;
- newValue?: any;
+ newValue?: string | number | boolean | object;
warning?: string;
} {
// Normalize field name (handle with/without underscore)
let normalizedFieldName = fieldName.startsWith('_') ? fieldName : fieldName;
- const strippedFieldName = fieldName.startsWith('_') ? fieldName.substring(1) : fieldName;
+ // const strippedFieldName = fieldName.startsWith('_') ? fieldName.substring(1) : fieldName;
// Handle common field name aliases (width → _width, height → _height)
// Many document fields use '_' prefix for layout properties
@@ -690,7 +690,7 @@ export class AgentDocumentManager {
}
// Set the field value on the target document
- targetDoc[normalizedFieldName] = convertedValue;
+ targetDoc[normalizedFieldName] = convertedValue; // bcz: converteValue needs to be typed properly. Dash fields can't accept a generic 'objext'
return {
success: true,
@@ -712,19 +712,19 @@ export class AgentDocumentManager {
* @param documentId Optional ID of a specific document to get metadata for
* @returns Document metadata or metadata for all documents
*/
- public getDocumentMetadata(documentId?: string): any {
+ public getDocumentMetadata(documentId?: string) {
if (documentId) {
console.log(`Returning document metadata for docID, ${documentId}:`, this.extractDocumentMetadata(documentId));
return this.extractDocumentMetadata(documentId);
} else {
// Get metadata for all documents
- const documentsMetadata: Record<string, Record<string, any>> = {};
- for (const documentId of this.documentsById.keys()) {
- const metadata = this.extractDocumentMetadata(documentId);
+ const documentsMetadata: Record<string, Record<string, any>> = {}; // bcz: CHANGE any to a proper type!
+ for (const docid of this.documentsById.keys()) {
+ const metadata = this.extractDocumentMetadata(docid);
if (metadata) {
- documentsMetadata[documentId] = metadata;
+ documentsMetadata[docid] = metadata;
} else {
- console.warn(`No metadata found for document with ID: ${documentId}`);
+ console.warn(`No metadata found for document with ID: ${docid}`);
}
}
return {
@@ -842,7 +842,7 @@ export class AgentDocumentManager {
* @returns The ID of the created document
*/
- public async createDocInDash(docType: string, data: string, options?: any): Promise<string> {
+ public async createDocInDash(docType: string, data: string, options?: DocumentOptions): Promise<string> {
// Validate doc_type
if (!this.isValidDocType(docType)) {
throw new Error(`Invalid document type: ${docType}`);
@@ -1054,13 +1054,13 @@ export class AgentDocumentManager {
endPage: chunk.metadata.end_page,
location: chunk.metadata.location,
} as SimplifiedChunk);
- } else if (docType === 'csv') {
+ } else if (docType === 'csv' && 'row_start' in chunk.metadata && 'row_end' in chunk.metadata && 'col_start' in chunk.metadata && 'col_end' in chunk.metadata) {
simplifiedChunks.push({
...baseChunk,
- rowStart: (chunk.metadata as any).row_start,
- rowEnd: (chunk.metadata as any).row_end,
- colStart: (chunk.metadata as any).col_start,
- colEnd: (chunk.metadata as any).col_end,
+ rowStart: chunk.metadata.row_start,
+ rowEnd: chunk.metadata.row_end,
+ colStart: chunk.metadata.col_start,
+ colEnd: chunk.metadata.col_end,
} as SimplifiedChunk);
} else {
// Default for other document types
@@ -1077,7 +1077,7 @@ export class AgentDocumentManager {
* @returns The simplified chunk if found, undefined otherwise
*/
@action
- public getSimplifiedChunkById(chunkId: string): any | undefined {
+ public getSimplifiedChunkById(chunkId: string) {
return { foundChunk: this.simplifiedChunks.get(chunkId), doc: this.getDocument(this.simplifiedChunks.get(chunkId)?.doc_id || chunkId), dataDoc: this.getDataDocument(this.simplifiedChunks.get(chunkId)?.doc_id || chunkId) };
}
@@ -1098,7 +1098,7 @@ export class AgentDocumentManager {
* @param doc The document containing original media segments
* @returns Array of media segments or empty array if none exist
*/
- public getOriginalSegments(doc: Doc): any[] {
+ public getOriginalSegments(doc: Doc): { text: string; index: string; start: number }[] {
if (!doc || !doc.original_segments) {
return [];
}