kernelbot 1.0.28 → 1.0.30

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 (56) hide show
  1. package/.env.example +4 -0
  2. package/README.md +0 -0
  3. package/bin/kernel.js +13 -6
  4. package/config.example.yaml +14 -1
  5. package/package.json +1 -1
  6. package/src/agent.js +482 -27
  7. package/src/automation/automation-manager.js +0 -0
  8. package/src/automation/automation.js +0 -0
  9. package/src/automation/index.js +0 -0
  10. package/src/automation/scheduler.js +0 -0
  11. package/src/bot.js +340 -3
  12. package/src/claude-auth.js +93 -0
  13. package/src/coder.js +48 -6
  14. package/src/conversation.js +0 -0
  15. package/src/intents/detector.js +0 -0
  16. package/src/intents/index.js +0 -0
  17. package/src/intents/planner.js +0 -0
  18. package/src/persona.js +0 -0
  19. package/src/prompts/orchestrator.js +53 -5
  20. package/src/prompts/persona.md +0 -0
  21. package/src/prompts/system.js +0 -0
  22. package/src/prompts/workers.js +61 -2
  23. package/src/providers/anthropic.js +0 -0
  24. package/src/providers/base.js +0 -0
  25. package/src/providers/index.js +0 -0
  26. package/src/providers/models.js +0 -0
  27. package/src/providers/openai-compat.js +0 -0
  28. package/src/security/audit.js +0 -0
  29. package/src/security/auth.js +0 -0
  30. package/src/security/confirm.js +0 -0
  31. package/src/self.js +122 -0
  32. package/src/services/stt.js +139 -0
  33. package/src/services/tts.js +124 -0
  34. package/src/skills/catalog.js +0 -0
  35. package/src/skills/custom.js +0 -0
  36. package/src/swarm/job-manager.js +54 -7
  37. package/src/swarm/job.js +19 -1
  38. package/src/swarm/worker-registry.js +5 -0
  39. package/src/tools/browser.js +0 -0
  40. package/src/tools/categories.js +0 -0
  41. package/src/tools/coding.js +5 -0
  42. package/src/tools/docker.js +0 -0
  43. package/src/tools/git.js +0 -0
  44. package/src/tools/github.js +0 -0
  45. package/src/tools/index.js +0 -0
  46. package/src/tools/jira.js +0 -0
  47. package/src/tools/monitor.js +0 -0
  48. package/src/tools/network.js +0 -0
  49. package/src/tools/orchestrator-tools.js +76 -19
  50. package/src/tools/os.js +14 -1
  51. package/src/tools/persona.js +0 -0
  52. package/src/tools/process.js +0 -0
  53. package/src/utils/config.js +105 -2
  54. package/src/utils/display.js +0 -0
  55. package/src/utils/logger.js +0 -0
  56. package/src/worker.js +96 -5
package/src/worker.js CHANGED
@@ -26,18 +26,22 @@ export class WorkerAgent {
26
26
  * @param {string} opts.jobId - Job ID for logging
27
27
  * @param {Array} opts.tools - Scoped tool definitions
28
28
  * @param {string|null} opts.skillId - Active skill ID (for worker prompt)
29
+ * @param {string|null} opts.workerContext - Structured context (conversation history, persona, dependency results)
29
30
  * @param {object} opts.callbacks - { onProgress, onComplete, onError }
30
31
  * @param {AbortController} opts.abortController - For cancellation
31
32
  */
32
- constructor({ config, workerType, jobId, tools, skillId, callbacks, abortController }) {
33
+ constructor({ config, workerType, jobId, tools, skillId, workerContext, callbacks, abortController }) {
33
34
  this.config = config;
34
35
  this.workerType = workerType;
35
36
  this.jobId = jobId;
36
37
  this.tools = tools;
37
38
  this.skillId = skillId;
39
+ this.workerContext = workerContext || null;
38
40
  this.callbacks = callbacks || {};
39
41
  this.abortController = abortController || new AbortController();
40
42
  this._cancelled = false;
43
+ this._toolCallCount = 0;
44
+ this._errors = [];
41
45
 
42
46
  // Create provider from worker brain config
43
47
  this.provider = createProvider(config);
@@ -51,7 +55,7 @@ export class WorkerAgent {
51
55
  this.maxIterations = 200;
52
56
 
53
57
  const logger = getLogger();
54
- logger.info(`[Worker ${jobId}] Created: type=${workerType}, provider=${config.brain.provider}/${config.brain.model}, tools=${tools.length}, skill=${skillId || 'none'}`);
58
+ logger.info(`[Worker ${jobId}] Created: type=${workerType}, provider=${config.brain.provider}/${config.brain.model}, tools=${tools.length}, skill=${skillId || 'none'}, context=${workerContext ? 'yes' : 'none'}`);
55
59
  }
56
60
 
57
61
  /** Cancel this worker. */
@@ -66,7 +70,14 @@ export class WorkerAgent {
66
70
  const logger = getLogger();
67
71
  logger.info(`[Worker ${this.jobId}] Starting task: "${task.slice(0, 150)}"`);
68
72
 
69
- const messages = [{ role: 'user', content: task }];
73
+ // Build first message: context sections + task
74
+ let firstMessage = '';
75
+ if (this.workerContext) {
76
+ firstMessage += this.workerContext + '\n\n---\n\n';
77
+ }
78
+ firstMessage += task;
79
+
80
+ const messages = [{ role: 'user', content: firstMessage }];
70
81
 
71
82
  try {
72
83
  const result = await this._runLoop(messages);
@@ -74,8 +85,9 @@ export class WorkerAgent {
74
85
  logger.info(`[Worker ${this.jobId}] Run completed but worker was cancelled — skipping callbacks`);
75
86
  return;
76
87
  }
77
- logger.info(`[Worker ${this.jobId}] Run finished successfully — result: "${(result || '').slice(0, 150)}"`);
78
- if (this.callbacks.onComplete) this.callbacks.onComplete(result);
88
+ const parsed = this._parseResult(result);
89
+ logger.info(`[Worker ${this.jobId}] Run finished successfully — structured=${!!parsed.structured}, result: "${(result || '').slice(0, 150)}"`);
90
+ if (this.callbacks.onComplete) this.callbacks.onComplete(result, parsed);
79
91
  } catch (err) {
80
92
  if (this._cancelled) {
81
93
  logger.info(`[Worker ${this.jobId}] Run threw error but worker was cancelled — ignoring: ${err.message}`);
@@ -144,6 +156,8 @@ export class WorkerAgent {
144
156
  logger.debug(`[Worker ${this.jobId}] Tool input: ${JSON.stringify(block.input).slice(0, 300)}`);
145
157
  this._reportProgress(`🔧 ${summary}`);
146
158
 
159
+ this._toolCallCount++;
160
+
147
161
  const result = await executeTool(block.name, block.input, {
148
162
  config: this.config,
149
163
  user: null, // workers don't have user context
@@ -151,8 +165,14 @@ export class WorkerAgent {
151
165
  onUpdate: this.callbacks.onUpdate || null, // Real bot onUpdate (returns message_id for coder.js smart output)
152
166
  sendPhoto: this.callbacks.sendPhoto || null,
153
167
  sessionId: this.jobId, // Per-worker browser session isolation
168
+ signal: this.abortController.signal, // For killing child processes on cancellation
154
169
  });
155
170
 
171
+ // Track errors
172
+ if (result && typeof result === 'object' && result.error) {
173
+ this._errors.push({ tool: block.name, error: result.error });
174
+ }
175
+
156
176
  const resultStr = this._truncateResult(block.name, result);
157
177
  logger.info(`[Worker ${this.jobId}] Tool ${block.name} result: ${resultStr.slice(0, 200)}`);
158
178
 
@@ -254,10 +274,81 @@ export class WorkerAgent {
254
274
  return null;
255
275
  }
256
276
 
277
+ /**
278
+ * Parse the worker's final text into a structured WorkerResult.
279
+ * Attempts JSON parse from ```json fences, falls back to wrapping raw text.
280
+ */
281
+ _parseResult(text) {
282
+ if (!text) {
283
+ return {
284
+ structured: false,
285
+ summary: 'Task completed.',
286
+ status: 'success',
287
+ details: '',
288
+ artifacts: [],
289
+ followUp: null,
290
+ toolsUsed: this._toolCallCount,
291
+ errors: this._errors,
292
+ };
293
+ }
294
+
295
+ // Try to extract JSON from ```json ... ``` fences
296
+ const fenceMatch = text.match(/```json\s*\n?([\s\S]*?)\n?\s*```/);
297
+ if (fenceMatch) {
298
+ try {
299
+ const parsed = JSON.parse(fenceMatch[1]);
300
+ if (parsed.summary && parsed.status) {
301
+ return {
302
+ structured: true,
303
+ summary: parsed.summary || '',
304
+ status: parsed.status || 'success',
305
+ details: parsed.details || '',
306
+ artifacts: Array.isArray(parsed.artifacts) ? parsed.artifacts : [],
307
+ followUp: parsed.followUp || null,
308
+ toolsUsed: this._toolCallCount,
309
+ errors: this._errors,
310
+ };
311
+ }
312
+ } catch { /* fall through */ }
313
+ }
314
+
315
+ // Try raw JSON parse (no fences)
316
+ try {
317
+ const parsed = JSON.parse(text);
318
+ if (parsed.summary && parsed.status) {
319
+ return {
320
+ structured: true,
321
+ summary: parsed.summary || '',
322
+ status: parsed.status || 'success',
323
+ details: parsed.details || '',
324
+ artifacts: Array.isArray(parsed.artifacts) ? parsed.artifacts : [],
325
+ followUp: parsed.followUp || null,
326
+ toolsUsed: this._toolCallCount,
327
+ errors: this._errors,
328
+ };
329
+ }
330
+ } catch { /* fall through */ }
331
+
332
+ // Fallback: wrap raw text
333
+ return {
334
+ structured: false,
335
+ summary: text.slice(0, 200),
336
+ status: 'success',
337
+ details: text,
338
+ artifacts: [],
339
+ followUp: null,
340
+ toolsUsed: this._toolCallCount,
341
+ errors: this._errors,
342
+ };
343
+ }
344
+
257
345
  _reportProgress(text) {
258
346
  if (this.callbacks.onProgress) {
259
347
  try { this.callbacks.onProgress(text); } catch {}
260
348
  }
349
+ if (this.callbacks.onHeartbeat) {
350
+ try { this.callbacks.onHeartbeat(text); } catch {}
351
+ }
261
352
  }
262
353
 
263
354
  _truncateResult(name, result) {