@townco/agent 0.1.23 → 0.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
1
  import { ExaSearchResults } from "@langchain/exa";
2
2
  export declare function makeWebSearchTool(): ExaSearchResults<{
3
- text: true;
3
+ text: {
4
+ maxCharacters: number;
5
+ };
4
6
  }>;
@@ -16,7 +16,9 @@ export function makeWebSearchTool() {
16
16
  searchArgs: {
17
17
  numResults: 5,
18
18
  type: "auto",
19
- text: true,
19
+ text: {
20
+ maxCharacters: 7500,
21
+ },
20
22
  },
21
23
  });
22
24
  return _webSearchInstance;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Initialize Claude Code workspace integration by creating AGENTS.town.md
3
+ * and adding references to it in CLAUDE.md and AGENTS.md.
4
+ *
5
+ * @param targetPath - The root directory of the Town project
6
+ * @throws Error if target path doesn't exist
7
+ */
8
+ export declare function initForClaudeCode(targetPath: string): Promise<void>;
@@ -0,0 +1,58 @@
1
+ import { existsSync } from "node:fs";
2
+ import { appendFile, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ /**
8
+ * Initialize Claude Code workspace integration by creating AGENTS.town.md
9
+ * and adding references to it in CLAUDE.md and AGENTS.md.
10
+ *
11
+ * @param targetPath - The root directory of the Town project
12
+ * @throws Error if target path doesn't exist
13
+ */
14
+ export async function initForClaudeCode(targetPath) {
15
+ // Verify target path exists
16
+ if (!existsSync(targetPath)) {
17
+ throw new Error(`Target path does not exist: ${targetPath}`);
18
+ }
19
+ // Source template directory (dot-claude in the scaffold package)
20
+ const templateDir = join(__dirname, "templates", "dot-claude");
21
+ const appendTemplatePath = join(templateDir, "CLAUDE-append.md");
22
+ if (!existsSync(appendTemplatePath)) {
23
+ throw new Error(`Claude template not found: ${appendTemplatePath}. This is a bug in the Town CLI.`);
24
+ }
25
+ // Handle AGENTS.town.md and references
26
+ const claudeMdPath = join(targetPath, "CLAUDE.md");
27
+ const agentsMdPath = join(targetPath, "AGENTS.md");
28
+ const agentsTownMdPath = join(targetPath, "AGENTS.town.md");
29
+ const townContent = await readFile(appendTemplatePath, "utf-8");
30
+ // Create AGENTS.town.md with the Town-specific content
31
+ await writeFile(agentsTownMdPath, townContent, "utf-8");
32
+ console.log("✓ Created AGENTS.town.md");
33
+ // Add reference to AGENTS.town.md in both CLAUDE.md and AGENTS.md
34
+ const referenceText = "\n\nThis repo uses the Town agent SDK -- please reference @AGENTS.town.md for more information\n";
35
+ // Handle CLAUDE.md
36
+ if (existsSync(claudeMdPath)) {
37
+ // CLAUDE.md exists, append reference
38
+ await appendFile(claudeMdPath, referenceText);
39
+ console.log("✓ Added Town SDK reference to CLAUDE.md");
40
+ }
41
+ else {
42
+ // CLAUDE.md doesn't exist, create it with just the reference
43
+ await writeFile(claudeMdPath, `${referenceText.trim()}\n`, "utf-8");
44
+ console.log("✓ Created CLAUDE.md with Town SDK reference");
45
+ }
46
+ // Handle AGENTS.md
47
+ if (existsSync(agentsMdPath)) {
48
+ // AGENTS.md exists, append reference
49
+ await appendFile(agentsMdPath, referenceText);
50
+ console.log("✓ Added Town SDK reference to AGENTS.md");
51
+ }
52
+ else {
53
+ // AGENTS.md doesn't exist, create it with just the reference
54
+ await writeFile(agentsMdPath, `${referenceText.trim()}\n`, "utf-8");
55
+ console.log("✓ Created AGENTS.md with Town SDK reference");
56
+ }
57
+ console.log("✓ Claude Code workspace initialized");
58
+ }
@@ -16,4 +16,5 @@ export interface ScaffoldResult {
16
16
  * Scaffold a new agent package
17
17
  */
18
18
  export declare function scaffoldAgent(options: ScaffoldOptions): Promise<ScaffoldResult>;
19
+ export { initForClaudeCode } from "./claude-scaffold";
19
20
  export { scaffoldProject } from "./project-scaffold";
@@ -94,5 +94,6 @@ function runBunInstall(agentPath) {
94
94
  });
95
95
  });
96
96
  }
97
+ export { initForClaudeCode } from "./claude-scaffold";
97
98
  // Export project scaffolding
98
99
  export { scaffoldProject } from "./project-scaffold";
@@ -1,6 +1,7 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { mkdir, writeFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
+ import { initForClaudeCode } from "./claude-scaffold.js";
4
5
  /**
5
6
  * Generate project package.json
6
7
  */
@@ -299,6 +300,8 @@ export async function scaffoldProject(options) {
299
300
  }
300
301
  // Run bun install
301
302
  await runBunInstall(projectPath);
303
+ // Initialize Claude Code workspace integration
304
+ await initForClaudeCode(projectPath);
302
305
  return {
303
306
  success: true,
304
307
  path: projectPath,
@@ -0,0 +1,99 @@
1
+ # Town Agent SDK
2
+ This project has code for agents developed using the Town agent SDK. The
3
+ structure of this repository is:
4
+ - `agents/`: code for main agent loop and configuration
5
+ - `tools/`: code for function-based tools that are shared by agents
6
+
7
+ ## Built-in tools
8
+ The following built-in tools are available:
9
+ - `todo_write`: Task management and planning tool
10
+ - `web_search`: Exa-powered web search (requires EXA_API_KEY)
11
+ - `filesystem`: Read, write, and search files in the project directory
12
+
13
+ To use built-in tools, simply add them to the `tools` array in your agent definition:
14
+ ```
15
+ const agent: AgentDefinition = {
16
+ model: "claude-sonnet-4-5-20250929",
17
+ systemPrompt: "You are a helpful assistant.\n",
18
+ tools: ["todo_write", "web_search", "filesystem"],
19
+ };
20
+ ```
21
+
22
+ The `filesystem` tool can also be configured with a custom working directory:
23
+ ```
24
+ const agent: AgentDefinition = {
25
+ model: "claude-sonnet-4-5-20250929",
26
+ systemPrompt: "You are a helpful assistant.\n",
27
+ tools: [
28
+ "todo_write",
29
+ "web_search",
30
+ { type: "filesystem", working_directory: "./src" }
31
+ ],
32
+ };
33
+ ```
34
+
35
+ ## Writing custom tools
36
+ You may add one of the built-in tools listed above, or
37
+ you may implement your own custom tools. To do this:
38
+ 1. add a file `tools/<tool-name>.ts` with the following structure:
39
+ ```
40
+ import * as z from 'zod';
41
+
42
+ export const schema = z.object({
43
+ a: z.number().describe("First number"),
44
+ b: z.number().describe("Second number"),
45
+ });
46
+
47
+ export const name = "add_two_numbers";
48
+ export const description = "Add two numbers together and return the result";
49
+
50
+ export default function addTwoNumbers(input: unknown) {
51
+ const { a, b } = input as { a: number; b: number };
52
+ return { result: a + b };
53
+ }
54
+ ```
55
+ where
56
+ - `schema` is a zod schema for the tool input
57
+ - `name` is the name of the tool (given to the LLM)
58
+ - `description` describes the tool (given to the LLM)
59
+ - default-exported function containing the body of the function
60
+
61
+ 2. Modify the agent code to import the `createTool` utility and the new tool
62
+ ```
63
+ import { createTool } from '@townco/agent/utils';
64
+ import * as newCoolTool from '../../tools/new-cool-tool';
65
+ ```
66
+ and modify the agent's tools list
67
+ ```
68
+ const agent: AgentDefinition = {
69
+ model: "claude-sonnet-4-5-20250929",
70
+ systemPrompt: "You are a helpful assistant.\n",
71
+ tools: ["todo_write", "web_search", createTool(newCoolTool)],
72
+ };
73
+ ```
74
+
75
+ ## Configuring MCPs
76
+ You may configure stdio and streamable HTTP-based MCPs. Here is an example:
77
+ ```
78
+ const agent: AgentDefinition = {
79
+ model: "claude-sonnet-4-5-20250929",
80
+ systemPrompt: "You are a helpful assistant.\n",
81
+ tools: ["todo_write", "web_search"],
82
+ mcps: [
83
+ {
84
+ transport: "http",
85
+ name: "foobar",
86
+ url: "http://town.com:8080/mcp",
87
+ headers: {
88
+ 'Authorization': `Bearer ${process.env.MCP_API_KEY}`
89
+ },
90
+ },
91
+ {
92
+ transport: 'stdio',
93
+ name: 'local-mcp',
94
+ command: 'node',
95
+ args: ['path/to/local/mcp.js'],
96
+ },
97
+ ],
98
+ };
99
+ ```