@curie-agent/core 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 (54) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/src/channel-registry.d.ts +26 -0
  3. package/dist/src/channel-registry.d.ts.map +1 -0
  4. package/dist/src/channel-registry.js +100 -0
  5. package/dist/src/channel-registry.js.map +1 -0
  6. package/dist/src/channel-router.d.ts +28 -0
  7. package/dist/src/channel-router.d.ts.map +1 -0
  8. package/dist/src/channel-router.js +52 -0
  9. package/dist/src/channel-router.js.map +1 -0
  10. package/dist/src/cron-manager.d.ts +73 -0
  11. package/dist/src/cron-manager.d.ts.map +1 -0
  12. package/dist/src/cron-manager.js +322 -0
  13. package/dist/src/cron-manager.js.map +1 -0
  14. package/dist/src/event-bus.d.ts +105 -0
  15. package/dist/src/event-bus.d.ts.map +1 -0
  16. package/dist/src/event-bus.js +56 -0
  17. package/dist/src/event-bus.js.map +1 -0
  18. package/dist/src/heartbeat-delivery.d.ts +27 -0
  19. package/dist/src/heartbeat-delivery.d.ts.map +1 -0
  20. package/dist/src/heartbeat-delivery.js +37 -0
  21. package/dist/src/heartbeat-delivery.js.map +1 -0
  22. package/dist/src/heartbeat-executor.d.ts +35 -0
  23. package/dist/src/heartbeat-executor.d.ts.map +1 -0
  24. package/dist/src/heartbeat-executor.js +174 -0
  25. package/dist/src/heartbeat-executor.js.map +1 -0
  26. package/dist/src/index.d.ts +26 -0
  27. package/dist/src/index.d.ts.map +1 -0
  28. package/dist/src/index.js +15 -0
  29. package/dist/src/index.js.map +1 -0
  30. package/dist/src/permission.d.ts +21 -0
  31. package/dist/src/permission.d.ts.map +1 -0
  32. package/dist/src/permission.js +69 -0
  33. package/dist/src/permission.js.map +1 -0
  34. package/dist/src/reminder-parser.d.ts +12 -0
  35. package/dist/src/reminder-parser.d.ts.map +1 -0
  36. package/dist/src/reminder-parser.js +164 -0
  37. package/dist/src/reminder-parser.js.map +1 -0
  38. package/dist/src/session-store.d.ts +32 -0
  39. package/dist/src/session-store.d.ts.map +1 -0
  40. package/dist/src/session-store.js +112 -0
  41. package/dist/src/session-store.js.map +1 -0
  42. package/dist/src/settings.d.ts +45 -0
  43. package/dist/src/settings.d.ts.map +1 -0
  44. package/dist/src/settings.js +133 -0
  45. package/dist/src/settings.js.map +1 -0
  46. package/dist/src/telegram-gateway.d.ts +35 -0
  47. package/dist/src/telegram-gateway.d.ts.map +1 -0
  48. package/dist/src/telegram-gateway.js +145 -0
  49. package/dist/src/telegram-gateway.js.map +1 -0
  50. package/dist/src/turn-loop.d.ts +145 -0
  51. package/dist/src/turn-loop.d.ts.map +1 -0
  52. package/dist/src/turn-loop.js +393 -0
  53. package/dist/src/turn-loop.js.map +1 -0
  54. package/package.json +33 -0
@@ -0,0 +1,322 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ /** Human-readable label for a schedule type. */
5
+ export function scheduleLabel(type) {
6
+ return type.toUpperCase(); // TIMES, DAILY, WEEKLY, MONTHLY
7
+ }
8
+ const CRON_DIR = join(homedir(), '.curie-agent');
9
+ const CRON_FILE = join(CRON_DIR, 'cron.json');
10
+ function loadCronFile() {
11
+ if (existsSync(CRON_FILE)) {
12
+ try {
13
+ const parsed = JSON.parse(readFileSync(CRON_FILE, 'utf-8'));
14
+ if (typeof parsed === 'object' && parsed !== null && 'tasks' in parsed && Array.isArray(parsed.tasks)) {
15
+ return parsed;
16
+ }
17
+ }
18
+ catch {
19
+ // corrupt file — start fresh
20
+ }
21
+ }
22
+ return { version: 1, tasks: [] };
23
+ }
24
+ function saveCronFile(data) {
25
+ if (!existsSync(CRON_DIR)) {
26
+ const { mkdirSync } = require('node:fs');
27
+ mkdirSync(CRON_DIR, { recursive: true });
28
+ }
29
+ writeFileSync(CRON_FILE, JSON.stringify(data, null, 2), 'utf-8');
30
+ }
31
+ /** Parse "H:MM" into { hour, minute }. */
32
+ function parseTime(value) {
33
+ const match = value.match(/^(\d{1,2}):(\d{2})$/);
34
+ if (!match)
35
+ return null;
36
+ const hour = parseInt(match[1] ?? '0', 10);
37
+ const minute = parseInt(match[2] ?? '0', 10);
38
+ if (hour < 0 || hour > 23 || minute < 0 || minute > 59)
39
+ return null;
40
+ return { hour, minute };
41
+ }
42
+ /** Parse "day@H:MM" into { day, hour, minute }. */
43
+ function parseWeekly(value) {
44
+ const atIdx = value.indexOf('@');
45
+ if (atIdx < 0)
46
+ return null;
47
+ const dayStr = value.slice(0, atIdx).toLowerCase();
48
+ const timeStr = value.slice(atIdx + 1);
49
+ const dayNames = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
50
+ const day = dayNames.indexOf(dayStr);
51
+ if (day < 0)
52
+ return null;
53
+ const time = parseTime(timeStr);
54
+ if (!time)
55
+ return null;
56
+ return { day, ...time };
57
+ }
58
+ /** Parse "D@H:MM" into { dayOfMonth, hour, minute }. */
59
+ function parseMonthly(value) {
60
+ const atIdx = value.indexOf('@');
61
+ if (atIdx < 0)
62
+ return null;
63
+ const dayStr = value.slice(0, atIdx);
64
+ const dayOfMonth = parseInt(dayStr, 10);
65
+ if (isNaN(dayOfMonth) || dayOfMonth < 1 || dayOfMonth > 31)
66
+ return null;
67
+ const time = parseTime(value.slice(atIdx + 1));
68
+ if (!time)
69
+ return null;
70
+ return { dayOfMonth, ...time };
71
+ }
72
+ /** Compute the next fire time for a schedule. Returns epoch ms. */
73
+ export function computeNextFire(schedule, now) {
74
+ if (!schedule)
75
+ return now;
76
+ const { type, value } = schedule;
77
+ if (!value)
78
+ return now;
79
+ if (type === 'times') {
80
+ const tokens = value.split(',').map((s) => s.trim()).filter(Boolean);
81
+ const slots = [];
82
+ for (const token of tokens) {
83
+ const t = parseTime(token);
84
+ if (t)
85
+ slots.push(t);
86
+ }
87
+ if (slots.length === 0)
88
+ return now;
89
+ slots.sort((a, b) => a.hour * 60 + a.minute - (b.hour * 60 + b.minute));
90
+ const firstSlot = slots[0];
91
+ const base = new Date(now);
92
+ for (const slot of slots) {
93
+ const candidate = new Date(base);
94
+ candidate.setHours(slot.hour, slot.minute, 0, 0);
95
+ if (candidate.getTime() > now)
96
+ return candidate.getTime();
97
+ }
98
+ // All slots passed today — use first slot tomorrow
99
+ const tomorrow = new Date(base);
100
+ tomorrow.setDate(tomorrow.getDate() + 1);
101
+ tomorrow.setHours(firstSlot.hour, firstSlot.minute, 0, 0);
102
+ return tomorrow.getTime();
103
+ }
104
+ if (type === 'daily') {
105
+ const t = parseTime(value);
106
+ if (!t)
107
+ return now;
108
+ const next = new Date(now);
109
+ next.setHours(t.hour, t.minute, 0, 0);
110
+ if (next.getTime() <= now) {
111
+ next.setDate(next.getDate() + 1);
112
+ }
113
+ return next.getTime();
114
+ }
115
+ if (type === 'weekly') {
116
+ const w = parseWeekly(value);
117
+ if (!w)
118
+ return now;
119
+ const next = new Date(now);
120
+ next.setHours(w.hour, w.minute, 0, 0);
121
+ // Move to the correct weekday
122
+ while (next.getDay() !== w.day) {
123
+ next.setDate(next.getDate() + 1);
124
+ }
125
+ if (next.getTime() <= now) {
126
+ next.setDate(next.getDate() + 7);
127
+ }
128
+ return next.getTime();
129
+ }
130
+ if (type === 'monthly') {
131
+ const m = parseMonthly(value);
132
+ if (!m)
133
+ return now;
134
+ const next = new Date(now);
135
+ next.setDate(m.dayOfMonth);
136
+ next.setHours(m.hour, m.minute, 0, 0);
137
+ if (next.getTime() <= now) {
138
+ next.setMonth(next.getMonth() + 1);
139
+ if (next.getMonth() > 11) {
140
+ next.setFullYear(next.getFullYear() + 1);
141
+ }
142
+ }
143
+ return next.getTime();
144
+ }
145
+ return now;
146
+ }
147
+ /**
148
+ * Evaluate all four heartbeat schedule settings and return the one
149
+ * with the earliest next fire time. Returns null if all are empty.
150
+ */
151
+ export function pickNextSchedule(settings, now) {
152
+ const reference = now ?? Date.now();
153
+ const candidates = [];
154
+ // Tie-break priority: times > daily > weekly > monthly
155
+ const priority = { times: 0, daily: 1, weekly: 2, monthly: 3 };
156
+ const schedules = [
157
+ { type: 'times', value: settings.HEARTBEAT_TIMES ?? '' },
158
+ { type: 'daily', value: settings.HEARTBEAT_DAILY ?? '' },
159
+ { type: 'weekly', value: settings.HEARTBEAT_WEEKLY ?? '' },
160
+ { type: 'monthly', value: settings.HEARTBEAT_MONTHLY ?? '' },
161
+ ];
162
+ for (const { type, value } of schedules) {
163
+ if (!value)
164
+ continue;
165
+ const nextFire = computeNextFire({ type, value }, reference);
166
+ candidates.push({ type, value, nextFire });
167
+ }
168
+ if (candidates.length === 0)
169
+ return null;
170
+ candidates.sort((a, b) => {
171
+ const diff = a.nextFire - b.nextFire;
172
+ if (diff !== 0)
173
+ return diff;
174
+ return priority[a.type] - priority[b.type];
175
+ });
176
+ const best = candidates[0];
177
+ return { type: best.type, value: best.value };
178
+ }
179
+ export class CronManager {
180
+ data;
181
+ checkerTimer = null;
182
+ onReminderFired = null;
183
+ ttlMs;
184
+ constructor(ttlMs) {
185
+ this.ttlMs = ttlMs ?? (7 * 24 * 60 * 60 * 1000); // 7 days default
186
+ this.data = loadCronFile();
187
+ this.pruneOld(Date.now() - this.ttlMs);
188
+ }
189
+ load() {
190
+ this.data = loadCronFile();
191
+ return this.data;
192
+ }
193
+ save() {
194
+ saveCronFile(this.data);
195
+ }
196
+ createReminder(message, scheduledAt) {
197
+ const task = {
198
+ id: crypto.randomUUID(),
199
+ type: 'reminder',
200
+ scheduledAt,
201
+ message,
202
+ status: 'pending',
203
+ createdAt: Date.now(),
204
+ };
205
+ this.data.tasks.push(task);
206
+ this.save();
207
+ return task;
208
+ }
209
+ cancelReminder(id) {
210
+ const task = this.data.tasks.find((t) => t.id === id);
211
+ if (!task)
212
+ return false;
213
+ task.status = 'cancelled';
214
+ this.save();
215
+ return true;
216
+ }
217
+ listReminders(filter) {
218
+ if (!filter)
219
+ return [...this.data.tasks];
220
+ return this.data.tasks.filter((t) => t.status === filter);
221
+ }
222
+ clearCompleted() {
223
+ const before = this.data.tasks.length;
224
+ this.data.tasks = this.data.tasks.filter((t) => t.status !== 'fired');
225
+ const removed = before - this.data.tasks.length;
226
+ if (removed > 0) {
227
+ this.save();
228
+ }
229
+ return removed;
230
+ }
231
+ /** Remove fired/cancelled tasks older than the cutoff. Pending tasks always kept. */
232
+ pruneOld(cutoff) {
233
+ const before = this.data.tasks.length;
234
+ this.data.tasks = this.data.tasks.filter((t) => t.status === 'pending' || t.createdAt >= cutoff);
235
+ const removed = before - this.data.tasks.length;
236
+ if (removed > 0) {
237
+ this.save();
238
+ }
239
+ return removed;
240
+ }
241
+ createHeartbeat(message, schedule) {
242
+ const now = Date.now();
243
+ const task = {
244
+ id: crypto.randomUUID(),
245
+ type: 'heartbeat',
246
+ scheduledAt: computeNextFire(schedule, now),
247
+ message,
248
+ schedule,
249
+ status: 'pending',
250
+ createdAt: now,
251
+ };
252
+ this.data.tasks.push(task);
253
+ this.save();
254
+ return task;
255
+ }
256
+ /** Update the schedule of all pending heartbeat tasks matching the given schedule type. */
257
+ updateHeartbeatSchedule(scheduleType, value) {
258
+ const now = Date.now();
259
+ const newSchedule = { type: scheduleType, value };
260
+ let changed = false;
261
+ for (const task of this.data.tasks) {
262
+ if (task.type === 'heartbeat' && task.status === 'pending' && task.schedule?.type === scheduleType) {
263
+ task.schedule = newSchedule;
264
+ task.scheduledAt = computeNextFire(newSchedule, now);
265
+ changed = true;
266
+ }
267
+ }
268
+ if (changed)
269
+ this.save();
270
+ }
271
+ /**
272
+ * Find the unified heartbeat task and re-evaluate all four schedule
273
+ * settings to pick the next earliest fire time. Called after a
274
+ * schedule setting changes or after a heartbeat fires.
275
+ */
276
+ rescheduleFromSettings(settings, now) {
277
+ const ref = now ?? Date.now();
278
+ const picked = pickNextSchedule(settings, ref);
279
+ if (!picked)
280
+ return;
281
+ const task = this.data.tasks.find((t) => t.type === 'heartbeat' && t.status === 'pending');
282
+ if (!task)
283
+ return;
284
+ task.schedule = picked;
285
+ task.scheduledAt = computeNextFire(picked, ref);
286
+ this.save();
287
+ }
288
+ startChecker(intervalMs = 60_000, callback) {
289
+ this.onReminderFired = callback;
290
+ this.checkerTimer = setInterval(() => {
291
+ this.data = loadCronFile();
292
+ this.pruneOld(Date.now() - this.ttlMs);
293
+ const now = Date.now();
294
+ const pending = this.data.tasks.filter((t) => t.status === 'pending' && t.scheduledAt <= now);
295
+ for (const task of pending) {
296
+ const isHeartbeat = task.type === 'heartbeat';
297
+ // Mark reminders as fired so they don't re-fire.
298
+ // Leave heartbeats as pending — the caller will call
299
+ // rescheduleFromSettings() which searches for pending heartbeats.
300
+ if (!isHeartbeat) {
301
+ task.status = 'fired';
302
+ }
303
+ callback(task);
304
+ // Don't re-schedule heartbeats here — let the caller (cli.tsx)
305
+ // call rescheduleFromSettings() with all four schedule settings
306
+ }
307
+ if (pending.length > 0) {
308
+ this.save();
309
+ }
310
+ }, intervalMs);
311
+ }
312
+ stopChecker() {
313
+ if (this.checkerTimer) {
314
+ clearInterval(this.checkerTimer);
315
+ this.checkerTimer = null;
316
+ }
317
+ }
318
+ get pendingCount() {
319
+ return this.data.tasks.filter((t) => t.status === 'pending').length;
320
+ }
321
+ }
322
+ //# sourceMappingURL=cron-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-manager.js","sourceRoot":"","sources":["../../src/cron-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ export type Event = {
2
+ type: 'user-prompt';
3
+ id: string;
4
+ text: string;
5
+ cwd: string;
6
+ timestamp: number;
7
+ } | {
8
+ type: 'assistant-delta';
9
+ id: string;
10
+ text: string;
11
+ timestamp: number;
12
+ } | {
13
+ type: 'assistant-stop';
14
+ id: string;
15
+ timestamp: number;
16
+ } | {
17
+ type: 'tool-call';
18
+ id: string;
19
+ toolCallId: string;
20
+ name: string;
21
+ input: Record<string, unknown>;
22
+ thoughtSignature?: string;
23
+ timestamp: number;
24
+ } | {
25
+ type: 'tool-result';
26
+ id: string;
27
+ toolCallId: string;
28
+ output: unknown;
29
+ error?: string;
30
+ timestamp: number;
31
+ } | {
32
+ type: 'approval-request';
33
+ id: string;
34
+ toolCallId: string;
35
+ name: string;
36
+ input: Record<string, unknown>;
37
+ decision?: 'allow' | 'deny' | 'ask';
38
+ timestamp: number;
39
+ } | {
40
+ type: 'approval-decision';
41
+ id: string;
42
+ toolCallId: string;
43
+ decision: 'allow' | 'deny';
44
+ by?: string;
45
+ timestamp: number;
46
+ } | {
47
+ type: 'usage';
48
+ id: string;
49
+ inputTokens: number;
50
+ outputTokens: number;
51
+ cacheReadTokens?: number;
52
+ cacheWriteTokens?: number;
53
+ timestamp: number;
54
+ } | {
55
+ type: 'error';
56
+ id: string;
57
+ message: string;
58
+ code?: string;
59
+ timestamp: number;
60
+ } | {
61
+ type: 'session-start';
62
+ id: string;
63
+ model: string;
64
+ provider: string;
65
+ cwd: string;
66
+ timestamp: number;
67
+ } | {
68
+ type: 'session-stop';
69
+ id: string;
70
+ reason: string;
71
+ timestamp: number;
72
+ } | {
73
+ type: 'hook';
74
+ id: string;
75
+ phase: string;
76
+ name: string;
77
+ result?: string;
78
+ error?: string;
79
+ timestamp: number;
80
+ } | {
81
+ type: 'status';
82
+ id: string;
83
+ message: string;
84
+ spinner?: boolean;
85
+ timestamp: number;
86
+ } | {
87
+ type: 'session-resumed';
88
+ id: string;
89
+ turnsRecovered: number;
90
+ timestamp: number;
91
+ };
92
+ export type EventType = Event['type'];
93
+ export declare class EventBus {
94
+ private listeners;
95
+ private onceListeners;
96
+ private _history;
97
+ subscribe<T extends Event>(type: T['type'], fn: (event: T) => void): () => void;
98
+ unsubscribe<T extends Event>(type: T['type'], fn: (event: T) => void): void;
99
+ once<T extends Event>(type: T['type'], fn: (event: T) => void): () => void;
100
+ emit<T extends Event>(event: T): void;
101
+ emitAll(events: Event[]): void;
102
+ history(): Event[];
103
+ clear(): void;
104
+ }
105
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/event-bus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ function filterEvent(events, type) {
2
+ return events.filter((h) => {
3
+ const fn = h;
4
+ return true;
5
+ });
6
+ }
7
+ export class EventBus {
8
+ listeners = new Map();
9
+ onceListeners = new Map();
10
+ _history = [];
11
+ subscribe(type, fn) {
12
+ if (!this.listeners.has(type)) {
13
+ this.listeners.set(type, new Set());
14
+ }
15
+ this.listeners.get(type).add(fn);
16
+ return () => this.unsubscribe(type, fn);
17
+ }
18
+ unsubscribe(type, fn) {
19
+ this.listeners.get(type)?.delete(fn);
20
+ }
21
+ once(type, fn) {
22
+ if (!this.onceListeners.has(type)) {
23
+ this.onceListeners.set(type, new Set());
24
+ }
25
+ this.onceListeners.get(type).add(fn);
26
+ return () => this.onceListeners.get(type)?.delete(fn);
27
+ }
28
+ emit(event) {
29
+ this._history.push(event);
30
+ const type = event.type;
31
+ for (const fn of this.listeners.get(type) ?? []) {
32
+ fn(event);
33
+ }
34
+ const onceSet = this.onceListeners.get(type);
35
+ if (onceSet) {
36
+ for (const fn of onceSet) {
37
+ fn(event);
38
+ }
39
+ this.onceListeners.delete(type);
40
+ }
41
+ }
42
+ emitAll(events) {
43
+ for (const event of events) {
44
+ this.emit(event);
45
+ }
46
+ }
47
+ history() {
48
+ return this._history;
49
+ }
50
+ clear() {
51
+ this.listeners.clear();
52
+ this.onceListeners.clear();
53
+ this._history = [];
54
+ }
55
+ }
56
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/event-bus.ts"],"names":[],"mappings":"AAoBA,SAAS,WAAW,CAAkB,MAAwB,EAAE,IAAe;IAC7E,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACzB,MAAM,EAAE,GAAG,CAAe,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC,CAAiB,CAAC;AACrB,CAAC;AAED,MAAM,OAAO,QAAQ;IACX,SAAS,GAAG,IAAI,GAAG,EAAkC,CAAC;IACtD,aAAa,GAAG,IAAI,GAAG,EAAkC,CAAC;IAC1D,QAAQ,GAAY,EAAE,CAAC;IAE/B,SAAS,CAAkB,IAAe,EAAE,EAAsB;QAChE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,GAAG,CAAC,EAAoB,CAAC,CAAC;QACpD,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAoB,CAAC,CAAC;IAC5D,CAAC;IAED,WAAW,CAAkB,IAAe,EAAE,EAAsB;QAClE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAoB,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CAAkB,IAAe,EAAE,EAAsB;QAC3D,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,GAAG,CAAC,EAAoB,CAAC,CAAC;QACxD,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAoB,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,CAAkB,KAAQ;QAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAExB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAChD,EAAE,CAAC,KAAK,CAAC,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;gBACzB,EAAE,CAAC,KAAK,CAAC,CAAC;YACZ,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,MAAe;QACrB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ import type { TelegramGateway } from './telegram-gateway.js';
2
+ export interface HeartbeatDeliveryConfig {
3
+ /** Telegram chatId to send to. */
4
+ chatId: string;
5
+ /** TelegramGateway instance for sending messages. */
6
+ telegramGateway: TelegramGateway;
7
+ /** Path to write output file. Default: ~/.curie-agent/heartbeat-brief-{date}.md */
8
+ filePath?: string;
9
+ }
10
+ /**
11
+ * Routes HeartbeatExecutor output to Telegram.
12
+ */
13
+ export declare class HeartbeatDelivery {
14
+ private config;
15
+ constructor(config: HeartbeatDeliveryConfig);
16
+ deliver(text: string): Promise<void>;
17
+ /**
18
+ * Format a Heartbeat Brief into a markdown-ready string.
19
+ */
20
+ static formatBrief(result: {
21
+ text: string;
22
+ toolCalls: number;
23
+ errors: string[];
24
+ sessionId: string;
25
+ }): string;
26
+ }
27
+ //# sourceMappingURL=heartbeat-delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat-delivery.d.ts","sourceRoot":"","sources":["../../src/heartbeat-delivery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAI7D,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,eAAe,EAAE,eAAe,CAAC;IACjC,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,uBAAuB;IAGnC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1C;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,MAAM;CAkBX"}
@@ -0,0 +1,37 @@
1
+ const TELEGRAM_MAX_LENGTH = 4096;
2
+ /**
3
+ * Routes HeartbeatExecutor output to Telegram.
4
+ */
5
+ export class HeartbeatDelivery {
6
+ config;
7
+ constructor(config) {
8
+ this.config = config;
9
+ }
10
+ async deliver(text) {
11
+ // Truncate to Telegram's 4096 char limit
12
+ const truncated = text.length > TELEGRAM_MAX_LENGTH
13
+ ? text.slice(0, TELEGRAM_MAX_LENGTH - 3) + '...'
14
+ : text;
15
+ await this.config.telegramGateway.sendMessage(this.config.chatId, truncated);
16
+ }
17
+ /**
18
+ * Format a Heartbeat Brief into a markdown-ready string.
19
+ */
20
+ static formatBrief(result) {
21
+ const lines = [
22
+ `*Heartbeat Brief*`,
23
+ '',
24
+ result.text,
25
+ '',
26
+ `_Tool calls: ${result.toolCalls} | Session: ${result.sessionId.slice(0, 8)}_`,
27
+ ];
28
+ if (result.errors.length > 0) {
29
+ lines.push('', '*Warnings:*');
30
+ for (const err of result.errors) {
31
+ lines.push(`- ${err}`);
32
+ }
33
+ }
34
+ return lines.join('\n');
35
+ }
36
+ }
37
+ //# sourceMappingURL=heartbeat-delivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat-delivery.js","sourceRoot":"","sources":["../../src/heartbeat-delivery.ts"],"names":[],"mappings":"AAKA,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAWjC;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAElB;IADV,YACU,MAA+B;QAA/B,WAAM,GAAN,MAAM,CAAyB;IACtC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,IAAY;QACxB,yCAAyC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,mBAAmB;YACjD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,GAAG,CAAC,CAAC,GAAG,KAAK;YAChD,CAAC,CAAC,IAAI,CAAC;QAET,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,WAAW,CAC3C,IAAI,CAAC,MAAM,CAAC,MAAM,EAClB,SAAS,CACV,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,MAKlB;QACC,MAAM,KAAK,GAAG;YACZ,mBAAmB;YACnB,EAAE;YACF,MAAM,CAAC,IAAI;YACX,EAAE;YACF,gBAAgB,MAAM,CAAC,SAAS,eAAe,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;SAC/E,CAAC;QAEF,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;YAC9B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ import { type ReasoningEffort, type ProviderStream, type Tool } from './turn-loop.js';
2
+ import type { HopperSettings } from './settings.js';
3
+ import type { ScheduleType } from './cron-manager.js';
4
+ export interface HeartbeatExecutorConfig {
5
+ provider: ProviderStream;
6
+ model: string;
7
+ tools: Tool[];
8
+ cwd: string;
9
+ settings: HopperSettings;
10
+ effort?: ReasoningEffort;
11
+ /** Max turns for the tool-use loop (default 30). */
12
+ maxTurns?: number;
13
+ /** Which HEARTBEAT.md section to execute (times|daily|weekly|monthly). */
14
+ scheduleType?: ScheduleType;
15
+ }
16
+ export interface HeartbeatResult {
17
+ sessionId: string;
18
+ text: string;
19
+ toolCalls: number;
20
+ usage: {
21
+ inputTokens: number;
22
+ outputTokens: number;
23
+ };
24
+ errors: string[];
25
+ }
26
+ export declare class HeartbeatExecutor {
27
+ private config;
28
+ private heartbeatDir;
29
+ constructor(config: HeartbeatExecutorConfig);
30
+ execute(): Promise<HeartbeatResult>;
31
+ private readHeartbeatMd;
32
+ private gatherContext;
33
+ private buildPrompt;
34
+ }
35
+ //# sourceMappingURL=heartbeat-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat-executor.d.ts","sourceRoot":"","sources":["../../src/heartbeat-executor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAY,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA8FD,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,YAAY,CAAS;gBAET,MAAM,EAAE,uBAAuB;IAI7C,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IA+BzC,OAAO,CAAC,eAAe;YAQT,aAAa;IAoC3B,OAAO,CAAC,WAAW;CA6BpB"}