Skip to content

Commit

Permalink
feat(plugin/chat): add a way to modify the text
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminshafii committed Jan 1, 2025
1 parent e28ca76 commit 520f8fa
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 50 deletions.
48 changes: 1 addition & 47 deletions packages/plugin/handlers/commandHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { WorkspaceLeaf } from "obsidian";
import FileOrganizer from "../index";
import { ORGANIZER_VIEW_TYPE, AssistantViewWrapper } from "../views/assistant/view";
import { App, TFile } from "obsidian";
import { logger } from "../services/logger";


import { App } from "obsidian";

export function initializeOrganizer(plugin: FileOrganizer) {

plugin.registerView(
ORGANIZER_VIEW_TYPE,
(leaf: WorkspaceLeaf) => new AssistantViewWrapper(leaf, plugin)
Expand All @@ -16,11 +12,9 @@ export function initializeOrganizer(plugin: FileOrganizer) {
plugin.addRibbonIcon("sparkle", "Fo2k Assistant View", () => {
plugin.ensureAssistantView();
});

}

export function initializeFileOrganizationCommands(plugin: FileOrganizer) {

plugin.addCommand({
id: "add-to-inbox",
name: "Put in inbox",
Expand All @@ -32,43 +26,3 @@ export function initializeFileOrganizationCommands(plugin: FileOrganizer) {
},
});
}

export async function addTextToDocument(app: App, content: string, path?: string): Promise<void> {
try {
let targetFile: TFile;
console.log("path", path, 'addTextToDocument');

if (path) {
targetFile = app.vault.getAbstractFileByPath(path) as TFile;
if (!targetFile) {
throw new Error(`File not found at path: ${path}`);
}
} else {
// Get the active file
targetFile = app.workspace.getActiveFile();
if (!targetFile) {
throw new Error("No active file found");
}
}

// Get current content
const currentContent = await app.vault.read(targetFile);

// Get editor if it exists
const editor = app.workspace.activeEditor?.editor;

if (editor) {
// If we have an editor, insert at cursor position
const cursor = editor.getCursor();
editor.replaceRange(content, cursor);
} else {
// Otherwise append to the end
await app.vault.modify(targetFile, currentContent + "\n" + content);
}

logger.info(`Successfully added text to document: ${targetFile.path}`);
} catch (error) {
logger.error("Error adding text to document:", error);
throw error;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useRef, useState } from "react";
import { App } from "obsidian";
import { addTextToDocument } from "../../../../handlers/commandHandlers";
import { App, TFile } from "obsidian";
import { logger } from "../../../../services/logger";

interface AddTextHandlerProps {
Expand All @@ -23,7 +22,37 @@ export function AddTextHandler({
hasFetchedRef.current = true;
const { content, path } = toolInvocation.args;
try {
await addTextToDocument(app, content, path);
let targetFile: TFile;

if (path) {
targetFile = app.vault.getAbstractFileByPath(path) as TFile;
if (!targetFile) {
throw new Error(`File not found at path: ${path}`);
}
} else {
// Get the active file
targetFile = app.workspace.getActiveFile();
if (!targetFile) {
throw new Error("No active file found");
}
}

// Get current content
const currentContent = await app.vault.read(targetFile);

// Get editor if it exists
const editor = app.workspace.activeEditor?.editor;

if (editor) {
// If we have an editor, insert at cursor position
const cursor = editor.getCursor();
editor.replaceRange(content, cursor);
} else {
// Otherwise append to the end
await app.vault.modify(targetFile, currentContent + "\n" + content);
}

logger.info(`Successfully added text to document: ${targetFile.path}`);
handleAddResult(`Successfully added text to document${path ? `: ${path}` : ""}`);
setAddSuccess(true);
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useRef, useState } from "react";
import { App, TFile } from "obsidian";
import { logger } from "../../../../services/logger";

interface ModifyTextHandlerProps {
toolInvocation: any;
handleAddResult: (result: string) => void;
app: App;
}

export function ModifyTextHandler({
toolInvocation,
handleAddResult,
app,
}: ModifyTextHandlerProps) {
const hasFetchedRef = useRef(false);
const [modifySuccess, setModifySuccess] = useState<boolean | null>(null);

React.useEffect(() => {
const handleModifyText = async () => {
if (!hasFetchedRef.current && !("result" in toolInvocation)) {
hasFetchedRef.current = true;
const { content, path } = toolInvocation.args;
try {
let targetFile: TFile;

if (path) {
targetFile = app.vault.getAbstractFileByPath(path) as TFile;
if (!targetFile) {
throw new Error(`File not found at path: ${path}`);
}
} else {
// Get the active file
targetFile = app.workspace.getActiveFile();
if (!targetFile) {
throw new Error("No active file found");
}
}

// Get editor if it exists
const editor = app.workspace.activeEditor?.editor;

if (editor) {
// If we have an editor, replace the selected text or entire content
const selection = editor.getSelection();
if (selection) {
// If there's selected text, replace just that
editor.replaceSelection(content);
} else {
// If no selection, replace entire content
editor.setValue(content);
}
} else {
// If no editor is open, modify the entire file
await app.vault.modify(targetFile, content);
}

logger.info(`Successfully modified text in document: ${targetFile.path}`);
handleAddResult(`Successfully modified text in document${path ? `: ${path}` : ""}`);
setModifySuccess(true);
} catch (error) {
logger.error("Error modifying text in document:", error);
handleAddResult(`Error: ${error.message}`);
setModifySuccess(false);
}
}
};

handleModifyText();
}, [toolInvocation, handleAddResult, app]);

if (modifySuccess === null) {
return <div className="text-sm text-[--text-muted]">Modifying text in document...</div>;
}

if (modifySuccess) {
return <div className="text-sm text-[--text-muted]">Text successfully modified in document</div>;
}

return <div className="text-sm text-[--text-error]">Failed to modify text in document</div>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { RenameFilesHandler } from "./rename-files-handler";
import { SearchRenameHandler } from "./search-rename-handler";
import { ExecuteActionsHandler } from "./execute-actions-handler";
import { AddTextHandler } from "./add-text-handler";
import { ModifyTextHandler } from "./modify-text-handler";

interface ToolInvocationHandlerProps {
toolInvocation: ToolInvocation;
Expand Down Expand Up @@ -48,6 +49,7 @@ function ToolInvocationHandler({
searchByName: "Search Files by Name",
executeActionsOnFileBasedOnPrompt: "Execute Actions on Files",
addTextToDocument: "Adding Text to Document",
modifyDocumentText: "Modifying Document Text",
};
return toolTitles[toolName] || "Tool Invocation";
};
Expand Down Expand Up @@ -142,6 +144,13 @@ function ToolInvocationHandler({
app={app}
/>
),
modifyDocumentText: () => (
<ModifyTextHandler
toolInvocation={toolInvocation}
handleAddResult={handleAddResult}
app={app}
/>
),
};

return handlers[toolInvocation.toolName]?.() || null;
Expand Down
7 changes: 7 additions & 0 deletions packages/web/app/api/(newai)/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ export async function POST(req: NextRequest) {
path: z.string().optional().describe("Optional path to the document. If not provided, uses current document"),
}),
},
modifyDocumentText: {
description: "Modifies the text in the current document or selected text according to user's request",
parameters: z.object({
content: z.string().describe("The new text content to replace the current content or selection"),
path: z.string().optional().describe("Optional path to the document. If not provided, uses current document"),
}),
},
generateSettings: {
description:
"Generate vault organization settings based on user preferences",
Expand Down

0 comments on commit 520f8fa

Please sign in to comment.