move_list_item
Relocate an item within a structured memory document by specifying source and destination sections, ensuring organized knowledge management for project contexts.
Instructions
Move an item from one section to another
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| from_section | Yes | The source section containing the item | |
| item_identifier | Yes | Identifier for the item to move (e.g., company name) | |
| memory_id | Yes | The ID of the memory document to update | |
| reason | No | Optional reason for the move (stored as metadata) | |
| to_section | Yes | The destination section for the item |
Input Schema (JSON Schema)
{
"properties": {
"from_section": {
"description": "The source section containing the item",
"type": "string"
},
"item_identifier": {
"description": "Identifier for the item to move (e.g., company name)",
"type": "string"
},
"memory_id": {
"description": "The ID of the memory document to update",
"type": "string"
},
"reason": {
"description": "Optional reason for the move (stored as metadata)",
"type": "string"
},
"to_section": {
"description": "The destination section for the item",
"type": "string"
}
},
"required": [
"memory_id",
"from_section",
"to_section",
"item_identifier"
],
"type": "object"
}
Implementation Reference
- src/tools/moveListItem.ts:11-77 (handler)Main handler function for the 'move_list_item' tool. Validates parameters, reads memory, locates sections, finds and extracts the item using helpers, removes from source, adds to destination, updates storage, and returns success message.export async function moveListItemTool( storageManager: StorageManager, args: any ): Promise<any> { const params = args as MoveListItemParams; if (!params.memory_id || !params.from_section || !params.to_section || !params.item_identifier) { throw new Error('memory_id, from_section, to_section, and item_identifier are required'); } // Read the memory document const memory = await storageManager.readMemory(params.memory_id); if (!memory) { throw new Error(`Memory document '${params.memory_id}' not found`); } // Find both sections const fromSection = storageManager.findSection(memory.content, params.from_section); if (!fromSection) { throw new Error(`Source section '${params.from_section}' not found in memory document '${params.memory_id}'`); } const toSection = storageManager.findSection(memory.content, params.to_section); const toSectionExists = toSection !== null; // Parse the from section to find and extract the item const fromLines = fromSection.content.split('\n'); const boundaries = findItemBoundaries(fromLines, params.item_identifier); if (!boundaries) { throw new Error(`Item '${params.item_identifier}' not found in section '${params.from_section}'`); } // Extract the item let extractedItem = extractItemLines(fromLines, boundaries); // Add reason as metadata if provided if (params.reason) { extractedItem = addReasonToItem(extractedItem, params.reason, params.from_section); } // Remove item from source section const remainingFromLines = removeItemFromLines(fromLines, boundaries); const newFromContent = remainingFromLines.join('\n'); // Add item to destination section const existingToContent = toSectionExists && toSection ? toSection.content : null; const newToContent = prepareDestinationContent(extractedItem, existingToContent); // Update both sections await storageManager.updateSection(params.memory_id, params.from_section, newFromContent, 'replace'); await storageManager.updateSection(params.memory_id, params.to_section, newToContent, 'replace'); return { content: [{ type: 'text', text: `Successfully moved item '${params.item_identifier}' from '${params.from_section}' to '${params.to_section}' in memory document '${params.memory_id}': **Item**: ${params.item_identifier} **From**: ${params.from_section} **To**: ${params.to_section}${params.reason ? `\n**Reason**: ${params.reason}` : ''} **Destination Section**: ${toSectionExists ? 'Updated existing section' : 'Created new section'} The item has been moved successfully. You can view both sections using the get_section tool.` }] }; }
- src/types/memory.ts:75-81 (schema)TypeScript interface defining the input parameters for the moveListItemTool, used for type validation in the handler.export interface MoveListItemParams { memory_id: string; from_section: string; to_section: string; item_identifier: string; reason?: string; }
- src/index.ts:198-233 (registration)Tool registration in the ListTools response, including name 'move_list_item', description, and inputSchema matching the MoveListItemParams interface.{ name: "move_list_item", description: "Move an item from one section to another", inputSchema: { type: "object", properties: { memory_id: { type: "string", description: "The ID of the memory document to update", }, from_section: { type: "string", description: "The source section containing the item", }, to_section: { type: "string", description: "The destination section for the item", }, item_identifier: { type: "string", description: "Identifier for the item to move (e.g., company name)", }, reason: { type: "string", description: "Optional reason for the move (stored as metadata)", }, }, required: [ "memory_id", "from_section", "to_section", "item_identifier", ], }, },
- src/index.ts:283-284 (registration)Dispatch handler in the CallToolRequest switch statement that routes 'move_list_item' calls to the moveListItemTool function.case "move_list_item": return await moveListItemTool(storageManager, args);
- Key helper functions used by the handler: finding item boundaries, extracting, removing, adding reason, and preparing destination content.export function findItemBoundaries(lines: string[], identifier: string): ItemBoundaries | null { for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); if (line.toLowerCase().includes(identifier.toLowerCase())) { const startIndex = i; let endIndex = i; // Find the end of this item by looking for the next heading or end of content for (let j = i + 1; j < lines.length; j++) { const nextLine = lines[j].trim(); // If we hit another heading (### ), this item ends at the previous line if (nextLine.startsWith('### ')) { endIndex = j - 1; break; } // If we hit an empty line followed by a heading, the item ends at the empty line if (nextLine === '' && lines[j + 1]?.trim().startsWith('### ')) { endIndex = j - 1; break; } // Otherwise, this line is part of the item endIndex = j; } return { startIndex, endIndex }; } } return null; } /** * Extracts an item from lines based on boundaries */ export function extractItemLines(lines: string[], boundaries: ItemBoundaries): string[] { return lines.slice(boundaries.startIndex, boundaries.endIndex + 1); } /** * Removes an item from lines based on boundaries */ export function removeItemFromLines(lines: string[], boundaries: ItemBoundaries): string[] { return [ ...lines.slice(0, boundaries.startIndex), ...lines.slice(boundaries.endIndex + 1) ]; } /** * Adds reason metadata to extracted item lines */ export function addReasonToItem(itemLines: string[], reason: string, fromSection: string): string[] { const reasonLine = ` <!-- Moved from ${fromSection}: ${reason} -->`; return [...itemLines, reasonLine]; } /** * Prepares content for destination section (new or existing) */ export function prepareDestinationContent( itemLines: string[], existingContent: string | null ): string { if (existingContent !== null) { // Append to existing section const existingLines = existingContent.split('\n'); const combinedLines = [...existingLines, '', ...itemLines]; return combinedLines.join('\n'); } else { // Create new section with the item return itemLines.join('\n'); } }