| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import { feature } from 'bun:bundle' |
| import { |
| MEMORY_FRONTMATTER_EXAMPLE, |
| TYPES_SECTION_COMBINED, |
| TYPES_SECTION_INDIVIDUAL, |
| WHAT_NOT_TO_SAVE_SECTION, |
| } from '../../memdir/memoryTypes.js' |
| import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js' |
| import { FILE_EDIT_TOOL_NAME } from '../../tools/FileEditTool/constants.js' |
| import { FILE_READ_TOOL_NAME } from '../../tools/FileReadTool/prompt.js' |
| import { FILE_WRITE_TOOL_NAME } from '../../tools/FileWriteTool/prompt.js' |
| import { GLOB_TOOL_NAME } from '../../tools/GlobTool/prompt.js' |
| import { GREP_TOOL_NAME } from '../../tools/GrepTool/prompt.js' |
|
|
| |
| |
| |
| function opener(newMessageCount: number, existingMemories: string): string { |
| const manifest = |
| existingMemories.length > 0 |
| ? `\n\n## Existing memory files\n\n${existingMemories}\n\nCheck this list before writing β update an existing file rather than creating a duplicate.` |
| : '' |
| return [ |
| `You are now acting as the memory extraction subagent. Analyze the most recent ~${newMessageCount} messages above and use them to update your persistent memory systems.`, |
| '', |
| `Available tools: ${FILE_READ_TOOL_NAME}, ${GREP_TOOL_NAME}, ${GLOB_TOOL_NAME}, read-only ${BASH_TOOL_NAME} (ls/find/cat/stat/wc/head/tail and similar), and ${FILE_EDIT_TOOL_NAME}/${FILE_WRITE_TOOL_NAME} for paths inside the memory directory only. ${BASH_TOOL_NAME} rm is not permitted. All other tools β MCP, Agent, write-capable ${BASH_TOOL_NAME}, etc β will be denied.`, |
| '', |
| `You have a limited turn budget. ${FILE_EDIT_TOOL_NAME} requires a prior ${FILE_READ_TOOL_NAME} of the same file, so the efficient strategy is: turn 1 β issue all ${FILE_READ_TOOL_NAME} calls in parallel for every file you might update; turn 2 β issue all ${FILE_WRITE_TOOL_NAME}/${FILE_EDIT_TOOL_NAME} calls in parallel. Do not interleave reads and writes across multiple turns.`, |
| '', |
| `You MUST only use content from the last ~${newMessageCount} messages to update your persistent memories. Do not waste any turns attempting to investigate or verify that content further β no grepping source files, no reading code to confirm a pattern exists, no git commands.` + |
| manifest, |
| ].join('\n') |
| } |
|
|
| |
| |
| |
| |
| export function buildExtractAutoOnlyPrompt( |
| newMessageCount: number, |
| existingMemories: string, |
| skipIndex = false, |
| ): string { |
| const howToSave = skipIndex |
| ? [ |
| '## How to save memories', |
| '', |
| 'Write each memory to its own file (e.g., `user_role.md`, `feedback_testing.md`) using this frontmatter format:', |
| '', |
| ...MEMORY_FRONTMATTER_EXAMPLE, |
| '', |
| '- Organize memory semantically by topic, not chronologically', |
| '- Update or remove memories that turn out to be wrong or outdated', |
| '- Do not write duplicate memories. First check if there is an existing memory you can update before writing a new one.', |
| ] |
| : [ |
| '## How to save memories', |
| '', |
| 'Saving a memory is a two-step process:', |
| '', |
| '**Step 1** β write the memory to its own file (e.g., `user_role.md`, `feedback_testing.md`) using this frontmatter format:', |
| '', |
| ...MEMORY_FRONTMATTER_EXAMPLE, |
| '', |
| '**Step 2** β add a pointer to that file in `MEMORY.md`. `MEMORY.md` is an index, not a memory β each entry should be one line, under ~150 characters: `- [Title](file.md) β one-line hook`. It has no frontmatter. Never write memory content directly into `MEMORY.md`.', |
| '', |
| '- `MEMORY.md` is always loaded into your system prompt β lines after 200 will be truncated, so keep the index concise', |
| '- Organize memory semantically by topic, not chronologically', |
| '- Update or remove memories that turn out to be wrong or outdated', |
| '- Do not write duplicate memories. First check if there is an existing memory you can update before writing a new one.', |
| ] |
|
|
| return [ |
| opener(newMessageCount, existingMemories), |
| '', |
| 'If the user explicitly asks you to remember something, save it immediately as whichever type fits best. If they ask you to forget something, find and remove the relevant entry.', |
| '', |
| ...TYPES_SECTION_INDIVIDUAL, |
| ...WHAT_NOT_TO_SAVE_SECTION, |
| '', |
| ...howToSave, |
| ].join('\n') |
| } |
|
|
| |
| |
| |
| |
| |
| export function buildExtractCombinedPrompt( |
| newMessageCount: number, |
| existingMemories: string, |
| skipIndex = false, |
| ): string { |
| if (!feature('TEAMMEM')) { |
| return buildExtractAutoOnlyPrompt( |
| newMessageCount, |
| existingMemories, |
| skipIndex, |
| ) |
| } |
|
|
| const howToSave = skipIndex |
| ? [ |
| '## How to save memories', |
| '', |
| "Write each memory to its own file in the chosen directory (private or team, per the type's scope guidance) using this frontmatter format:", |
| '', |
| ...MEMORY_FRONTMATTER_EXAMPLE, |
| '', |
| '- Organize memory semantically by topic, not chronologically', |
| '- Update or remove memories that turn out to be wrong or outdated', |
| '- Do not write duplicate memories. First check if there is an existing memory you can update before writing a new one.', |
| ] |
| : [ |
| '## How to save memories', |
| '', |
| 'Saving a memory is a two-step process:', |
| '', |
| "**Step 1** β write the memory to its own file in the chosen directory (private or team, per the type's scope guidance) using this frontmatter format:", |
| '', |
| ...MEMORY_FRONTMATTER_EXAMPLE, |
| '', |
| "**Step 2** β add a pointer to that file in the same directory's `MEMORY.md`. Each directory (private and team) has its own `MEMORY.md` index β each entry should be one line, under ~150 characters: `- [Title](file.md) β one-line hook`. They have no frontmatter. Never write memory content directly into a `MEMORY.md`.", |
| '', |
| '- Both `MEMORY.md` indexes are loaded into your system prompt β lines after 200 will be truncated, so keep them concise', |
| '- Organize memory semantically by topic, not chronologically', |
| '- Update or remove memories that turn out to be wrong or outdated', |
| '- Do not write duplicate memories. First check if there is an existing memory you can update before writing a new one.', |
| ] |
|
|
| return [ |
| opener(newMessageCount, existingMemories), |
| '', |
| 'If the user explicitly asks you to remember something, save it immediately as whichever type fits best. If they ask you to forget something, find and remove the relevant entry.', |
| '', |
| ...TYPES_SECTION_COMBINED, |
| ...WHAT_NOT_TO_SAVE_SECTION, |
| '- You MUST avoid saving sensitive data within shared team memories. For example, never save API keys or user credentials.', |
| '', |
| ...howToSave, |
| ].join('\n') |
| } |
|
|