diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index f97370181c..87f887f46b 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -70,6 +70,7 @@ "whatsapp", "wikipedia", "x", - "youtube" + "youtube", + "zep" ] } diff --git a/apps/docs/content/docs/en/tools/microsoft_teams.mdx b/apps/docs/content/docs/en/tools/microsoft_teams.mdx index 1a11e709a2..91d4ba3cb9 100644 --- a/apps/docs/content/docs/en/tools/microsoft_teams.mdx +++ b/apps/docs/content/docs/en/tools/microsoft_teams.mdx @@ -113,6 +113,7 @@ Read content from a Microsoft Teams chat | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `chatId` | string | Yes | The ID of the chat to read from | +| `includeAttachments` | boolean | No | Download and include message attachments \(hosted contents\) into storage | #### Output @@ -125,6 +126,7 @@ Read content from a Microsoft Teams chat | `attachmentCount` | number | Total number of attachments found | | `attachmentTypes` | array | Types of attachments found | | `content` | string | Formatted content of chat messages | +| `attachments` | file[] | Uploaded attachments for convenience \(flattened\) | ### `microsoft_teams_write_chat` @@ -158,6 +160,7 @@ Read content from a Microsoft Teams channel | --------- | ---- | -------- | ----------- | | `teamId` | string | Yes | The ID of the team to read from | | `channelId` | string | Yes | The ID of the channel to read from | +| `includeAttachments` | boolean | No | Download and include message attachments \(hosted contents\) into storage | #### Output @@ -171,6 +174,7 @@ Read content from a Microsoft Teams channel | `attachmentCount` | number | Total number of attachments found | | `attachmentTypes` | array | Types of attachments found | | `content` | string | Formatted content of channel messages | +| `attachments` | file[] | Uploaded attachments for convenience \(flattened\) | ### `microsoft_teams_write_channel` diff --git a/apps/docs/content/docs/en/tools/outlook.mdx b/apps/docs/content/docs/en/tools/outlook.mdx index 48e4ad3016..f9493b72d7 100644 --- a/apps/docs/content/docs/en/tools/outlook.mdx +++ b/apps/docs/content/docs/en/tools/outlook.mdx @@ -206,6 +206,7 @@ Read emails from Outlook | --------- | ---- | -------- | ----------- | | `folder` | string | No | Folder ID to read emails from \(default: Inbox\) | | `maxResults` | number | No | Maximum number of emails to retrieve \(default: 1, max: 10\) | +| `includeAttachments` | boolean | No | Download and include email attachments | #### Output @@ -213,6 +214,7 @@ Read emails from Outlook | --------- | ---- | ----------- | | `message` | string | Success or status message | | `results` | array | Array of email message objects | +| `attachments` | file[] | All email attachments flattened from all emails | ### `outlook_forward` diff --git a/apps/docs/content/docs/en/tools/zep.mdx b/apps/docs/content/docs/en/tools/zep.mdx new file mode 100644 index 0000000000..6c8437b44d --- /dev/null +++ b/apps/docs/content/docs/en/tools/zep.mdx @@ -0,0 +1,246 @@ +--- +title: Zep +description: Long-term memory for AI agents +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + + + + + `} +/> + +## Usage Instructions + +Integrate Zep for long-term memory management. Create threads, add messages, retrieve context with AI-powered summaries and facts extraction. + + + +## Tools + +### `zep_create_thread` + +Start a new conversation thread in Zep + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `threadId` | string | Yes | Unique identifier for the thread | +| `userId` | string | Yes | User ID associated with the thread | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `threadId` | string | The thread ID | +| `userId` | string | The user ID | +| `uuid` | string | Internal UUID | +| `createdAt` | string | Creation timestamp | +| `projectUuid` | string | Project UUID | + +### `zep_get_threads` + +List all conversation threads + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `pageSize` | number | No | Number of threads to retrieve per page | +| `pageNumber` | number | No | Page number for pagination | +| `orderBy` | string | No | Field to order results by \(created_at, updated_at, user_id, thread_id\) | +| `asc` | boolean | No | Order direction: true for ascending, false for descending | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `threads` | array | Array of thread objects | +| `responseCount` | number | Number of threads in this response | +| `totalCount` | number | Total number of threads available | + +### `zep_delete_thread` + +Delete a conversation thread from Zep + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `threadId` | string | Yes | Thread ID to delete | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `deleted` | boolean | Whether the thread was deleted | + +### `zep_get_context` + +Retrieve user context from a thread with summary or basic mode + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `threadId` | string | Yes | Thread ID to get context from | +| `mode` | string | No | Context mode: "summary" \(natural language\) or "basic" \(raw facts\) | +| `minRating` | number | No | Minimum rating by which to filter relevant facts | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `context` | string | The context string \(summary or basic\) | +| `facts` | array | Extracted facts | +| `entities` | array | Extracted entities | +| `summary` | string | Conversation summary | + +### `zep_get_messages` + +Retrieve messages from a thread + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `threadId` | string | Yes | Thread ID to get messages from | +| `limit` | number | No | Maximum number of messages to return | +| `cursor` | string | No | Cursor for pagination | +| `lastn` | number | No | Number of most recent messages to return \(overrides limit and cursor\) | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messages` | array | Array of message objects | +| `rowCount` | number | Number of messages in this response | +| `totalCount` | number | Total number of messages in the thread | + +### `zep_add_messages` + +Add messages to an existing thread + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `threadId` | string | Yes | Thread ID to add messages to | +| `messages` | json | Yes | Array of message objects with role and content | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `context` | string | Updated context after adding messages | +| `messageIds` | array | Array of added message UUIDs | +| `threadId` | string | The thread ID | + +### `zep_add_user` + +Create a new user in Zep + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `userId` | string | Yes | Unique identifier for the user | +| `email` | string | No | User email address | +| `firstName` | string | No | User first name | +| `lastName` | string | No | User last name | +| `metadata` | json | No | Additional metadata as JSON object | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `userId` | string | The user ID | +| `email` | string | User email | +| `firstName` | string | User first name | +| `lastName` | string | User last name | +| `uuid` | string | Internal UUID | +| `createdAt` | string | Creation timestamp | +| `metadata` | object | User metadata | + +### `zep_get_user` + +Retrieve user information from Zep + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `userId` | string | Yes | User ID to retrieve | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `userId` | string | The user ID | +| `email` | string | User email | +| `firstName` | string | User first name | +| `lastName` | string | User last name | +| `uuid` | string | Internal UUID | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last update timestamp | +| `metadata` | object | User metadata | + +### `zep_get_user_threads` + +List all conversation threads for a specific user + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `userId` | string | Yes | User ID to get threads for | +| `limit` | number | No | Maximum number of threads to return | +| `apiKey` | string | Yes | Your Zep API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `threads` | array | Array of thread objects for this user | +| `userId` | string | The user ID | + + + +## Notes + +- Category: `tools` +- Type: `zep` diff --git a/apps/sim/app/(landing)/components/footer/footer.tsx b/apps/sim/app/(landing)/components/footer/footer.tsx index 942a3e32e3..8fbf783b8f 100644 --- a/apps/sim/app/(landing)/components/footer/footer.tsx +++ b/apps/sim/app/(landing)/components/footer/footer.tsx @@ -90,6 +90,7 @@ const tools = [ 'Wikipedia', 'X', 'YouTube', + 'Zep', ] interface FooterProps { diff --git a/apps/sim/blocks/blocks/zep.ts b/apps/sim/blocks/blocks/zep.ts new file mode 100644 index 0000000000..a676e13f12 --- /dev/null +++ b/apps/sim/blocks/blocks/zep.ts @@ -0,0 +1,329 @@ +import { ZepIcon } from '@/components/icons' +import { AuthMode, type BlockConfig } from '@/blocks/types' +import type { ZepResponse } from '@/tools/zep/types' + +export const ZepBlock: BlockConfig = { + type: 'zep', + name: 'Zep', + description: 'Long-term memory for AI agents', + authMode: AuthMode.ApiKey, + longDescription: + 'Integrate Zep for long-term memory management. Create threads, add messages, retrieve context with AI-powered summaries and facts extraction.', + bgColor: '#E8E8E8', + icon: ZepIcon, + category: 'tools', + docsLink: 'https://docs.sim.ai/tools/zep', + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + layout: 'half', + options: [ + { label: 'Create Thread', id: 'create_thread' }, + { label: 'Add Messages', id: 'add_messages' }, + { label: 'Get Context', id: 'get_context' }, + { label: 'Get Messages', id: 'get_messages' }, + { label: 'Get Threads', id: 'get_threads' }, + { label: 'Delete Thread', id: 'delete_thread' }, + { label: 'Add User', id: 'add_user' }, + { label: 'Get User', id: 'get_user' }, + { label: 'Get User Threads', id: 'get_user_threads' }, + ], + placeholder: 'Select an operation', + value: () => 'create_thread', + }, + { + id: 'threadId', + title: 'Thread ID', + type: 'short-input', + layout: 'full', + placeholder: 'Enter unique thread identifier', + condition: { + field: 'operation', + value: ['create_thread', 'add_messages', 'get_context', 'get_messages', 'delete_thread'], + }, + required: true, + }, + { + id: 'userId', + title: 'User ID', + type: 'short-input', + layout: 'full', + placeholder: 'Enter user identifier', + condition: { + field: 'operation', + value: ['create_thread', 'add_user', 'get_user', 'get_user_threads'], + }, + required: true, + }, + { + id: 'email', + title: 'Email', + type: 'short-input', + layout: 'half', + placeholder: 'user@example.com', + condition: { + field: 'operation', + value: 'add_user', + }, + }, + { + id: 'firstName', + title: 'First Name', + type: 'short-input', + layout: 'half', + placeholder: 'John', + condition: { + field: 'operation', + value: 'add_user', + }, + }, + { + id: 'lastName', + title: 'Last Name', + type: 'short-input', + layout: 'half', + placeholder: 'Doe', + condition: { + field: 'operation', + value: 'add_user', + }, + }, + { + id: 'metadata', + title: 'Metadata', + type: 'code', + layout: 'full', + placeholder: '{"key": "value"}', + language: 'json', + condition: { + field: 'operation', + value: 'add_user', + }, + }, + { + id: 'messages', + title: 'Messages', + type: 'code', + layout: 'full', + placeholder: '[{"role": "user", "content": "Hello!"}]', + language: 'json', + condition: { + field: 'operation', + value: 'add_messages', + }, + required: true, + }, + { + id: 'mode', + title: 'Context Mode', + type: 'dropdown', + layout: 'half', + options: [ + { label: 'Summary (Natural Language)', id: 'summary' }, + { label: 'Basic (Raw Facts)', id: 'basic' }, + ], + placeholder: 'Select context mode', + value: () => 'summary', + condition: { + field: 'operation', + value: 'get_context', + }, + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + layout: 'full', + placeholder: 'Enter your Zep API key', + password: true, + required: true, + }, + { + id: 'limit', + title: 'Result Limit', + type: 'slider', + layout: 'full', + min: 1, + max: 100, + step: 1, + integer: true, + condition: { + field: 'operation', + value: ['get_messages', 'get_threads'], + }, + }, + ], + tools: { + access: [ + 'zep_create_thread', + 'zep_get_threads', + 'zep_delete_thread', + 'zep_get_context', + 'zep_get_messages', + 'zep_add_messages', + 'zep_add_user', + 'zep_get_user', + 'zep_get_user_threads', + ], + config: { + tool: (params: Record) => { + const operation = params.operation || 'create_thread' + switch (operation) { + case 'create_thread': + return 'zep_create_thread' + case 'add_messages': + return 'zep_add_messages' + case 'get_context': + return 'zep_get_context' + case 'get_messages': + return 'zep_get_messages' + case 'get_threads': + return 'zep_get_threads' + case 'delete_thread': + return 'zep_delete_thread' + case 'add_user': + return 'zep_add_user' + case 'get_user': + return 'zep_get_user' + case 'get_user_threads': + return 'zep_get_user_threads' + default: + return 'zep_create_thread' + } + }, + params: (params: Record) => { + const errors: string[] = [] + + // Validate required API key for all operations + if (!params.apiKey) { + errors.push('API Key is required') + } + + const operation = params.operation || 'create_thread' + + // Validate operation-specific required fields + if ( + [ + 'create_thread', + 'add_messages', + 'get_context', + 'get_messages', + 'delete_thread', + ].includes(operation) + ) { + if (!params.threadId) { + errors.push('Thread ID is required') + } + } + + if (operation === 'create_thread' || operation === 'add_user') { + if (!params.userId) { + errors.push('User ID is required') + } + } + + if (operation === 'get_user' || operation === 'get_user_threads') { + if (!params.userId) { + errors.push('User ID is required') + } + } + + if (operation === 'add_messages') { + if (!params.messages) { + errors.push('Messages are required') + } else { + try { + const messagesArray = + typeof params.messages === 'string' ? JSON.parse(params.messages) : params.messages + + if (!Array.isArray(messagesArray) || messagesArray.length === 0) { + errors.push('Messages must be a non-empty array') + } else { + for (const msg of messagesArray) { + if (!msg.role || !msg.content) { + errors.push("Each message must have 'role' and 'content' properties") + break + } + } + } + } catch (_e: any) { + errors.push('Messages must be valid JSON') + } + } + } + + // Throw error if any required fields are missing + if (errors.length > 0) { + throw new Error(`Zep Block Error: ${errors.join(', ')}`) + } + + // Build the result params + const result: Record = { + apiKey: params.apiKey, + } + + if (params.threadId) result.threadId = params.threadId + if (params.userId) result.userId = params.userId + if (params.mode) result.mode = params.mode + if (params.limit) result.limit = Number(params.limit) + if (params.email) result.email = params.email + if (params.firstName) result.firstName = params.firstName + if (params.lastName) result.lastName = params.lastName + if (params.metadata) result.metadata = params.metadata + + // Add messages for add operation + if (operation === 'add_messages') { + if (params.messages) { + try { + const messagesArray = + typeof params.messages === 'string' ? JSON.parse(params.messages) : params.messages + result.messages = messagesArray + } catch (e: any) { + throw new Error(`Zep Block Error: ${e.message || 'Messages must be valid JSON'}`) + } + } + } + + return result + }, + }, + }, + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + apiKey: { type: 'string', description: 'Zep API key' }, + threadId: { type: 'string', description: 'Thread identifier' }, + userId: { type: 'string', description: 'User identifier' }, + messages: { type: 'json', description: 'Message data array' }, + mode: { type: 'string', description: 'Context mode (summary or basic)' }, + limit: { type: 'number', description: 'Result limit' }, + email: { type: 'string', description: 'User email' }, + firstName: { type: 'string', description: 'User first name' }, + lastName: { type: 'string', description: 'User last name' }, + metadata: { type: 'json', description: 'User metadata' }, + }, + outputs: { + threadId: { type: 'string', description: 'Thread identifier' }, + userId: { type: 'string', description: 'User identifier' }, + uuid: { type: 'string', description: 'Internal UUID' }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Update timestamp' }, + threads: { type: 'json', description: 'Array of threads' }, + deleted: { type: 'boolean', description: 'Deletion status' }, + messages: { type: 'json', description: 'Message data' }, + messageIds: { type: 'json', description: 'Message identifiers' }, + context: { type: 'string', description: 'User context string' }, + facts: { type: 'json', description: 'Extracted facts' }, + entities: { type: 'json', description: 'Extracted entities' }, + summary: { type: 'string', description: 'Conversation summary' }, + batchId: { type: 'string', description: 'Batch operation ID' }, + email: { type: 'string', description: 'User email' }, + firstName: { type: 'string', description: 'User first name' }, + lastName: { type: 'string', description: 'User last name' }, + metadata: { type: 'json', description: 'User metadata' }, + responseCount: { type: 'number', description: 'Number of items in response' }, + totalCount: { type: 'number', description: 'Total number of items available' }, + rowCount: { type: 'number', description: 'Number of rows in response' }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index 31ed5f5c68..f84c842f32 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -87,6 +87,7 @@ import { WorkflowBlock } from '@/blocks/blocks/workflow' import { WorkflowInputBlock } from '@/blocks/blocks/workflow_input' import { XBlock } from '@/blocks/blocks/x' import { YouTubeBlock } from '@/blocks/blocks/youtube' +import { ZepBlock } from '@/blocks/blocks/zep' import type { BlockConfig } from '@/blocks/types' // Registry of all available blocks, alphabetically sorted @@ -127,6 +128,7 @@ export const registry: Record = { linkup: LinkupBlock, mcp: McpBlock, mem0: Mem0Block, + zep: ZepBlock, microsoft_excel: MicrosoftExcelBlock, microsoft_planner: MicrosoftPlannerBlock, microsoft_teams: MicrosoftTeamsBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index c8c1324539..38fe8b0057 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -3746,3 +3746,32 @@ export const GoogleVaultIcon = (props: SVGProps) => ( /> ) + +export function ZepIcon(props: SVGProps) { + return ( + + + + + + + ) +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 858085ab60..79de8b1692 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -212,6 +212,17 @@ import { youtubeSearchTool, youtubeVideoDetailsTool, } from '@/tools/youtube' +import { + zepAddMessagesTool, + zepAddUserTool, + zepCreateThreadTool, + zepDeleteThreadTool, + zepGetContextTool, + zepGetMessagesTool, + zepGetThreadsTool, + zepGetUserThreadsTool, + zepGetUserTool, +} from '@/tools/zep' // Registry of all available tools export const tools: Record = { @@ -333,6 +344,15 @@ export const tools: Record = { mem0_add_memories: mem0AddMemoriesTool, mem0_search_memories: mem0SearchMemoriesTool, mem0_get_memories: mem0GetMemoriesTool, + zep_create_thread: zepCreateThreadTool, + zep_get_threads: zepGetThreadsTool, + zep_delete_thread: zepDeleteThreadTool, + zep_get_context: zepGetContextTool, + zep_get_messages: zepGetMessagesTool, + zep_add_messages: zepAddMessagesTool, + zep_add_user: zepAddUserTool, + zep_get_user: zepGetUserTool, + zep_get_user_threads: zepGetUserThreadsTool, memory_add: memoryAddTool, memory_get: memoryGetTool, memory_get_all: memoryGetAllTool, diff --git a/apps/sim/tools/zep/add_messages.ts b/apps/sim/tools/zep/add_messages.ts new file mode 100644 index 0000000000..4ba0b58a26 --- /dev/null +++ b/apps/sim/tools/zep/add_messages.ts @@ -0,0 +1,110 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Add Messages Tool - Add messages to a thread (Zep v3) +export const zepAddMessagesTool: ToolConfig = { + id: 'zep_add_messages', + name: 'Add Messages', + description: 'Add messages to an existing thread', + version: '1.0.0', + + params: { + threadId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Thread ID to add messages to', + }, + messages: { + type: 'json', + required: true, + visibility: 'user-or-llm', + description: 'Array of message objects with role and content', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: (params) => `https://api.getzep.com/api/v2/threads/${params.threadId}/messages`, + method: 'POST', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + let messagesArray = params.messages + if (typeof messagesArray === 'string') { + try { + messagesArray = JSON.parse(messagesArray) + } catch (_e) { + throw new Error('Messages must be a valid JSON array') + } + } + + if (!Array.isArray(messagesArray) || messagesArray.length === 0) { + throw new Error('Messages must be a non-empty array') + } + + for (const msg of messagesArray) { + if (!msg.role || !msg.content) { + throw new Error('Each message must have role and content properties') + } + } + + return { + messages: messagesArray, + } + }, + }, + + transformResponse: async (response, params) => { + const threadId = params.threadId + + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + if (!text || text.trim() === '') { + return { + success: true, + output: { + threadId, + added: true, + }, + } + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + threadId, + context: data.context, + messageIds: data.message_uuids || [], + }, + } + }, + + outputs: { + context: { + type: 'string', + description: 'Updated context after adding messages', + }, + messageIds: { + type: 'array', + description: 'Array of added message UUIDs', + }, + threadId: { + type: 'string', + description: 'The thread ID', + }, + }, +} diff --git a/apps/sim/tools/zep/add_user.ts b/apps/sim/tools/zep/add_user.ts new file mode 100644 index 0000000000..591c0dc43c --- /dev/null +++ b/apps/sim/tools/zep/add_user.ts @@ -0,0 +1,142 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Add User Tool - Create a new user (Zep v3) +export const zepAddUserTool: ToolConfig = { + id: 'zep_add_user', + name: 'Add User', + description: 'Create a new user in Zep', + version: '1.0.0', + + params: { + userId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Unique identifier for the user', + }, + email: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'User email address', + }, + firstName: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'User first name', + }, + lastName: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'User last name', + }, + metadata: { + type: 'json', + required: false, + visibility: 'user-only', + description: 'Additional metadata as JSON object', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: 'https://api.getzep.com/api/v2/users', + method: 'POST', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = { + user_id: params.userId, + } + + if (params.email) body.email = params.email + if (params.firstName) body.first_name = params.firstName + if (params.lastName) body.last_name = params.lastName + + if (params.metadata) { + let metadataObj = params.metadata + if (typeof metadataObj === 'string') { + try { + metadataObj = JSON.parse(metadataObj) + } catch (_e) { + throw new Error('Metadata must be a valid JSON object') + } + } + body.metadata = metadataObj + } + + return body + }, + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + if (!text || text.trim() === '') { + return { + success: true, + output: {}, + } + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + userId: data.user_id, + email: data.email, + firstName: data.first_name, + lastName: data.last_name, + uuid: data.uuid, + createdAt: data.created_at, + metadata: data.metadata, + }, + } + }, + + outputs: { + userId: { + type: 'string', + description: 'The user ID', + }, + email: { + type: 'string', + description: 'User email', + }, + firstName: { + type: 'string', + description: 'User first name', + }, + lastName: { + type: 'string', + description: 'User last name', + }, + uuid: { + type: 'string', + description: 'Internal UUID', + }, + createdAt: { + type: 'string', + description: 'Creation timestamp', + }, + metadata: { + type: 'object', + description: 'User metadata', + }, + }, +} diff --git a/apps/sim/tools/zep/create_thread.ts b/apps/sim/tools/zep/create_thread.ts new file mode 100644 index 0000000000..6a98d56165 --- /dev/null +++ b/apps/sim/tools/zep/create_thread.ts @@ -0,0 +1,95 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Create Thread Tool - Start a new thread (Zep v3) +export const zepCreateThreadTool: ToolConfig = { + id: 'zep_create_thread', + name: 'Create Thread', + description: 'Start a new conversation thread in Zep', + version: '1.0.0', + + params: { + threadId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Unique identifier for the thread', + }, + userId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'User ID associated with the thread', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: 'https://api.getzep.com/api/v2/threads', + method: 'POST', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + thread_id: params.threadId, + user_id: params.userId, + }), + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + if (!text || text.trim() === '') { + return { + success: true, + output: {}, + } + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + threadId: data.thread_id, + userId: data.user_id, + uuid: data.uuid, + createdAt: data.created_at, + projectUuid: data.project_uuid, + }, + } + }, + + outputs: { + threadId: { + type: 'string', + description: 'The thread ID', + }, + userId: { + type: 'string', + description: 'The user ID', + }, + uuid: { + type: 'string', + description: 'Internal UUID', + }, + createdAt: { + type: 'string', + description: 'Creation timestamp', + }, + projectUuid: { + type: 'string', + description: 'Project UUID', + }, + }, +} diff --git a/apps/sim/tools/zep/delete_thread.ts b/apps/sim/tools/zep/delete_thread.ts new file mode 100644 index 0000000000..901a4f5ce2 --- /dev/null +++ b/apps/sim/tools/zep/delete_thread.ts @@ -0,0 +1,56 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Delete Thread Tool - Delete a thread (Zep v3) +export const zepDeleteThreadTool: ToolConfig = { + id: 'zep_delete_thread', + name: 'Delete Thread', + description: 'Delete a conversation thread from Zep', + version: '1.0.0', + + params: { + threadId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Thread ID to delete', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: (params) => `https://api.getzep.com/api/v2/threads/${params.threadId}`, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + return { + success: true, + output: { + deleted: true, + }, + } + }, + + outputs: { + deleted: { + type: 'boolean', + description: 'Whether the thread was deleted', + }, + }, +} diff --git a/apps/sim/tools/zep/get_context.ts b/apps/sim/tools/zep/get_context.ts new file mode 100644 index 0000000000..7f1a8a7571 --- /dev/null +++ b/apps/sim/tools/zep/get_context.ts @@ -0,0 +1,92 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Get User Context Tool - Retrieve user context with mode (Zep v3) +export const zepGetContextTool: ToolConfig = { + id: 'zep_get_context', + name: 'Get User Context', + description: 'Retrieve user context from a thread with summary or basic mode', + version: '1.0.0', + + params: { + threadId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Thread ID to get context from', + }, + mode: { + type: 'string', + required: false, + default: 'summary', + visibility: 'user-only', + description: 'Context mode: "summary" (natural language) or "basic" (raw facts)', + }, + minRating: { + type: 'number', + required: false, + visibility: 'user-only', + description: 'Minimum rating by which to filter relevant facts', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: (params) => { + const queryParams = new URLSearchParams() + const mode = params.mode || 'summary' + queryParams.append('mode', mode) + if (params.minRating !== undefined) queryParams.append('minRating', String(params.minRating)) + return `https://api.getzep.com/api/v2/threads/${params.threadId}/context?${queryParams.toString()}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + context: data.context || data, + facts: data.facts || [], + entities: data.entities || [], + summary: data.summary, + }, + } + }, + + outputs: { + context: { + type: 'string', + description: 'The context string (summary or basic)', + }, + facts: { + type: 'array', + description: 'Extracted facts', + }, + entities: { + type: 'array', + description: 'Extracted entities', + }, + summary: { + type: 'string', + description: 'Conversation summary', + }, + }, +} diff --git a/apps/sim/tools/zep/get_messages.ts b/apps/sim/tools/zep/get_messages.ts new file mode 100644 index 0000000000..3af99c1c99 --- /dev/null +++ b/apps/sim/tools/zep/get_messages.ts @@ -0,0 +1,94 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Get Messages Tool - Retrieve messages from a thread (Zep v3) +export const zepGetMessagesTool: ToolConfig = { + id: 'zep_get_messages', + name: 'Get Messages', + description: 'Retrieve messages from a thread', + version: '1.0.0', + + params: { + threadId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Thread ID to get messages from', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-only', + description: 'Maximum number of messages to return', + }, + cursor: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Cursor for pagination', + }, + lastn: { + type: 'number', + required: false, + visibility: 'user-only', + description: 'Number of most recent messages to return (overrides limit and cursor)', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: (params) => { + const queryParams = new URLSearchParams() + if (params.limit) queryParams.append('limit', String(params.limit)) + if (params.cursor) queryParams.append('cursor', params.cursor) + if (params.lastn) queryParams.append('lastn', String(params.lastn)) + + const queryString = queryParams.toString() + return `https://api.getzep.com/api/v2/threads/${params.threadId}/messages${queryString ? `?${queryString}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + messages: data.messages || [], + rowCount: data.row_count, + totalCount: data.total_count, + }, + } + }, + + outputs: { + messages: { + type: 'array', + description: 'Array of message objects', + }, + rowCount: { + type: 'number', + description: 'Number of messages in this response', + }, + totalCount: { + type: 'number', + description: 'Total number of messages in the thread', + }, + }, +} diff --git a/apps/sim/tools/zep/get_threads.ts b/apps/sim/tools/zep/get_threads.ts new file mode 100644 index 0000000000..322e36fa54 --- /dev/null +++ b/apps/sim/tools/zep/get_threads.ts @@ -0,0 +1,96 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Get Threads Tool - List all threads (Zep v3) +export const zepGetThreadsTool: ToolConfig = { + id: 'zep_get_threads', + name: 'Get Threads', + description: 'List all conversation threads', + version: '1.0.0', + + params: { + pageSize: { + type: 'number', + required: false, + default: 10, + visibility: 'user-only', + description: 'Number of threads to retrieve per page', + }, + pageNumber: { + type: 'number', + required: false, + default: 1, + visibility: 'user-only', + description: 'Page number for pagination', + }, + orderBy: { + type: 'string', + required: false, + visibility: 'user-only', + description: 'Field to order results by (created_at, updated_at, user_id, thread_id)', + }, + asc: { + type: 'boolean', + required: false, + default: false, + visibility: 'user-only', + description: 'Order direction: true for ascending, false for descending', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: (params) => { + const queryParams = new URLSearchParams() + queryParams.append('page_size', String(params.pageSize || 10)) + queryParams.append('page_number', String(params.pageNumber || 1)) + if (params.orderBy) queryParams.append('order_by', params.orderBy) + if (params.asc !== undefined) queryParams.append('asc', String(params.asc)) + return `https://api.getzep.com/api/v2/threads?${queryParams.toString()}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + threads: data.threads || [], + responseCount: data.response_count, + totalCount: data.total_count, + }, + } + }, + + outputs: { + threads: { + type: 'array', + description: 'Array of thread objects', + }, + responseCount: { + type: 'number', + description: 'Number of threads in this response', + }, + totalCount: { + type: 'number', + description: 'Total number of threads available', + }, + }, +} diff --git a/apps/sim/tools/zep/get_user.ts b/apps/sim/tools/zep/get_user.ts new file mode 100644 index 0000000000..2de9346700 --- /dev/null +++ b/apps/sim/tools/zep/get_user.ts @@ -0,0 +1,93 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Get User Tool - Retrieve user information (Zep v3) +export const zepGetUserTool: ToolConfig = { + id: 'zep_get_user', + name: 'Get User', + description: 'Retrieve user information from Zep', + version: '1.0.0', + + params: { + userId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'User ID to retrieve', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: (params) => `https://api.getzep.com/api/v2/users/${params.userId}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + userId: data.user_id, + email: data.email, + firstName: data.first_name, + lastName: data.last_name, + uuid: data.uuid, + createdAt: data.created_at, + updatedAt: data.updated_at, + metadata: data.metadata, + }, + } + }, + + outputs: { + userId: { + type: 'string', + description: 'The user ID', + }, + email: { + type: 'string', + description: 'User email', + }, + firstName: { + type: 'string', + description: 'User first name', + }, + lastName: { + type: 'string', + description: 'User last name', + }, + uuid: { + type: 'string', + description: 'Internal UUID', + }, + createdAt: { + type: 'string', + description: 'Creation timestamp', + }, + updatedAt: { + type: 'string', + description: 'Last update timestamp', + }, + metadata: { + type: 'object', + description: 'User metadata', + }, + }, +} diff --git a/apps/sim/tools/zep/get_user_threads.ts b/apps/sim/tools/zep/get_user_threads.ts new file mode 100644 index 0000000000..67c4b79920 --- /dev/null +++ b/apps/sim/tools/zep/get_user_threads.ts @@ -0,0 +1,73 @@ +import type { ToolConfig } from '@/tools/types' +import type { ZepResponse } from '@/tools/zep/types' + +// Get User Threads Tool - List all threads for a user (Zep v3) +export const zepGetUserThreadsTool: ToolConfig = { + id: 'zep_get_user_threads', + name: 'Get User Threads', + description: 'List all conversation threads for a specific user', + version: '1.0.0', + + params: { + userId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'User ID to get threads for', + }, + limit: { + type: 'number', + required: false, + default: 10, + visibility: 'user-only', + description: 'Maximum number of threads to return', + }, + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Your Zep API key', + }, + }, + + request: { + url: (params) => { + const limit = params.limit || 10 + return `https://api.getzep.com/api/v2/users/${params.userId}/threads?limit=${limit}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Api-Key ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response) => { + const text = await response.text() + + if (!response.ok) { + throw new Error(`Zep API error (${response.status}): ${text || response.statusText}`) + } + + const data = JSON.parse(text.replace(/^\uFEFF/, '').trim()) + + return { + success: true, + output: { + threads: data.threads || data || [], + userId: data.user_id, + }, + } + }, + + outputs: { + threads: { + type: 'array', + description: 'Array of thread objects for this user', + }, + userId: { + type: 'string', + description: 'The user ID', + }, + }, +} diff --git a/apps/sim/tools/zep/index.ts b/apps/sim/tools/zep/index.ts new file mode 100644 index 0000000000..3f3e4c3c62 --- /dev/null +++ b/apps/sim/tools/zep/index.ts @@ -0,0 +1,21 @@ +import { zepAddMessagesTool } from '@/tools/zep/add_messages' +import { zepAddUserTool } from '@/tools/zep/add_user' +import { zepCreateThreadTool } from '@/tools/zep/create_thread' +import { zepDeleteThreadTool } from '@/tools/zep/delete_thread' +import { zepGetContextTool } from '@/tools/zep/get_context' +import { zepGetMessagesTool } from '@/tools/zep/get_messages' +import { zepGetThreadsTool } from '@/tools/zep/get_threads' +import { zepGetUserTool } from '@/tools/zep/get_user' +import { zepGetUserThreadsTool } from '@/tools/zep/get_user_threads' + +export { + zepCreateThreadTool, + zepGetThreadsTool, + zepDeleteThreadTool, + zepGetContextTool, + zepGetMessagesTool, + zepAddMessagesTool, + zepAddUserTool, + zepGetUserTool, + zepGetUserThreadsTool, +} diff --git a/apps/sim/tools/zep/types.ts b/apps/sim/tools/zep/types.ts new file mode 100644 index 0000000000..ebbdcce99a --- /dev/null +++ b/apps/sim/tools/zep/types.ts @@ -0,0 +1,42 @@ +import type { ToolResponse } from '@/tools/types' + +// Zep v3 Response Type +export interface ZepResponse extends ToolResponse { + output: { + // Thread operations + threadId?: string + userId?: string + uuid?: string + createdAt?: string + updatedAt?: string + projectUuid?: string + threads?: any[] + deleted?: boolean + + // Message operations + messages?: any[] + messageIds?: string[] + added?: boolean + batchId?: string + + // Context operations + context?: string + facts?: any[] + entities?: any[] + summary?: string + + // User operations + email?: string + firstName?: string + lastName?: string + metadata?: any + + // Pagination + responseCount?: number + totalCount?: number + rowCount?: number + + // Search results (if needed in future) + searchResults?: any[] + } +}