Skip to main content
Glama

Letta MCP Server

by oculairmedia
delete-passage.test.js16.9 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { handleDeletePassage, deletePassageDefinition, } from '../../../tools/passages/delete-passage.js'; import { createMockLettaServer } from '../../utils/mock-server.js'; import { expectValidToolResponse } from '../../utils/test-helpers.js'; describe('Delete Passage', () => { let mockServer; beforeEach(() => { mockServer = createMockLettaServer(); }); afterEach(() => { vi.restoreAllMocks(); }); describe('Tool Definition', () => { it('should have correct tool definition', () => { expect(deletePassageDefinition.name).toBe('delete_passage'); expect(deletePassageDefinition.description).toContain( "Delete a memory from an agent's archival memory", ); expect(deletePassageDefinition.description).toContain( 'WARNING: This action is permanent', ); expect(deletePassageDefinition.inputSchema.required).toEqual(['agent_id', 'memory_id']); expect(deletePassageDefinition.inputSchema.properties).toHaveProperty('agent_id'); expect(deletePassageDefinition.inputSchema.properties).toHaveProperty('memory_id'); }); }); describe('Functionality Tests', () => { it('should delete passage successfully', async () => { const agentId = 'agent-123'; const memoryId = 'passage-456'; // Mock successful deletion (returns empty response) mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); // Verify API call expect(mockServer.api.delete).toHaveBeenCalledWith( `/agents/${agentId}/archival-memory/${memoryId}`, expect.objectContaining({ headers: expect.any(Object), }), ); // Verify response contains IDs const data = expectValidToolResponse(result); expect(data.memory_id).toBe(memoryId); expect(data.agent_id).toBe(agentId); }); it('should handle special characters in agent ID', async () => { const agentId = 'agent@special#id'; const encodedAgentId = encodeURIComponent(agentId); const memoryId = 'passage-123'; mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); expect(mockServer.api.delete).toHaveBeenCalledWith( `/agents/${encodedAgentId}/archival-memory/${memoryId}`, expect.any(Object), ); const data = expectValidToolResponse(result); expect(data.agent_id).toBe(agentId); }); it('should handle special characters in memory ID', async () => { const agentId = 'agent-123'; const memoryId = 'passage@special#id'; const encodedMemoryId = encodeURIComponent(memoryId); mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); expect(mockServer.api.delete).toHaveBeenCalledWith( `/agents/${agentId}/archival-memory/${encodedMemoryId}`, expect.any(Object), ); const data = expectValidToolResponse(result); expect(data.memory_id).toBe(memoryId); }); it('should handle UUID format IDs', async () => { const agentId = '550e8400-e29b-41d4-a716-446655440000'; const memoryId = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'; mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); expect(mockServer.api.delete).toHaveBeenCalledWith( `/agents/${agentId}/archival-memory/${memoryId}`, expect.any(Object), ); const data = expectValidToolResponse(result); expect(data.agent_id).toBe(agentId); expect(data.memory_id).toBe(memoryId); }); it('should handle 204 No Content response', async () => { const agentId = 'agent-204'; const memoryId = 'passage-204'; // Mock 204 response (no content) mockServer.api.delete.mockResolvedValueOnce({ data: null, status: 204, statusText: 'No Content', }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); const data = expectValidToolResponse(result); expect(data.memory_id).toBe(memoryId); expect(data.agent_id).toBe(agentId); }); it('should delete multiple passages in sequence', async () => { const agentId = 'agent-multi'; const memoryIds = ['passage-1', 'passage-2', 'passage-3']; for (const memoryId of memoryIds) { mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); const data = expectValidToolResponse(result); expect(data.memory_id).toBe(memoryId); } expect(mockServer.api.delete).toHaveBeenCalledTimes(3); }); it('should handle deletion with complex IDs', async () => { const agentId = 'agent_123-456.test'; const memoryId = 'passage_789-012.data'; mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); const data = expectValidToolResponse(result); expect(data.agent_id).toBe(agentId); expect(data.memory_id).toBe(memoryId); }); }); describe('Error Handling', () => { it('should handle missing agent_id', async () => { await expect( handleDeletePassage(mockServer, { memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith( 'Missing required argument: agent_id', ); }); it('should handle missing memory_id', async () => { await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith( 'Missing required argument: memory_id', ); }); it('should handle null args', async () => { await expect(handleDeletePassage(mockServer, null)).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith( 'Missing required argument: agent_id', ); }); it('should handle 404 not found error', async () => { const agentId = 'agent-123'; const memoryId = 'non-existent-passage'; const error = new Error('Not found'); error.response = { status: 404, data: { error: 'Passage not found' }, }; mockServer.api.delete.mockRejectedValueOnce(error); await expect( handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith( `Agent or Passage not found: agent_id=${agentId}, memory_id=${memoryId}`, ); }); it('should handle 401 unauthorized error', async () => { const error = new Error('Unauthorized'); error.response = { status: 401, data: { error: 'Invalid authentication' }, }; mockServer.api.delete.mockRejectedValueOnce(error); await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith(error); }); it('should handle 403 forbidden error', async () => { const error = new Error('Forbidden'); error.response = { status: 403, data: { error: 'Cannot delete this passage' }, }; mockServer.api.delete.mockRejectedValueOnce(error); await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith(error); }); it('should handle 409 conflict error', async () => { const error = new Error('Conflict'); error.response = { status: 409, data: { error: 'Passage is in use and cannot be deleted' }, }; mockServer.api.delete.mockRejectedValueOnce(error); await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith(error); }); it('should handle server errors', async () => { const error = new Error('Internal server error'); error.response = { status: 500, data: { error: 'Database error during deletion' }, }; mockServer.api.delete.mockRejectedValueOnce(error); await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith(error); }); it('should handle network errors without response', async () => { const error = new Error('Network error: Connection refused'); // No response property mockServer.api.delete.mockRejectedValueOnce(error); await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith(error); }); it('should handle timeout errors', async () => { const error = new Error('Request timeout'); error.code = 'ECONNABORTED'; mockServer.api.delete.mockRejectedValueOnce(error); await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith(error); }); }); describe('Edge Cases', () => { it('should handle empty string IDs gracefully', async () => { await expect( handleDeletePassage(mockServer, { agent_id: '', memory_id: 'passage-123', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith( 'Missing required argument: agent_id', ); await expect( handleDeletePassage(mockServer, { agent_id: 'agent-123', memory_id: '', }), ).rejects.toThrow(); expect(mockServer.createErrorResponse).toHaveBeenCalledWith( 'Missing required argument: memory_id', ); }); it('should handle very long IDs', async () => { const longAgentId = 'agent-' + 'x'.repeat(1000); const longMemoryId = 'passage-' + 'y'.repeat(1000); mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: longAgentId, memory_id: longMemoryId, }); const data = expectValidToolResponse(result); expect(data.agent_id).toBe(longAgentId); expect(data.memory_id).toBe(longMemoryId); }); it('should handle IDs with unicode characters', async () => { const agentId = 'agent-你好-🚀'; const memoryId = 'passage-世界-💬'; const encodedAgentId = encodeURIComponent(agentId); const encodedMemoryId = encodeURIComponent(memoryId); mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); expect(mockServer.api.delete).toHaveBeenCalledWith( `/agents/${encodedAgentId}/archival-memory/${encodedMemoryId}`, expect.any(Object), ); const data = expectValidToolResponse(result); expect(data.agent_id).toBe(agentId); expect(data.memory_id).toBe(memoryId); }); it('should handle deletion with unexpected response data', async () => { const agentId = 'agent-unexpected'; const memoryId = 'passage-unexpected'; // API returns unexpected data structure mockServer.api.delete.mockResolvedValueOnce({ data: { success: true, deleted_count: 1, message: 'Passage deleted successfully', }, }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); // Should still return standard response const data = expectValidToolResponse(result); expect(data.memory_id).toBe(memoryId); expect(data.agent_id).toBe(agentId); }); it('should handle rapid successive deletions', async () => { const agentId = 'agent-rapid'; const memoryIds = Array.from({ length: 10 }, (_, i) => `passage-${i}`); // Mock all deletions memoryIds.forEach(() => { mockServer.api.delete.mockResolvedValueOnce({ data: {} }); }); // Delete all passages rapidly const promises = memoryIds.map((memoryId) => handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }), ); const results = await Promise.all(promises); // Verify all deletions succeeded results.forEach((result, index) => { const data = expectValidToolResponse(result); expect(data.memory_id).toBe(memoryIds[index]); }); expect(mockServer.api.delete).toHaveBeenCalledTimes(10); }); it('should handle case-sensitive IDs correctly', async () => { const agentId = 'Agent-ABC'; const memoryId = 'Passage-XYZ'; mockServer.api.delete.mockResolvedValueOnce({ data: {} }); const result = await handleDeletePassage(mockServer, { agent_id: agentId, memory_id: memoryId, }); // Should preserve case const data = expectValidToolResponse(result); expect(data.agent_id).toBe('Agent-ABC'); expect(data.memory_id).toBe('Passage-XYZ'); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oculairmedia/Letta-MCP-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server