Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/commands/$default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ export const handler = async (argv: ArgumentsCamelCase<Options>) => {
if (argv.file) {
try {
prompt = await fs.readFile(argv.file, "utf-8");
} catch (error) {
logger.error(`Failed to read prompt file: ${argv.file}`);
} catch (error: any) {
logger.error(
`Failed to read prompt file: ${argv.file}, ${error?.message}`
);
process.exit(1);
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/commands/tools.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ArgumentsCamelCase, Argv } from "yargs";
import type { Argv } from "yargs";
import { getTools } from "../tools/getTools.js";
import type { JsonSchema7Type } from "zod-to-json-schema";

Expand Down Expand Up @@ -42,7 +42,7 @@ function formatSchema(schema: {
return output;
}

export const handler = async (_argv: ArgumentsCamelCase<ListToolsOptions>) => {
export const handler = async () => {
try {
const tools = await getTools();

Expand All @@ -61,8 +61,8 @@ export const handler = async (_argv: ArgumentsCamelCase<ListToolsOptions>) => {
tool.parameters as {
properties?: Record<string, JsonSchema7Type>;
required?: string[];
},
),
}
)
);

// Returns section
Expand All @@ -73,8 +73,8 @@ export const handler = async (_argv: ArgumentsCamelCase<ListToolsOptions>) => {
tool.returns as {
properties?: Record<string, JsonSchema7Type>;
required?: string[];
},
),
}
)
);
} else {
console.log(" Type: any");
Expand Down
2 changes: 1 addition & 1 deletion src/core/executeToolCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const OUTPUT_LIMIT = 12 * 1024; // 10KB limit
export const executeToolCall = async (
toolCall: ToolCall,
tools: Tool[],
parentLogger: Logger
parentLogger: Logger,
): Promise<string> => {
const logger = new Logger({
name: `Tool:${toolCall.name}`,
Expand Down
12 changes: 6 additions & 6 deletions src/core/toolAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe("toolAgent", () => {
input: { input: "test" },
},
[mockTool],
logger
logger,
);

expect(result.includes("Processed: test")).toBeTruthy();
Expand All @@ -111,8 +111,8 @@ describe("toolAgent", () => {
input: {},
},
[mockTool],
logger
)
logger,
),
).rejects.toThrow("No tool with the name 'nonexistentTool' exists.");
});

Expand Down Expand Up @@ -142,8 +142,8 @@ describe("toolAgent", () => {
input: {},
},
[errorTool],
logger
)
logger,
),
).rejects.toThrow("Deliberate failure");
});

Expand All @@ -153,7 +153,7 @@ describe("toolAgent", () => {
"Test prompt",
[sequenceCompleteTool],
logger,
testConfig
testConfig,
);

expect(result.result).toBe("Test complete");
Expand Down
18 changes: 9 additions & 9 deletions src/core/toolAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async function executeTools(
toolCalls: ToolUseContent[],
tools: Tool[],
messages: Message[],
logger: Logger
logger: Logger,
): Promise<ToolCallResult> {
if (toolCalls.length === 0) {
return { sequenceCompleted: false, toolResults: [] };
Expand All @@ -134,7 +134,7 @@ async function executeTools(
content: toolResult,
isComplete: call.name === "sequenceComplete",
};
})
}),
);

const toolResults = results.map(({ type, tool_use_id, content }) => ({
Expand All @@ -160,7 +160,7 @@ export const toolAgent = async (
initialPrompt: string,
tools: Tool[],
logger: Logger,
config = CONFIG
config = CONFIG,
): Promise<ToolAgentResult> => {
logger.verbose("Starting agent execution");
logger.verbose("Initial prompt:", initialPrompt);
Expand Down Expand Up @@ -189,7 +189,7 @@ export const toolAgent = async (
logger.verbose(
`Requesting completion ${i + 1} with ${messages.length} messages with ${
JSON.stringify(messages).length
} bytes`
} bytes`,
);

interactions++;
Expand Down Expand Up @@ -218,15 +218,15 @@ export const toolAgent = async (
interactions,
};
logger.verbose(
`Agent completed with ${result.tokens.input} input tokens, ${result.tokens.output} output tokens in ${result.interactions} interactions`
`Agent completed with ${result.tokens.input} input tokens, ${result.tokens.output} output tokens in ${result.interactions} interactions`,
);
return result;
}

totalInputTokens += response.usage.input_tokens;
totalOutputTokens += response.usage.output_tokens;
logger.verbose(
` Token usage: ${response.usage.input_tokens} input, ${response.usage.output_tokens} output`
` Token usage: ${response.usage.input_tokens} input, ${response.usage.output_tokens} output`,
);

const { content, toolCalls } = processResponse(response);
Expand All @@ -245,7 +245,7 @@ export const toolAgent = async (
toolCalls,
tools,
messages,
logger
logger,
);

if (sequenceCompleted) {
Expand All @@ -260,7 +260,7 @@ export const toolAgent = async (
interactions,
};
logger.verbose(
`Agent completed with ${result.tokens.input} input tokens, ${result.tokens.output} output tokens in ${result.interactions} interactions`
`Agent completed with ${result.tokens.input} input tokens, ${result.tokens.output} output tokens in ${result.interactions} interactions`,
);
return result;
}
Expand All @@ -276,7 +276,7 @@ export const toolAgent = async (
interactions,
};
logger.verbose(
`Agent completed with ${result.tokens.input} input tokens, ${result.tokens.output} output tokens in ${result.interactions} interactions`
`Agent completed with ${result.tokens.input} input tokens, ${result.tokens.output} output tokens in ${result.interactions} interactions`,
);
return result;
};
10 changes: 8 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createRequire } from "module";
import { join } from "path";
import { fileURLToPath } from "url";
import { fileCommands } from "yargs-file-commands";
import { checkForUpdates } from "./utils/versionCheck.js";

import sourceMapSupport from "source-map-support";

Expand All @@ -20,6 +21,11 @@ const main = async () => {

const logger = new Logger({ name: "Main", color: "white" });

const updateMessage = await checkForUpdates();
if (updateMessage) {
logger.info(updateMessage);
}

// Error handling
process.on("SIGINT", () => {
logger.warn("\nGracefully shutting down...");
Expand All @@ -31,7 +37,7 @@ const main = async () => {
"Fatal error:",
error.constructor.name,
error.message,
error.stack
error.stack,
);
process.exit(1);
});
Expand Down Expand Up @@ -63,7 +69,7 @@ const main = async () => {
await fileCommands({
commandDirs: [commandsDir],
logLevel: "info",
})
}),
)
.strict()
.showHelpOnFail(true)
Expand Down
2 changes: 1 addition & 1 deletion src/tools/getTools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("getTools", () => {
name: expect.any(String),
description: expect.any(String),
parameters: expect.any(Object),
})
}),
);
}
});
Expand Down
10 changes: 5 additions & 5 deletions src/tools/interaction/subAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe("subAgent", () => {
prompt: "Test sub-agent task",
description: "A test agent for unit testing",
},
{ logger }
{ logger },
);

expect(result.toString()).toContain("Sub-agent task complete");
Expand All @@ -57,8 +57,8 @@ describe("subAgent", () => {
prompt: "Test task",
description: "An agent that should fail",
},
{ logger }
)
{ logger },
),
).rejects.toThrow("ANTHROPIC_API_KEY environment variable is not set");
});

Expand All @@ -72,8 +72,8 @@ describe("subAgent", () => {
prompt: "Test task",
description: longDescription,
},
{ logger }
)
{ logger },
),
).rejects.toThrow();
});
});
4 changes: 2 additions & 2 deletions src/tools/interaction/subAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const parameterSchema = z.object({
const returnSchema = z
.string()
.describe(
"The response from the sub-agent including its reasoning and tool usage"
"The response from the sub-agent including its reasoning and tool usage",
);

type Parameters = z.infer<typeof parameterSchema>;
Expand Down Expand Up @@ -49,7 +49,7 @@ export const subAgentTool: Tool<Parameters, ReturnType> = {
const { prompt } = parameterSchema.parse(params);

const tools = (await getTools()).filter(
(tool) => tool.name !== "userPrompt"
(tool) => tool.name !== "userPrompt",
);

const result = await toolAgent(prompt, tools, logger, subAgentConfig);
Expand Down
10 changes: 5 additions & 5 deletions src/tools/io/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const parameterSchema = z.object({
method: z
.string()
.describe(
"HTTP method to use (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)"
"HTTP method to use (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)",
),
url: z.string().describe("URL to make the request to"),
params: z
Expand Down Expand Up @@ -39,7 +39,7 @@ export const fetchTool: Tool<Parameters, ReturnType> = {
returns: zodToJsonSchema(returnSchema),
execute: async (
{ method, url, params, body, headers }: Parameters,
{ logger }
{ logger },
): Promise<ReturnType> => {
logger.verbose(`Starting ${method} request to ${url}`);
const urlObj = new URL(url);
Expand All @@ -48,7 +48,7 @@ export const fetchTool: Tool<Parameters, ReturnType> = {
if (params) {
logger.verbose("Adding query parameters:", params);
Object.entries(params).forEach(([key, value]) =>
urlObj.searchParams.append(key, value as string)
urlObj.searchParams.append(key, value as string),
);
}

Expand All @@ -71,7 +71,7 @@ export const fetchTool: Tool<Parameters, ReturnType> = {
logger.verbose("Request options:", options);
const response = await fetch(urlObj.toString(), options);
logger.verbose(
`Request completed with status ${response.status} ${response.statusText}`
`Request completed with status ${response.status} ${response.statusText}`,
);

const contentType = response.headers.get("content-type");
Expand All @@ -91,7 +91,7 @@ export const fetchTool: Tool<Parameters, ReturnType> = {
logParameters(params, { logger }) {
const { method, url, params: queryParams } = params;
logger.info(
`${method} ${url}${queryParams ? `?${new URLSearchParams(queryParams)}` : ""}`
`${method} ${url}${queryParams ? `?${new URLSearchParams(queryParams)}` : ""}`,
);
},
};
4 changes: 2 additions & 2 deletions src/tools/io/readFile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("readFile", () => {
it("should read a file", async () => {
const { content } = await readFileTool.execute(
{ path: "package.json", description: "test" },
{ logger }
{ logger },
);
expect(content).toContain("mycoder");
});
Expand All @@ -17,7 +17,7 @@ describe("readFile", () => {
try {
await readFileTool.execute(
{ path: "nonexistent.txt", description: "test" },
{ logger }
{ logger },
);
expect(true).toBe(false); // Should not reach here
} catch (error: any) {
Expand Down
6 changes: 3 additions & 3 deletions src/tools/io/readFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const parameterSchema = z.object({
.number()
.optional()
.describe(
"Maximum size to read, prevents reading arbitrarily large files that blow up the context window"
"Maximum size to read, prevents reading arbitrarily large files that blow up the context window",
),
description: z
.string()
Expand Down Expand Up @@ -54,7 +54,7 @@ export const readFileTool: Tool<Parameters, ReturnType> = {
const readSize = range ? range.end - range.start : stats.size;
if (readSize > maxSize) {
throw new Error(
`Requested size ${readSize} bytes exceeds maximum ${maxSize} bytes`
`Requested size ${readSize} bytes exceeds maximum ${maxSize} bytes`,
);
}

Expand All @@ -66,7 +66,7 @@ export const readFileTool: Tool<Parameters, ReturnType> = {
buffer,
0,
readSize,
range.start
range.start,
);
return {
path: filePath,
Expand Down
Loading