diff --git a/src/command/commandManager.ts b/src/command/commandManager.ts index af3f597..0a892f1 100644 --- a/src/command/commandManager.ts +++ b/src/command/commandManager.ts @@ -52,16 +52,27 @@ class CommandManager { // 定义一个异步函数来处理单个命令 const processCommand = async (commandObj: Command, userInput: string) => { // 转义特殊字符 - const escapedPattern = commandObj.pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - const commandPattern = new RegExp( - `\\/(${escapedPattern.replace('\\{\\{prompt\\}\\}', '\\{\\{(.+?)\\}\\}')})`, - 'g' - ); + let commandPattern: RegExp; + if (commandObj.pattern.indexOf("{{") > 0) { + const escapedPattern = commandObj.pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + commandPattern = new RegExp( + `\\/(${escapedPattern.replace('\\{\\{prompt\\}\\}', '\\{\\{(.+?)\\}\\}')})`, + 'g' + ); + } else { + const escapedPattern = commandObj.pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); + // Update the regex pattern to match commands ending with space or newline + commandPattern = new RegExp( + `\\/(?${escapedPattern.replace('{{prompt}}', '(?.+?)')})(?=\\s|\\n|$)`, + 'g' + ); + } + const matches = Array.from(text.matchAll(commandPattern)); const replacements = await Promise.all( matches.map(async (match) => { - const matchedUserInput = match[2]; + const matchedUserInput = commandObj.pattern.indexOf("{{") > 0 ? match[2] : match.groups!.userInput; return await commandObj.handler(commandObj.name, matchedUserInput); }) ); diff --git a/src/handler/sendMessageBase.ts b/src/handler/sendMessageBase.ts index 777e29d..ca4b2d0 100644 --- a/src/handler/sendMessageBase.ts +++ b/src/handler/sendMessageBase.ts @@ -95,7 +95,7 @@ export async function parseMessageAndSetOptions(message: any, chatOptions: any): } chatOptions.header = getInstructionFiles(); - if (parsedMessage.instruction && parsedMessage.instruction.length > 0) { + if ((parsedMessage.instruction && parsedMessage.instruction.length > 0) || newText2 !== message.text) { chatOptions.header = parsedMessage.instruction; } diff --git a/test/command/commandManager.test.ts b/test/command/commandManager.test.ts index d5a1f75..da2826f 100644 --- a/test/command/commandManager.test.ts +++ b/test/command/commandManager.test.ts @@ -1,80 +1,122 @@ import { expect } from 'chai'; import { describe, it } from 'mocha'; import CommandManager, { Command } from '../../src/command/commandManager'; -import CustomCommands, { Command as CCommand} from '../../src/command/customCommand'; +import CustomCommands, { Command as CCommand } from '../../src/command/customCommand'; describe('CommandManager', () => { - let commandManager: CommandManager; + let commandManager: CommandManager; - beforeEach(() => { - commandManager = CommandManager.getInstance(); - }); + beforeEach(() => { + commandManager = CommandManager.getInstance(); + }); - afterEach(() => { - // Reset the command list after each test - commandManager['commands'] = []; - }); + afterEach(() => { + // Reset the command list after each test + commandManager['commands'] = []; + }); - it('should register a command', () => { + it('should register a command', () => { + const command: Command = { + name: 'test', + pattern: 'test', + description: 'Test command', + args: 0, + handler: async (commandName: string, userInput: string) => { + return 'Test result'; + }, + }; + + commandManager.registerCommand(command); + expect(commandManager['commands']).to.include(command); + }); + + it('should return the command list', () => { + const command: Command = { + name: 'test', + pattern: 'test', + description: 'Test command', + args: 0, + handler: async (commandName: string, userInput: string) => { + return 'Test result'; + }, + }; + + commandManager.registerCommand(command); + expect(commandManager.getCommandList()).to.include(command); + }); + + it('should process text with a command', async () => { + const command: Command = { + name: 'test', + pattern: 'test', + description: 'Test command', + args: 0, + handler: async (commandName: string, userInput: string) => { + return 'Test result'; + }, + }; + + commandManager.registerCommand(command); + const result = await commandManager.processText('/test'); + expect(result).to.equal('Test result'); + }); + + it('should process text with a custom command', async () => { + const customCommand: CCommand = { + name: 'customTest', + pattern: 'customTest', + description: 'Custom test command', + message: 'Custom test result', + args: 0, + show: true, + default: false, + instructions: [] + }; + + CustomCommands.getInstance().regCommand(customCommand); + const result = await commandManager.processText('/customTest'); + expect(result).to.equal(' Custom test result'); + }); + + it('should match /xxx with space or newline, but not with other characters', async () => { + const command: Command = { + name: 'xxx', + pattern: 'xxx', + description: 'Test command', + args: 0, + handler: async (commandName: string, userInput: string) => { + return 'Matched'; + }, + }; + + commandManager.registerCommand(command); + + const result1 = await commandManager.processText('/xxx someother text'); + expect(result1).to.equal('Matched someother text'); + + const result2 = await commandManager.processText('/xxx\n'); + expect(result2).to.equal('Matched\n'); + + const result3 = await commandManager.processText('/xxx-123'); + expect(result3).to.equal('/xxx-123'); + + const result4 = await commandManager.processText('/xxx123'); + expect(result4).to.equal('/xxx123'); + }); + + it('should process text with a command containing two arguments', async () => { const command: Command = { - name: 'test', - pattern: 'test', - description: 'Test command', - args: 0, - handler: async (commandName: string, userInput: string) => { - return 'Test result'; - }, + name: 'test', + pattern: 'xxx {{prompt}}', + description: 'Test command with two arguments ${1} and ${2}', + args: 2, + handler: async (commandName: string, userInput: string) => { + return `Test result with argument: ["arg1", "arg2"]`; + }, }; commandManager.registerCommand(command); - expect(commandManager['commands']).to.include(command); - }); - - it('should return the command list', () => { - const command: Command = { - name: 'test', - pattern: 'test', - description: 'Test command', - args: 0, - handler: async (commandName: string, userInput: string) => { - return 'Test result'; - }, - }; - - commandManager.registerCommand(command); - expect(commandManager.getCommandList()).to.include(command); - }); - - it('should process text with a command', async () => { - const command: Command = { - name: 'test', - pattern: 'test', - description: 'Test command', - args: 0, - handler: async (commandName: string, userInput: string) => { - return 'Test result'; - }, - }; - - commandManager.registerCommand(command); - const result = await commandManager.processText('/test'); - expect(result).to.equal('Test result'); - }); - - it('should process text with a custom command', async () => { - const customCommand: CCommand = { - name: 'customTest', - pattern: 'customTest', - description: 'Custom test command', - message: 'Custom test result', - args: 0, - show: true, - default: false, - instructions: [] - }; - - CustomCommands.getInstance().regCommand(customCommand); - const result = await commandManager.processText('/customTest'); - expect(result).to.equal(' Custom test result'); - }); + const result = await commandManager.processText('/xxx {{["arg1", "arg2"]}}'); + expect(result).to.equal('Test result with argument: ["arg1", "arg2"]'); +}); }); \ No newline at end of file diff --git a/test/context/customContext.test.ts b/test/context/customContext.test.ts index 2246408..f16ca48 100644 --- a/test/context/customContext.test.ts +++ b/test/context/customContext.test.ts @@ -2,6 +2,7 @@ import { expect } from 'chai'; import CustomContexts from '../../src/context/customContext'; import fs from 'fs'; import path from 'path'; +import CustomCommands, { Command } from '../../src/command/customCommand'; describe('CustomContexts', () => { const workflowsDir = path.join(__dirname, 'test-workflows'); @@ -33,4 +34,6 @@ describe('CustomContexts', () => { expect(contexts[0].name).to.equal('test-context'); expect(contexts[0].description).to.equal('Test context'); }); + + }); \ No newline at end of file