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,245 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RECENT_TURNS_TO_KEEP = exports.COMPRESSION_THRESHOLD = exports.DEFAULT_CONTEXT_WINDOW = exports.MODEL_CONTEXT_WINDOWS = void 0;
4
+ exports.getContextWindow = getContextWindow;
5
+ exports.shouldCompress = shouldCompress;
6
+ exports.serializeMessages = serializeMessages;
7
+ exports.countRecentMessages = countRecentMessages;
8
+ exports.extractFacts = extractFacts;
9
+ exports.compressHistory = compressHistory;
10
+ const ai_1 = require("ai");
11
+ const index_js_1 = require("./providers/index.js");
12
+ const logger_js_1 = require("./logger.js");
13
+ /** Model name → context window size in tokens */
14
+ exports.MODEL_CONTEXT_WINDOWS = {
15
+ // Anthropic
16
+ 'claude-sonnet-4-5-20250929': 200_000,
17
+ 'claude-opus-4-20250514': 200_000,
18
+ 'claude-sonnet-4-20250514': 200_000,
19
+ 'claude-3-5-haiku-latest': 200_000,
20
+ // OpenAI
21
+ 'gpt-4o': 128_000,
22
+ 'gpt-4o-mini': 128_000,
23
+ 'o3': 200_000,
24
+ 'o3-mini': 200_000,
25
+ 'o4-mini': 200_000,
26
+ 'gpt-4.1': 1_000_000,
27
+ 'gpt-4.1-mini': 1_000_000,
28
+ 'gpt-4.1-nano': 1_000_000,
29
+ // xAI
30
+ 'grok-3': 131_072,
31
+ 'grok-3-fast': 131_072,
32
+ 'grok-3-mini': 131_072,
33
+ 'grok-3-mini-fast': 131_072,
34
+ };
35
+ exports.DEFAULT_CONTEXT_WINDOW = 128_000;
36
+ exports.COMPRESSION_THRESHOLD = 0.75;
37
+ exports.RECENT_TURNS_TO_KEEP = 4;
38
+ /** Look up context window for a model, falling back to 128k for unknown models. */
39
+ function getContextWindow(model) {
40
+ return exports.MODEL_CONTEXT_WINDOWS[model] ?? exports.DEFAULT_CONTEXT_WINDOW;
41
+ }
42
+ /**
43
+ * Returns true when estimated token usage exceeds the compression threshold.
44
+ * @param lastPromptTokens - actual prompt token count from the last API call
45
+ * @param newMessageEstimate - rough token estimate for the new user message
46
+ * @param model - model name for context window lookup
47
+ */
48
+ function shouldCompress(lastPromptTokens, newMessageEstimate, model) {
49
+ const contextWindow = getContextWindow(model);
50
+ const estimated = lastPromptTokens + newMessageEstimate;
51
+ return estimated > contextWindow * exports.COMPRESSION_THRESHOLD;
52
+ }
53
+ /** Convert a CoreMessage array into readable text for the summarizer. */
54
+ function serializeMessages(messages) {
55
+ const lines = [];
56
+ for (const msg of messages) {
57
+ if (msg.role === 'user') {
58
+ const text = extractText(msg);
59
+ if (text)
60
+ lines.push(`User: ${text}`);
61
+ }
62
+ else if (msg.role === 'assistant') {
63
+ const text = extractText(msg);
64
+ if (text)
65
+ lines.push(`Assistant: ${text}`);
66
+ // Include tool calls if present
67
+ if (Array.isArray(msg.content)) {
68
+ for (const part of msg.content) {
69
+ if (typeof part === 'object' && part !== null && 'type' in part && part.type === 'tool-call') {
70
+ const tc = part;
71
+ lines.push(`Assistant [tool call]: ${tc.toolName}(${JSON.stringify(tc.args)})`);
72
+ }
73
+ }
74
+ }
75
+ }
76
+ else if (msg.role === 'tool') {
77
+ // Tool results
78
+ if (Array.isArray(msg.content)) {
79
+ for (const part of msg.content) {
80
+ if (typeof part === 'object' && part !== null && 'type' in part && part.type === 'tool-result') {
81
+ const tr = part;
82
+ const name = tr.toolName ?? 'tool';
83
+ const resultStr = typeof tr.result === 'string' ? tr.result : JSON.stringify(tr.result);
84
+ const truncated = resultStr.length > 500 ? resultStr.slice(0, 500) + '...' : resultStr;
85
+ lines.push(`Tool [${name}]: ${truncated}`);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return lines.join('\n');
92
+ }
93
+ /**
94
+ * Walk backward through history to find the split point that keeps the last N
95
+ * user/assistant exchanges intact.
96
+ * Returns the index where "recent" messages start (0 means nothing to compress).
97
+ */
98
+ function countRecentMessages(history, turnsToKeep) {
99
+ let userTurns = 0;
100
+ for (let i = history.length - 1; i >= 0; i--) {
101
+ if (history[i].role === 'user') {
102
+ userTurns++;
103
+ if (userTurns === turnsToKeep) {
104
+ // If this is already the start, there's nothing older to compress
105
+ if (i === 0)
106
+ return 0;
107
+ return i;
108
+ }
109
+ }
110
+ }
111
+ // Fewer user turns than turnsToKeep — nothing to compress
112
+ return 0;
113
+ }
114
+ const FACT_EXTRACTION_PROMPT = `You are a fact extraction system. Extract notable, self-contained facts from the conversation below that would be useful to recall in future sessions.
115
+
116
+ Extract:
117
+ - User preferences and habits
118
+ - Project details, structure, and conventions
119
+ - Technical environment info (OS, languages, tools, versions)
120
+ - Decisions made and their reasoning
121
+ - Recurring patterns or workflows
122
+ - Names, roles, and relationships mentioned
123
+
124
+ Do NOT extract:
125
+ - Task-specific transient details (e.g., "the user asked to fix a typo on line 42")
126
+ - Generic knowledge that any AI would know
127
+ - Greetings, filler, or conversational noise
128
+
129
+ Return a JSON array of strings. Each string should be a self-contained fact (understandable without the original conversation). Maximum 500 characters per fact. If there are no notable facts, return an empty array [].`;
130
+ const FACT_EXTRACTION_MAX = 500;
131
+ /**
132
+ * Extract notable facts from serialized conversation text via LLM.
133
+ * Returns an empty array on any failure.
134
+ * @internal
135
+ */
136
+ async function extractFacts(serializedText, config) {
137
+ if (!serializedText.trim())
138
+ return [];
139
+ try {
140
+ const result = await (0, ai_1.generateText)({
141
+ model: (0, index_js_1.getModel)(config.provider, config.model),
142
+ maxTokens: 2048,
143
+ system: FACT_EXTRACTION_PROMPT,
144
+ messages: [
145
+ { role: 'user', content: `Extract facts from this conversation:\n\n${serializedText}` },
146
+ ],
147
+ });
148
+ const text = result.text?.trim();
149
+ if (!text)
150
+ return [];
151
+ // Parse JSON array from response — handle markdown code fences
152
+ const jsonStr = text.replace(/^```(?:json)?\s*/m, '').replace(/\s*```$/m, '');
153
+ const parsed = JSON.parse(jsonStr);
154
+ if (!Array.isArray(parsed))
155
+ return [];
156
+ return parsed
157
+ .filter((item) => typeof item === 'string' && item.length > 0)
158
+ .filter((item) => item.length <= FACT_EXTRACTION_MAX);
159
+ }
160
+ catch (err) {
161
+ (0, logger_js_1.debugLog)('context:extractFacts', `Failed: ${err instanceof Error ? err.message : String(err)}`);
162
+ return [];
163
+ }
164
+ }
165
+ const SUMMARIZATION_PROMPT = `You are a conversation summarizer. Produce a concise summary of the conversation below, preserving:
166
+ - Key facts, decisions, and outcomes
167
+ - Important tool results and command outputs
168
+ - Any user preferences or requirements mentioned
169
+ - The overall arc of what was discussed and accomplished
170
+
171
+ Be concise but complete. Use bullet points. Do not include greetings or filler.`;
172
+ /**
173
+ * Compress conversation history by summarizing older messages via the LLM.
174
+ * Keeps the most recent turns intact and replaces older messages with a summary.
175
+ * On failure, returns the original history unchanged.
176
+ */
177
+ async function compressHistory(history, config, ragStore) {
178
+ const splitIndex = countRecentMessages(history, exports.RECENT_TURNS_TO_KEEP);
179
+ // Not enough history to compress
180
+ if (splitIndex === 0) {
181
+ return history;
182
+ }
183
+ const oldMessages = history.slice(0, splitIndex);
184
+ const recentMessages = history.slice(splitIndex);
185
+ const serialized = serializeMessages(oldMessages);
186
+ if (!serialized.trim()) {
187
+ return history;
188
+ }
189
+ try {
190
+ // Run summarization and fact extraction in parallel
191
+ const summarizePromise = (0, ai_1.generateText)({
192
+ model: (0, index_js_1.getModel)(config.provider, config.model),
193
+ maxTokens: 2048,
194
+ system: SUMMARIZATION_PROMPT,
195
+ messages: [
196
+ { role: 'user', content: `Summarize this conversation:\n\n${serialized}` },
197
+ ],
198
+ });
199
+ const extractPromise = ragStore
200
+ ? extractFacts(serialized, config)
201
+ : Promise.resolve([]);
202
+ const [result, facts] = await Promise.all([summarizePromise, extractPromise]);
203
+ // Store extracted facts fire-and-forget
204
+ if (ragStore && facts.length > 0) {
205
+ ragStore.addFacts(facts, 'compression').catch((err) => {
206
+ (0, logger_js_1.debugLog)('context:compress:rag', `Failed to store facts: ${err instanceof Error ? err.message : String(err)}`);
207
+ });
208
+ }
209
+ const summary = result.text?.trim();
210
+ if (!summary) {
211
+ (0, logger_js_1.debugLog)('context:compress', 'Summary was empty, keeping original history');
212
+ return history;
213
+ }
214
+ const summaryMessage = {
215
+ role: 'user',
216
+ content: `[Context Summary — earlier conversation was compressed]\n\n${summary}`,
217
+ };
218
+ const ackMessage = {
219
+ role: 'assistant',
220
+ content: 'Understood. I have the context from our earlier conversation. Let\'s continue.',
221
+ };
222
+ (0, logger_js_1.debugLog)('context:compress', {
223
+ oldMessageCount: oldMessages.length,
224
+ recentMessageCount: recentMessages.length,
225
+ summaryLength: summary.length,
226
+ factsExtracted: facts.length,
227
+ });
228
+ return [summaryMessage, ackMessage, ...recentMessages];
229
+ }
230
+ catch (err) {
231
+ (0, logger_js_1.debugLog)('context:compress:error', err instanceof Error ? err.message : String(err));
232
+ return history;
233
+ }
234
+ }
235
+ function extractText(msg) {
236
+ if (typeof msg.content === 'string')
237
+ return msg.content;
238
+ if (!Array.isArray(msg.content))
239
+ return null;
240
+ const textParts = msg.content
241
+ .filter((p) => typeof p === 'object' && p !== null && 'type' in p && p.type === 'text')
242
+ .map(p => p.text);
243
+ return textParts.length > 0 ? textParts.join(' ') : null;
244
+ }
245
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function isDaemonRunning(): boolean;
2
+ export declare function getDaemonPid(): number | null;
3
+ export declare function startDaemon(): boolean;
4
+ export declare function stopDaemon(): boolean;
@@ -0,0 +1,113 @@
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.isDaemonRunning = isDaemonRunning;
37
+ exports.getDaemonPid = getDaemonPid;
38
+ exports.startDaemon = startDaemon;
39
+ exports.stopDaemon = stopDaemon;
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const node_child_process_1 = require("node:child_process");
43
+ const store_js_1 = require("./store.js");
44
+ function isDaemonRunning() {
45
+ const pidFile = store_js_1.CronStore.pidFile;
46
+ if (!fs.existsSync(pidFile))
47
+ return false;
48
+ try {
49
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
50
+ if (isNaN(pid)) {
51
+ fs.unlinkSync(pidFile);
52
+ return false;
53
+ }
54
+ // Check if process is alive (signal 0 doesn't kill, just checks)
55
+ process.kill(pid, 0);
56
+ return true;
57
+ }
58
+ catch {
59
+ // Process not running — clean up stale PID file
60
+ try {
61
+ fs.unlinkSync(pidFile);
62
+ }
63
+ catch { }
64
+ return false;
65
+ }
66
+ }
67
+ function getDaemonPid() {
68
+ const pidFile = store_js_1.CronStore.pidFile;
69
+ if (!fs.existsSync(pidFile))
70
+ return null;
71
+ try {
72
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
73
+ return isNaN(pid) ? null : pid;
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ function startDaemon() {
80
+ if (isDaemonRunning())
81
+ return true;
82
+ const daemonPath = path.resolve(__dirname, 'daemon.js');
83
+ if (!fs.existsSync(daemonPath)) {
84
+ throw new Error(`Daemon script not found at ${daemonPath}. Run "npm run build" first.`);
85
+ }
86
+ const child = (0, node_child_process_1.fork)(daemonPath, [], {
87
+ detached: true,
88
+ stdio: 'ignore',
89
+ });
90
+ child.unref();
91
+ if (child.pid) {
92
+ fs.writeFileSync(store_js_1.CronStore.pidFile, String(child.pid), 'utf-8');
93
+ return true;
94
+ }
95
+ return false;
96
+ }
97
+ function stopDaemon() {
98
+ const pid = getDaemonPid();
99
+ if (pid === null)
100
+ return false;
101
+ try {
102
+ process.kill(pid, 'SIGTERM');
103
+ }
104
+ catch {
105
+ // Process already dead
106
+ }
107
+ try {
108
+ fs.unlinkSync(store_js_1.CronStore.pidFile);
109
+ }
110
+ catch { }
111
+ return true;
112
+ }
113
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/cron/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,132 @@
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
+ const fs = __importStar(require("node:fs"));
37
+ const store_js_1 = require("./store.js");
38
+ const scheduler_js_1 = require("./scheduler.js");
39
+ const config_js_1 = require("../config.js");
40
+ const MAX_LOG_SIZE = 1_000_000; // 1MB
41
+ function createLogger() {
42
+ const logFile = store_js_1.CronStore.logFile;
43
+ return (msg) => {
44
+ const line = `[${new Date().toISOString()}] ${msg}\n`;
45
+ try {
46
+ // Rotate if log exceeds max size
47
+ try {
48
+ const stat = fs.statSync(logFile);
49
+ if (stat.size > MAX_LOG_SIZE) {
50
+ const rotated = logFile + '.old';
51
+ try {
52
+ fs.unlinkSync(rotated);
53
+ }
54
+ catch { }
55
+ fs.renameSync(logFile, rotated);
56
+ }
57
+ }
58
+ catch {
59
+ // File doesn't exist yet, that's fine
60
+ }
61
+ fs.appendFileSync(logFile, line);
62
+ }
63
+ catch {
64
+ // Can't log, nothing we can do
65
+ }
66
+ };
67
+ }
68
+ function main() {
69
+ const log = createLogger();
70
+ log('Daemon starting');
71
+ // Load config to ensure .env is loaded for API keys
72
+ try {
73
+ (0, config_js_1.loadConfig)();
74
+ }
75
+ catch (err) {
76
+ const message = err instanceof Error ? err.message : String(err);
77
+ log(`Config error: ${message}`);
78
+ process.exit(1);
79
+ }
80
+ const store = new store_js_1.CronStore();
81
+ const scheduler = new scheduler_js_1.Scheduler(store, log);
82
+ // Write PID file
83
+ fs.writeFileSync(store_js_1.CronStore.pidFile, String(process.pid), 'utf-8');
84
+ log(`PID ${process.pid} written`);
85
+ // Detect stale running jobs from a previous crash
86
+ const jobs = store.loadJobs();
87
+ for (const job of jobs) {
88
+ if (job.lastRunStatus === 'running') {
89
+ log(`Warning: Job "${job.name}" (${job.id}) was in running state at startup — previous daemon may have crashed`);
90
+ store.updateJob(job.id, { lastRunStatus: 'error', lastResult: 'Daemon restarted while job was running' });
91
+ }
92
+ }
93
+ // Initial reconcile
94
+ scheduler.reconcile();
95
+ log(`Initial reconcile done. ${scheduler.activeCount} tasks scheduled.`);
96
+ // Watch cron directory for changes (watching the file directly breaks
97
+ // on Linux after atomic writes replace the inode via rename)
98
+ let debounceTimer = null;
99
+ try {
100
+ fs.watch(store_js_1.CronStore.cronDir, (eventType, filename) => {
101
+ if (filename !== 'jobs.json' && filename !== 'jobs.json.tmp')
102
+ return;
103
+ if (debounceTimer)
104
+ clearTimeout(debounceTimer);
105
+ debounceTimer = setTimeout(() => {
106
+ log('jobs.json changed, reconciling');
107
+ scheduler.reconcile();
108
+ log(`Reconcile done. ${scheduler.activeCount} tasks scheduled.`);
109
+ }, 500);
110
+ });
111
+ }
112
+ catch (err) {
113
+ const message = err instanceof Error ? err.message : String(err);
114
+ log(`Warning: Could not watch cron directory: ${message}. Changes won't be detected until restart.`);
115
+ }
116
+ // Graceful shutdown
117
+ const shutdown = (signal) => {
118
+ log(`Received ${signal}, shutting down`);
119
+ scheduler.stopAll();
120
+ try {
121
+ fs.unlinkSync(store_js_1.CronStore.pidFile);
122
+ }
123
+ catch { }
124
+ log('Daemon stopped');
125
+ process.exit(0);
126
+ };
127
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
128
+ process.on('SIGINT', () => shutdown('SIGINT'));
129
+ log('Daemon running');
130
+ }
131
+ main();
132
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/cron/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ export interface CronLogStep {
2
+ stepIndex: number;
3
+ timestamp: string;
4
+ text: string;
5
+ toolCalls: Array<{
6
+ toolName: string;
7
+ toolCallId: string;
8
+ args: Record<string, unknown>;
9
+ }>;
10
+ toolResults: Array<{
11
+ toolName: string;
12
+ toolCallId: string;
13
+ result: unknown;
14
+ }>;
15
+ usage: {
16
+ promptTokens: number;
17
+ completionTokens: number;
18
+ totalTokens: number;
19
+ };
20
+ finishReason: string;
21
+ }
22
+ export interface CronLogEntry {
23
+ runId: string;
24
+ jobId: string;
25
+ jobName: string;
26
+ prompt: string;
27
+ startedAt: string;
28
+ completedAt: string;
29
+ durationMs: number;
30
+ success: boolean;
31
+ error?: string;
32
+ finalOutput: string;
33
+ steps: CronLogStep[];
34
+ totalUsage: {
35
+ promptTokens: number;
36
+ completionTokens: number;
37
+ totalTokens: number;
38
+ };
39
+ }
40
+ export declare class CronLogStore {
41
+ constructor();
42
+ static get logsDir(): string;
43
+ private logPath;
44
+ appendEntry(entry: CronLogEntry): void;
45
+ getEntries(jobId: string, limit?: number, offset?: number): CronLogEntry[];
46
+ getEntry(jobId: string, runId: string): CronLogEntry | undefined;
47
+ listJobIds(): string[];
48
+ getEntryCount(jobId: string): number;
49
+ rotate(jobId: string, keep?: number): void;
50
+ deleteJobLogs(jobId: string): boolean;
51
+ }