bernard-agent 0.1.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.
Files changed (112) hide show
  1. package/.env.example +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +629 -0
  4. package/dist/agent.d.ts +24 -0
  5. package/dist/agent.js +174 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/config.d.ts +44 -0
  8. package/dist/config.js +267 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/context.d.ts +37 -0
  11. package/dist/context.js +245 -0
  12. package/dist/context.js.map +1 -0
  13. package/dist/cron/client.d.ts +4 -0
  14. package/dist/cron/client.js +113 -0
  15. package/dist/cron/client.js.map +1 -0
  16. package/dist/cron/daemon.d.ts +1 -0
  17. package/dist/cron/daemon.js +132 -0
  18. package/dist/cron/daemon.js.map +1 -0
  19. package/dist/cron/log-store.d.ts +51 -0
  20. package/dist/cron/log-store.js +135 -0
  21. package/dist/cron/log-store.js.map +1 -0
  22. package/dist/cron/notify.d.ts +7 -0
  23. package/dist/cron/notify.js +136 -0
  24. package/dist/cron/notify.js.map +1 -0
  25. package/dist/cron/runner.d.ts +6 -0
  26. package/dist/cron/runner.js +219 -0
  27. package/dist/cron/runner.js.map +1 -0
  28. package/dist/cron/scheduler.d.ts +16 -0
  29. package/dist/cron/scheduler.js +105 -0
  30. package/dist/cron/scheduler.js.map +1 -0
  31. package/dist/cron/store.d.ts +20 -0
  32. package/dist/cron/store.js +170 -0
  33. package/dist/cron/store.js.map +1 -0
  34. package/dist/cron/types.d.ts +21 -0
  35. package/dist/cron/types.js +3 -0
  36. package/dist/cron/types.js.map +1 -0
  37. package/dist/embeddings.d.ts +14 -0
  38. package/dist/embeddings.js +61 -0
  39. package/dist/embeddings.js.map +1 -0
  40. package/dist/history.d.ts +6 -0
  41. package/dist/history.js +71 -0
  42. package/dist/history.js.map +1 -0
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.js +231 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/logger.d.ts +1 -0
  47. package/dist/logger.js +24 -0
  48. package/dist/logger.js.map +1 -0
  49. package/dist/mcp.d.ts +43 -0
  50. package/dist/mcp.js +303 -0
  51. package/dist/mcp.js.map +1 -0
  52. package/dist/memory.d.ts +17 -0
  53. package/dist/memory.js +106 -0
  54. package/dist/memory.js.map +1 -0
  55. package/dist/output.d.ts +13 -0
  56. package/dist/output.js +151 -0
  57. package/dist/output.js.map +1 -0
  58. package/dist/providers/index.d.ts +2 -0
  59. package/dist/providers/index.js +19 -0
  60. package/dist/providers/index.js.map +1 -0
  61. package/dist/providers/types.d.ts +5 -0
  62. package/dist/providers/types.js +3 -0
  63. package/dist/providers/types.js.map +1 -0
  64. package/dist/rag-worker.d.ts +10 -0
  65. package/dist/rag-worker.js +84 -0
  66. package/dist/rag-worker.js.map +1 -0
  67. package/dist/rag.d.ts +53 -0
  68. package/dist/rag.js +242 -0
  69. package/dist/rag.js.map +1 -0
  70. package/dist/repl.d.ts +2 -0
  71. package/dist/repl.js +531 -0
  72. package/dist/repl.js.map +1 -0
  73. package/dist/setup.d.ts +1 -0
  74. package/dist/setup.js +104 -0
  75. package/dist/setup.js.map +1 -0
  76. package/dist/tools/cron-logs.d.ts +67 -0
  77. package/dist/tools/cron-logs.js +131 -0
  78. package/dist/tools/cron-logs.js.map +1 -0
  79. package/dist/tools/cron.d.ts +98 -0
  80. package/dist/tools/cron.js +248 -0
  81. package/dist/tools/cron.js.map +1 -0
  82. package/dist/tools/datetime.d.ts +4 -0
  83. package/dist/tools/datetime.js +25 -0
  84. package/dist/tools/datetime.js.map +1 -0
  85. package/dist/tools/index.d.ts +317 -0
  86. package/dist/tools/index.js +28 -0
  87. package/dist/tools/index.js.map +1 -0
  88. package/dist/tools/mcp-url.d.ts +16 -0
  89. package/dist/tools/mcp-url.js +27 -0
  90. package/dist/tools/mcp-url.js.map +1 -0
  91. package/dist/tools/mcp.d.ts +28 -0
  92. package/dist/tools/mcp.js +107 -0
  93. package/dist/tools/mcp.js.map +1 -0
  94. package/dist/tools/memory.d.ts +40 -0
  95. package/dist/tools/memory.js +99 -0
  96. package/dist/tools/memory.js.map +1 -0
  97. package/dist/tools/shell.d.ts +15 -0
  98. package/dist/tools/shell.js +60 -0
  99. package/dist/tools/shell.js.map +1 -0
  100. package/dist/tools/subagent.d.ts +21 -0
  101. package/dist/tools/subagent.js +81 -0
  102. package/dist/tools/subagent.js.map +1 -0
  103. package/dist/tools/time.d.ts +50 -0
  104. package/dist/tools/time.js +61 -0
  105. package/dist/tools/time.js.map +1 -0
  106. package/dist/tools/types.d.ts +8 -0
  107. package/dist/tools/types.js +3 -0
  108. package/dist/tools/types.js.map +1 -0
  109. package/dist/tools/web.d.ts +16 -0
  110. package/dist/tools/web.js +136 -0
  111. package/dist/tools/web.js.map +1 -0
  112. package/package.json +73 -0
@@ -0,0 +1,135 @@
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.CronLogStore = void 0;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const os = __importStar(require("node:os"));
40
+ const LOGS_DIR = path.join(os.homedir(), '.bernard', 'logs');
41
+ const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
42
+ const DEFAULT_KEEP = 500;
43
+ class CronLogStore {
44
+ constructor() {
45
+ fs.mkdirSync(LOGS_DIR, { recursive: true });
46
+ }
47
+ static get logsDir() { return LOGS_DIR; }
48
+ logPath(jobId) {
49
+ return path.join(LOGS_DIR, `${jobId}.jsonl`);
50
+ }
51
+ appendEntry(entry) {
52
+ const filePath = this.logPath(entry.jobId);
53
+ // Auto-rotate if file exceeds size limit
54
+ if (fs.existsSync(filePath)) {
55
+ const stat = fs.statSync(filePath);
56
+ if (stat.size > MAX_FILE_SIZE) {
57
+ this.rotate(entry.jobId, DEFAULT_KEEP);
58
+ }
59
+ }
60
+ fs.appendFileSync(filePath, JSON.stringify(entry) + '\n', 'utf-8');
61
+ }
62
+ getEntries(jobId, limit = 10, offset = 0) {
63
+ const filePath = this.logPath(jobId);
64
+ if (!fs.existsSync(filePath))
65
+ return [];
66
+ const lines = fs.readFileSync(filePath, 'utf-8')
67
+ .split('\n')
68
+ .filter(line => line.trim() !== '');
69
+ // Newest first
70
+ const reversed = lines.reverse();
71
+ const sliced = reversed.slice(offset, offset + limit);
72
+ return sliced.map(line => {
73
+ try {
74
+ return JSON.parse(line);
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }).filter((e) => e !== null);
80
+ }
81
+ getEntry(jobId, runId) {
82
+ const filePath = this.logPath(jobId);
83
+ if (!fs.existsSync(filePath))
84
+ return undefined;
85
+ const lines = fs.readFileSync(filePath, 'utf-8')
86
+ .split('\n')
87
+ .filter(line => line.trim() !== '');
88
+ for (const line of lines) {
89
+ try {
90
+ const entry = JSON.parse(line);
91
+ if (entry.runId === runId)
92
+ return entry;
93
+ }
94
+ catch {
95
+ // skip corrupted lines
96
+ }
97
+ }
98
+ return undefined;
99
+ }
100
+ listJobIds() {
101
+ if (!fs.existsSync(LOGS_DIR))
102
+ return [];
103
+ return fs.readdirSync(LOGS_DIR)
104
+ .filter(f => f.endsWith('.jsonl'))
105
+ .map(f => f.replace('.jsonl', ''));
106
+ }
107
+ getEntryCount(jobId) {
108
+ const filePath = this.logPath(jobId);
109
+ if (!fs.existsSync(filePath))
110
+ return 0;
111
+ const content = fs.readFileSync(filePath, 'utf-8');
112
+ return content.split('\n').filter(line => line.trim() !== '').length;
113
+ }
114
+ rotate(jobId, keep = DEFAULT_KEEP) {
115
+ const filePath = this.logPath(jobId);
116
+ if (!fs.existsSync(filePath))
117
+ return;
118
+ const lines = fs.readFileSync(filePath, 'utf-8')
119
+ .split('\n')
120
+ .filter(line => line.trim() !== '');
121
+ const kept = lines.slice(-keep);
122
+ const tmp = filePath + '.tmp';
123
+ fs.writeFileSync(tmp, kept.join('\n') + '\n', 'utf-8');
124
+ fs.renameSync(tmp, filePath);
125
+ }
126
+ deleteJobLogs(jobId) {
127
+ const filePath = this.logPath(jobId);
128
+ if (!fs.existsSync(filePath))
129
+ return false;
130
+ fs.unlinkSync(filePath);
131
+ return true;
132
+ }
133
+ }
134
+ exports.CronLogStore = CronLogStore;
135
+ //# sourceMappingURL=log-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-store.js","sourceRoot":"","sources":["../../src/cron/log-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function sendNotification(options: {
2
+ title: string;
3
+ message: string;
4
+ severity: 'low' | 'normal' | 'critical';
5
+ alertId: string;
6
+ log?: (msg: string) => void;
7
+ }): void;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.sendNotification = sendNotification;
7
+ const node_child_process_1 = require("node:child_process");
8
+ const node_os_1 = require("node:os");
9
+ const node_notifier_1 = __importDefault(require("node-notifier"));
10
+ const LINUX_TERMINALS = [
11
+ 'x-terminal-emulator',
12
+ 'gnome-terminal',
13
+ 'konsole',
14
+ 'xfce4-terminal',
15
+ 'alacritty',
16
+ 'kitty',
17
+ 'xterm',
18
+ ];
19
+ function findLinuxTerminal() {
20
+ for (const term of LINUX_TERMINALS) {
21
+ try {
22
+ (0, node_child_process_1.execSync)(`which ${term}`, { stdio: 'pipe' });
23
+ return term;
24
+ }
25
+ catch {
26
+ // not found, try next
27
+ }
28
+ }
29
+ return null;
30
+ }
31
+ function getLinuxTerminalArgs(terminal, command) {
32
+ switch (terminal) {
33
+ case 'gnome-terminal':
34
+ return ['--', 'bash', '-c', command];
35
+ case 'konsole':
36
+ return ['-e', 'bash', '-c', command];
37
+ case 'xfce4-terminal':
38
+ return ['-e', command];
39
+ case 'alacritty':
40
+ return ['-e', 'bash', '-c', command];
41
+ case 'kitty':
42
+ return ['bash', '-c', command];
43
+ default:
44
+ // x-terminal-emulator, xterm, and others
45
+ return ['-e', 'bash', '-c', command];
46
+ }
47
+ }
48
+ function openAlertInTerminal(alertId, log, platform) {
49
+ const plat = platform ?? (0, node_os_1.platform)();
50
+ const command = `bernard --alert ${alertId}`;
51
+ if (plat === 'darwin') {
52
+ try {
53
+ const child = (0, node_child_process_1.spawn)('osascript', ['-e', `tell application "Terminal" to do script "${command}"`], {
54
+ detached: true,
55
+ stdio: 'ignore',
56
+ });
57
+ child.unref();
58
+ }
59
+ catch (err) {
60
+ if (log)
61
+ log(`Warning: Failed to open macOS Terminal: ${err instanceof Error ? err.message : String(err)}`);
62
+ }
63
+ return;
64
+ }
65
+ if (plat === 'win32') {
66
+ // Try Windows Terminal first, fall back to cmd
67
+ try {
68
+ const child = (0, node_child_process_1.spawn)('wt', ['--', 'cmd', '/k', command], {
69
+ detached: true,
70
+ stdio: 'ignore',
71
+ shell: true,
72
+ });
73
+ child.unref();
74
+ }
75
+ catch {
76
+ try {
77
+ const child = (0, node_child_process_1.spawn)('cmd', ['/c', 'start', 'cmd', '/k', command], {
78
+ detached: true,
79
+ stdio: 'ignore',
80
+ shell: true,
81
+ });
82
+ child.unref();
83
+ }
84
+ catch (err) {
85
+ if (log)
86
+ log(`Warning: Failed to open Windows terminal: ${err instanceof Error ? err.message : String(err)}`);
87
+ }
88
+ }
89
+ return;
90
+ }
91
+ // Linux
92
+ const terminal = findLinuxTerminal();
93
+ if (!terminal) {
94
+ if (log)
95
+ log('Warning: No supported terminal emulator found for alert display.');
96
+ return;
97
+ }
98
+ const args = getLinuxTerminalArgs(terminal, command);
99
+ try {
100
+ const child = (0, node_child_process_1.spawn)(terminal, args, {
101
+ detached: true,
102
+ stdio: 'ignore',
103
+ });
104
+ child.unref();
105
+ }
106
+ catch (err) {
107
+ if (log)
108
+ log(`Warning: Failed to open terminal: ${err instanceof Error ? err.message : String(err)}`);
109
+ }
110
+ }
111
+ let pendingAlertId = null;
112
+ let clickListenerRegistered = false;
113
+ function sendNotification(options) {
114
+ const { title, message, severity, alertId, log } = options;
115
+ pendingAlertId = alertId;
116
+ if (!clickListenerRegistered) {
117
+ clickListenerRegistered = true;
118
+ node_notifier_1.default.on('click', () => {
119
+ if (pendingAlertId) {
120
+ openAlertInTerminal(pendingAlertId, log);
121
+ pendingAlertId = null;
122
+ }
123
+ });
124
+ }
125
+ const plat = (0, node_os_1.platform)();
126
+ // sound is macOS-only (NotificationCenter), urgency is Linux-only (NotifySend).
127
+ // node-notifier ignores unknown fields per-platform, so we merge them.
128
+ node_notifier_1.default.notify({
129
+ title,
130
+ message,
131
+ sound: severity === 'critical',
132
+ wait: plat !== 'linux',
133
+ urgency: severity,
134
+ });
135
+ }
136
+ //# sourceMappingURL=notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/cron/notify.ts"],"names":[],"mappings":";;;;;AA2GA,4CAgCC;AA3ID,2DAAqD;AACrD,qCAAiD;AACjD,kEAAqC;AAErC,MAAM,eAAe,GAAG;IACtB,qBAAqB;IACrB,gBAAgB;IAChB,SAAS;IACT,gBAAgB;IAChB,WAAW;IACX,OAAO;IACP,OAAO;CACR,CAAC;AAEF,SAAS,iBAAiB;IACxB,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,IAAA,6BAAQ,EAAC,SAAS,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAE,OAAe;IAC7D,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,gBAAgB;YACnB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,KAAK,SAAS;YACZ,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,KAAK,gBAAgB;YACnB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzB,KAAK,WAAW;YACd,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,KAAK,OAAO;YACV,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACjC;YACE,yCAAyC;YACzC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe,EAAE,GAA2B,EAAE,QAAiB;IAC1F,MAAM,IAAI,GAAG,QAAQ,IAAI,IAAA,kBAAU,GAAE,CAAC;IACtC,MAAM,OAAO,GAAG,mBAAmB,OAAO,EAAE,CAAC;IAE7C,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAA,0BAAK,EAAC,WAAW,EAAE,CAAC,IAAI,EAAE,6CAA6C,OAAO,GAAG,CAAC,EAAE;gBAChG,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG;gBAAE,GAAG,CAAC,2CAA2C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9G,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,+CAA+C;QAC/C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAA,0BAAK,EAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;gBACtD,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAA,0BAAK,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;oBAChE,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,QAAQ;oBACf,KAAK,EAAE,IAAI;iBACZ,CAAC,CAAC;gBACH,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG;oBAAE,GAAG,CAAC,6CAA6C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChH,CAAC;QACH,CAAC;QACD,OAAO;IACT,CAAC;IAED,QAAQ;IACR,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,GAAG;YAAE,GAAG,CAAC,kEAAkE,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAA,0BAAK,EAAC,QAAQ,EAAE,IAAI,EAAE;YAClC,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG;YAAE,GAAG,CAAC,qCAAqC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxG,CAAC;AACH,CAAC;AAED,IAAI,cAAc,GAAkB,IAAI,CAAC;AACzC,IAAI,uBAAuB,GAAG,KAAK,CAAC;AAEpC,SAAgB,gBAAgB,CAAC,OAMhC;IACC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAE3D,cAAc,GAAG,OAAO,CAAC;IAEzB,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC7B,uBAAuB,GAAG,IAAI,CAAC;QAC/B,uBAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACxB,IAAI,cAAc,EAAE,CAAC;gBACnB,mBAAmB,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;gBACzC,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,kBAAU,GAAE,CAAC;IAE1B,gFAAgF;IAChF,uEAAuE;IACvE,uBAAQ,CAAC,MAAM,CAAC;QACd,KAAK;QACL,OAAO;QACP,KAAK,EAAE,QAAQ,KAAK,UAAU;QAC9B,IAAI,EAAE,IAAI,KAAK,OAAO;QACtB,OAAO,EAAE,QAAQ;KACsB,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { CronJob } from './types.js';
2
+ export interface RunJobResult {
3
+ success: boolean;
4
+ output: string;
5
+ }
6
+ export declare function runJob(job: CronJob, log: (msg: string) => void): Promise<RunJobResult>;
@@ -0,0 +1,219 @@
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.runJob = runJob;
37
+ const crypto = __importStar(require("node:crypto"));
38
+ const ai_1 = require("ai");
39
+ const ai_2 = require("ai");
40
+ const zod_1 = require("zod");
41
+ const index_js_1 = require("../providers/index.js");
42
+ const config_js_1 = require("../config.js");
43
+ const memory_js_1 = require("../memory.js");
44
+ const shell_js_1 = require("../tools/shell.js");
45
+ const memory_js_2 = require("../tools/memory.js");
46
+ const datetime_js_1 = require("../tools/datetime.js");
47
+ const mcp_js_1 = require("../mcp.js");
48
+ const store_js_1 = require("./store.js");
49
+ const log_store_js_1 = require("./log-store.js");
50
+ const notify_js_1 = require("./notify.js");
51
+ const DAEMON_SYSTEM_PROMPT = `You are Bernard, running in background daemon mode as a scheduled cron job.
52
+
53
+ Guidelines:
54
+ - Execute the task described in the user prompt.
55
+ - You have access to shell, memory, scratch, and datetime tools.
56
+ - IMPORTANT: Dangerous shell commands are automatically denied in daemon mode. There is no user present to confirm them.
57
+ - If you discover something that requires user attention, use the \`notify\` tool to send a desktop notification. Clicking the notification will open a terminal with the alert context.
58
+ - You may also have access to MCP tools such as email, calendar, and others depending on configuration.
59
+ - Be concise in your analysis. Focus on actionable findings.
60
+ - If everything looks normal and no action is needed, simply report the results without notifying.`;
61
+ async function runJob(job, log) {
62
+ const config = (0, config_js_1.loadConfig)();
63
+ const memoryStore = new memory_js_1.MemoryStore();
64
+ const store = new store_js_1.CronStore();
65
+ const mcpManager = new mcp_js_1.MCPManager();
66
+ let mcpTools = {};
67
+ try {
68
+ await mcpManager.connect();
69
+ mcpTools = mcpManager.getTools();
70
+ const serverNames = mcpManager.getConnectedServerNames();
71
+ if (serverNames.length > 0) {
72
+ log(`MCP servers connected: ${serverNames.join(', ')}`);
73
+ }
74
+ }
75
+ catch (err) {
76
+ const message = err instanceof Error ? err.message : String(err);
77
+ log(`MCP initialization failed, continuing without MCP tools: ${message}`);
78
+ }
79
+ const logStore = new log_store_js_1.CronLogStore();
80
+ const runId = crypto.randomUUID();
81
+ const startedAt = new Date().toISOString();
82
+ const startMs = Date.now();
83
+ const steps = [];
84
+ let stepIndex = 0;
85
+ try {
86
+ const notifyTool = (0, ai_2.tool)({
87
+ description: 'Send a desktop notification to alert the user. Use this when you find something that requires user attention. Clicking the notification will open a terminal with the alert context.',
88
+ parameters: zod_1.z.object({
89
+ message: zod_1.z.string().describe('The alert message to show the user'),
90
+ severity: zod_1.z.enum(['low', 'normal', 'critical']).describe('Urgency level of the notification'),
91
+ }),
92
+ execute: async ({ message, severity }) => {
93
+ const alert = store.createAlert({
94
+ jobId: job.id,
95
+ jobName: job.name,
96
+ message,
97
+ prompt: job.prompt,
98
+ response: '', // Will be updated after generation completes
99
+ });
100
+ (0, notify_js_1.sendNotification)({
101
+ title: `Bernard: ${job.name}`,
102
+ message,
103
+ severity,
104
+ alertId: alert.id,
105
+ log,
106
+ });
107
+ return `Notification sent for alert ${alert.id}. Terminal will open when the user clicks the notification.`;
108
+ },
109
+ });
110
+ const shellTool = (0, shell_js_1.createShellTool)({
111
+ shellTimeout: config.shellTimeout,
112
+ confirmDangerous: async () => false, // Auto-deny in daemon mode
113
+ });
114
+ const tools = {
115
+ shell: shellTool,
116
+ memory: (0, memory_js_2.createMemoryTool)(memoryStore),
117
+ scratch: (0, memory_js_2.createScratchTool)(memoryStore),
118
+ datetime: (0, datetime_js_1.createDateTimeTool)(),
119
+ notify: notifyTool,
120
+ ...mcpTools,
121
+ };
122
+ const result = await (0, ai_1.generateText)({
123
+ model: (0, index_js_1.getModel)(config.provider, config.model),
124
+ tools,
125
+ maxSteps: 20,
126
+ maxTokens: config.maxTokens,
127
+ system: DAEMON_SYSTEM_PROMPT,
128
+ messages: [{ role: 'user', content: job.prompt }],
129
+ onStepFinish: ({ text, toolCalls, toolResults, usage, finishReason }) => {
130
+ const truncatedResults = (toolResults || []).map(tr => ({
131
+ toolName: tr.toolName,
132
+ toolCallId: tr.toolCallId,
133
+ result: truncateResult(tr.result, 10240),
134
+ }));
135
+ steps.push({
136
+ stepIndex: stepIndex++,
137
+ timestamp: new Date().toISOString(),
138
+ text: text || '',
139
+ toolCalls: (toolCalls || []).map(tc => ({
140
+ toolName: tc.toolName,
141
+ toolCallId: tc.toolCallId,
142
+ args: tc.args,
143
+ })),
144
+ toolResults: truncatedResults,
145
+ usage: {
146
+ promptTokens: usage?.promptTokens ?? 0,
147
+ completionTokens: usage?.completionTokens ?? 0,
148
+ totalTokens: (usage?.promptTokens ?? 0) + (usage?.completionTokens ?? 0),
149
+ },
150
+ finishReason: finishReason || 'unknown',
151
+ });
152
+ },
153
+ });
154
+ const output = result.text || '(no text output)';
155
+ try {
156
+ const totalUsage = steps.reduce((acc, s) => ({
157
+ promptTokens: acc.promptTokens + s.usage.promptTokens,
158
+ completionTokens: acc.completionTokens + s.usage.completionTokens,
159
+ totalTokens: acc.totalTokens + s.usage.totalTokens,
160
+ }), { promptTokens: 0, completionTokens: 0, totalTokens: 0 });
161
+ logStore.appendEntry({
162
+ runId,
163
+ jobId: job.id,
164
+ jobName: job.name,
165
+ prompt: job.prompt,
166
+ startedAt,
167
+ completedAt: new Date().toISOString(),
168
+ durationMs: Date.now() - startMs,
169
+ success: true,
170
+ finalOutput: output,
171
+ steps,
172
+ totalUsage,
173
+ });
174
+ }
175
+ catch (logErr) {
176
+ const logMsg = logErr instanceof Error ? logErr.message : String(logErr);
177
+ log(`Warning: failed to write execution log: ${logMsg}`);
178
+ }
179
+ return { success: true, output };
180
+ }
181
+ catch (err) {
182
+ const message = err instanceof Error ? err.message : String(err);
183
+ try {
184
+ const totalUsage = steps.reduce((acc, s) => ({
185
+ promptTokens: acc.promptTokens + s.usage.promptTokens,
186
+ completionTokens: acc.completionTokens + s.usage.completionTokens,
187
+ totalTokens: acc.totalTokens + s.usage.totalTokens,
188
+ }), { promptTokens: 0, completionTokens: 0, totalTokens: 0 });
189
+ logStore.appendEntry({
190
+ runId,
191
+ jobId: job.id,
192
+ jobName: job.name,
193
+ prompt: job.prompt,
194
+ startedAt,
195
+ completedAt: new Date().toISOString(),
196
+ durationMs: Date.now() - startMs,
197
+ success: false,
198
+ error: message,
199
+ finalOutput: '',
200
+ steps,
201
+ totalUsage,
202
+ });
203
+ }
204
+ catch {
205
+ // best-effort logging
206
+ }
207
+ return { success: false, output: `Error: ${message}` };
208
+ }
209
+ finally {
210
+ await mcpManager.close();
211
+ }
212
+ }
213
+ function truncateResult(result, maxLen) {
214
+ if (typeof result === 'string' && result.length > maxLen) {
215
+ return result.slice(0, maxLen) + `... (truncated, ${result.length} chars total)`;
216
+ }
217
+ return result;
218
+ }
219
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/cron/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { CronStore } from './store.js';
2
+ export declare class Scheduler {
3
+ private tasks;
4
+ private store;
5
+ private log;
6
+ private maxConcurrent;
7
+ private runningCount;
8
+ private queue;
9
+ constructor(store: CronStore, log: (msg: string) => void);
10
+ reconcile(): void;
11
+ private enqueueRun;
12
+ private executeJob;
13
+ private drainQueue;
14
+ stopAll(): void;
15
+ get activeCount(): number;
16
+ }
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Scheduler = void 0;
7
+ const node_cron_1 = __importDefault(require("node-cron"));
8
+ const runner_js_1 = require("./runner.js");
9
+ const DEFAULT_MAX_CONCURRENT = 3;
10
+ class Scheduler {
11
+ tasks = new Map();
12
+ store;
13
+ log;
14
+ maxConcurrent;
15
+ runningCount = 0;
16
+ queue = [];
17
+ constructor(store, log) {
18
+ this.store = store;
19
+ this.log = log;
20
+ this.maxConcurrent = parseInt(process.env.BERNARD_CRON_MAX_CONCURRENT || '', 10) || DEFAULT_MAX_CONCURRENT;
21
+ }
22
+ reconcile() {
23
+ const jobs = this.store.loadJobs();
24
+ const jobMap = new Map(jobs.map(j => [j.id, j]));
25
+ // Stop tasks for removed or disabled jobs
26
+ for (const [id, task] of this.tasks) {
27
+ const job = jobMap.get(id);
28
+ if (!job || !job.enabled) {
29
+ this.log(`Stopping task for job "${id}"`);
30
+ task.stop();
31
+ this.tasks.delete(id);
32
+ }
33
+ }
34
+ // Start tasks for new or re-enabled jobs
35
+ for (const job of jobs) {
36
+ if (!job.enabled)
37
+ continue;
38
+ if (this.tasks.has(job.id))
39
+ continue;
40
+ if (!node_cron_1.default.validate(job.schedule)) {
41
+ this.log(`Invalid cron expression for job "${job.name}" (${job.id}): ${job.schedule}`);
42
+ continue;
43
+ }
44
+ this.log(`Scheduling job "${job.name}" (${job.id}): ${job.schedule}`);
45
+ const task = node_cron_1.default.schedule(job.schedule, () => {
46
+ this.enqueueRun(job);
47
+ });
48
+ this.tasks.set(job.id, task);
49
+ }
50
+ }
51
+ enqueueRun(job) {
52
+ if (this.runningCount >= this.maxConcurrent) {
53
+ this.log(`Job "${job.name}" queued (${this.runningCount}/${this.maxConcurrent} running)`);
54
+ this.queue.push(job);
55
+ return;
56
+ }
57
+ this.executeJob(job);
58
+ }
59
+ async executeJob(job) {
60
+ this.runningCount++;
61
+ const startTime = new Date().toISOString();
62
+ this.log(`Running job "${job.name}" (${job.id}) at ${startTime}`);
63
+ this.store.updateJob(job.id, {
64
+ lastRun: startTime,
65
+ lastRunStatus: 'running',
66
+ });
67
+ try {
68
+ const result = await (0, runner_js_1.runJob)(job, this.log);
69
+ this.store.updateJob(job.id, {
70
+ lastRunStatus: result.success ? 'success' : 'error',
71
+ lastResult: result.output.slice(0, 2000), // Truncate to avoid huge JSON
72
+ });
73
+ this.log(`Job "${job.name}" finished: ${result.success ? 'success' : 'error'}`);
74
+ }
75
+ catch (err) {
76
+ const message = err instanceof Error ? err.message : String(err);
77
+ this.store.updateJob(job.id, {
78
+ lastRunStatus: 'error',
79
+ lastResult: message.slice(0, 2000),
80
+ });
81
+ this.log(`Job "${job.name}" threw: ${message}`);
82
+ }
83
+ finally {
84
+ this.runningCount--;
85
+ this.drainQueue();
86
+ }
87
+ }
88
+ drainQueue() {
89
+ while (this.queue.length > 0 && this.runningCount < this.maxConcurrent) {
90
+ const next = this.queue.shift();
91
+ this.executeJob(next);
92
+ }
93
+ }
94
+ stopAll() {
95
+ for (const [id, task] of this.tasks) {
96
+ task.stop();
97
+ this.tasks.delete(id);
98
+ }
99
+ }
100
+ get activeCount() {
101
+ return this.tasks.size;
102
+ }
103
+ }
104
+ exports.Scheduler = Scheduler;
105
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/cron/scheduler.ts"],"names":[],"mappings":"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"}