create-bk-agent 0.23.4 → 0.23.6
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 +0 -2
- package/dist/src/add/modules/knowledge.js +18 -18
- package/dist/src/add/modules/server.js +1 -1
- package/dist/src/add/patcher.js +106 -68
- package/dist/src/scaffold.js +29 -16
- package/package.json +2 -2
- package/templates/README.md +26 -0
- package/templates/base/autonomous/package.json +1 -1
- package/templates/base/autonomous/src/index.ts +83 -83
- package/templates/base/coding/package.json +1 -1
- package/templates/base/enterprise/package.json +1 -1
- package/templates/base/minimal/package.json +1 -1
- package/templates/base/minimal/src/index.ts +43 -43
- package/templates/base/multi-agent/package.json +2 -2
- package/templates/base/multi-agent/src/engine.ts +78 -78
- package/templates/base/single/package.json +2 -2
- package/templates/base/single/src/engine.ts +67 -67
- package/templates/autonomous/.env.example +0 -8
- package/templates/autonomous/package.json +0 -25
- package/templates/autonomous/src/index.ts +0 -64
- package/templates/autonomous/tsconfig.json +0 -16
- package/templates/base/multi-agent/src/providers/openai-compatible.ts +0 -104
- package/templates/base/single/src/providers/openai-compatible.ts +0 -104
- package/templates/coding/.env.example +0 -8
- package/templates/coding/package.json +0 -26
- package/templates/coding/src/index.ts +0 -42
- package/templates/coding/tsconfig.json +0 -17
- package/templates/domain-agent/.env.example +0 -7
- package/templates/domain-agent/package.json +0 -27
- package/templates/domain-agent/src/agents/orchestrator.ts +0 -22
- package/templates/domain-agent/src/agents/specialist-a.ts +0 -17
- package/templates/domain-agent/src/agents/specialist-b.ts +0 -16
- package/templates/domain-agent/src/config.ts +0 -19
- package/templates/domain-agent/src/engine.ts +0 -49
- package/templates/domain-agent/src/index.ts +0 -27
- package/templates/domain-agent/src/providers/openai-compatible.ts +0 -104
- package/templates/domain-agent/src/tools/example-tools.ts +0 -28
- package/templates/domain-agent/tsconfig.json +0 -17
- package/templates/mcp-server/package.json +0 -30
- package/templates/mcp-server/src/server.ts +0 -40
- package/templates/mcp-server/src/tools/example.ts +0 -10
- package/templates/mcp-server/tsconfig.json +0 -16
- package/templates/minimal/package.json +0 -25
- package/templates/minimal/src/index.ts +0 -40
- package/templates/minimal/tsconfig.json +0 -16
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# create-bk-agent
|
|
2
2
|
|
|
3
|
-
> **Status: `stable`** — Maintained and production-ready. No new features during the pilot phase.
|
|
4
|
-
|
|
5
3
|
CLI scaffolding tool for the BackendKit Labs agent framework. Generates a fully configured TypeScript agent project in seconds — choose your architecture, deployment mode, and LLM provider, and get a working project with all dependencies wired.
|
|
6
4
|
|
|
7
5
|
## Usage
|
|
@@ -154,7 +154,7 @@ function addNewVault(engineFile, vaultPath) {
|
|
|
154
154
|
// ── Non-enterprise setup ──────────────────────────────────────────────────────
|
|
155
155
|
function setupRagFromScratch(info, vaultPath) {
|
|
156
156
|
console.log('\n📦 Installing @backendkit-labs/agent-enterprise ...');
|
|
157
|
-
const added = (0, patcher_1.addPackageDependency)(info.pkgFile, '@backendkit-labs/agent-enterprise', '^0.
|
|
157
|
+
const added = (0, patcher_1.addPackageDependency)(info.pkgFile, '@backendkit-labs/agent-enterprise', '^0.8.8');
|
|
158
158
|
if (added) {
|
|
159
159
|
(0, child_process_1.execSync)('npm install', { cwd: info.cwd, stdio: 'inherit' });
|
|
160
160
|
}
|
|
@@ -195,26 +195,26 @@ function setupRagFromScratch(info, vaultPath) {
|
|
|
195
195
|
}
|
|
196
196
|
function printManualInstructions(vaultPath) {
|
|
197
197
|
const normalized = vaultPath.replace(/\\/g, '/');
|
|
198
|
-
console.log(`
|
|
199
|
-
1. Import in engine.ts:
|
|
200
|
-
import { ObsidianRAGProvider } from '@backendkit-labs/agent-enterprise';
|
|
201
|
-
|
|
202
|
-
2. Create RAG instance:
|
|
203
|
-
const rag = new ObsidianRAGProvider({ vaultPath: '${normalized}' });
|
|
204
|
-
|
|
205
|
-
3. Register tool:
|
|
206
|
-
tools.register(rag.createTool());
|
|
198
|
+
console.log(`
|
|
199
|
+
1. Import in engine.ts:
|
|
200
|
+
import { ObsidianRAGProvider } from '@backendkit-labs/agent-enterprise';
|
|
201
|
+
|
|
202
|
+
2. Create RAG instance:
|
|
203
|
+
const rag = new ObsidianRAGProvider({ vaultPath: '${normalized}' });
|
|
204
|
+
|
|
205
|
+
3. Register tool:
|
|
206
|
+
tools.register(rag.createTool());
|
|
207
207
|
`);
|
|
208
208
|
}
|
|
209
209
|
// ── Main export ───────────────────────────────────────────────────────────────
|
|
210
|
-
const USAGE = `
|
|
211
|
-
Usage: npx create-bk-agent add knowledge <folder-path>
|
|
212
|
-
npx create-bk-agent add knowledge --vault <vault-path>
|
|
213
|
-
|
|
214
|
-
Examples:
|
|
215
|
-
npx create-bk-agent add knowledge ./docs
|
|
216
|
-
npx create-bk-agent add knowledge "04-Recursos/Backend"
|
|
217
|
-
npx create-bk-agent add knowledge --vault "C:/Company/HR-Vault"
|
|
210
|
+
const USAGE = `
|
|
211
|
+
Usage: npx create-bk-agent add knowledge <folder-path>
|
|
212
|
+
npx create-bk-agent add knowledge --vault <vault-path>
|
|
213
|
+
|
|
214
|
+
Examples:
|
|
215
|
+
npx create-bk-agent add knowledge ./docs
|
|
216
|
+
npx create-bk-agent add knowledge "04-Recursos/Backend"
|
|
217
|
+
npx create-bk-agent add knowledge --vault "C:/Company/HR-Vault"
|
|
218
218
|
`;
|
|
219
219
|
function addKnowledge(info, args) {
|
|
220
220
|
const parsed = parseArgs(args);
|
|
@@ -85,7 +85,7 @@ function addServer(info, args) {
|
|
|
85
85
|
}
|
|
86
86
|
fs.writeFileSync(info.serverFile, generateServerTs(info, opts));
|
|
87
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.
|
|
88
|
+
const added = (0, patcher_1.addPackageDependency)(info.pkgFile, '@backendkit-labs/mcp-server', '^0.19.0');
|
|
89
89
|
(0, patcher_1.addPackageDependency)(info.pkgFile, 'zod', '^4.6.6');
|
|
90
90
|
(0, patcher_1.addPackageScript)(info.pkgFile, 'server', 'ts-node src/server.ts');
|
|
91
91
|
if (added) {
|
package/dist/src/add/patcher.js
CHANGED
|
@@ -134,87 +134,125 @@ function addPackageDevDependency(pkgFile, depName, version) {
|
|
|
134
134
|
fs.writeFileSync(pkgFile, JSON.stringify(pkg, null, 2) + '\n');
|
|
135
135
|
return true;
|
|
136
136
|
}
|
|
137
|
-
// ── AgentEngine options patcher ───────────────────────────────────────────────
|
|
138
137
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
* Returns true on success.
|
|
138
|
+
* `mcpServers` is an option of createBaseEngine only. AgentEngine takes an `mcpManager`, so patching
|
|
139
|
+
* `mcpServers` into `new AgentEngine({...})` produced code that does not compile (an unknown property).
|
|
142
140
|
*/
|
|
143
|
-
function
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
// Insert new mcpServers block before the closing of AgentEngine({ ... })
|
|
157
|
-
const lines = content.split('\n');
|
|
141
|
+
function findEngineCall(content) {
|
|
142
|
+
const base = content.search(/createBaseEngine\s*\(\s*\{/);
|
|
143
|
+
if (base !== -1)
|
|
144
|
+
return { kind: 'base', open: content.indexOf('{', base) };
|
|
145
|
+
const engine = content.search(/new AgentEngine\s*\(\s*\{/);
|
|
146
|
+
if (engine !== -1)
|
|
147
|
+
return { kind: 'engine', open: content.indexOf('{', engine) };
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
/** Index of the `}` that closes the object literal opened at `open`, skipping strings, templates and comments. */
|
|
151
|
+
function matchingBrace(content, open) {
|
|
158
152
|
let depth = 0;
|
|
159
|
-
let
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
|
|
153
|
+
for (let i = open; i < content.length; i++) {
|
|
154
|
+
const c = content[i];
|
|
155
|
+
const next = content[i + 1];
|
|
156
|
+
if (c === '/' && next === '/') {
|
|
157
|
+
i = content.indexOf('\n', i);
|
|
158
|
+
if (i === -1)
|
|
159
|
+
return -1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (c === '/' && next === '*') {
|
|
163
|
+
i = content.indexOf('*/', i + 2);
|
|
164
|
+
if (i === -1)
|
|
165
|
+
return -1;
|
|
166
|
+
i++;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (c === "'" || c === '"') {
|
|
170
|
+
for (i++; i < content.length && content[i] !== c; i++)
|
|
171
|
+
if (content[i] === '\\')
|
|
172
|
+
i++;
|
|
173
|
+
continue;
|
|
165
174
|
}
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
if (c === '`') {
|
|
176
|
+
for (i++; i < content.length && content[i] !== '`'; i++) {
|
|
177
|
+
if (content[i] === '\\') {
|
|
178
|
+
i++;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (content[i] === '$' && content[i + 1] === '{') {
|
|
182
|
+
const inner = matchingBrace(content, i + 1);
|
|
183
|
+
if (inner === -1)
|
|
184
|
+
return -1;
|
|
185
|
+
i = inner;
|
|
186
|
+
}
|
|
172
187
|
}
|
|
188
|
+
continue;
|
|
173
189
|
}
|
|
190
|
+
if (c === '{')
|
|
191
|
+
depth++;
|
|
192
|
+
else if (c === '}' && --depth === 0)
|
|
193
|
+
return i;
|
|
174
194
|
}
|
|
175
|
-
|
|
176
|
-
return false;
|
|
177
|
-
lines.splice(closeIdx, 0, ` mcpServers: [\n${entry}\n ],`);
|
|
178
|
-
fs.writeFileSync(file, lines.join('\n'));
|
|
179
|
-
return true;
|
|
195
|
+
return -1;
|
|
180
196
|
}
|
|
181
197
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
198
|
+
* Registers one MCP server entry (an object literal source) in the project's engine:
|
|
199
|
+
* appends to an existing list, or adds the option, keeping the file valid TypeScript.
|
|
184
200
|
*/
|
|
185
|
-
function
|
|
201
|
+
function addMcpEntry(file, entry, alreadyThere) {
|
|
186
202
|
const content = fs.readFileSync(file, 'utf-8');
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
203
|
+
if (content.includes(alreadyThere))
|
|
204
|
+
return true;
|
|
205
|
+
const call = findEngineCall(content);
|
|
206
|
+
if (!call)
|
|
207
|
+
return false;
|
|
208
|
+
const line = ` ${entry},`;
|
|
209
|
+
// An existing list: add to its start.
|
|
210
|
+
const existing = call.kind === 'base' ? /mcpServers:\s*\[/ : /new MCPClientManager\(\s*\[/;
|
|
211
|
+
const m = existing.exec(content);
|
|
212
|
+
if (m) {
|
|
213
|
+
fs.writeFileSync(file, content.slice(0, m.index + m[0].length) + '\n' + line + content.slice(m.index + m[0].length));
|
|
195
214
|
return true;
|
|
196
215
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let closeIdx = -1;
|
|
201
|
-
for (let i = 0; i < lines.length; i++) {
|
|
202
|
-
if (lines[i].includes('new AgentEngine({')) {
|
|
203
|
-
engineStart = i;
|
|
204
|
-
depth = 0;
|
|
205
|
-
}
|
|
206
|
-
if (engineStart !== -1) {
|
|
207
|
-
depth += (lines[i].match(/\{/g) ?? []).length;
|
|
208
|
-
depth -= (lines[i].match(/\}/g) ?? []).length;
|
|
209
|
-
if (depth === 0 && i > engineStart) {
|
|
210
|
-
closeIdx = i;
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (closeIdx === -1)
|
|
216
|
+
// No list yet: add the option just before the closing brace of the options object.
|
|
217
|
+
const close = matchingBrace(content, call.open);
|
|
218
|
+
if (close === -1)
|
|
216
219
|
return false;
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
const before = content.slice(0, close).replace(/\s+$/, '');
|
|
221
|
+
const needsComma = !/[,{]$/.test(before); // the last property may have no trailing comma
|
|
222
|
+
const option = call.kind === 'base'
|
|
223
|
+
? ` mcpServers: [\n${line}\n ],`
|
|
224
|
+
: ` mcpManager: new MCPClientManager([\n${line}\n ]),`;
|
|
225
|
+
fs.writeFileSync(file, before + (needsComma ? ',' : '') + '\n' + option + '\n' + content.slice(close));
|
|
226
|
+
if (call.kind === 'engine')
|
|
227
|
+
addMcpManagerImport(file);
|
|
219
228
|
return true;
|
|
220
229
|
}
|
|
230
|
+
/** Makes `MCPClientManager` available from agent-core: into the existing import, or as a new one. */
|
|
231
|
+
function addMcpManagerImport(file) {
|
|
232
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
233
|
+
if (/\bMCPClientManager\b[^;]*from\s+['"]@backendkit-labs\/agent-core['"]/.test(content))
|
|
234
|
+
return;
|
|
235
|
+
const named = /import\s*\{([^}]*)\}\s*from\s*(['"])@backendkit-labs\/agent-core\2/.exec(content);
|
|
236
|
+
if (named) {
|
|
237
|
+
const names = named[1].replace(/\s+$/, '');
|
|
238
|
+
const sep = names.trim().endsWith(',') ? '' : ',';
|
|
239
|
+
const multiline = named[1].includes('\n');
|
|
240
|
+
const added = multiline ? `${names}${sep}\n MCPClientManager,\n` : `${names}${sep} MCPClientManager `;
|
|
241
|
+
fs.writeFileSync(file, content.replace(named[0], `import {${added}} from ${named[2]}@backendkit-labs/agent-core${named[2]}`));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
addImportLine(file, "import { MCPClientManager } from '@backendkit-labs/agent-core';");
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Adds a remote MCP server `{ name, url }` to the engine of a generated project (createBaseEngine or AgentEngine).
|
|
248
|
+
* Appends if a list exists. Returns true on success.
|
|
249
|
+
*/
|
|
250
|
+
function addMcpServerEntry(file, name, url) {
|
|
251
|
+
return addMcpEntry(file, `{ name: '${name}', url: '${url}' }`, `url: '${url}'`);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Adds a stdio MCP server `{ name, command: 'npx', args: ['-y', pkg] }`. Returns true on success.
|
|
255
|
+
*/
|
|
256
|
+
function addMcpStdioEntry(file, name, npmPackage) {
|
|
257
|
+
return addMcpEntry(file, `{ name: '${name}', command: 'npx', args: ['-y', '${npmPackage}'] }`, `'${npmPackage}'`);
|
|
258
|
+
}
|
package/dist/src/scaffold.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.GENERATED_DEP_RANGES = void 0;
|
|
36
|
+
exports.ORCHESTRATOR_PROVIDERS = exports.GENERATED_DEP_RANGES = exports.PROVIDER_ENV = exports.PROVIDER_DEFAULTS = void 0;
|
|
37
37
|
exports.scaffold = scaffold;
|
|
38
38
|
exports.installDeps = installDeps;
|
|
39
39
|
const fs = __importStar(require("fs"));
|
|
@@ -46,11 +46,23 @@ const DEPLOY_DIR = path.join(TEMPLATES_DIR, 'deploy');
|
|
|
46
46
|
// The rest (coding, autonomous, minimal) are self-contained in base/.
|
|
47
47
|
const LAYERED = ['multi-agent', 'single', 'enterprise'];
|
|
48
48
|
// ── Provider env var hints ────────────────────────────────────────────────────
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
/**
|
|
50
|
+
* What is true of a provider whichever kind of project is generated: its default model and API endpoint.
|
|
51
|
+
* The two tables below (project .env, orchestrator.yaml) used to repeat these and could drift apart.
|
|
52
|
+
* Each keeps its own environment-variable naming, which does differ on purpose (a generated project reads
|
|
53
|
+
* `LLM_API_KEY` for DeepSeek, the orchestrator `DEEPSEEK_API_KEY`).
|
|
54
|
+
*/
|
|
55
|
+
exports.PROVIDER_DEFAULTS = {
|
|
56
|
+
anthropic: { model: 'claude-sonnet-4-6' },
|
|
57
|
+
openai: { model: 'gpt-4o', baseUrl: 'https://api.openai.com/v1' },
|
|
58
|
+
deepseek: { model: 'deepseek-chat', baseUrl: 'https://api.deepseek.com/v1' },
|
|
59
|
+
ollama: { model: 'llama3.2' },
|
|
60
|
+
};
|
|
61
|
+
exports.PROVIDER_ENV = {
|
|
62
|
+
anthropic: { varName: 'ANTHROPIC_API_KEY', placeholder: 'sk-ant-...', ...exports.PROVIDER_DEFAULTS.anthropic },
|
|
63
|
+
openai: { varName: 'OPENAI_API_KEY', placeholder: 'sk-...', ...exports.PROVIDER_DEFAULTS.openai },
|
|
64
|
+
deepseek: { varName: 'LLM_API_KEY', placeholder: 'sk-...', ...exports.PROVIDER_DEFAULTS.deepseek },
|
|
65
|
+
ollama: { varName: 'OLLAMA_BASE_URL', placeholder: 'http://localhost:11434', ...exports.PROVIDER_DEFAULTS.ollama },
|
|
54
66
|
};
|
|
55
67
|
// ── Copy directory (overlay-safe) ─────────────────────────────────────────────
|
|
56
68
|
// dst may already exist from the base layer — files are overwritten, dirs merged.
|
|
@@ -67,7 +79,7 @@ function copyDir(src, dst) {
|
|
|
67
79
|
* minor, so these must follow the workspace versions (guarded by a test).
|
|
68
80
|
*/
|
|
69
81
|
exports.GENERATED_DEP_RANGES = {
|
|
70
|
-
'@backendkit-labs/mcp-server': '^0.
|
|
82
|
+
'@backendkit-labs/mcp-server': '^0.19.0',
|
|
71
83
|
'@backendkit-labs/agent-web': '^0.6.0',
|
|
72
84
|
'@backendkit-labs/agent-testkit': '^0.1.0',
|
|
73
85
|
};
|
|
@@ -135,7 +147,7 @@ function writeEnv(dir, provider, choices) {
|
|
|
135
147
|
fs.writeFileSync(envFile, content);
|
|
136
148
|
return;
|
|
137
149
|
}
|
|
138
|
-
const p = PROVIDER_ENV[provider];
|
|
150
|
+
const p = exports.PROVIDER_ENV[provider];
|
|
139
151
|
const content = [
|
|
140
152
|
'# Generated by create-bk-agent',
|
|
141
153
|
`${p.varName}=${p.placeholder}`,
|
|
@@ -168,14 +180,15 @@ function injectSkillPack(targetDir, pack) {
|
|
|
168
180
|
].join('\n');
|
|
169
181
|
fs.appendFileSync(engineFile, block + '\n');
|
|
170
182
|
}
|
|
171
|
-
|
|
172
|
-
deepseek: { id: 'deepseek', keyVar: 'DEEPSEEK_API_KEY',
|
|
173
|
-
anthropic: { id: 'anthropic', keyVar: 'ANTHROPIC_API_KEY',
|
|
174
|
-
openai: { id: 'openai', keyVar: 'OPENAI_API_KEY',
|
|
175
|
-
|
|
183
|
+
exports.ORCHESTRATOR_PROVIDERS = {
|
|
184
|
+
deepseek: { id: 'deepseek', keyVar: 'DEEPSEEK_API_KEY', ...exports.PROVIDER_DEFAULTS.deepseek },
|
|
185
|
+
anthropic: { id: 'anthropic', keyVar: 'ANTHROPIC_API_KEY', ...exports.PROVIDER_DEFAULTS.anthropic },
|
|
186
|
+
openai: { id: 'openai', keyVar: 'OPENAI_API_KEY', ...exports.PROVIDER_DEFAULTS.openai },
|
|
187
|
+
// orchestrator.yaml wants an explicit base_url for Ollama; a generated project reads it from OLLAMA_BASE_URL instead
|
|
188
|
+
ollama: { id: 'ollama', keyVar: '', ...exports.PROVIDER_DEFAULTS.ollama, baseUrl: 'http://localhost:11434' },
|
|
176
189
|
};
|
|
177
190
|
function buildProvidersBlock(provider) {
|
|
178
|
-
const p = ORCHESTRATOR_PROVIDERS[provider];
|
|
191
|
+
const p = exports.ORCHESTRATOR_PROVIDERS[provider];
|
|
179
192
|
const lines = ['providers:', ` ${p.id}:`];
|
|
180
193
|
if (p.keyVar)
|
|
181
194
|
lines.push(` api_key: \${${p.keyVar}}`);
|
|
@@ -197,7 +210,7 @@ function scaffoldOrchestrator(choices, targetDir) {
|
|
|
197
210
|
const orchYaml = path.join(targetDir, 'orchestrator.yaml');
|
|
198
211
|
if (fs.existsSync(orchYaml)) {
|
|
199
212
|
let content = fs.readFileSync(orchYaml, 'utf-8');
|
|
200
|
-
const providerId = ORCHESTRATOR_PROVIDERS[choices.provider].id;
|
|
213
|
+
const providerId = exports.ORCHESTRATOR_PROVIDERS[choices.provider].id;
|
|
201
214
|
const providersBlock = buildProvidersBlock(choices.provider);
|
|
202
215
|
content = content.replace(/__PROVIDER_ID__/g, providerId);
|
|
203
216
|
content = content.replace('__PROVIDERS_BLOCK__', providersBlock);
|
|
@@ -214,7 +227,7 @@ function scaffoldOrchestrator(choices, targetDir) {
|
|
|
214
227
|
const envExample = path.join(targetDir, '.env.example');
|
|
215
228
|
const envFile = path.join(targetDir, '.env');
|
|
216
229
|
if (fs.existsSync(envExample) && !fs.existsSync(envFile)) {
|
|
217
|
-
const p = ORCHESTRATOR_PROVIDERS[choices.provider];
|
|
230
|
+
const p = exports.ORCHESTRATOR_PROVIDERS[choices.provider];
|
|
218
231
|
const keyLine = p.keyVar
|
|
219
232
|
? `${p.keyVar}=your-api-key-here`
|
|
220
233
|
: `# No API key needed for Ollama\nOLLAMA_BASE_URL=${p.baseUrl}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bk-agent",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.6",
|
|
4
4
|
"description": "Create a new BackendKit agent project",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"test": "jest"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@backendkit-labs/agent-core": ">=0.24.0 <0.
|
|
31
|
+
"@backendkit-labs/agent-core": ">=0.24.0 <0.40.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependenciesMeta": {
|
|
34
34
|
"@backendkit-labs/agent-core": {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Project templates
|
|
2
|
+
|
|
3
|
+
Source of the projects that [`create-bk-agent`](../create-bk-agent) generates. This directory is not published on its own: `create-bk-agent` copies it into its package when it is packed (`scripts/copy-templates.js`).
|
|
4
|
+
|
|
5
|
+
A generated project is one **architecture** from `base/` plus one **deploy mode** from `deploy/`:
|
|
6
|
+
|
|
7
|
+
| `base/` | What it is |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `coding` | Coding assistant: 10 agents and the file, git and command tools |
|
|
10
|
+
| `multi-agent` | Orchestrator and specialists, no tools: you define the domain |
|
|
11
|
+
| `single` | One agent with tools |
|
|
12
|
+
| `autonomous` | Cron, webhook and event triggers |
|
|
13
|
+
| `enterprise` | Local LLM and an Obsidian knowledge base (RAG) |
|
|
14
|
+
| `orchestrator` | Multi-step workflows with approval gates |
|
|
15
|
+
| `minimal` | The bare engine |
|
|
16
|
+
|
|
17
|
+
| `deploy/` | How it runs |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `repl` | Interactive terminal |
|
|
20
|
+
| `mcp-stdio` | MCP server over stdio (for Claude Desktop, IDEs, other agents) |
|
|
21
|
+
| `mcp-http` | MCP server over HTTP |
|
|
22
|
+
| `hybrid` | Terminal and MCP HTTP together |
|
|
23
|
+
|
|
24
|
+
`coding/AGENT.md` is the default project description the coding architecture starts with.
|
|
25
|
+
|
|
26
|
+
When you change a framework version range here, keep it in step with the workspace version: the scaffolder's tests (`create-bk-agent/src/__tests__/scaffold.test.ts`) fail if a template asks for a version the repository does not have.
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
import * as os from 'os';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import { createAutonomousAgent, createMemorySystem } from '@backendkit-labs/agent-core';
|
|
5
|
-
import type { AgentProfile } from '@backendkit-labs/agent-core';
|
|
6
|
-
|
|
7
|
-
// ── Agent definition ──────────────────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
const monitorAgent: AgentProfile = {
|
|
10
|
-
id: 'monitor',
|
|
11
|
-
name: 'Monitor',
|
|
12
|
-
icon: '👁',
|
|
13
|
-
description: 'Monitors events and executes scheduled tasks',
|
|
14
|
-
allowedTools: [],
|
|
15
|
-
delegatesTo: [],
|
|
16
|
-
systemPrompt: `You are an autonomous monitor agent.
|
|
17
|
-
// TODO: describe what this agent monitors and what actions it takes.
|
|
18
|
-
When activated by a trigger, analyze the input and take appropriate action.`,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// ── Provider ──────────────────────────────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
const provider = process.env.LLM_PROVIDER ?? 'anthropic';
|
|
24
|
-
const apiKey = process.env.ANTHROPIC_API_KEY ?? process.env.OPENAI_API_KEY ?? '';
|
|
25
|
-
|
|
26
|
-
if (!apiKey) { console.error('Missing API key'); process.exit(1); }
|
|
27
|
-
|
|
28
|
-
// ── Memory — persists context between trigger executions ──────────────────────
|
|
29
|
-
|
|
30
|
-
const APP_DIR = path.join(os.homedir(), '.my-autonomous-agent');
|
|
31
|
-
const MEM_DIR = path.join(APP_DIR, 'memory');
|
|
32
|
-
|
|
33
|
-
const memory = createMemorySystem({
|
|
34
|
-
episodic: { provider: 'json', path: path.join(MEM_DIR, 'episodes.json') },
|
|
35
|
-
semantic: { provider: 'json', path: path.join(MEM_DIR, 'knowledge.json') },
|
|
36
|
-
procedural: { provider: 'json', path: path.join(MEM_DIR, 'patterns.json') },
|
|
37
|
-
retention: { maxEpisodes: 200 },
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// ── Autonomous agent ──────────────────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
|
-
const agent = createAutonomousAgent({
|
|
44
|
-
providers: { [provider]: { apiKey } } as any,
|
|
45
|
-
defaultProvider: provider,
|
|
46
|
-
agents: [monitorAgent],
|
|
47
|
-
defaultAgent: 'monitor',
|
|
48
|
-
goal: 'TODO: describe the agent goal',
|
|
49
|
-
memorySystem: memory,
|
|
50
|
-
|
|
51
|
-
triggers: [
|
|
52
|
-
// Run every day at 9:00 AM
|
|
53
|
-
{
|
|
54
|
-
type: 'schedule',
|
|
55
|
-
cron: '0 9 * * *',
|
|
56
|
-
task: 'Run daily check and report findings',
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
// Listen for webhook events (e.g. from GitHub, Slack, etc.)
|
|
60
|
-
{
|
|
61
|
-
type: 'webhook',
|
|
62
|
-
path: '/events',
|
|
63
|
-
// secret: process.env.WEBHOOK_SECRET,
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
// TODO: add more triggers as needed
|
|
67
|
-
// { type: 'event', topic: 'my.custom.event' },
|
|
68
|
-
],
|
|
69
|
-
|
|
70
|
-
webhookPort: parseInt(process.env.WEBHOOK_PORT ?? '3000'),
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// ── Start ─────────────────────────────────────────────────────────────────────
|
|
74
|
-
|
|
75
|
-
void (async () => {
|
|
76
|
-
await agent.start();
|
|
77
|
-
console.log('Autonomous agent started.');
|
|
78
|
-
console.log('Webhook listening on port', process.env.WEBHOOK_PORT ?? 3000);
|
|
79
|
-
console.log(`Memory stored in: ${APP_DIR}`);
|
|
80
|
-
|
|
81
|
-
process.on('SIGTERM', async () => { await agent.stop(); process.exit(0); });
|
|
82
|
-
process.on('SIGINT', async () => { await agent.stop(); process.exit(0); });
|
|
83
|
-
})();
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { createAutonomousAgent, createMemorySystem } from '@backendkit-labs/agent-core';
|
|
5
|
+
import type { AgentProfile } from '@backendkit-labs/agent-core';
|
|
6
|
+
|
|
7
|
+
// ── Agent definition ──────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
const monitorAgent: AgentProfile = {
|
|
10
|
+
id: 'monitor',
|
|
11
|
+
name: 'Monitor',
|
|
12
|
+
icon: '👁',
|
|
13
|
+
description: 'Monitors events and executes scheduled tasks',
|
|
14
|
+
allowedTools: [], // the tools this agent may call, by name; empty means none (a tool that is registered but not listed here is refused)
|
|
15
|
+
delegatesTo: [],
|
|
16
|
+
systemPrompt: `You are an autonomous monitor agent.
|
|
17
|
+
// TODO: describe what this agent monitors and what actions it takes.
|
|
18
|
+
When activated by a trigger, analyze the input and take appropriate action.`,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// ── Provider ──────────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
const provider = process.env.LLM_PROVIDER ?? 'anthropic';
|
|
24
|
+
const apiKey = process.env.ANTHROPIC_API_KEY ?? process.env.OPENAI_API_KEY ?? '';
|
|
25
|
+
|
|
26
|
+
if (!apiKey) { console.error('Missing API key'); process.exit(1); }
|
|
27
|
+
|
|
28
|
+
// ── Memory — persists context between trigger executions ──────────────────────
|
|
29
|
+
|
|
30
|
+
const APP_DIR = path.join(os.homedir(), '.my-autonomous-agent');
|
|
31
|
+
const MEM_DIR = path.join(APP_DIR, 'memory');
|
|
32
|
+
|
|
33
|
+
const memory = createMemorySystem({
|
|
34
|
+
episodic: { provider: 'json', path: path.join(MEM_DIR, 'episodes.json') },
|
|
35
|
+
semantic: { provider: 'json', path: path.join(MEM_DIR, 'knowledge.json') },
|
|
36
|
+
procedural: { provider: 'json', path: path.join(MEM_DIR, 'patterns.json') },
|
|
37
|
+
retention: { maxEpisodes: 200 },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// ── Autonomous agent ──────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
|
+
const agent = createAutonomousAgent({
|
|
44
|
+
providers: { [provider]: { apiKey } } as any,
|
|
45
|
+
defaultProvider: provider,
|
|
46
|
+
agents: [monitorAgent],
|
|
47
|
+
defaultAgent: 'monitor',
|
|
48
|
+
goal: 'TODO: describe the agent goal',
|
|
49
|
+
memorySystem: memory,
|
|
50
|
+
|
|
51
|
+
triggers: [
|
|
52
|
+
// Run every day at 9:00 AM
|
|
53
|
+
{
|
|
54
|
+
type: 'schedule',
|
|
55
|
+
cron: '0 9 * * *',
|
|
56
|
+
task: 'Run daily check and report findings',
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
// Listen for webhook events (e.g. from GitHub, Slack, etc.)
|
|
60
|
+
{
|
|
61
|
+
type: 'webhook',
|
|
62
|
+
path: '/events',
|
|
63
|
+
// secret: process.env.WEBHOOK_SECRET,
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// TODO: add more triggers as needed
|
|
67
|
+
// { type: 'event', topic: 'my.custom.event' },
|
|
68
|
+
],
|
|
69
|
+
|
|
70
|
+
webhookPort: parseInt(process.env.WEBHOOK_PORT ?? '3000'),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// ── Start ─────────────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
void (async () => {
|
|
76
|
+
await agent.start();
|
|
77
|
+
console.log('Autonomous agent started.');
|
|
78
|
+
console.log('Webhook listening on port', process.env.WEBHOOK_PORT ?? 3000);
|
|
79
|
+
console.log(`Memory stored in: ${APP_DIR}`);
|
|
80
|
+
|
|
81
|
+
process.on('SIGTERM', async () => { await agent.stop(); process.exit(0); });
|
|
82
|
+
process.on('SIGINT', async () => { await agent.stop(); process.exit(0); });
|
|
83
|
+
})();
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@backendkit-labs/agent-core": "^0.
|
|
15
|
+
"@backendkit-labs/agent-core": "^0.38.0",
|
|
16
16
|
"@backendkit-labs/agent-coding": "^0.28.0",
|
|
17
17
|
"@backendkit-labs/agent-enterprise": "^0.8.0",
|
|
18
18
|
"dotenv": "^16.0.0",
|