aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/DocumentTypes.ts2
-rw-r--r--src/client/documents/Documents.ts1
-rw-r--r--src/client/views/nodes/chatbot/agentsystem/Agent.ts13
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx114
-rw-r--r--src/client/views/nodes/chatbot/tools/CreateAnyDocTool.ts145
-rw-r--r--src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts33
6 files changed, 145 insertions, 163 deletions
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index efe73fbbe..8aa844c0b 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -26,7 +26,7 @@ export enum DocumentType {
SCRIPTING = 'script', // script editor
CHAT = 'chat', // chat with GPT about files
EQUATION = 'equation', // equation editor
- FUNCPLOT = 'funcplot', // function plotter
+ FUNCPLOT = 'function plot', // function plotter
MAP = 'map',
DATAVIZ = 'dataviz',
ANNOPALETTE = 'annopalette',
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 0bff74ac1..7f1387ff8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -19,7 +19,6 @@ import { DocServer } from '../DocServer';
import { dropActionType } from '../util/DropActionTypes';
import { CollectionViewType, DocumentType } from './DocumentTypes';
import { Id } from '../../fields/FieldSymbols';
-import { FireflyImageData } from '../views/smartdraw/FireflyConstants';
class EmptyBox {
public static LayoutString() {
diff --git a/src/client/views/nodes/chatbot/agentsystem/Agent.ts b/src/client/views/nodes/chatbot/agentsystem/Agent.ts
index 4d3f1e4e7..ee91ccb92 100644
--- a/src/client/views/nodes/chatbot/agentsystem/Agent.ts
+++ b/src/client/views/nodes/chatbot/agentsystem/Agent.ts
@@ -8,7 +8,7 @@ import { AnswerParser } from '../response_parsers/AnswerParser';
import { StreamedAnswerParser } from '../response_parsers/StreamedAnswerParser';
import { BaseTool } from '../tools/BaseTool';
import { CalculateTool } from '../tools/CalculateTool';
-import { CreateAnyDocumentTool } from '../tools/CreateAnyDocTool';
+import { CreateAnyDocumentTool, supportedDocumentTypes } from '../tools/CreateAnyDocTool';
import { CreateDocTool } from '../tools/CreateDocumentTool';
import { DataAnalysisTool } from '../tools/DataAnalysisTool';
import { NoTool } from '../tools/NoTool';
@@ -55,7 +55,8 @@ export class Agent {
history: () => string,
csvData: () => { filename: string; id: string; text: string }[],
addLinkedUrlDoc: (url: string, id: string) => void,
- addLinkedDoc: (doc_type: string, data: string | undefined, options: DocumentOptions, id: string) => void,
+ addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
createCSVInDash: (url: string, title: string, id: string, data: string) => void
) {
// Initialize OpenAI client with API key from environment
@@ -134,6 +135,7 @@ export class Agent {
console.log(this.interMessages);
console.log(`Turn ${i}/${maxTurns}`);
+ // eslint-disable-next-line no-await-in-loop
const result = await this.execute(onProcessingUpdate, onAnswerUpdate);
this.interMessages.push({ role: 'assistant', content: result });
@@ -195,6 +197,7 @@ export class Agent {
if (currentAction) {
try {
// Process the action with its input
+ // eslint-disable-next-line no-await-in-loop
const observation = (await this.processAction(currentAction, actionInput.inputs)) as Observation[];
const nextPrompt = [{ type: 'text', text: `<stage number="${i + 1}" role="user"> <observation>` }, ...observation, { type: 'text', text: '</observation></stage>' }] as Observation[];
console.log(observation);
@@ -299,7 +302,7 @@ export class Agent {
* @param response The parsed XML response from the assistant.
* @throws An error if the response does not meet the expected structure.
*/
- private validateAssistantResponse(response: any) {
+ private validateAssistantResponse(response: { stage: { [key: string]: object | string } }) {
if (!response.stage) {
throw new Error('Response does not contain a <stage> element');
}
@@ -342,7 +345,7 @@ export class Agent {
// If 'action_input' is present, validate its structure
if ('action_input' in stage) {
- const actionInput = stage.action_input;
+ const actionInput = stage.action_input as object;
if (!('action_input_description' in actionInput) || typeof actionInput.action_input_description !== 'string') {
throw new Error('action_input must contain an action_input_description string');
@@ -357,7 +360,7 @@ export class Agent {
// If 'answer' is present, validate its structure
if ('answer' in stage) {
- const answer = stage.answer;
+ const answer = stage.answer as object;
// Ensure answer contains at least one of the required elements
if (!('grounded_text' in answer || 'normal_text' in answer)) {
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 83b50c8c6..076f49831 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -14,7 +14,7 @@ import OpenAI, { ClientOptions } from 'openai';
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { ClientUtils } from '../../../../../ClientUtils';
-import { Doc, DocListCast, Opt } from '../../../../../fields/Doc';
+import { Doc, DocListCast, FieldType, Opt } from '../../../../../fields/Doc';
import { DocData, DocViews } from '../../../../../fields/DocSymbols';
import { CsvCast, DocCast, NumCast, PDFCast, RTFCast, StrCast } from '../../../../../fields/Types';
import { Networking } from '../../../../Network';
@@ -324,7 +324,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
processing_info: [],
});
} finally {
- this._isLoading = false;
+ runInAction(() => {
+ this._isLoading = false;
+ });
this.scrollToBottom();
}
}
@@ -402,19 +404,17 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
data.map(doc =>
doc.doc_type !== 'collection' // Handle non-collection documents
? this.whichDoc(doc.doc_type, doc.data, { backgroundColor: doc.backgroundColor, _width: doc.width, _height: doc.height }, doc.id, insideCol)
- : // Recursively process collections
- this.createCollectionWithChildren(doc.data, true).then(nestedDocs =>
- Docs.Create.FreeformDocument(nestedDocs, {
- title: doc.title,
- backgroundColor: doc.backgroundColor,
- _width: doc.width,
- _height: doc.height,
- _layout_fitWidth: true,
- _freeform_backgroundGrid: true,
- })
- )
- )
- .flat() // prettier-ignore
+ : this.createCollectionWithChildren(doc.data, true).then(nestedDocs =>
+ Docs.Create.FreeformDocument(nestedDocs, {
+ title: doc.title,
+ backgroundColor: doc.backgroundColor,
+ _width: doc.width,
+ _height: doc.height,
+ _layout_fitWidth: true,
+ _freeform_backgroundGrid: true,
+ })
+ )
+ ) // prettier-ignore
).then(childDocs => childDocs.filter(doc => doc).map(doc => doc!));
// .then(nestedResults => {
// // Flatten any nested arrays from recursive collection calls
@@ -427,23 +427,18 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// return childDocs;
// });
- // @action
- // createSingleFlashcard = (data: any, options: DocumentOptions) => {
-
- // }
-
@action
- whichDoc = (doc_type: string, data: string, options: DocumentOptions, id: string, insideCol: boolean): Promise<Opt<Doc>> =>
+ whichDoc = (doc_type: string, data: unknown, options: DocumentOptions, id: string, insideCol: boolean): Promise<Opt<Doc>> =>
(async () => {
switch (doc_type) {
- case 'text': return Docs.Create.TextDocument(data, options);
- case 'flashcard': return this.createFlashcard(data, options);
- case 'deck': return this.createDeck(data, options);
- case 'image': return Docs.Create.ImageDocument(data, options);
- case 'equation': return Docs.Create.EquationDocument(data, options);
+ case 'text': return Docs.Create.TextDocument(data as string, options);
+ case 'flashcard': return this.createFlashcard(data as string[], options);
+ case 'deck': return this.createDeck(data as string, options);
+ case 'image': return Docs.Create.ImageDocument(data as string, options);
+ case 'equation': return Docs.Create.EquationDocument(data as string, options);
case 'noteboard': return Docs.Create.NoteTakingDocument([], options);
case 'simulation': return Docs.Create.SimulationDocument(options);
- case 'collection': return this.createCollectionWithChildren(data as any, true).
+ case 'collection': return this.createCollectionWithChildren(data as { doc_type: string; id: string; data: any; title: string; width: number; height: number; backgroundColor: string }[] , true).
then((arr, collOpts = { ...options, _layout_fitWidth: true, _freeform_backgroundGrid: true }) =>
(() => {
switch (options.type_collection) {
@@ -457,10 +452,10 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
})()
);
- case 'web': return Docs.Create.WebDocument(data, { ...options, data_useCors: true });
- case 'comparison': return this.createComparison(data, options);
+ case 'web': return Docs.Create.WebDocument(data as string, { ...options, data_useCors: true });
+ case 'comparison': return this.createComparison(data as {left: {width:number ,height: number, backgroundColor: string, data: string}, right: {width:number ,height: number, backgroundColor: string, data: string}}, options);
case 'diagram': return Docs.Create.DiagramDocument(options);
- case 'audio': return Docs.Create.AudioDocument(data, options);
+ case 'audio': return Docs.Create.AudioDocument(data as string, options);
case 'map': return Docs.Create.MapDocument([], options);
case 'screengrab': return Docs.Create.ScreenshotDocument(options);
case 'webcam': return Docs.Create.WebCamDocument('', options);
@@ -471,7 +466,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
case 'trail': return Docs.Create.PresDocument(options);
case 'tab': return Docs.Create.FreeformDocument([], options);
case 'slide': return Docs.Create.TreeDocument([], options);
- default: return Docs.Create.TextDocument(data, options);
+ default: return Docs.Create.TextDocument(data as string, options);
} // prettier-ignore
})().then(doc => {
if (doc) {
@@ -491,7 +486,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
* @returns {Promise<void>} A promise that resolves once the document is created and displayed.
*/
@action
- createDocInDash = (doc_type: string, data: string | undefined, options: DocumentOptions, id: string) => {
+ createDocInDash = (doc_type: string, data: unknown, options: DocumentOptions /*, id: string */) => {
const linkAndShowDoc = (doc: Opt<Doc>) => {
if (doc) {
LinkManager.Instance.addLink(Docs.Create.LinkDocument(this.Document, doc));
@@ -501,22 +496,21 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
const doc = (() => {
switch (doc_type.toLowerCase()) {
- case 'text': return Docs.Create.TextDocument(data || '', options);
- case 'image': return Docs.Create.ImageDocument(data || '', options);
- case 'pdf': return Docs.Create.PdfDocument(data || '', options);
- case 'video': return Docs.Create.VideoDocument(data || '', options);
- case 'audio': return Docs.Create.AudioDocument(data || '', options);
- case 'web': return Docs.Create.WebDocument(data || '', options);
- case 'equation': return Docs.Create.EquationDocument(data || '', options);
+ case 'flashcard': return this.createFlashcard(data as string[], options);
+ case 'text': return Docs.Create.TextDocument(data as string || '', options);
+ case 'image': return Docs.Create.ImageDocument(data as string || '', options);
+ case 'pdf': return Docs.Create.PdfDocument(data as string || '', options);
+ case 'video': return Docs.Create.VideoDocument(data as string || '', options);
+ case 'audio': return Docs.Create.AudioDocument(data as string || '', options);
+ case 'web': return Docs.Create.WebDocument(data as string || '', options);
+ case 'equation': return Docs.Create.EquationDocument(data as string || '', options);
case 'chat': return Docs.Create.ChatDocument(options);
- case 'functionplot':
- case 'function_plot': return Docs.Create.FunctionPlotDocument([], options);
- case 'dataviz':
- case 'data_viz': Networking.PostToServer('/createCSV', {
+ case 'functionplot': return Docs.Create.FunctionPlotDocument([], options);
+ case 'dataviz': Networking.PostToServer('/createCSV', {
filename: (options.title as string).replace(/\s+/g, '') + '.csv',
data: data,
})?.then(({ fileUrl, id }) => {
- const vdoc = Docs.Create.DataVizDocument(fileUrl, { ...options, text: RTFCast(data) });
+ const vdoc = Docs.Create.DataVizDocument(fileUrl, { ...options, text: RTFCast(data as FieldType) });
this.addCSVForAnalysis(vdoc, id);
linkAndShowDoc(vdoc);
});
@@ -537,14 +531,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
* @returns {Doc} A carousel document containing the flashcard deck.
*/
@action
- createDeck = (data: any, options: DocumentOptions) => {
+ createDeck = (data: string | unknown[], options: DocumentOptions) => {
const flashcardDeck: Doc[] = [];
// Parse `data` only if it’s a string
- const deckData = typeof data === 'string' ? JSON.parse(data) : data;
- const flashcardArray = Array.isArray(deckData) ? deckData : Object.values(deckData);
+ const deckData = typeof data === 'string' ? (JSON.parse(data) as unknown) : data;
+ const flashcardArray = Array.isArray(deckData) ? deckData : Object.values(deckData as object);
// Process each flashcard document in the `deckData` array
if (flashcardArray.length == 2 && flashcardArray[0].doc_type == 'text' && flashcardArray[1].doc_type == 'text') {
- this.createFlashcard(flashcardArray, options);
+ this.createFlashcard(flashcardArray as string[], options);
} else {
flashcardArray.forEach(doc => {
const flashcardDoc = this.createFlashcard(doc, options);
@@ -570,24 +564,24 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
* @returns {Doc | undefined} The created flashcard document, or undefined if the flashcard cannot be created.
*/
@action
- createFlashcard = (data: any, options: any) => {
+ createFlashcard = (data: string[], options: DocumentOptions) => {
const deckData = typeof data === 'string' ? JSON.parse(data) : data;
- const flashcardArray = Array.isArray(deckData) ? deckData : Object.values(deckData)[2];
+ const flashcardArray = Array.isArray(deckData) ? deckData : (Object.values(deckData)[2] as string[]);
const [front, back] = flashcardArray;
- if (front.doc_type === 'text' && back.doc_type === 'text') {
+ if (typeof front === 'string' && typeof back === 'string') {
const sideOptions: DocumentOptions = {
backgroundColor: options.backgroundColor,
_width: options._width,
- _height: options._height,
+ _height: options._height || 300,
};
// Create front and back text documents
- const side1 = Docs.Create.CenteredTextCreator(front.title, front.data, sideOptions);
- const side2 = Docs.Create.CenteredTextCreator(back.title, back.data, sideOptions);
+ const side1 = Docs.Create.CenteredTextCreator('question', front, sideOptions);
+ const side2 = Docs.Create.CenteredTextCreator('answer', back, sideOptions);
// Create the flashcard document with both sides
- return Docs.Create.FlashcardDocument(data.title, side1, side2, sideOptions);
+ return Docs.Create.FlashcardDocument('flashcard', side1, side2, sideOptions);
}
};
@@ -599,12 +593,12 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
* @returns {Doc} The created comparison document.
*/
@action
- createComparison = (doc: { left: any; right: any }, options: any) =>
- Docs.Create.ComparisonDocument(options.title, {
+ createComparison = (doc: { left: { width: number; height: number; backgroundColor: string; data: string }; right: { width: number; height: number; backgroundColor: string; data: string } }, options: DocumentOptions) =>
+ Docs.Create.ComparisonDocument(options.title as string, {
data_back: Docs.Create.TextDocument(doc.left.data, { backgroundColor: doc.left.backgroundColor, _width: doc.left.width, _height: doc.left.height }),
data_front: Docs.Create.TextDocument(doc.right.data, { backgroundColor: doc.right.backgroundColor, _width: doc.right.width, _height: doc.right.height }),
- _width: options.width,
- _height: options.height | 300,
+ _width: options._width,
+ _height: options._height || 300,
backgroundColor: options.backgroundColor,
});
@@ -909,7 +903,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
</div>
<form onSubmit={this.askGPT} className="chat-input">
- <input type="text" name="messageInput" autoComplete="off" placeholder="Type your message here..." value={this._inputValue} onChange={e => (this._inputValue = e.target.value)} disabled={this._isLoading} />
+ <input type="text" name="messageInput" autoComplete="off" placeholder="Type your message here..." value={this._inputValue} onChange={action(e => (this._inputValue = e.target.value))} disabled={this._isLoading} />
<button className="submit-button" type="submit" disabled={this._isLoading || !this._inputValue.trim()}>
{this._isLoading ? (
<div className="spinner"></div>
diff --git a/src/client/views/nodes/chatbot/tools/CreateAnyDocTool.ts b/src/client/views/nodes/chatbot/tools/CreateAnyDocTool.ts
index 6f61b77d4..0049612fd 100644
--- a/src/client/views/nodes/chatbot/tools/CreateAnyDocTool.ts
+++ b/src/client/views/nodes/chatbot/tools/CreateAnyDocTool.ts
@@ -1,49 +1,61 @@
import { v4 as uuidv4 } from 'uuid';
import { BaseTool } from './BaseTool';
import { Observation } from '../types/types';
-import { ParametersType, Parameter } from '../types/tool_types';
-import { DocumentOptions, Docs } from '../../../../documents/Documents';
+import { ParametersType } from '../types/tool_types';
+import { DocumentOptions } from '../../../../documents/Documents';
+import { toLower } from 'lodash';
-/**
- * List of supported document types that can be created via text LLM.
- */
-type supportedDocumentTypesType = 'text' | 'html' | 'equation' | 'functionPlot' | 'dataviz' | 'noteTaking' | 'rtf' | 'message';
-const supportedDocumentTypes: supportedDocumentTypesType[] = ['text', 'html', 'equation', 'functionPlot', 'dataviz', 'noteTaking', 'rtf', 'message'];
+export enum supportedDocumentTypes {
+ flashcard = 'flashcard',
+ text = 'text',
+ html = 'html',
+ equation = 'equation',
+ functionplot = 'functionplot',
+ dataviz = 'dataviz',
+ notetaking = 'notetaking',
+ rtf = 'rtf',
+ message = 'message',
+}
+const standardOptions = ['title', 'backgroundColor', 'layout'];
/**
* Description of document options and data field for each type.
*/
-const documentTypesInfo = {
- text: {
- options: ['title', 'backgroundColor', 'fontColor', 'text_align', 'layout'],
+const documentTypesInfo: { [key in supportedDocumentTypes]: { options: string[]; dataDescription: string } } = {
+ [supportedDocumentTypes.flashcard]: {
+ options: [...standardOptions, 'fontColor', 'text_align'],
+ dataDescription: 'an array of two strings. the first string contains a question, and the second string contains an answer',
+ },
+ [supportedDocumentTypes.text]: {
+ options: [...standardOptions, 'fontColor', 'text_align'],
dataDescription: 'The text content of the document.',
},
- html: {
- options: ['title', 'backgroundColor', 'layout'],
+ [supportedDocumentTypes.html]: {
+ options: [],
dataDescription: 'The HTML-formatted text content of the document.',
},
- equation: {
- options: ['title', 'backgroundColor', 'fontColor', 'layout'],
+ [supportedDocumentTypes.equation]: {
+ options: [...standardOptions, 'fontColor'],
dataDescription: 'The equation content as a string.',
},
- functionPlot: {
- options: ['title', 'backgroundColor', 'layout', 'function_definition'],
+ [supportedDocumentTypes.functionplot]: {
+ options: [...standardOptions, 'function_definition'],
dataDescription: 'The function definition(s) for plotting. Provide as a string or array of function definitions.',
},
- dataviz: {
- options: ['title', 'backgroundColor', 'layout', 'chartType'],
+ [supportedDocumentTypes.dataviz]: {
+ options: [...standardOptions, 'chartType'],
dataDescription: 'A string of comma-separated values representing the CSV data.',
},
- noteTaking: {
- options: ['title', 'backgroundColor', 'layout'],
+ [supportedDocumentTypes.notetaking]: {
+ options: standardOptions,
dataDescription: 'The initial content or structure for note-taking.',
},
- rtf: {
- options: ['title', 'backgroundColor', 'layout'],
+ [supportedDocumentTypes.rtf]: {
+ options: standardOptions,
dataDescription: 'The rich text content in RTF format.',
},
- message: {
- options: ['title', 'backgroundColor', 'layout'],
+ [supportedDocumentTypes.message]: {
+ options: standardOptions,
dataDescription: 'The message content of the document.',
},
};
@@ -52,7 +64,7 @@ const createAnyDocumentToolParams = [
{
name: 'document_type',
type: 'string',
- description: `The type of the document to create. Supported types are: ${supportedDocumentTypes.join(', ')}`,
+ description: `The type of the document to create. Supported types are: ${Object.values(supportedDocumentTypes).join(', ')}`,
required: true,
},
{
@@ -64,90 +76,63 @@ const createAnyDocumentToolParams = [
{
name: 'options',
type: 'string',
- description: `A JSON string representing the document options. Available options depend on the document type. For example:
-${supportedDocumentTypes
- .map(
- docType => `
-- For '${docType}' documents, options include: ${documentTypesInfo[docType].options.join(', ')}`
- )
- .join('\n')}`,
required: false,
+ description: `A JSON string representing the document options. Available options depend on the document type. For example:
+ ${Object.entries(documentTypesInfo).map( ([doc_type, info]) => `
+- For '${doc_type}' documents, options include: ${info.options.join(', ')}`)
+ .join('\n')}`, // prettier-ignore
},
] as const;
type CreateAnyDocumentToolParamsType = typeof createAnyDocumentToolParams;
export class CreateAnyDocumentTool extends BaseTool<CreateAnyDocumentToolParamsType> {
- private _addLinkedDoc: (doc_type: string, data: string | undefined, options: DocumentOptions, id: string) => void;
+ private _addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void;
- constructor(addLinkedDoc: (doc_type: string, data: string | undefined, options: DocumentOptions, id: string) => void) {
+ constructor(addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void) {
+ // prettier-ignore
super(
'createAnyDocument',
- `Creates any type of document with the provided options and data. Supported document types are: ${supportedDocumentTypes.join(', ')}. dataviz is a csv table tool, so for CSVs, use dataviz. Here are the options for each type:
+ `Creates any type of document with the provided options and data. Supported document types are: ${Object.values(supportedDocumentTypes).join(', ')}. dataviz is a csv table tool, so for CSVs, use dataviz. Here are the options for each type:
<supported_document_types>
- ${supportedDocumentTypes
- .map(
- docType => `
- <document_type name="${docType}">
- <data_description>${documentTypesInfo[docType].dataDescription}</data_description>
- <options>
- ${documentTypesInfo[docType].options.map(option => `<option>${option}</option>`).join('\n')}
- </options>
- </document_type>
- `
- )
- .join('\n')}
- </supported_document_types>`,
+ ${Object.entries(documentTypesInfo).map(([doc_type, info]) => `
+ <document_type name="${doc_type}">
+ <data_description>${info.dataDescription}</data_description>
+ <options>
+ ${info.options.map(option => `<option>${option}</option>`).join('\n')}
+ </options>
+ </document_type>
+ `).join('\n')}
+ </supported_document_types>`,
createAnyDocumentToolParams,
'Provide the document type, data, and options for the document. Options should be a valid JSON string containing the document options specific to the document type.',
- `Creates any type of document with the provided options and data. Supported document types are: ${supportedDocumentTypes.join(', ')}.`
+ `Creates any type of document with the provided options and data. Supported document types are: ${Object.values(supportedDocumentTypes).join(', ')}.`
);
this._addLinkedDoc = addLinkedDoc;
}
async execute(args: ParametersType<CreateAnyDocumentToolParamsType>): Promise<Observation[]> {
try {
- const documentType: supportedDocumentTypesType = args.document_type.toLowerCase() as supportedDocumentTypesType;
- let options: DocumentOptions = {};
+ const documentType = toLower(args.document_type) as unknown as supportedDocumentTypes;
+ const info = documentTypesInfo[documentType];
- if (!supportedDocumentTypes.includes(documentType)) {
- throw new Error(`Unsupported document type: ${documentType}. Supported types are: ${supportedDocumentTypes.join(', ')}.`);
+ if (info === undefined) {
+ throw new Error(`Unsupported document type: ${documentType}. Supported types are: ${Object.values(supportedDocumentTypes).join(', ')}.`);
}
if (!args.data) {
- throw new Error(`Data is required for ${documentType} documents. ${documentTypesInfo[documentType].dataDescription}`);
- }
-
- if (args.options) {
- try {
- options = JSON.parse(args.options as string) as DocumentOptions;
- } catch (e) {
- throw new Error('Options must be a valid JSON string.');
- }
+ throw new Error(`Data is required for ${documentType} documents. ${info.dataDescription}`);
}
- const data = args.data as string;
const id = uuidv4();
+ const options: DocumentOptions = !args.options ? {} : JSON.parse(args.options);
- // Set default options if not provided
- options.title = options.title || `New ${documentType.charAt(0).toUpperCase() + documentType.slice(1)} Document`;
-
- // Call the function to add the linked document
- this._addLinkedDoc(documentType, data, options, id);
+ // Call the function to add the linked document (add default title that can be overriden if set in options)
+ this._addLinkedDoc(documentType, args.data, { title: `New ${documentType.charAt(0).toUpperCase() + documentType.slice(1)} Document`, ...options }, id);
- return [
- {
- type: 'text',
- text: `Created ${documentType} document with ID ${id}.`,
- },
- ];
+ return [{ type: 'text', text: `Created ${documentType} document with ID ${id}.` }];
} catch (error) {
- return [
- {
- type: 'text',
- text: 'Error creating document: ' + (error as Error).message,
- },
- ];
+ return [{ type: 'text', text: 'Error creating document: ' + (error as Error).message }];
}
}
}
diff --git a/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts b/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts
index 63a6004a7..f0f2fe703 100644
--- a/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts
+++ b/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts
@@ -3,6 +3,7 @@ import { BaseTool } from './BaseTool';
import { Observation } from '../types/types';
import { ParametersType } from '../types/tool_types';
import { DocumentOptions } from '../../../../documents/Documents';
+import { supportedDocumentTypes } from './CreateAnyDocTool';
/**
* Tthe CreateDocTool class is responsible for creating
@@ -343,9 +344,9 @@ type CreateListDocToolParamsType = typeof createListDocToolParams;
// Tool class for creating documents
export class CreateDocTool extends BaseTool<CreateListDocToolParamsType> {
- private _addLinkedDoc: (doc_type: string, data: string, options: DocumentOptions, id: string) => void;
+ private _addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void;
- constructor(addLinkedDoc: (doc_type: string, data: string, options: DocumentOptions, id: string) => void) {
+ constructor(addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void) {
super(
'createDoc',
'Creates one or more documents that best fit the user’s request. If the user requests a "dashboard," first call the search tool and then generate a variety of document types individually, with absolutely a minimum of 20 documents with two stacks of flashcards that are small and it should have a couple nested freeform collections of things, each with different content and color schemes. For example, create multiple individual documents like "text," "deck," "web", "equation," and "comparison." Use decks instead of flashcards for dashboards. Decks should have at least three flashcards. Really think about what documents are useful to the user. If they ask for a dashboard about the skeletal system, include flashcards, as they would be helpful. Arrange the documents in a grid layout, ensuring that the x and y coordinates are calculated so no documents overlap but they should be directly next to each other with 20 padding in between. Take into account the width and height of each document, spacing them appropriately to prevent collisions. Use a systematic approach, such as placing each document in a grid cell based on its order, where cell dimensions match the document dimensions plus a fixed margin for spacing. Do not nest all documents within a single collection unless explicitly requested by the user. Instead, create a set of independent documents with diverse document types. Each type should appear separately unless specified otherwise.',
@@ -363,27 +364,27 @@ export class CreateDocTool extends BaseTool<CreateListDocToolParamsType> {
async execute(args: ParametersType<CreateListDocToolParamsType>): Promise<Observation[]> {
try {
console.log('EXE' + args.docs);
- const parsedDoc = JSON.parse(args.docs);
+ const parsedDoc = JSON.parse(args.docs) as ({ doc_type: supportedDocumentTypes; data: unknown } & DocumentOptions)[];
console.log('parsed' + parsedDoc);
- parsedDoc.forEach(doc => {
+ parsedDoc.forEach(doc =>
this._addLinkedDoc(
- doc['doc_type'],
- doc['data'],
+ doc.doc_type,
+ doc.data,
{
- title: doc['title'],
- backgroundColor: doc['backgroundColor'],
- text_fontColor: doc['font_color'],
- _width: doc['width'],
- _height: doc['height'],
- type_collection: doc['type_collection'],
+ title: doc.title,
+ backgroundColor: doc.backgroundColor,
+ text_fontColor: doc.text_fontColor,
+ _width: doc._width,
+ _height: doc._height,
+ type_collection: doc.type_collection,
_layout_fitWidth: false,
_layout_autoHeight: true,
- x: doc['x'],
- y: doc['y'],
+ x: doc.x,
+ y: doc.y,
},
uuidv4()
- );
- });
+ )
+ );
return [{ type: 'text', text: 'Created document.' }];
} catch (error) {
return [{ type: 'text', text: 'Error creating text document, ' + error }];