@townco/agent 0.1.11 → 0.1.12

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.
Files changed (44) hide show
  1. package/dist/acp-server/adapter.d.ts +10 -14
  2. package/dist/acp-server/adapter.js +72 -73
  3. package/dist/acp-server/cli.d.ts +1 -3
  4. package/dist/acp-server/cli.js +5 -9
  5. package/dist/acp-server/http.d.ts +1 -3
  6. package/dist/acp-server/http.js +163 -173
  7. package/dist/bin.js +0 -0
  8. package/dist/definition/index.d.ts +4 -1
  9. package/dist/definition/index.js +8 -1
  10. package/dist/index.js +13 -12
  11. package/dist/runner/agent-runner.d.ts +4 -1
  12. package/dist/runner/agent-runner.js +4 -4
  13. package/dist/runner/index.d.ts +1 -3
  14. package/dist/runner/index.js +14 -18
  15. package/dist/runner/langchain/index.d.ts +8 -19
  16. package/dist/runner/langchain/index.js +55 -6
  17. package/dist/runner/langchain/tools/todo.d.ts +32 -48
  18. package/dist/runner/langchain/tools/todo.js +13 -16
  19. package/dist/runner/langchain/tools/web_search.d.ts +1 -1
  20. package/dist/runner/langchain/tools/web_search.js +18 -21
  21. package/dist/runner/tool-loader.d.ts +14 -0
  22. package/dist/runner/tool-loader.js +42 -0
  23. package/dist/runner/tools.d.ts +8 -7
  24. package/dist/runner/tools.js +12 -4
  25. package/dist/scaffold/bundle.d.ts +1 -1
  26. package/dist/scaffold/bundle.js +1 -1
  27. package/dist/scaffold/copy-gui.js +1 -1
  28. package/dist/scaffold/index.d.ts +8 -10
  29. package/dist/scaffold/index.js +82 -90
  30. package/dist/storage/index.js +24 -23
  31. package/dist/templates/index.d.ts +4 -1
  32. package/dist/templates/index.js +7 -3
  33. package/dist/test-script.js +11 -12
  34. package/dist/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +2 -2
  36. package/templates/index.ts +11 -4
  37. package/dist/definition/mcp.d.ts +0 -0
  38. package/dist/definition/mcp.js +0 -0
  39. package/dist/definition/tools/todo.d.ts +0 -49
  40. package/dist/definition/tools/todo.js +0 -80
  41. package/dist/definition/tools/web_search.d.ts +0 -4
  42. package/dist/definition/tools/web_search.js +0 -26
  43. package/dist/example.d.ts +0 -2
  44. package/dist/example.js +0 -19
@@ -2,105 +2,97 @@ import { spawn } from "node:child_process";
2
2
  import { chmod, mkdir, writeFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { agentExists, ensureAgentsDir, getAgentPath } from "../storage";
5
- import {
6
- generateAgentJson,
7
- generateBinTs,
8
- generateEnvExample,
9
- generateGitignore,
10
- generateIndexTs,
11
- generatePackageJson,
12
- generateReadme,
13
- generateTsConfig,
14
- getTemplateVars,
15
- } from "../templates";
5
+ import { generateAgentJson, generateBinTs, generateEnvExample, generateGitignore, generateIndexTs, generatePackageJson, generateReadme, generateTsConfig, getTemplateVars, } from "../templates";
16
6
  import { bundleAgentDependencies } from "./bundle";
17
7
  import { copyGuiApp } from "./copy-gui";
18
8
  /**
19
9
  * Scaffold a new agent package
20
10
  */
21
11
  export async function scaffoldAgent(options) {
22
- const { name, definition, overwrite = false, includeGui = true } = options;
23
- try {
24
- // Ensure base directory exists
25
- await ensureAgentsDir();
26
- // Check if agent already exists
27
- const exists = await agentExists(name);
28
- if (exists && !overwrite) {
29
- return {
30
- success: false,
31
- path: getAgentPath(name),
32
- error: `Agent "${name}" already exists. Use overwrite option to replace it.`,
33
- };
34
- }
35
- const agentPath = getAgentPath(name);
36
- // Create the agent directory
37
- await mkdir(agentPath, { recursive: true });
38
- const vars = getTemplateVars(name, definition);
39
- // Generate all template files
40
- const files = [
41
- { path: "package.json", content: generatePackageJson(vars) },
42
- { path: "agent.json", content: generateAgentJson(vars) },
43
- { path: "index.ts", content: generateIndexTs() },
44
- { path: "bin.ts", content: generateBinTs(), executable: true },
45
- { path: "tsconfig.json", content: generateTsConfig() },
46
- { path: "README.md", content: generateReadme(vars) },
47
- { path: ".gitignore", content: generateGitignore() },
48
- ];
49
- // Add .env.example if needed
50
- const envExample = generateEnvExample(vars);
51
- if (envExample) {
52
- files.push({ path: ".env.example", content: envExample });
53
- }
54
- // Write all files
55
- for (const file of files) {
56
- const filePath = join(agentPath, file.path);
57
- await writeFile(filePath, file.content, "utf-8");
58
- // Make executable if needed
59
- if (file.executable) {
60
- await chmod(filePath, 0o755);
61
- }
62
- }
63
- // Bundle agent dependencies (copy lib files)
64
- await bundleAgentDependencies(agentPath);
65
- // Copy GUI app if requested
66
- if (includeGui) {
67
- await copyGuiApp(agentPath);
68
- // Run bun install in the GUI directory
69
- const guiPath = join(agentPath, "gui");
70
- await runBunInstall(guiPath);
71
- }
72
- // Run bun install in agent root
73
- await runBunInstall(agentPath);
74
- return {
75
- success: true,
76
- path: agentPath,
77
- };
78
- } catch (error) {
79
- return {
80
- success: false,
81
- path: getAgentPath(name),
82
- error: error instanceof Error ? error.message : String(error),
83
- };
84
- }
12
+ const { name, definition, overwrite = false, includeGui = true } = options;
13
+ try {
14
+ // Ensure base directory exists
15
+ await ensureAgentsDir();
16
+ // Check if agent already exists
17
+ const exists = await agentExists(name);
18
+ if (exists && !overwrite) {
19
+ return {
20
+ success: false,
21
+ path: getAgentPath(name),
22
+ error: `Agent "${name}" already exists. Use overwrite option to replace it.`,
23
+ };
24
+ }
25
+ const agentPath = getAgentPath(name);
26
+ // Create the agent directory
27
+ await mkdir(agentPath, { recursive: true });
28
+ const vars = getTemplateVars(name, definition);
29
+ // Generate all template files
30
+ const files = [
31
+ { path: "package.json", content: generatePackageJson(vars) },
32
+ { path: "agent.json", content: generateAgentJson(vars) },
33
+ { path: "index.ts", content: generateIndexTs() },
34
+ { path: "bin.ts", content: generateBinTs(), executable: true },
35
+ { path: "tsconfig.json", content: generateTsConfig() },
36
+ { path: "README.md", content: generateReadme(vars) },
37
+ { path: ".gitignore", content: generateGitignore() },
38
+ ];
39
+ // Add .env.example if needed
40
+ const envExample = generateEnvExample(vars);
41
+ if (envExample) {
42
+ files.push({ path: ".env.example", content: envExample });
43
+ }
44
+ // Write all files
45
+ for (const file of files) {
46
+ const filePath = join(agentPath, file.path);
47
+ await writeFile(filePath, file.content, "utf-8");
48
+ // Make executable if needed
49
+ if (file.executable) {
50
+ await chmod(filePath, 0o755);
51
+ }
52
+ }
53
+ // Bundle agent dependencies (copy lib files)
54
+ await bundleAgentDependencies(agentPath);
55
+ // Copy GUI app if requested
56
+ if (includeGui) {
57
+ await copyGuiApp(agentPath);
58
+ // Run bun install in the GUI directory
59
+ const guiPath = join(agentPath, "gui");
60
+ await runBunInstall(guiPath);
61
+ }
62
+ // Run bun install in agent root
63
+ await runBunInstall(agentPath);
64
+ return {
65
+ success: true,
66
+ path: agentPath,
67
+ };
68
+ }
69
+ catch (error) {
70
+ return {
71
+ success: false,
72
+ path: getAgentPath(name),
73
+ error: error instanceof Error ? error.message : String(error),
74
+ };
75
+ }
85
76
  }
86
77
  /**
87
78
  * Run bun install in the agent directory
88
79
  */
89
80
  function runBunInstall(agentPath) {
90
- return new Promise((resolve, reject) => {
91
- const bunInstall = spawn("bun", ["install"], {
92
- cwd: agentPath,
93
- stdio: "ignore",
94
- });
95
- bunInstall.on("close", (code) => {
96
- if (code === 0) {
97
- resolve();
98
- } else {
99
- reject(new Error(`bun install failed with code ${code}`));
100
- }
101
- });
102
- bunInstall.on("error", (error) => {
103
- reject(error);
104
- });
105
- });
81
+ return new Promise((resolve, reject) => {
82
+ const bunInstall = spawn("bun", ["install"], {
83
+ cwd: agentPath,
84
+ stdio: "ignore",
85
+ });
86
+ bunInstall.on("close", (code) => {
87
+ if (code === 0) {
88
+ resolve();
89
+ }
90
+ else {
91
+ reject(new Error(`bun install failed with code ${code}`));
92
+ }
93
+ });
94
+ bunInstall.on("error", (error) => {
95
+ reject(error);
96
+ });
97
+ });
106
98
  }
@@ -1,57 +1,58 @@
1
1
  import { mkdir, readdir, rm, stat } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
-
5
4
  const AGENTS_DIR = join(homedir(), ".config", "town", "agents");
6
5
  /**
7
6
  * Get the base directory where all agents are stored
8
7
  */
9
8
  export function getAgentsDir() {
10
- return AGENTS_DIR;
9
+ return AGENTS_DIR;
11
10
  }
12
11
  /**
13
12
  * Get the directory path for a specific agent
14
13
  */
15
14
  export function getAgentPath(name) {
16
- return join(AGENTS_DIR, name);
15
+ return join(AGENTS_DIR, name);
17
16
  }
18
17
  /**
19
18
  * Check if an agent exists
20
19
  */
21
20
  export async function agentExists(name) {
22
- try {
23
- const agentPath = getAgentPath(name);
24
- const stats = await stat(agentPath);
25
- return stats.isDirectory();
26
- } catch {
27
- return false;
28
- }
21
+ try {
22
+ const agentPath = getAgentPath(name);
23
+ const stats = await stat(agentPath);
24
+ return stats.isDirectory();
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
29
  }
30
30
  /**
31
31
  * List all created agents
32
32
  */
33
33
  export async function listAgents() {
34
- try {
35
- await mkdir(AGENTS_DIR, { recursive: true });
36
- const entries = await readdir(AGENTS_DIR, { withFileTypes: true });
37
- return entries
38
- .filter((entry) => entry.isDirectory())
39
- .map((entry) => entry.name);
40
- } catch (error) {
41
- console.error("Error listing agents:", error);
42
- return [];
43
- }
34
+ try {
35
+ await mkdir(AGENTS_DIR, { recursive: true });
36
+ const entries = await readdir(AGENTS_DIR, { withFileTypes: true });
37
+ return entries
38
+ .filter((entry) => entry.isDirectory())
39
+ .map((entry) => entry.name);
40
+ }
41
+ catch (error) {
42
+ console.error("Error listing agents:", error);
43
+ return [];
44
+ }
44
45
  }
45
46
  /**
46
47
  * Delete an agent
47
48
  */
48
49
  export async function deleteAgent(name) {
49
- const agentPath = getAgentPath(name);
50
- await rm(agentPath, { recursive: true, force: true });
50
+ const agentPath = getAgentPath(name);
51
+ await rm(agentPath, { recursive: true, force: true });
51
52
  }
52
53
  /**
53
54
  * Ensure the agents directory exists
54
55
  */
55
56
  export async function ensureAgentsDir() {
56
- await mkdir(AGENTS_DIR, { recursive: true });
57
+ await mkdir(AGENTS_DIR, { recursive: true });
57
58
  }
@@ -2,7 +2,10 @@ import type { AgentDefinition } from "../definition";
2
2
  export interface TemplateVars {
3
3
  name: string;
4
4
  model: string;
5
- tools: string[];
5
+ tools: Array<string | {
6
+ type: "custom";
7
+ modulePath: string;
8
+ }>;
6
9
  systemPrompt: string | null;
7
10
  hasWebSearch: boolean;
8
11
  }
@@ -5,7 +5,7 @@ export function getTemplateVars(name, definition) {
5
5
  model: definition.model,
6
6
  tools,
7
7
  systemPrompt: definition.systemPrompt,
8
- hasWebSearch: tools.includes("web_search"),
8
+ hasWebSearch: tools.some((tool) => typeof tool === "string" && tool === "web_search"),
9
9
  };
10
10
  }
11
11
  export function generatePackageJson(vars) {
@@ -23,7 +23,7 @@ export function generatePackageJson(vars) {
23
23
  zod: "^4.1.12",
24
24
  };
25
25
  const pkg = {
26
- name: `@town/agent-${vars.name}`,
26
+ name: `@townco/agent-${vars.name}`,
27
27
  version: "0.0.1",
28
28
  type: "module",
29
29
  module: "index.ts",
@@ -102,7 +102,11 @@ export function generateTsConfig() {
102
102
  return JSON.stringify(config, null, 2);
103
103
  }
104
104
  export function generateReadme(vars) {
105
- const toolsList = vars.tools.length > 0 ? vars.tools.join(", ") : "None";
105
+ const toolsList = vars.tools.length > 0
106
+ ? vars.tools
107
+ .map((tool) => (typeof tool === "string" ? tool : tool.modulePath))
108
+ .join(", ")
109
+ : "None";
106
110
  const envVars = vars.hasWebSearch
107
111
  ? "\n- `EXA_API_KEY`: Required for web_search tool"
108
112
  : "";
@@ -1,18 +1,17 @@
1
1
  import { LangchainAgent } from "./runner/langchain";
2
-
3
2
  const agent = new LangchainAgent({
4
- model: "claude-sonnet-4-5-20250929",
5
- systemPrompt: "You are a helpful assistant.",
6
- tools: ["todo_write"],
3
+ model: "claude-sonnet-4-5-20250929",
4
+ systemPrompt: "You are a helpful assistant.",
5
+ tools: ["todo_write"],
7
6
  });
8
7
  for await (const event of agent.invoke({
9
- prompt: [
10
- {
11
- type: "text",
12
- text: "Whats the weather in Tokyo?",
13
- },
14
- ],
15
- sessionId: "test-session",
8
+ prompt: [
9
+ {
10
+ type: "text",
11
+ text: "Whats the weather in Tokyo?",
12
+ },
13
+ ],
14
+ sessionId: "test-session",
16
15
  })) {
17
- console.log(event);
16
+ console.log(event);
18
17
  }