diff --git a/__tests__/unit/context.test.ts b/__tests__/unit/context.test.ts index e4b0ab5..36f0a37 100644 --- a/__tests__/unit/context.test.ts +++ b/__tests__/unit/context.test.ts @@ -1,111 +1,59 @@ -import { describe, test, expect } from "bun:test"; -import { buildConversationContext } from "../../src/utils/context"; -import { - createMockRuntime, - createMockMessage, - createMockState, -} from "../helpers/mockRuntime"; +import { describe, test, expect } from 'bun:test'; +import { buildConversationContext } from '../../src/utils/context'; +import { createMockMessage, createMockState } from '../helpers/mockRuntime'; -describe("buildConversationContext", () => { - test("returns message text when no recent messages", () => { - const runtime = createMockRuntime(); +describe('buildConversationContext', () => { + test('returns message text when no recent messages in values', () => { const message = createMockMessage({ - content: { text: "Activate my workflow" }, + content: { text: 'Activate my workflow' }, }); const state = createMockState(); - const result = buildConversationContext(runtime, message, state); - expect(result).toBe("Activate my workflow"); + const result = buildConversationContext(message, state); + expect(result).toBe('Activate my workflow'); }); - test("returns empty string when no text and no recent messages", () => { - const runtime = createMockRuntime(); - const message = createMockMessage({ content: { text: "" } }); + test('returns empty string when no text and no recent messages', () => { + const message = createMockMessage({ content: { text: '' } }); const state = createMockState(); - const result = buildConversationContext(runtime, message, state); - expect(result).toBe(""); + const result = buildConversationContext(message, state); + expect(result).toBe(''); }); - test("handles undefined state", () => { - const runtime = createMockRuntime(); - const message = createMockMessage({ content: { text: "Hello" } }); + test('handles undefined state', () => { + const message = createMockMessage({ content: { text: 'Hello' } }); - const result = buildConversationContext(runtime, message, undefined); - expect(result).toBe("Hello"); + const result = buildConversationContext(message, undefined); + expect(result).toBe('Hello'); }); - test("includes recent messages in context", () => { - const runtime = createMockRuntime({ agentId: "agent-001" }); - const message = createMockMessage({ content: { text: "Activate it" } }); + test('appends current request to recentMessages', () => { + const message = createMockMessage({ content: { text: 'Activate it' } }); const state = createMockState({ - data: { - recentMessages: [ - { - entityId: "user-001", - content: { text: "Show me my workflows" }, - }, - { - entityId: "agent-001", - content: { text: "Here are your workflows: Stripe, Gmail" }, - }, - ], + values: { + recentMessages: + 'User: Show me my workflows\nAssistant: Here are your workflows: Stripe, Gmail', }, }); - const result = buildConversationContext(runtime, message, state); - expect(result).toContain("User: Show me my workflows"); - expect(result).toContain("Assistant: Here are your workflows"); - expect(result).toContain("Current request: Activate it"); + const result = buildConversationContext(message, state); + expect(result).toContain('User: Show me my workflows'); + expect(result).toContain('Assistant: Here are your workflows'); + expect(result).toContain('Current request: Activate it'); }); - test("limits to last 5 messages", () => { - const runtime = createMockRuntime({ agentId: "agent-001" }); - const message = createMockMessage({ content: { text: "Current" } }); - - const messages = Array.from({ length: 10 }, (_, i) => ({ - entityId: "user-001", - content: { text: `Message ${i}` }, - })); + test('preserves recentMessages formatting from provider', () => { + const message = createMockMessage({ content: { text: 'Do something' } }); + const preformattedMessages = `[2024-01-01 10:00] Alice: Hello +[2024-01-01 10:01] Bot: Hi there! +[2024-01-01 10:02] Alice: Help me`; const state = createMockState({ - data: { recentMessages: messages }, - }); - - const result = buildConversationContext(runtime, message, state); - // Should only contain the last 5 messages (5-9) - expect(result).not.toContain("Message 4"); - expect(result).toContain("Message 5"); - expect(result).toContain("Message 9"); - }); - - test("labels agent messages as Assistant", () => { - const runtime = createMockRuntime({ agentId: "agent-001" }); - const message = createMockMessage({ content: { text: "Next" } }); - const state = createMockState({ - data: { - recentMessages: [ - { entityId: "agent-001", content: { text: "Bot response" } }, - ], - }, - }); - - const result = buildConversationContext(runtime, message, state); - expect(result).toContain("Assistant: Bot response"); - }); - - test("labels non-agent messages as User", () => { - const runtime = createMockRuntime({ agentId: "agent-001" }); - const message = createMockMessage({ content: { text: "Next" } }); - const state = createMockState({ - data: { - recentMessages: [ - { entityId: "someone-else", content: { text: "User msg" } }, - ], - }, + values: { recentMessages: preformattedMessages }, }); - const result = buildConversationContext(runtime, message, state); - expect(result).toContain("User: User msg"); + const result = buildConversationContext(message, state); + expect(result).toBe(`${preformattedMessages}\n\nCurrent request: Do something`); }); }); diff --git a/package.json b/package.json index 9519624..545c81c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-n8n-workflow", - "version": "1.0.10", + "version": "1.0.11", "description": "ElizaOS plugin for generating and managing n8n workflows from natural language", "type": "module", "main": "dist/index.js", diff --git a/src/actions/activateWorkflow.ts b/src/actions/activateWorkflow.ts index 95c70a2..982e4f4 100644 --- a/src/actions/activateWorkflow.ts +++ b/src/actions/activateWorkflow.ts @@ -176,7 +176,7 @@ export const activateWorkflowAction: Action = { return { success: false }; } - const context = buildConversationContext(runtime, message, state); + const context = buildConversationContext(message, state); const matchResult = await matchWorkflow(runtime, context, workflows); if (!matchResult.matchedWorkflowId || matchResult.confidence === 'none') { diff --git a/src/actions/createWorkflow.ts b/src/actions/createWorkflow.ts index 05d1b08..9b3cf29 100644 --- a/src/actions/createWorkflow.ts +++ b/src/actions/createWorkflow.ts @@ -269,7 +269,7 @@ export const createWorkflowAction: Action = { const userText = (content.text ?? '').trim(); const userId = message.entityId; const cacheKey = `workflow_draft:${userId}`; - const generationContext = buildConversationContext(runtime, message, state); + const generationContext = buildConversationContext(message, state); try { let existingDraft = await runtime.getCache(cacheKey); diff --git a/src/actions/deactivateWorkflow.ts b/src/actions/deactivateWorkflow.ts index abc12c6..bc1b12b 100644 --- a/src/actions/deactivateWorkflow.ts +++ b/src/actions/deactivateWorkflow.ts @@ -114,7 +114,7 @@ export const deactivateWorkflowAction: Action = { return { success: false }; } - const context = buildConversationContext(runtime, message, state); + const context = buildConversationContext(message, state); const matchResult = await matchWorkflow(runtime, context, workflows); if (!matchResult.matchedWorkflowId || matchResult.confidence === 'none') { diff --git a/src/actions/deleteWorkflow.ts b/src/actions/deleteWorkflow.ts index 3b84109..8f86502 100644 --- a/src/actions/deleteWorkflow.ts +++ b/src/actions/deleteWorkflow.ts @@ -108,7 +108,7 @@ export const deleteWorkflowAction: Action = { return { success: false }; } - const context = buildConversationContext(runtime, message, state); + const context = buildConversationContext(message, state); const matchResult = await matchWorkflow(runtime, context, workflows); if (!matchResult.matchedWorkflowId || matchResult.confidence === 'none') { diff --git a/src/actions/getExecutions.ts b/src/actions/getExecutions.ts index 13ff386..d507bc4 100644 --- a/src/actions/getExecutions.ts +++ b/src/actions/getExecutions.ts @@ -98,7 +98,7 @@ export const getExecutionsAction: Action = { return { success: false }; } - const context = buildConversationContext(runtime, message, state); + const context = buildConversationContext(message, state); const matchResult = await matchWorkflow(runtime, context, workflows); if (!matchResult.matchedWorkflowId || matchResult.confidence === 'none') { diff --git a/src/utils/context.ts b/src/utils/context.ts index fe38b65..1391a9f 100644 --- a/src/utils/context.ts +++ b/src/utils/context.ts @@ -1,22 +1,15 @@ import { type IAgentRuntime, type Memory, type State, type UUID } from '@elizaos/core'; -export function buildConversationContext( - runtime: IAgentRuntime, - message: Memory, - state: State | undefined -): string { - const recentMessages = (state?.data?.recentMessages as Memory[]) || []; +export function buildConversationContext(message: Memory, state: State | undefined): string { + const raw = state?.values?.recentMessages; + const recentMessages = typeof raw === 'string' ? raw : ''; + const currentText = message.content?.text ?? ''; - if (recentMessages.length === 0) { - return message.content.text || ''; + if (!recentMessages) { + return currentText; } - const context = recentMessages - .slice(-5) - .map((m) => `${m.entityId === runtime.agentId ? 'Assistant' : 'User'}: ${m.content.text}`) - .join('\n'); - - return `Recent conversation:\n${context}\n\nCurrent request: ${message.content.text || ''}`; + return `${recentMessages}\n\nCurrent request: ${currentText}`; } export async function getUserTagName(runtime: IAgentRuntime, userId: string): Promise {