summaryrefslogtreecommitdiff
path: root/packages/server/src/tools/memoryTool.ts
diff options
context:
space:
mode:
authorTommaso Sciortino <[email protected]>2025-05-30 18:25:47 -0700
committerGitHub <[email protected]>2025-05-30 18:25:47 -0700
commit21fba832d1b4ea7af43fb887d9b2b38fcf8210d0 (patch)
tree7200d2fac3a55c385e0a2dac34b5282c942364bc /packages/server/src/tools/memoryTool.ts
parentc81148a0cc8489f657901c2cc7247c0834075e1a (diff)
Rename server->core (#638)
Diffstat (limited to 'packages/server/src/tools/memoryTool.ts')
-rw-r--r--packages/server/src/tools/memoryTool.ts194
1 files changed, 0 insertions, 194 deletions
diff --git a/packages/server/src/tools/memoryTool.ts b/packages/server/src/tools/memoryTool.ts
deleted file mode 100644
index 49dce59d..00000000
--- a/packages/server/src/tools/memoryTool.ts
+++ /dev/null
@@ -1,194 +0,0 @@
-/**
- * @license
- * Copyright 2025 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import { BaseTool, ToolResult } from './tools.js';
-import * as fs from 'fs/promises';
-import * as path from 'path';
-import { homedir } from 'os';
-
-const memoryToolSchemaData = {
- name: 'save_memory',
- description:
- 'Saves a specific piece of information or fact to your long-term memory. Use this when the user explicitly asks you to remember something, or when they state a clear, concise fact that seems important to retain for future interactions.',
- parameters: {
- type: 'object',
- properties: {
- fact: {
- type: 'string',
- description:
- 'The specific fact or piece of information to remember. Should be a clear, self-contained statement.',
- },
- },
- required: ['fact'],
- },
-};
-
-const memoryToolDescription = `
-Saves a specific piece of information or fact to your long-term memory.
-
-Use this tool:
-
-- When the user explicitly asks you to remember something (e.g., "Remember that I like pineapple on pizza", "Please save this: my cat's name is Whiskers").
-- When the user states a clear, concise fact about themselves, their preferences, or their environment that seems important for you to retain for future interactions to provide a more personalized and effective assistance.
-
-Do NOT use this tool:
-
-- To remember conversational context that is only relevant for the current session.
-- To save long, complex, or rambling pieces of text. The fact should be relatively short and to the point.
-- If you are unsure whether the information is a fact worth remembering long-term. If in doubt, you can ask the user, "Should I remember that for you?"
-
-## Parameters
-
-- \`fact\` (string, required): The specific fact or piece of information to remember. This should be a clear, self-contained statement. For example, if the user says "My favorite color is blue", the fact would be "My favorite color is blue".
-`;
-
-export const GEMINI_CONFIG_DIR = '.gemini';
-export const GEMINI_MD_FILENAME = 'GEMINI.md';
-export const MEMORY_SECTION_HEADER = '## Gemini Added Memories';
-
-interface SaveMemoryParams {
- fact: string;
-}
-
-function getGlobalMemoryFilePath(): string {
- return path.join(homedir(), GEMINI_CONFIG_DIR, GEMINI_MD_FILENAME);
-}
-
-/**
- * Ensures proper newline separation before appending content.
- */
-function ensureNewlineSeparation(currentContent: string): string {
- if (currentContent.length === 0) return '';
- if (currentContent.endsWith('\n\n') || currentContent.endsWith('\r\n\r\n'))
- return '';
- if (currentContent.endsWith('\n') || currentContent.endsWith('\r\n'))
- return '\n';
- return '\n\n';
-}
-
-export class MemoryTool extends BaseTool<SaveMemoryParams, ToolResult> {
- static readonly Name: string = memoryToolSchemaData.name;
- constructor() {
- super(
- MemoryTool.Name,
- 'Save Memory',
- memoryToolDescription,
- memoryToolSchemaData.parameters as Record<string, unknown>,
- );
- }
-
- static async performAddMemoryEntry(
- text: string,
- memoryFilePath: string,
- fsAdapter: {
- readFile: (path: string, encoding: 'utf-8') => Promise<string>;
- writeFile: (
- path: string,
- data: string,
- encoding: 'utf-8',
- ) => Promise<void>;
- mkdir: (
- path: string,
- options: { recursive: boolean },
- ) => Promise<string | undefined>;
- },
- ): Promise<void> {
- let processedText = text.trim();
- // Remove leading hyphens and spaces that might be misinterpreted as markdown list items
- processedText = processedText.replace(/^(-+\s*)+/, '').trim();
- const newMemoryItem = `- ${processedText}`;
-
- try {
- await fsAdapter.mkdir(path.dirname(memoryFilePath), { recursive: true });
- let content = '';
- try {
- content = await fsAdapter.readFile(memoryFilePath, 'utf-8');
- } catch (_e) {
- // File doesn't exist, will be created with header and item.
- }
-
- const headerIndex = content.indexOf(MEMORY_SECTION_HEADER);
-
- if (headerIndex === -1) {
- // Header not found, append header and then the entry
- const separator = ensureNewlineSeparation(content);
- content += `${separator}${MEMORY_SECTION_HEADER}\n${newMemoryItem}\n`;
- } else {
- // Header found, find where to insert the new memory entry
- const startOfSectionContent =
- headerIndex + MEMORY_SECTION_HEADER.length;
- let endOfSectionIndex = content.indexOf('\n## ', startOfSectionContent);
- if (endOfSectionIndex === -1) {
- endOfSectionIndex = content.length; // End of file
- }
-
- const beforeSectionMarker = content
- .substring(0, startOfSectionContent)
- .trimEnd();
- let sectionContent = content
- .substring(startOfSectionContent, endOfSectionIndex)
- .trimEnd();
- const afterSectionMarker = content.substring(endOfSectionIndex);
-
- sectionContent += `\n${newMemoryItem}`;
- content =
- `${beforeSectionMarker}\n${sectionContent.trimStart()}\n${afterSectionMarker}`.trimEnd() +
- '\n';
- }
- await fsAdapter.writeFile(memoryFilePath, content, 'utf-8');
- } catch (error) {
- console.error(
- `[MemoryTool] Error adding memory entry to ${memoryFilePath}:`,
- error,
- );
- throw new Error(
- `[MemoryTool] Failed to add memory entry: ${error instanceof Error ? error.message : String(error)}`,
- );
- }
- }
-
- async execute(
- params: SaveMemoryParams,
- _signal: AbortSignal,
- ): Promise<ToolResult> {
- const { fact } = params;
-
- if (!fact || typeof fact !== 'string' || fact.trim() === '') {
- const errorMessage = 'Parameter "fact" must be a non-empty string.';
- return {
- llmContent: JSON.stringify({ success: false, error: errorMessage }),
- returnDisplay: `Error: ${errorMessage}`,
- };
- }
-
- try {
- // Use the static method with actual fs promises
- await MemoryTool.performAddMemoryEntry(fact, getGlobalMemoryFilePath(), {
- readFile: fs.readFile,
- writeFile: fs.writeFile,
- mkdir: fs.mkdir,
- });
- const successMessage = `Okay, I've remembered that: "${fact}"`;
- return {
- llmContent: JSON.stringify({ success: true, message: successMessage }),
- returnDisplay: successMessage,
- };
- } catch (error) {
- const errorMessage =
- error instanceof Error ? error.message : String(error);
- console.error(
- `[MemoryTool] Error executing save_memory for fact "${fact}": ${errorMessage}`,
- );
- return {
- llmContent: JSON.stringify({
- success: false,
- error: `Failed to save memory. Detail: ${errorMessage}`,
- }),
- returnDisplay: `Error saving memory: ${errorMessage}`,
- };
- }
- }
-}