Skip to content

Commit

Permalink
Command parsing tests (#498)
Browse files Browse the repository at this point in the history
  • Loading branch information
curtisman authored Dec 14, 2024
1 parent 027a575 commit f9c9e81
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 36 deletions.
10 changes: 6 additions & 4 deletions ts/packages/dispatcher/src/command/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,19 @@ async function parseCommand(
!context.agents.isCommandEnabled(result.parsedAppAgentName)
) {
throw new Error(
`Command for '${result.parsedAppAgentName}' is not disabled.`,
`Command for '${result.parsedAppAgentName}' is disabled.`,
);
}

if (result.table === undefined) {
throw new Error(`Unknown command '${input}'`);
}
const message =
result.suffix.length === 0
? `@${command}' requires a subcommand.`
: `'${result.suffix}' is not a subcommand for '@${command}'`;
command.length === 0
? "Command or agent name required."
: result.suffix.length === 0
? `'@${command}' requires a subcommand.`
: `'${result.suffix}' is not a subcommand for '@${command}'.`;

throw new Error(
`${message}\n\n${chalk.black(getHandlerTableUsage(result.table, command, context))}`,
Expand Down
2 changes: 1 addition & 1 deletion ts/packages/dispatcher/src/context/appAgentManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ export class AppAgentManager implements ActionConfigProvider {
} else {
record.schemas.delete(name);
changedSchemas.push([name, enableSchema]);
debug(`Schema disnabled ${name}`);
debug(`Schema disabled ${name}`);
}
}

Expand Down
119 changes: 88 additions & 31 deletions ts/packages/dispatcher/test/basic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT License.

import { createNpmAppAgentProvider } from "../src/agentProvider/npmAgentProvider.js";
import { createDispatcher } from "../src/dispatcher.js";
import { createDispatcher, Dispatcher } from "../src/dispatcher.js";
import { fileURLToPath } from "node:url";
import { getBuiltinAppAgentProvider } from "../src/utils/defaultAppProviders.js";
import {
Expand Down Expand Up @@ -32,40 +32,97 @@ function createTestClientIO(data: IAgentMessage[]): ClientIO {
}

describe("dispatcher", () => {
it("startup and shutdown", async () => {
const dispatcher = await createDispatcher("test", {
appAgentProviders: [getBuiltinAppAgentProvider()],
describe("Built-in Provider", () => {
it("startup and shutdown", async () => {
const dispatcher = await createDispatcher("test", {
appAgentProviders: [getBuiltinAppAgentProvider()],
});
await dispatcher.close();
});
await dispatcher.close();
});
it("Custom NPM App Agent Provider", async () => {
const output: IAgentMessage[] = [];
const dispatcher = await createDispatcher("test", {
appAgentProviders: [testAppAgentProvider],
clientIO: createTestClientIO(output),
});
await dispatcher.processCommand(
'@action test add --parameters \'{"a": 1, "b": 2}\'',
);
await dispatcher.close();

expect(output.length).toBe(2);
expect(output[1].message).toBe("The sum of 1 and 2 is 3");
});
it("Alternate request handler", async () => {
const output: IAgentMessage[] = [];
const dispatcher = await createDispatcher("test", {
appAgentProviders: [testAppAgentProvider],
clientIO: createTestClientIO(output),
describe("Custom Provider", () => {
describe("Command", () => {
const output: IAgentMessage[] = [];
let dispatcher: Dispatcher;
beforeAll(async () => {
dispatcher = await createDispatcher("test", {
appAgentProviders: [testAppAgentProvider],
commands: { test: true },
clientIO: createTestClientIO(output),
});
});
beforeEach(() => {
output.length = 0;
});
afterAll(async () => {
if (dispatcher) {
await dispatcher.close();
}
});
it("action command", async () => {
await dispatcher.processCommand(
'@action test add --parameters \'{"a": 1, "b": 2}\'',
);

expect(output).toHaveLength(2);
expect(output[1].message).toBe("The sum of 1 and 2 is 3");
});

const errorCommands = [
{
name: "Empty Command",
command: "@",
match: /^ERROR: Command or agent name required./,
},
{
name: "Invalid agent name",
command: "@something",
match: /^ERROR: Command or agent name required./,
},
{
name: "Missing subcommand",
command: "@test",
match: /^ERROR: '@test' requires a subcommand./,
},
{
name: "Invalid subcommand",
command: "@test sub",
match: /^ERROR: 'sub' is not a subcommand for '@test'./,
},
{
name: "Disable command",
command: "@dispatcher something",
match: /^ERROR: Command for 'dispatcher' is disabled./,
},
];

it.each(errorCommands)("$name", async ({ command, match }) => {
await dispatcher.processCommand(command);
expect(output).toHaveLength(1);
expect(typeof output[0].message).toBe("object");
const content = output[0].message as any;
expect(content.type).toBe("text");
expect(content.kind).toBe("error");
expect(content.content).toMatch(match);
});
});
await dispatcher.processCommand("@config request test");
await dispatcher.processCommand("test");
await dispatcher.close();

expect(output.length).toBe(2);
expect(output[0].message).toBe(
"Natural langue request handling agent is set to 'test'",
);
expect(output[1].message).toBe("test");
it("Alternate request handler", async () => {
const output: IAgentMessage[] = [];
const dispatcher = await createDispatcher("test", {
appAgentProviders: [testAppAgentProvider],
clientIO: createTestClientIO(output),
});
await dispatcher.processCommand("@config request test");
await dispatcher.processCommand("test");
await dispatcher.close();

expect(output).toHaveLength(2);
expect(output[0].message).toBe(
"Natural langue request handling agent is set to 'test'",
);
expect(output[1].message).toBe("test");
});
});
});

0 comments on commit f9c9e81

Please sign in to comment.