taskforce-aiagent
Version:
TaskForce is a modular, open-source, production-ready TypeScript agent framework for orchestrating AI agents, LLM-powered autonomous agents, task pipelines, dynamic toolchains, RAG workflows and memory/retrieval systems.
126 lines (125 loc) • 5.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-nocheck
const toolExecutor_1 = require("./toolExecutor");
const baseTool_1 = require("../base/baseTool");
class DummyTool extends baseTool_1.Tool {
constructor() {
super(...arguments);
this.id = "dummy-tool";
this.name = "Dummy Tool";
this.description = "A dummy tool for testing.";
this.inputSchema = { type: "string", required: true };
this.parameters = {
type: "object",
properties: {
param1: {
type: "string",
description: "A test parameter",
example: "example value",
},
},
required: ["param1"],
};
this.cacheable = true;
}
async handler(input) {
if (typeof input !== "string")
throw new Error("Invalid input");
return `Handled: ${input}`;
}
}
describe("ToolExecutor", () => {
let tool;
let executor;
beforeEach(() => {
tool = new DummyTool();
executor = new toolExecutor_1.ToolExecutor([tool]);
});
it("should get tools", () => {
expect(executor.getTools()).toContain(tool);
});
it("should get tool name by id or fallback", () => {
expect(executor.getToolNameById(tool.id)).toBe(tool.name);
expect(executor.getToolNameById("unknown")).toBe("unknown");
});
it("should build tool usage examples string", () => {
const usage = executor.buildToolUsageExamples([tool]);
expect(usage).toContain(tool.id);
expect(usage).toContain(tool.description);
expect(usage).toContain("param1");
expect(usage).toContain("Example Dummy Tool Usage");
});
it("should validate input correctly", () => {
expect(executor.isValidInput("test", { type: "string", required: true })).toBe(true);
expect(executor.isValidInput(123, { type: "string", required: true })).toBe(false);
expect(executor.isValidInput(123, { type: "number", required: true })).toBe(true);
expect(executor.isValidInput(null, { type: "object", required: true })).toBe(false);
expect(executor.isValidInput({}, { type: "object", required: true })).toBe(true);
expect(executor.isValidInput("anything", { type: "string", required: false })).toBe(true);
});
it("should execute tool and return result", async () => {
const result = await executor.executeToolById(tool.id, "input string");
expect(result).toBe("Handled: input string");
});
it("should return warning if tool not found", async () => {
const result = await executor.executeToolById("non-existent-tool", "input");
expect(result).toMatch(/not found/);
});
it("should return warning on invalid input", async () => {
const result = await executor.executeToolById(tool.id, 123);
expect(result).toMatch(/Invalid input/);
});
it("should cache results if tool is cacheable", async () => {
// first call, no cache
const result1 = await executor.executeToolById(tool.id, "cache-test");
expect(result1).toBe("Handled: cache-test");
// second call, should hit cache and return cached value prefix
const result2 = await executor.executeToolById(tool.id, "cache-test");
expect(result2).toContain("tool cached");
});
it("should respect cacheFunction override", async () => {
tool.cacheFunction = jest.fn(() => false); // never cache
const result1 = await executor.executeToolById(tool.id, "input");
expect(tool.cacheFunction).toHaveBeenCalled();
const result2 = await executor.executeToolById(tool.id, "input");
// Second call should not hit cache since cacheFunction returns false
expect(result2).toBe("Handled: input");
});
it("should use errorHandler if tool handler throws", async () => {
const errorTool = new DummyTool();
errorTool.handler = jest.fn(() => {
throw new Error("fail");
});
errorTool.errorHandler = jest.fn(() => "Handled error");
const exec = new toolExecutor_1.ToolExecutor([errorTool]);
const result = await exec.executeToolById(errorTool.id, "input");
expect(result).toBe("Handled error");
expect(errorTool.errorHandler).toHaveBeenCalled();
});
it("should return error message if handler throws and no errorHandler", async () => {
const errorTool = new DummyTool();
errorTool.handler = jest.fn(() => {
throw new Error("fail");
});
errorTool.errorHandler = undefined;
const exec = new toolExecutor_1.ToolExecutor([errorTool]);
const result = await exec.executeToolById(errorTool.id, "input");
expect(result).toMatch(/execution error: fail/i);
});
it("should emit step event when EMITTING=true", async () => {
process.env.EMITTING = "true";
const taskForceMock = {
emitStep: jest.fn(),
};
const exec = new toolExecutor_1.ToolExecutor([tool], taskForceMock, "agent1");
await exec.executeToolById(tool.id, "emit test");
expect(taskForceMock.emitStep).toHaveBeenCalledWith(expect.objectContaining({
action: "tool_executed",
agent: "agent1",
tool: tool.id,
toolPayload: "emit test",
}));
process.env.EMITTING = undefined;
});
});