kernelbot 1.0.38 → 1.0.40

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 (83) hide show
  1. package/bin/kernel.js +335 -451
  2. package/config.example.yaml +1 -1
  3. package/knowledge_base/active_inference_foraging.md +126 -0
  4. package/knowledge_base/index.md +1 -1
  5. package/package.json +2 -1
  6. package/skills/business/business-analyst.md +32 -0
  7. package/skills/business/product-manager.md +32 -0
  8. package/skills/business/project-manager.md +32 -0
  9. package/skills/business/startup-advisor.md +32 -0
  10. package/skills/creative/music-producer.md +32 -0
  11. package/skills/creative/photographer.md +32 -0
  12. package/skills/creative/video-producer.md +32 -0
  13. package/skills/data/bi-analyst.md +37 -0
  14. package/skills/data/data-scientist.md +38 -0
  15. package/skills/data/ml-engineer.md +38 -0
  16. package/skills/design/graphic-designer.md +38 -0
  17. package/skills/design/product-designer.md +41 -0
  18. package/skills/design/ui-ux.md +38 -0
  19. package/skills/education/curriculum-designer.md +32 -0
  20. package/skills/education/language-teacher.md +32 -0
  21. package/skills/education/tutor.md +32 -0
  22. package/skills/engineering/data-eng.md +55 -0
  23. package/skills/engineering/devops.md +56 -0
  24. package/skills/engineering/mobile-dev.md +55 -0
  25. package/skills/engineering/security-eng.md +55 -0
  26. package/skills/engineering/sr-backend.md +55 -0
  27. package/skills/engineering/sr-frontend.md +55 -0
  28. package/skills/finance/accountant.md +35 -0
  29. package/skills/finance/crypto-defi.md +39 -0
  30. package/skills/finance/financial-analyst.md +35 -0
  31. package/skills/healthcare/health-wellness.md +32 -0
  32. package/skills/healthcare/medical-researcher.md +33 -0
  33. package/skills/legal/contract-reviewer.md +35 -0
  34. package/skills/legal/legal-advisor.md +36 -0
  35. package/skills/marketing/content-marketer.md +38 -0
  36. package/skills/marketing/growth.md +38 -0
  37. package/skills/marketing/seo.md +43 -0
  38. package/skills/marketing/social-media.md +43 -0
  39. package/skills/writing/academic-writer.md +33 -0
  40. package/skills/writing/copywriter.md +32 -0
  41. package/skills/writing/creative-writer.md +32 -0
  42. package/skills/writing/tech-writer.md +33 -0
  43. package/src/agent.js +153 -118
  44. package/src/automation/scheduler.js +36 -3
  45. package/src/bot.js +147 -64
  46. package/src/coder.js +30 -8
  47. package/src/conversation.js +96 -19
  48. package/src/dashboard/dashboard.css +6 -0
  49. package/src/dashboard/dashboard.js +28 -1
  50. package/src/dashboard/index.html +12 -0
  51. package/src/dashboard/server.js +77 -15
  52. package/src/dashboard/shared.js +10 -1
  53. package/src/life/codebase.js +2 -1
  54. package/src/life/daydream_engine.js +386 -0
  55. package/src/life/engine.js +88 -6
  56. package/src/life/evolution.js +4 -3
  57. package/src/prompts/orchestrator.js +1 -1
  58. package/src/prompts/system.js +1 -1
  59. package/src/prompts/workers.js +8 -1
  60. package/src/providers/anthropic.js +3 -1
  61. package/src/providers/base.js +33 -0
  62. package/src/providers/index.js +1 -1
  63. package/src/providers/models.js +22 -0
  64. package/src/providers/openai-compat.js +3 -0
  65. package/src/services/x-api.js +14 -3
  66. package/src/skills/loader.js +382 -0
  67. package/src/swarm/worker-registry.js +2 -2
  68. package/src/tools/browser.js +10 -3
  69. package/src/tools/coding.js +16 -0
  70. package/src/tools/docker.js +13 -0
  71. package/src/tools/git.js +31 -29
  72. package/src/tools/jira.js +11 -2
  73. package/src/tools/monitor.js +9 -1
  74. package/src/tools/network.js +34 -0
  75. package/src/tools/orchestrator-tools.js +2 -1
  76. package/src/tools/os.js +20 -6
  77. package/src/utils/config.js +87 -83
  78. package/src/utils/display.js +118 -66
  79. package/src/utils/logger.js +1 -1
  80. package/src/utils/timeAwareness.js +72 -0
  81. package/src/worker.js +26 -33
  82. package/src/skills/catalog.js +0 -506
  83. package/src/skills/custom.js +0 -128
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Time Awareness Utility — Riyadh-local helpers.
3
+ *
4
+ * Provides timezone-aware helpers anchored to Asia/Riyadh so that
5
+ * automated tasks can respect the user's real-world schedule.
6
+ *
7
+ * Quiet hours (02:00 – 10:00 Riyadh time) are intentionally wider than
8
+ * the generic defaults in timeUtils.js because the owner fasts during
9
+ * Ramadan and typically sleeps through the early-morning hours.
10
+ *
11
+ * @module utils/timeAwareness
12
+ */
13
+
14
+ const TIMEZONE = 'Asia/Riyadh';
15
+ const QUIET_START_HOUR = 2;
16
+ const QUIET_END_HOUR = 10;
17
+
18
+ /**
19
+ * Return the current date/time in the Asia/Riyadh timezone.
20
+ *
21
+ * The returned object contains the full ISO-style formatted string,
22
+ * the numeric hour (0-23), and the raw Date for further processing.
23
+ *
24
+ * @returns {{ formatted: string, hour: number, date: Date }}
25
+ */
26
+ export function getCurrentRiyadhTime() {
27
+ const now = new Date();
28
+
29
+ const formatted = now.toLocaleString('en-US', {
30
+ weekday: 'long',
31
+ year: 'numeric',
32
+ month: 'long',
33
+ day: 'numeric',
34
+ hour: '2-digit',
35
+ minute: '2-digit',
36
+ second: '2-digit',
37
+ hour12: true,
38
+ timeZone: TIMEZONE,
39
+ });
40
+
41
+ const hourParts = new Intl.DateTimeFormat('en-US', {
42
+ hour: 'numeric',
43
+ hour12: false,
44
+ timeZone: TIMEZONE,
45
+ }).formatToParts(now);
46
+
47
+ const hour = parseInt(
48
+ hourParts.find((p) => p.type === 'hour')?.value || '0',
49
+ 10,
50
+ );
51
+
52
+ return { formatted, hour, date: now };
53
+ }
54
+
55
+ /**
56
+ * Check whether the current Riyadh time falls within quiet hours.
57
+ *
58
+ * Quiet hours are defined as **02:00 – 10:00 (Asia/Riyadh)** to
59
+ * respect the user's sleep schedule during Ramadan fasting, when
60
+ * they tend to sleep through the early-morning period.
61
+ *
62
+ * Automated tasks (notifications, self-improvement PRs, noisy jobs)
63
+ * should check this flag and defer non-urgent work until after the
64
+ * quiet window closes.
65
+ *
66
+ * @returns {boolean} `true` when the current Riyadh time is between
67
+ * 02:00 and 10:00 (inclusive start, exclusive end).
68
+ */
69
+ export function isQuietHours() {
70
+ const { hour } = getCurrentRiyadhTime();
71
+ return hour >= QUIET_START_HOUR && hour < QUIET_END_HOUR;
72
+ }
package/src/worker.js CHANGED
@@ -3,7 +3,7 @@ import { executeTool } from './tools/index.js';
3
3
  import { closeSession } from './tools/browser.js';
4
4
  import { getMissingCredential } from './utils/config.js';
5
5
  import { getWorkerPrompt } from './prompts/workers.js';
6
- import { getUnifiedSkillById } from './skills/custom.js';
6
+ import { buildSkillPrompt } from './skills/loader.js';
7
7
  import { getLogger } from './utils/logger.js';
8
8
  import { truncateToolResult } from './utils/truncate.js';
9
9
 
@@ -23,17 +23,17 @@ export class WorkerAgent {
23
23
  * @param {string} opts.workerType - coding, browser, system, devops, research
24
24
  * @param {string} opts.jobId - Job ID for logging
25
25
  * @param {Array} opts.tools - Scoped tool definitions
26
- * @param {string|null} opts.skillId - Active skill ID (for worker prompt)
26
+ * @param {string[]|null} opts.skillIds - Active skill IDs (for worker prompt)
27
27
  * @param {string|null} opts.workerContext - Structured context (conversation history, persona, dependency results)
28
28
  * @param {object} opts.callbacks - { onProgress, onComplete, onError }
29
29
  * @param {AbortController} opts.abortController - For cancellation
30
30
  */
31
- constructor({ config, workerType, jobId, tools, skillId, workerContext, callbacks, abortController }) {
31
+ constructor({ config, workerType, jobId, tools, skillIds, workerContext, callbacks, abortController }) {
32
32
  this.config = config;
33
33
  this.workerType = workerType;
34
34
  this.jobId = jobId;
35
35
  this.tools = tools;
36
- this.skillId = skillId;
36
+ this.skillIds = skillIds || [];
37
37
  this.workerContext = workerContext || null;
38
38
  this.callbacks = callbacks || {};
39
39
  this.abortController = abortController || new AbortController();
@@ -45,8 +45,8 @@ export class WorkerAgent {
45
45
  // Create provider from worker brain config
46
46
  this.provider = createProvider(config);
47
47
 
48
- // Build system prompt
49
- const skillPrompt = skillId ? getUnifiedSkillById(skillId)?.systemPrompt : null;
48
+ // Build system prompt with combined skill expertise
49
+ const skillPrompt = buildSkillPrompt(this.skillIds);
50
50
  this.systemPrompt = getWorkerPrompt(workerType, config, skillPrompt);
51
51
 
52
52
  // Safety ceiling — not a real limit, just prevents infinite loops
@@ -54,7 +54,7 @@ export class WorkerAgent {
54
54
  this.maxIterations = 200;
55
55
 
56
56
  const logger = getLogger();
57
- logger.info(`[Worker ${jobId}] Created: type=${workerType}, provider=${config.brain.provider}/${config.brain.model}, tools=${tools.length}, skill=${skillId || 'none'}, context=${workerContext ? 'yes' : 'none'}`);
57
+ logger.info(`[Worker ${jobId}] Created: type=${workerType}, provider=${config.brain.provider}/${config.brain.model}, tools=${tools.length}, skills=${this.skillIds.length > 0 ? this.skillIds.join(',') : 'none'}, context=${workerContext ? 'yes' : 'none'}`);
58
58
  }
59
59
 
60
60
  /** Cancel this worker. */
@@ -297,41 +297,34 @@ export class WorkerAgent {
297
297
 
298
298
  const _str = (v) => typeof v === 'string' ? v : (v ? JSON.stringify(v, null, 2) : '');
299
299
 
300
+ /** Try to build a structured result from a parsed JSON object. */
301
+ const _fromParsed = (parsed) => {
302
+ if (!parsed?.summary || !parsed?.status) return null;
303
+ return {
304
+ structured: true,
305
+ summary: String(parsed.summary || ''),
306
+ status: String(parsed.status || 'success'),
307
+ details: _str(parsed.details),
308
+ artifacts: Array.isArray(parsed.artifacts) ? parsed.artifacts : [],
309
+ followUp: parsed.followUp ? String(parsed.followUp) : null,
310
+ toolsUsed: this._toolCallCount,
311
+ errors: this._errors,
312
+ };
313
+ };
314
+
300
315
  // Try to extract JSON from ```json ... ``` fences
301
316
  const fenceMatch = text.match(/```json\s*\n?([\s\S]*?)\n?\s*```/);
302
317
  if (fenceMatch) {
303
318
  try {
304
- const parsed = JSON.parse(fenceMatch[1]);
305
- if (parsed.summary && parsed.status) {
306
- return {
307
- structured: true,
308
- summary: String(parsed.summary || ''),
309
- status: String(parsed.status || 'success'),
310
- details: _str(parsed.details),
311
- artifacts: Array.isArray(parsed.artifacts) ? parsed.artifacts : [],
312
- followUp: parsed.followUp ? String(parsed.followUp) : null,
313
- toolsUsed: this._toolCallCount,
314
- errors: this._errors,
315
- };
316
- }
319
+ const result = _fromParsed(JSON.parse(fenceMatch[1]));
320
+ if (result) return result;
317
321
  } catch { /* fall through */ }
318
322
  }
319
323
 
320
324
  // Try raw JSON parse (no fences)
321
325
  try {
322
- const parsed = JSON.parse(text);
323
- if (parsed.summary && parsed.status) {
324
- return {
325
- structured: true,
326
- summary: String(parsed.summary || ''),
327
- status: String(parsed.status || 'success'),
328
- details: _str(parsed.details),
329
- artifacts: Array.isArray(parsed.artifacts) ? parsed.artifacts : [],
330
- followUp: parsed.followUp ? String(parsed.followUp) : null,
331
- toolsUsed: this._toolCallCount,
332
- errors: this._errors,
333
- };
334
- }
326
+ const result = _fromParsed(JSON.parse(text));
327
+ if (result) return result;
335
328
  } catch { /* fall through */ }
336
329
 
337
330
  // Fallback: wrap raw text