kernelbot 1.0.26 → 1.0.28
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 +198 -124
- package/bin/kernel.js +201 -4
- package/package.json +1 -1
- package/src/agent.js +397 -222
- package/src/automation/automation-manager.js +377 -0
- package/src/automation/automation.js +79 -0
- package/src/automation/index.js +2 -0
- package/src/automation/scheduler.js +141 -0
- package/src/bot.js +667 -21
- package/src/conversation.js +33 -0
- package/src/intents/detector.js +50 -0
- package/src/intents/index.js +2 -0
- package/src/intents/planner.js +58 -0
- package/src/persona.js +68 -0
- package/src/prompts/orchestrator.js +76 -0
- package/src/prompts/persona.md +21 -0
- package/src/prompts/system.js +59 -6
- package/src/prompts/workers.js +89 -0
- package/src/providers/anthropic.js +23 -16
- package/src/providers/base.js +76 -2
- package/src/providers/index.js +1 -0
- package/src/providers/models.js +2 -1
- package/src/providers/openai-compat.js +5 -3
- package/src/security/confirm.js +7 -2
- package/src/skills/catalog.js +506 -0
- package/src/skills/custom.js +128 -0
- package/src/swarm/job-manager.js +169 -0
- package/src/swarm/job.js +67 -0
- package/src/swarm/worker-registry.js +74 -0
- package/src/tools/browser.js +458 -335
- package/src/tools/categories.js +3 -3
- package/src/tools/index.js +3 -0
- package/src/tools/orchestrator-tools.js +371 -0
- package/src/tools/persona.js +32 -0
- package/src/utils/config.js +50 -15
- package/src/worker.js +305 -0
- package/.agents/skills/interface-design/SKILL.md +0 -391
- package/.agents/skills/interface-design/references/critique.md +0 -67
- package/.agents/skills/interface-design/references/example.md +0 -86
- package/.agents/skills/interface-design/references/principles.md +0 -235
- package/.agents/skills/interface-design/references/validation.md +0 -48
package/bin/kernel.js
CHANGED
|
@@ -19,9 +19,18 @@ import {
|
|
|
19
19
|
} from '../src/utils/display.js';
|
|
20
20
|
import { createAuditLogger } from '../src/security/audit.js';
|
|
21
21
|
import { ConversationManager } from '../src/conversation.js';
|
|
22
|
+
import { UserPersonaManager } from '../src/persona.js';
|
|
22
23
|
import { Agent } from '../src/agent.js';
|
|
24
|
+
import { JobManager } from '../src/swarm/job-manager.js';
|
|
23
25
|
import { startBot } from '../src/bot.js';
|
|
26
|
+
import { AutomationManager } from '../src/automation/index.js';
|
|
24
27
|
import { createProvider, PROVIDERS } from '../src/providers/index.js';
|
|
28
|
+
import {
|
|
29
|
+
loadCustomSkills,
|
|
30
|
+
getCustomSkills,
|
|
31
|
+
addCustomSkill,
|
|
32
|
+
deleteCustomSkill,
|
|
33
|
+
} from '../src/skills/custom.js';
|
|
25
34
|
|
|
26
35
|
function showMenu(config) {
|
|
27
36
|
const providerDef = PROVIDERS[config.brain.provider];
|
|
@@ -37,7 +46,9 @@ function showMenu(config) {
|
|
|
37
46
|
console.log(` ${chalk.cyan('3.')} View logs`);
|
|
38
47
|
console.log(` ${chalk.cyan('4.')} View audit logs`);
|
|
39
48
|
console.log(` ${chalk.cyan('5.')} Change brain model`);
|
|
40
|
-
console.log(` ${chalk.cyan('6.')}
|
|
49
|
+
console.log(` ${chalk.cyan('6.')} Manage custom skills`);
|
|
50
|
+
console.log(` ${chalk.cyan('7.')} Manage automations`);
|
|
51
|
+
console.log(` ${chalk.cyan('8.')} Exit`);
|
|
41
52
|
console.log('');
|
|
42
53
|
}
|
|
43
54
|
|
|
@@ -114,8 +125,27 @@ async function startBotFlow(config) {
|
|
|
114
125
|
|
|
115
126
|
const checks = [];
|
|
116
127
|
|
|
128
|
+
// Orchestrator always needs Anthropic API key
|
|
129
|
+
checks.push(
|
|
130
|
+
await showStartupCheck('Orchestrator (Anthropic) API', async () => {
|
|
131
|
+
const orchestratorKey = config.orchestrator.api_key || process.env.ANTHROPIC_API_KEY;
|
|
132
|
+
if (!orchestratorKey) throw new Error('ANTHROPIC_API_KEY is required for the orchestrator');
|
|
133
|
+
const provider = createProvider({
|
|
134
|
+
brain: {
|
|
135
|
+
provider: 'anthropic',
|
|
136
|
+
model: config.orchestrator.model,
|
|
137
|
+
max_tokens: config.orchestrator.max_tokens,
|
|
138
|
+
temperature: config.orchestrator.temperature,
|
|
139
|
+
api_key: orchestratorKey,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
await provider.ping();
|
|
143
|
+
}),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// Worker brain check
|
|
117
147
|
checks.push(
|
|
118
|
-
await showStartupCheck(
|
|
148
|
+
await showStartupCheck(`Worker (${providerLabel}) API`, async () => {
|
|
119
149
|
const provider = createProvider(config);
|
|
120
150
|
await provider.ping();
|
|
121
151
|
}),
|
|
@@ -137,13 +167,174 @@ async function startBotFlow(config) {
|
|
|
137
167
|
}
|
|
138
168
|
|
|
139
169
|
const conversationManager = new ConversationManager(config);
|
|
140
|
-
const
|
|
170
|
+
const personaManager = new UserPersonaManager();
|
|
171
|
+
const jobManager = new JobManager({
|
|
172
|
+
jobTimeoutSeconds: config.swarm.job_timeout_seconds,
|
|
173
|
+
cleanupIntervalMinutes: config.swarm.cleanup_interval_minutes,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const automationManager = new AutomationManager();
|
|
177
|
+
|
|
178
|
+
const agent = new Agent({ config, conversationManager, personaManager, jobManager, automationManager });
|
|
179
|
+
|
|
180
|
+
startBot(config, agent, conversationManager, jobManager, automationManager);
|
|
181
|
+
|
|
182
|
+
// Periodic job cleanup and timeout enforcement
|
|
183
|
+
const cleanupMs = (config.swarm.cleanup_interval_minutes || 30) * 60 * 1000;
|
|
184
|
+
setInterval(() => {
|
|
185
|
+
jobManager.cleanup();
|
|
186
|
+
jobManager.enforceTimeouts();
|
|
187
|
+
}, Math.min(cleanupMs, 60_000)); // enforce timeouts every minute at most
|
|
141
188
|
|
|
142
|
-
startBot(config, agent, conversationManager);
|
|
143
189
|
showStartupComplete();
|
|
144
190
|
return true;
|
|
145
191
|
}
|
|
146
192
|
|
|
193
|
+
async function manageCustomSkills(rl) {
|
|
194
|
+
loadCustomSkills();
|
|
195
|
+
|
|
196
|
+
let managing = true;
|
|
197
|
+
while (managing) {
|
|
198
|
+
const customs = getCustomSkills();
|
|
199
|
+
console.log('');
|
|
200
|
+
console.log(chalk.bold(' Custom Skills\n'));
|
|
201
|
+
console.log(` ${chalk.cyan('1.')} Create new skill`);
|
|
202
|
+
console.log(` ${chalk.cyan('2.')} List skills (${customs.length})`);
|
|
203
|
+
console.log(` ${chalk.cyan('3.')} Delete a skill`);
|
|
204
|
+
console.log(` ${chalk.cyan('4.')} Back`);
|
|
205
|
+
console.log('');
|
|
206
|
+
|
|
207
|
+
const choice = await ask(rl, chalk.cyan(' > '));
|
|
208
|
+
switch (choice.trim()) {
|
|
209
|
+
case '1': {
|
|
210
|
+
const name = await ask(rl, chalk.cyan(' Skill name: '));
|
|
211
|
+
if (!name.trim()) {
|
|
212
|
+
console.log(chalk.dim(' Cancelled.\n'));
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
console.log(chalk.dim(' Enter the system prompt (multi-line). Type END on a blank line to finish:\n'));
|
|
216
|
+
const lines = [];
|
|
217
|
+
while (true) {
|
|
218
|
+
const line = await ask(rl, ' ');
|
|
219
|
+
if (line.trim() === 'END') break;
|
|
220
|
+
lines.push(line);
|
|
221
|
+
}
|
|
222
|
+
const prompt = lines.join('\n').trim();
|
|
223
|
+
if (!prompt) {
|
|
224
|
+
console.log(chalk.dim(' Empty prompt — cancelled.\n'));
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
const skill = addCustomSkill({ name: name.trim(), systemPrompt: prompt });
|
|
228
|
+
console.log(chalk.green(`\n ✅ Created: ${skill.name} (${skill.id})\n`));
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
case '2': {
|
|
232
|
+
const customs = getCustomSkills();
|
|
233
|
+
if (!customs.length) {
|
|
234
|
+
console.log(chalk.dim('\n No custom skills yet.\n'));
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
console.log('');
|
|
238
|
+
for (const s of customs) {
|
|
239
|
+
const preview = s.systemPrompt.slice(0, 60).replace(/\n/g, ' ');
|
|
240
|
+
console.log(` 🛠️ ${chalk.bold(s.name)} (${s.id})`);
|
|
241
|
+
console.log(chalk.dim(` ${preview}${s.systemPrompt.length > 60 ? '...' : ''}`));
|
|
242
|
+
}
|
|
243
|
+
console.log('');
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
case '3': {
|
|
247
|
+
const customs = getCustomSkills();
|
|
248
|
+
if (!customs.length) {
|
|
249
|
+
console.log(chalk.dim('\n No custom skills to delete.\n'));
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
console.log('');
|
|
253
|
+
customs.forEach((s, i) => {
|
|
254
|
+
console.log(` ${chalk.cyan(`${i + 1}.`)} ${s.name} (${s.id})`);
|
|
255
|
+
});
|
|
256
|
+
console.log('');
|
|
257
|
+
const pick = await ask(rl, chalk.cyan(' Delete #: '));
|
|
258
|
+
const idx = parseInt(pick, 10) - 1;
|
|
259
|
+
if (idx >= 0 && idx < customs.length) {
|
|
260
|
+
const deleted = deleteCustomSkill(customs[idx].id);
|
|
261
|
+
if (deleted) console.log(chalk.green(`\n 🗑️ Deleted: ${customs[idx].name}\n`));
|
|
262
|
+
else console.log(chalk.dim(' Not found.\n'));
|
|
263
|
+
} else {
|
|
264
|
+
console.log(chalk.dim(' Cancelled.\n'));
|
|
265
|
+
}
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case '4':
|
|
269
|
+
managing = false;
|
|
270
|
+
break;
|
|
271
|
+
default:
|
|
272
|
+
console.log(chalk.dim(' Invalid choice.\n'));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async function manageAutomations(rl) {
|
|
278
|
+
const manager = new AutomationManager();
|
|
279
|
+
|
|
280
|
+
let managing = true;
|
|
281
|
+
while (managing) {
|
|
282
|
+
const autos = manager.listAll();
|
|
283
|
+
console.log('');
|
|
284
|
+
console.log(chalk.bold(' Automations\n'));
|
|
285
|
+
console.log(` ${chalk.cyan('1.')} List all automations (${autos.length})`);
|
|
286
|
+
console.log(` ${chalk.cyan('2.')} Delete an automation`);
|
|
287
|
+
console.log(` ${chalk.cyan('3.')} Back`);
|
|
288
|
+
console.log('');
|
|
289
|
+
|
|
290
|
+
const choice = await ask(rl, chalk.cyan(' > '));
|
|
291
|
+
switch (choice.trim()) {
|
|
292
|
+
case '1': {
|
|
293
|
+
if (!autos.length) {
|
|
294
|
+
console.log(chalk.dim('\n No automations found.\n'));
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
console.log('');
|
|
298
|
+
for (const a of autos) {
|
|
299
|
+
const status = a.enabled ? chalk.green('enabled') : chalk.yellow('paused');
|
|
300
|
+
const next = a.nextRun ? new Date(a.nextRun).toLocaleString() : 'not scheduled';
|
|
301
|
+
console.log(` ${chalk.bold(a.name)} (${a.id}) — chat ${a.chatId}`);
|
|
302
|
+
console.log(chalk.dim(` Status: ${status} | Runs: ${a.runCount} | Next: ${next}`));
|
|
303
|
+
console.log(chalk.dim(` Task: ${a.description.slice(0, 80)}${a.description.length > 80 ? '...' : ''}`));
|
|
304
|
+
}
|
|
305
|
+
console.log('');
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
case '2': {
|
|
309
|
+
if (!autos.length) {
|
|
310
|
+
console.log(chalk.dim('\n No automations to delete.\n'));
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
console.log('');
|
|
314
|
+
autos.forEach((a, i) => {
|
|
315
|
+
console.log(` ${chalk.cyan(`${i + 1}.`)} ${a.name} (${a.id}) — chat ${a.chatId}`);
|
|
316
|
+
});
|
|
317
|
+
console.log('');
|
|
318
|
+
const pick = await ask(rl, chalk.cyan(' Delete #: '));
|
|
319
|
+
const idx = parseInt(pick, 10) - 1;
|
|
320
|
+
if (idx >= 0 && idx < autos.length) {
|
|
321
|
+
const deleted = manager.delete(autos[idx].id);
|
|
322
|
+
if (deleted) console.log(chalk.green(`\n 🗑️ Deleted: ${autos[idx].name}\n`));
|
|
323
|
+
else console.log(chalk.dim(' Not found.\n'));
|
|
324
|
+
} else {
|
|
325
|
+
console.log(chalk.dim(' Cancelled.\n'));
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
case '3':
|
|
330
|
+
managing = false;
|
|
331
|
+
break;
|
|
332
|
+
default:
|
|
333
|
+
console.log(chalk.dim(' Invalid choice.\n'));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
147
338
|
async function main() {
|
|
148
339
|
showLogo();
|
|
149
340
|
|
|
@@ -177,6 +368,12 @@ async function main() {
|
|
|
177
368
|
await changeBrainModel(config, rl);
|
|
178
369
|
break;
|
|
179
370
|
case '6':
|
|
371
|
+
await manageCustomSkills(rl);
|
|
372
|
+
break;
|
|
373
|
+
case '7':
|
|
374
|
+
await manageAutomations(rl);
|
|
375
|
+
break;
|
|
376
|
+
case '8':
|
|
180
377
|
running = false;
|
|
181
378
|
break;
|
|
182
379
|
default:
|