create-bk-agent 0.16.0 → 0.17.0

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.
package/README.md CHANGED
@@ -1,54 +1,118 @@
1
1
  # create-bk-agent
2
2
 
3
- Scaffold a new [BackendKit agent](https://github.com/BackendKit-labs/backendkit-agent-framework) project in seconds.
3
+ Scaffold a new [BackendKit agent](https://github.com/BackendKit-labs/backendkit-agent-framework) project in seconds — or add capabilities to an existing one.
4
4
 
5
- ## Usage
5
+ ## Create a project
6
6
 
7
7
  ```bash
8
8
  npx create-bk-agent my-project
9
9
  ```
10
10
 
11
+ The CLI asks three questions and generates a production-ready project:
12
+
11
13
  ```
12
- ✨ create-bk-agent v0.14.0
14
+ ✨ create-bk-agent v0.17.0
13
15
 
14
- ? Project name: my-project
15
- ? Template: coding — Coding assistant (files, git, code execution)
16
- ? LLM provider: Anthropic (Claude)
16
+ ? Project name: my-project
17
+ ? Architecture: Multi-agent (orchestrator + specialists)
18
+ ? Skill packs: Node.js / TypeScript
19
+ ? How will it be used? MCP Server (HTTP)
17
20
 
18
- Creating coding agent in ./my-project...
21
+ Creating Multi-agent — MCP Server (HTTP) agent in ./my-project...
19
22
  Installing dependencies...
20
23
 
21
- ✅ Done!
24
+ ✅ Done! Your agent is ready.
25
+
22
26
  cd my-project
23
- cp .env.example .env
24
- npm run dev
27
+ cp .env.example .env # add your API key
28
+ npm run server # starts HTTP MCP on port 3001
25
29
  ```
26
30
 
27
- ## Templates
31
+ ## Architectures
32
+
33
+ | Architecture | What it gives you | Best for |
34
+ |---|---|---|
35
+ | `multi-agent` | Orchestrator + specialists with delegation | Domain agents (DevOps, finance, data, etc.) |
36
+ | `single` | One agent with a tool registry | Simple task automation |
37
+ | `coding` | 10 pre-built agents + all coding tools | Coding assistants, ready out of the box |
38
+ | `autonomous` | Trigger system (cron / webhook / event) | Scheduled or event-driven daemons |
39
+ | `minimal` | Bare engine, no entry point | Library embedding |
28
40
 
29
- ### `coding` — complete, ready to run
30
- 10 specialized agents (backend, frontend, QA, security, architecture…) and all
31
- coding tools (read/write files, run commands, git, search) are already configured.
32
- Add your API key, describe your project in `AGENT.md`, and it works out of the box.
33
- **Choose this when you want a coding assistant, not when you want to build one.**
41
+ ## Deploy modes
34
42
 
35
- ### `domain-agent` — blank multi-agent architecture
36
- Orchestrator + specialists pattern with no pre-built agents or tools. You define
37
- the agents and tools for your specific domain (Docker, AWS, databases, APIs, etc.).
38
- The framework handles orchestration, delegation, and parallel execution.
39
- **Choose this when you are building a new type of agent from scratch.**
43
+ Available for `multi-agent` and `single` architectures:
40
44
 
41
- | Template | What it gives you | You provide |
42
- |----------|------------------|-------------|
43
- | `coding` | 10 agents + all coding tools | API key + `AGENT.md` |
44
- | `domain-agent` | Orchestration skeleton | Agents + tools for your domain |
45
- | `autonomous` | Trigger system (cron / webhook / event) | Agent logic |
46
- | `mcp-server` | MCP server boilerplate | Tools to expose |
47
- | `minimal` | Bare engine | Everything |
45
+ | Mode | Entry point | Use case |
46
+ |---|---|---|
47
+ | `repl` | `src/index.ts` — readline loop | Local terminal tool |
48
+ | `mcp-http` | `src/server.ts` — HTTP MCP server | Connect to Claude Desktop, Cursor, etc. |
49
+ | `mcp-stdio` | `src/server.ts` — stdio MCP server | Subprocess / pipe-based MCP |
50
+ | `hybrid` | Both `index.ts` + `server.ts` | REPL for dev, server for production |
51
+ | `library` | Only `src/engine.ts` exported | Import the engine in your own app |
48
52
 
49
53
  ## Providers
50
54
 
51
- Supports Anthropic (Claude), OpenAI, DeepSeek / OpenAI-compatible endpoints, and Ollama (local).
55
+ Anthropic (Claude), OpenAI, DeepSeek / any OpenAI-compatible endpoint, and Ollama (local).
56
+
57
+ ---
58
+
59
+ ## Add capabilities to an existing project
60
+
61
+ Once a project is created, use `add` to extend it without editing code manually:
62
+
63
+ ```bash
64
+ npx create-bk-agent add <module> [options]
65
+ ```
66
+
67
+ ### `add server` — expose the agent as an HTTP MCP server
68
+
69
+ ```bash
70
+ npx create-bk-agent add server
71
+ npx create-bk-agent add server --port 4000 --name my-agent
72
+ ```
73
+
74
+ - Generates `src/server.ts` wired to the existing engine
75
+ - Adds `@backendkit-labs/mcp-server` to `dependencies`
76
+ - Adds `"server"` script to `package.json`
77
+
78
+ ### `add specialist <name>` — add a specialist agent (multi-agent projects)
79
+
80
+ ```bash
81
+ npx create-bk-agent add specialist data-analyst
82
+ npx create-bk-agent add specialist git-expert
83
+ ```
84
+
85
+ - Creates `src/agents/<name>.ts` with an `AgentProfile` stub
86
+ - Patches `src/engine.ts`: adds the import and `agents.register()`
87
+
88
+ ### `add tools <domain>` — add a tool file for a new domain
89
+
90
+ ```bash
91
+ npx create-bk-agent add tools github
92
+ npx create-bk-agent add tools my-database
93
+ ```
94
+
95
+ - Creates `src/tools/<domain>-tools.ts` with two stub tools (action + query)
96
+ - Patches `src/engine.ts`: adds the import and `tools.register()`
97
+
98
+ ### `add mcp-client <url>` — connect to a remote MCP server
99
+
100
+ ```bash
101
+ npx create-bk-agent add mcp-client http://localhost:3001/mcp
102
+ npx create-bk-agent add mcp-client http://billing-agent/mcp --name billing
103
+ ```
104
+
105
+ - Patches `src/engine.ts`: adds the entry to `mcpServers: [...]` inside `AgentEngine`
106
+ - Creates the `mcpServers` array if it doesn't exist yet
107
+
108
+ All `add` commands are **idempotent** — running the same command twice won't duplicate entries.
109
+
110
+ ---
111
+
112
+ ## Requirements
113
+
114
+ - Node.js >= 20
115
+ - An API key for your chosen provider (Anthropic, OpenAI, DeepSeek, or Ollama)
52
116
 
53
117
  ## License
54
118
 
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.detectProject = detectProject;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ function detectProject(cwd) {
40
+ const pkgFile = path.join(cwd, 'package.json');
41
+ if (!fs.existsSync(pkgFile))
42
+ return null;
43
+ let pkg;
44
+ try {
45
+ pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ const deps = {
51
+ ...(pkg.dependencies ?? {}),
52
+ ...(pkg.devDependencies ?? {}),
53
+ };
54
+ if (!deps['@backendkit-labs/agent-core'])
55
+ return null;
56
+ const engineFile = path.join(cwd, 'src', 'engine.ts');
57
+ let architecture = 'unknown';
58
+ let engineFnName = 'createEngine';
59
+ if (fs.existsSync(engineFile)) {
60
+ const content = fs.readFileSync(engineFile, 'utf-8');
61
+ if (content.includes('ORCHESTRATOR_PROFILE') || content.includes("id: 'orchestrator'")) {
62
+ architecture = 'multi-agent';
63
+ }
64
+ else if (content.includes('export function create')) {
65
+ architecture = 'single';
66
+ }
67
+ const match = content.match(/export function (\w+)\s*\(/);
68
+ if (match)
69
+ engineFnName = match[1];
70
+ }
71
+ return {
72
+ cwd,
73
+ architecture,
74
+ engineFile,
75
+ indexFile: path.join(cwd, 'src', 'index.ts'),
76
+ serverFile: path.join(cwd, 'src', 'server.ts'),
77
+ pkgFile,
78
+ engineFnName,
79
+ };
80
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAdd = runAdd;
4
+ const detector_1 = require("./detector");
5
+ const server_1 = require("./modules/server");
6
+ const specialist_1 = require("./modules/specialist");
7
+ const tools_1 = require("./modules/tools");
8
+ const mcp_client_1 = require("./modules/mcp-client");
9
+ const HELP = `
10
+ Usage: npx create-bk-agent add <module> [options]
11
+
12
+ Modules:
13
+ server Add an HTTP MCP server (src/server.ts)
14
+ --port <n> Port to listen on (default: 3001)
15
+ --name <s> MCP server name (default: project directory name)
16
+
17
+ specialist <name> Add a new specialist agent to a multi-agent project
18
+ (creates src/agents/<name>.ts and patches engine.ts)
19
+
20
+ tools <domain> Add a tool file for a new domain
21
+ (creates src/tools/<domain>-tools.ts and patches engine.ts)
22
+
23
+ mcp-client <url> Add a remote MCP server to the engine
24
+ --name <s> Name for the mcpServers entry (default: last URL segment)
25
+
26
+ Examples:
27
+ npx create-bk-agent add server --port 4000
28
+ npx create-bk-agent add specialist data-analyst
29
+ npx create-bk-agent add tools github
30
+ npx create-bk-agent add mcp-client http://localhost:3001/mcp --name billing
31
+ `;
32
+ function runAdd(args, cwd) {
33
+ const [module, ...rest] = args;
34
+ if (!module || module === '--help' || module === '-h') {
35
+ console.log(HELP);
36
+ process.exit(0);
37
+ }
38
+ const info = (0, detector_1.detectProject)(cwd);
39
+ if (!info) {
40
+ console.error('\n✗ No bk-agent project detected in the current directory.\n' +
41
+ ' Make sure you are inside a project created with npx create-bk-agent.\n');
42
+ process.exit(1);
43
+ }
44
+ switch (module) {
45
+ case 'server':
46
+ (0, server_1.addServer)(info, rest);
47
+ break;
48
+ case 'specialist':
49
+ if (info.architecture !== 'multi-agent') {
50
+ console.error(`\n⚠ "add specialist" is designed for multi-agent projects.\n` +
51
+ ` Detected architecture: ${info.architecture}.\n` +
52
+ ` Proceeding anyway — verify engine.ts manually.\n`);
53
+ }
54
+ (0, specialist_1.addSpecialist)(info, rest);
55
+ break;
56
+ case 'tools':
57
+ (0, tools_1.addTools)(info, rest);
58
+ break;
59
+ case 'mcp-client':
60
+ (0, mcp_client_1.addMcpClient)(info, rest);
61
+ break;
62
+ default:
63
+ console.error(`\n✗ Unknown module: "${module}"\n`);
64
+ console.log(HELP);
65
+ process.exit(1);
66
+ }
67
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.addMcpClient = addMcpClient;
37
+ const fs = __importStar(require("fs"));
38
+ const patcher_1 = require("../patcher");
39
+ function addMcpClient(info, args) {
40
+ const url = args[0];
41
+ if (!url) {
42
+ console.error('\n✗ Usage: add mcp-client <url> [--name <name>]\n');
43
+ process.exit(1);
44
+ }
45
+ let name = url.split('/').filter(Boolean).pop() ?? 'remote-agent';
46
+ for (let i = 1; i < args.length; i++) {
47
+ if (args[i] === '--name' && args[i + 1]) {
48
+ name = args[++i];
49
+ break;
50
+ }
51
+ }
52
+ if (!fs.existsSync(info.engineFile)) {
53
+ console.error('\n✗ src/engine.ts not found.\n');
54
+ process.exit(1);
55
+ }
56
+ const ok = (0, patcher_1.addMcpServerEntry)(info.engineFile, name, url);
57
+ if (ok) {
58
+ console.log(`\n✓ Patched src/engine.ts (mcpServers: { name: '${name}', url: '${url}' })`);
59
+ console.log(`\nNext steps:\n npm run dev\n`);
60
+ }
61
+ else {
62
+ console.error('\n✗ Could not locate AgentEngine constructor to inject mcpServers.\n');
63
+ process.exit(1);
64
+ }
65
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.addServer = addServer;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const patcher_1 = require("../patcher");
40
+ function parseArgs(args, defaultName) {
41
+ let port = 3001;
42
+ let name = defaultName;
43
+ for (let i = 0; i < args.length; i++) {
44
+ if (args[i] === '--port' && args[i + 1])
45
+ port = parseInt(args[++i]);
46
+ if (args[i] === '--name' && args[i + 1])
47
+ name = args[++i];
48
+ }
49
+ return { port, name };
50
+ }
51
+ function generateServerTs(info, opts) {
52
+ return `import 'dotenv/config';
53
+ import { AgentMCPServer } from '@backendkit-labs/mcp-server';
54
+ import { CallbackTransport } from '@backendkit-labs/agent-core';
55
+ import { z } from 'zod';
56
+ import { ${info.engineFnName} } from './engine';
57
+
58
+ const server = new AgentMCPServer({
59
+ name: '${opts.name}',
60
+ version: '1.0.0',
61
+ port: parseInt(process.env.MCP_PORT ?? '${opts.port}'),
62
+
63
+ tools: [
64
+ {
65
+ name: 'agent_request',
66
+ description: 'TODO: describe what requests this agent handles',
67
+ schema: {
68
+ request: z.string().describe('Natural-language request for the agent'),
69
+ },
70
+ buildPrompt: ({ request }: { request: string }) => request,
71
+ },
72
+ ],
73
+
74
+ engineFactory: (transport: CallbackTransport) => ${info.engineFnName}(transport),
75
+ });
76
+
77
+ await server.start();
78
+ `;
79
+ }
80
+ function addServer(info, args) {
81
+ const opts = parseArgs(args, path.basename(info.cwd));
82
+ if (fs.existsSync(info.serverFile)) {
83
+ console.error(`\n✗ src/server.ts already exists. Remove it first to regenerate.\n`);
84
+ process.exit(1);
85
+ }
86
+ fs.writeFileSync(info.serverFile, generateServerTs(info, opts));
87
+ console.log(`\n✓ Created src/server.ts (HTTP MCP on port ${opts.port})`);
88
+ const added = (0, patcher_1.addPackageDependency)(info.pkgFile, '@backendkit-labs/mcp-server', '^0.16.0');
89
+ (0, patcher_1.addPackageDependency)(info.pkgFile, 'zod', '^3.25.0');
90
+ (0, patcher_1.addPackageScript)(info.pkgFile, 'server', 'ts-node src/server.ts');
91
+ if (added) {
92
+ console.log(`✓ package.json (@backendkit-labs/mcp-server added)`);
93
+ }
94
+ console.log(`✓ package.json (script "server" added)`);
95
+ console.log(`
96
+ Next steps:
97
+ npm install
98
+ npm run server # starts HTTP MCP on port ${opts.port}
99
+ `);
100
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.addSpecialist = addSpecialist;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const patcher_1 = require("../patcher");
40
+ function toConstName(name) {
41
+ return name.replace(/-/g, '_').toUpperCase() + '_PROFILE';
42
+ }
43
+ function toDisplayName(name) {
44
+ return name.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
45
+ }
46
+ function generateSpecialistTs(name) {
47
+ const constName = toConstName(name);
48
+ return `import type { AgentProfile } from '@backendkit-labs/agent-core';
49
+
50
+ // TODO: Rename this file and export to match your domain
51
+ export const ${constName}: AgentProfile = {
52
+ id: '${name}',
53
+ name: '${toDisplayName(name)}',
54
+ icon: '🔧',
55
+ description: 'TODO: describe what this specialist does',
56
+ delegatesTo: [],
57
+ allowedTools: [
58
+ // TODO: list the tool names this agent can use
59
+ ],
60
+ systemPrompt: \`You are a specialist in TODO: <your domain area>.
61
+
62
+ Use the available tools to complete the task delegated to you.
63
+ Be precise and report results clearly.\`,
64
+ };
65
+ `;
66
+ }
67
+ function addSpecialist(info, args) {
68
+ const name = args[0];
69
+ if (!name) {
70
+ console.error('\n✗ Usage: add specialist <name>\n');
71
+ process.exit(1);
72
+ }
73
+ const agentFile = path.join(info.cwd, 'src', 'agents', `${name}.ts`);
74
+ if (fs.existsSync(agentFile)) {
75
+ console.error(`\n✗ src/agents/${name}.ts already exists.\n`);
76
+ process.exit(1);
77
+ }
78
+ fs.writeFileSync(agentFile, generateSpecialistTs(name));
79
+ console.log(`\n✓ Created src/agents/${name}.ts`);
80
+ if (fs.existsSync(info.engineFile)) {
81
+ const constName = toConstName(name);
82
+ (0, patcher_1.addImportLine)(info.engineFile, `import { ${constName} } from './agents/${name}';`);
83
+ // Primary: insert after TODO comment; fallback: after last .register( call
84
+ const inserted = (0, patcher_1.insertAfterPattern)(info.engineFile, /\/\/ TODO: register more specialists/, ` agents.register(${constName});`) ||
85
+ (0, patcher_1.insertAfterPattern)(info.engineFile, /agents\.register\(/, ` agents.register(${constName});`);
86
+ if (inserted) {
87
+ console.log(`✓ Patched src/engine.ts (agents.register(${constName}))`);
88
+ }
89
+ else {
90
+ console.log(`⚠ Could not auto-patch engine.ts — add manually: agents.register(${constName})`);
91
+ }
92
+ const orchestratorFile = path.join(info.cwd, 'src', 'agents', 'orchestrator.ts');
93
+ if (fs.existsSync(orchestratorFile)) {
94
+ console.log(`\n Reminder: add '${name}' to orchestrator.ts delegatesTo[] and update the systemPrompt.`);
95
+ }
96
+ }
97
+ console.log(`\nNext steps:\n Implement src/agents/${name}.ts\n npm run dev\n`);
98
+ }
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.addTools = addTools;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const patcher_1 = require("../patcher");
40
+ function toCamelCase(name) {
41
+ return name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
42
+ }
43
+ function generateToolsTs(domain) {
44
+ const fn = toCamelCase(domain);
45
+ return `import { defineTool, z } from '@backendkit-labs/agent-core';
46
+
47
+ // TODO: replace with real ${domain} SDK/API calls
48
+
49
+ export const ${fn}Action = defineTool({
50
+ name: '${domain}_action',
51
+ description: 'TODO: describe what this tool does',
52
+ input: z.object({
53
+ target: z.string().describe('Target to act on'),
54
+ // TODO: add more parameters
55
+ }),
56
+ execute: async ({ target }) => {
57
+ // TODO: implement
58
+ return \`${domain} action on: \${target}\`;
59
+ },
60
+ });
61
+
62
+ export const ${fn}Query = defineTool({
63
+ name: '${domain}_query',
64
+ description: 'TODO: describe what this query returns',
65
+ input: z.object({
66
+ filter: z.string().optional().describe('Optional filter'),
67
+ }),
68
+ execute: async ({ filter }) => {
69
+ // TODO: implement
70
+ return JSON.stringify({ results: [], filter });
71
+ },
72
+ });
73
+ `;
74
+ }
75
+ function addTools(info, args) {
76
+ const domain = args[0];
77
+ if (!domain) {
78
+ console.error('\n✗ Usage: add tools <domain>\n');
79
+ process.exit(1);
80
+ }
81
+ const toolsFile = path.join(info.cwd, 'src', 'tools', `${domain}-tools.ts`);
82
+ if (fs.existsSync(toolsFile)) {
83
+ console.error(`\n✗ src/tools/${domain}-tools.ts already exists.\n`);
84
+ process.exit(1);
85
+ }
86
+ fs.mkdirSync(path.dirname(toolsFile), { recursive: true });
87
+ fs.writeFileSync(toolsFile, generateToolsTs(domain));
88
+ console.log(`\n✓ Created src/tools/${domain}-tools.ts`);
89
+ if (fs.existsSync(info.engineFile)) {
90
+ const fn = toCamelCase(domain);
91
+ (0, patcher_1.addImportLine)(info.engineFile, `import { ${fn}Action, ${fn}Query } from './tools/${domain}-tools';`);
92
+ const inserted = (0, patcher_1.insertAfterPattern)(info.engineFile, /\/\/ TODO: register more tools/, ` tools.register(${fn}Action).register(${fn}Query);`) ||
93
+ (0, patcher_1.insertAfterPattern)(info.engineFile, /tools\.register\(/, ` tools.register(${fn}Action).register(${fn}Query);`);
94
+ if (inserted) {
95
+ console.log(`✓ Patched src/engine.ts (tools.register(${fn}Action, ${fn}Query))`);
96
+ }
97
+ else {
98
+ console.log(`⚠ Could not auto-patch engine.ts — add manually: tools.register(${fn}Action).register(${fn}Query)`);
99
+ }
100
+ }
101
+ console.log(`\nNext steps:\n Implement src/tools/${domain}-tools.ts\n npm run dev\n`);
102
+ }