@@ -1302,7 +1302,6 @@ fn parse_optional_digits(bytes: &[u8], idx: usize, end: usize) -> (Option<u32>,
|
||||
parse_digits(bytes, idx, end).map_or((None, idx), |(v, i)| (Some(v), i))
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -1320,4 +1319,4 @@ mod tests {
|
||||
assert_eq!(parse_key_inner(b"\x1b[127;1:2u", true).as_deref(), Some("backspace"));
|
||||
assert_eq!(parse_key_inner(b"\x1b[127;1:3u", true).as_deref(), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,10 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
|
||||
} else if (arg === "--no-pty") {
|
||||
result.noPty = true;
|
||||
} else if (arg === "--tools" && i + 1 < args.length) {
|
||||
const toolNames = args[++i].split(",").map(s => s.trim());
|
||||
const toolNames = args[++i]
|
||||
.split(",")
|
||||
.map(s => s.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
const validTools: string[] = [];
|
||||
for (const name of toolNames) {
|
||||
if (name in BUILTIN_TOOLS) {
|
||||
|
||||
@@ -206,7 +206,7 @@ export function parseAgentFields(frontmatter: Record<string, unknown>): ParsedAg
|
||||
return null;
|
||||
}
|
||||
|
||||
let tools = parseArrayOrCSV(frontmatter.tools);
|
||||
let tools = parseArrayOrCSV(frontmatter.tools)?.map(tool => tool.toLowerCase());
|
||||
|
||||
// Subagents with explicit tool lists always need submit_result
|
||||
if (tools && !tools.includes("submit_result")) {
|
||||
|
||||
@@ -1251,9 +1251,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
||||
};
|
||||
|
||||
const toolNamesFromRegistry = Array.from(toolRegistry.keys());
|
||||
const requestedToolNames = options.toolNames ?? toolNamesFromRegistry;
|
||||
const requestedToolNames = options.toolNames?.map(name => name.toLowerCase()) ?? toolNamesFromRegistry;
|
||||
const normalizedRequested = requestedToolNames.filter(name => toolRegistry.has(name));
|
||||
const includeExitPlanMode = options.toolNames?.includes("exit_plan_mode") ?? false;
|
||||
const includeExitPlanMode = requestedToolNames.includes("exit_plan_mode");
|
||||
const initialToolNames = includeExitPlanMode
|
||||
? normalizedRequested
|
||||
: normalizedRequested.filter(name => name !== "exit_plan_mode");
|
||||
|
||||
@@ -227,7 +227,8 @@ function getPythonModeFromEnv(): PythonToolMode | null {
|
||||
export async function createTools(session: ToolSession, toolNames?: string[]): Promise<Tool[]> {
|
||||
const includeSubmitResult = session.requireSubmitResultTool === true;
|
||||
const enableLsp = session.enableLsp ?? true;
|
||||
const requestedTools = toolNames && toolNames.length > 0 ? [...new Set(toolNames)] : undefined;
|
||||
const requestedTools =
|
||||
toolNames && toolNames.length > 0 ? [...new Set(toolNames.map(name => name.toLowerCase()))] : undefined;
|
||||
if (requestedTools && !requestedTools.includes("exit_plan_mode")) {
|
||||
requestedTools.push("exit_plan_mode");
|
||||
}
|
||||
|
||||
@@ -200,6 +200,11 @@ describe("parseArgs", () => {
|
||||
expect(result.noTools).toBe(true);
|
||||
expect(result.tools).toEqual(["read", "bash"]);
|
||||
});
|
||||
|
||||
test("lowercases tool names passed to --tools", () => {
|
||||
const result = parseArgs(["--tools", "Read,Grep"]);
|
||||
expect(result.tools).toEqual(["read", "grep"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("--no-lsp flag", () => {
|
||||
|
||||
@@ -56,4 +56,14 @@ describe("parseAgentFields", () => {
|
||||
|
||||
expect(fields?.thinkingLevel).toBe(Effort.High);
|
||||
});
|
||||
|
||||
test("lowercases tool names", () => {
|
||||
const fields = parseAgentFields({
|
||||
name: "reviewer",
|
||||
description: "desc",
|
||||
tools: ["Read", "Grep"],
|
||||
});
|
||||
|
||||
expect(fields?.tools).toEqual(["read", "grep", "submit_result"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -98,6 +98,14 @@ describe("createTools", () => {
|
||||
expect(names).toEqual(["read", "write", "exit_plan_mode"]);
|
||||
});
|
||||
|
||||
it("lowercases requested tool subset", async () => {
|
||||
const session = createTestSession();
|
||||
const tools = await createTools(session, ["Read", "Write"]);
|
||||
const names = tools.map(t => t.name);
|
||||
|
||||
expect(names).toEqual(["read", "write", "exit_plan_mode"]);
|
||||
});
|
||||
|
||||
it("includes hidden tools when explicitly requested", async () => {
|
||||
const session = createTestSession();
|
||||
const tools = await createTools(session, ["report_finding"]);
|
||||
|
||||
@@ -132,7 +132,6 @@ describe("Input component", () => {
|
||||
setKittyProtocolActive(false);
|
||||
});
|
||||
|
||||
|
||||
it("never renders a line wider than the terminal width (wide chars)", () => {
|
||||
const input = new Input();
|
||||
input.focused = true;
|
||||
|
||||
@@ -60,7 +60,6 @@ describe("parseKey", () => {
|
||||
setKittyProtocolActive(false);
|
||||
});
|
||||
|
||||
|
||||
it("should prefer codepoint for symbol keys when base layout differs", () => {
|
||||
setKittyProtocolActive(true);
|
||||
const dvorakCtrlSlash = "\x1b[47::91;5u";
|
||||
|
||||
Reference in New Issue
Block a user