@@ -257,17 +257,48 @@ describe("parseArgs", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("--no-tools flag", () => {
|
||||
describe("tool flags", () => {
|
||||
test("parses --no-tools flag", () => {
|
||||
const result = parseArgs(["--no-tools"]);
|
||||
expect(result.noTools).toBe(true);
|
||||
});
|
||||
|
||||
test("parses -nt shorthand", () => {
|
||||
const result = parseArgs(["-nt"]);
|
||||
expect(result.noTools).toBe(true);
|
||||
});
|
||||
|
||||
test("parses --no-builtin-tools flag", () => {
|
||||
const result = parseArgs(["--no-builtin-tools"]);
|
||||
expect(result.noBuiltinTools).toBe(true);
|
||||
});
|
||||
|
||||
test("parses -nbt shorthand", () => {
|
||||
const result = parseArgs(["-nbt"]);
|
||||
expect(result.noBuiltinTools).toBe(true);
|
||||
});
|
||||
|
||||
test("parses --tools flag", () => {
|
||||
const result = parseArgs(["--tools", "read,bash"]);
|
||||
expect(result.tools).toEqual(["read", "bash"]);
|
||||
});
|
||||
|
||||
test("parses -t shorthand", () => {
|
||||
const result = parseArgs(["-t", "read,bash"]);
|
||||
expect(result.tools).toEqual(["read", "bash"]);
|
||||
});
|
||||
|
||||
test("parses --no-tools with explicit --tools flags", () => {
|
||||
const result = parseArgs(["--no-tools", "--tools", "read,bash"]);
|
||||
expect(result.noTools).toBe(true);
|
||||
expect(result.tools).toEqual(["read", "bash"]);
|
||||
});
|
||||
|
||||
test("parses --no-builtin-tools with explicit --tools flags", () => {
|
||||
const result = parseArgs(["--no-builtin-tools", "--tools", "read,bash"]);
|
||||
expect(result.noBuiltinTools).toBe(true);
|
||||
expect(result.tools).toEqual(["read", "bash"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("messages and file args", () => {
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { existsSync, mkdirSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { getModel } from "@mariozechner/pi-ai";
|
||||
import { Type } from "typebox";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { DefaultResourceLoader } from "../../../src/core/resource-loader.js";
|
||||
import { createAgentSession } from "../../../src/core/sdk.js";
|
||||
import { SessionManager } from "../../../src/core/session-manager.js";
|
||||
import { SettingsManager } from "../../../src/core/settings-manager.js";
|
||||
|
||||
describe("regression #3592: no-builtin-tools keeps extension tools enabled", () => {
|
||||
let tempDir: string;
|
||||
let agentDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tempDir = join(tmpdir(), `pi-no-builtin-tools-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
||||
agentDir = join(tempDir, "agent");
|
||||
mkdirSync(agentDir, { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (tempDir && existsSync(tempDir)) {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
async function createSession(options?: { noTools?: "all" | "builtin"; tools?: string[] }) {
|
||||
const settingsManager = SettingsManager.create(tempDir, agentDir);
|
||||
const sessionManager = SessionManager.inMemory(tempDir);
|
||||
const resourceLoader = new DefaultResourceLoader({
|
||||
cwd: tempDir,
|
||||
agentDir,
|
||||
settingsManager,
|
||||
extensionFactories: [
|
||||
(pi) => {
|
||||
pi.on("session_start", () => {
|
||||
pi.registerTool({
|
||||
name: "dynamic_tool",
|
||||
label: "Dynamic Tool",
|
||||
description: "Tool registered from session_start",
|
||||
promptSnippet: "Run dynamic test behavior",
|
||||
parameters: Type.Object({}),
|
||||
execute: async () => ({
|
||||
content: [{ type: "text", text: "ok" }],
|
||||
details: {},
|
||||
}),
|
||||
});
|
||||
});
|
||||
},
|
||||
],
|
||||
});
|
||||
await resourceLoader.reload();
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
cwd: tempDir,
|
||||
agentDir,
|
||||
model: getModel("anthropic", "claude-sonnet-4-5")!,
|
||||
settingsManager,
|
||||
sessionManager,
|
||||
resourceLoader,
|
||||
noTools: options?.noTools,
|
||||
tools: options?.tools,
|
||||
});
|
||||
await session.bindExtensions({});
|
||||
return session;
|
||||
}
|
||||
|
||||
it("keeps extension tools active when built-in defaults are disabled", async () => {
|
||||
const session = await createSession({ noTools: "builtin" });
|
||||
|
||||
expect(
|
||||
session
|
||||
.getAllTools()
|
||||
.map((tool) => tool.name)
|
||||
.sort(),
|
||||
).toEqual(["bash", "dynamic_tool", "edit", "find", "grep", "ls", "read", "write"]);
|
||||
expect(session.getActiveToolNames()).toEqual(["dynamic_tool"]);
|
||||
expect(session.systemPrompt).toContain("- dynamic_tool: Run dynamic test behavior");
|
||||
expect(session.systemPrompt).not.toContain("- read:");
|
||||
expect(session.systemPrompt).not.toContain("- bash:");
|
||||
session.dispose();
|
||||
});
|
||||
|
||||
it("still disables all tools when noTools is all", async () => {
|
||||
const session = await createSession({ noTools: "all" });
|
||||
|
||||
expect(session.getAllTools()).toEqual([]);
|
||||
expect(session.getActiveToolNames()).toEqual([]);
|
||||
expect(session.systemPrompt).toContain("Available tools:\n(none)");
|
||||
session.dispose();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user