@curie-agent/core 0.2.3 → 0.2.5

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 (80) hide show
  1. package/LICENSE +179 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/channel-router.js +1 -1
  4. package/dist/src/channel-router.js.map +1 -1
  5. package/dist/src/context.d.ts +11 -0
  6. package/dist/src/context.d.ts.map +1 -0
  7. package/dist/src/context.js +63 -0
  8. package/dist/src/context.js.map +1 -0
  9. package/dist/src/cron-manager.d.ts +27 -8
  10. package/dist/src/cron-manager.d.ts.map +1 -1
  11. package/dist/src/cron-manager.js +121 -33
  12. package/dist/src/cron-manager.js.map +1 -1
  13. package/dist/src/event-bus.d.ts +71 -0
  14. package/dist/src/event-bus.d.ts.map +1 -1
  15. package/dist/src/event-bus.js.map +1 -1
  16. package/dist/src/heartbeat-delivery.d.ts +2 -0
  17. package/dist/src/heartbeat-delivery.d.ts.map +1 -1
  18. package/dist/src/heartbeat-delivery.js +20 -3
  19. package/dist/src/heartbeat-delivery.js.map +1 -1
  20. package/dist/src/heartbeat-executor.d.ts +36 -2
  21. package/dist/src/heartbeat-executor.d.ts.map +1 -1
  22. package/dist/src/heartbeat-executor.js +32 -40
  23. package/dist/src/heartbeat-executor.js.map +1 -1
  24. package/dist/src/identity-files.d.ts +18 -0
  25. package/dist/src/identity-files.d.ts.map +1 -0
  26. package/dist/src/identity-files.js +198 -0
  27. package/dist/src/identity-files.js.map +1 -0
  28. package/dist/src/index.d.ts +18 -4
  29. package/dist/src/index.d.ts.map +1 -1
  30. package/dist/src/index.js +12 -2
  31. package/dist/src/index.js.map +1 -1
  32. package/dist/src/pricing.d.ts +29 -0
  33. package/dist/src/pricing.d.ts.map +1 -0
  34. package/dist/src/pricing.js +85 -0
  35. package/dist/src/pricing.js.map +1 -0
  36. package/dist/src/safety/path-guard.d.ts +7 -3
  37. package/dist/src/safety/path-guard.d.ts.map +1 -1
  38. package/dist/src/safety/path-guard.js +14 -5
  39. package/dist/src/safety/path-guard.js.map +1 -1
  40. package/dist/src/session-store.d.ts +3 -1
  41. package/dist/src/session-store.d.ts.map +1 -1
  42. package/dist/src/session-store.js +24 -1
  43. package/dist/src/session-store.js.map +1 -1
  44. package/dist/src/settings.d.ts +91 -1
  45. package/dist/src/settings.d.ts.map +1 -1
  46. package/dist/src/settings.js +353 -82
  47. package/dist/src/settings.js.map +1 -1
  48. package/dist/src/subagent-executor.d.ts +68 -0
  49. package/dist/src/subagent-executor.d.ts.map +1 -0
  50. package/dist/src/subagent-executor.js +289 -0
  51. package/dist/src/subagent-executor.js.map +1 -0
  52. package/dist/src/task-executor.d.ts +31 -0
  53. package/dist/src/task-executor.d.ts.map +1 -0
  54. package/dist/src/task-executor.js +91 -0
  55. package/dist/src/task-executor.js.map +1 -0
  56. package/dist/src/task-manager.d.ts +83 -0
  57. package/dist/src/task-manager.d.ts.map +1 -0
  58. package/dist/src/task-manager.js +304 -0
  59. package/dist/src/task-manager.js.map +1 -0
  60. package/dist/src/task-migration.d.ts +10 -0
  61. package/dist/src/task-migration.d.ts.map +1 -0
  62. package/dist/src/task-migration.js +144 -0
  63. package/dist/src/task-migration.js.map +1 -0
  64. package/dist/src/task-summary.d.ts +7 -0
  65. package/dist/src/task-summary.d.ts.map +1 -0
  66. package/dist/src/task-summary.js +34 -0
  67. package/dist/src/task-summary.js.map +1 -0
  68. package/dist/src/token-monitor.d.ts +50 -0
  69. package/dist/src/token-monitor.d.ts.map +1 -0
  70. package/dist/src/token-monitor.js +119 -0
  71. package/dist/src/token-monitor.js.map +1 -0
  72. package/dist/src/turn-loop.d.ts +7 -1
  73. package/dist/src/turn-loop.d.ts.map +1 -1
  74. package/dist/src/turn-loop.js +42 -11
  75. package/dist/src/turn-loop.js.map +1 -1
  76. package/dist/src/unified-task.d.ts +76 -0
  77. package/dist/src/unified-task.d.ts.map +1 -0
  78. package/dist/src/unified-task.js +196 -0
  79. package/dist/src/unified-task.js.map +1 -0
  80. package/package.json +10 -10
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Unified task manager — replaces CronManager as the primary task store.
3
+ * Manages tasks across both personal (~/.curie-agent/tasks.json) and project (<cwd>/tasks.json) scopes.
4
+ */
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { dirname, join } from 'node:path';
8
+ import { scheduleLabel, createTaskDefaults, generateTaskId, taskTimestamp, pickNextSchedule, computeNextFire } from './unified-task.js';
9
+ // ---------------------------------------------------------------------------
10
+ // Constants
11
+ // ---------------------------------------------------------------------------
12
+ const DEFAULT_FILE = join(homedir(), '.curie-agent', 'tasks.json');
13
+ const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
14
+ // ---------------------------------------------------------------------------
15
+ // File I/O helpers
16
+ // ---------------------------------------------------------------------------
17
+ function loadTasksFile(filePath) {
18
+ if (existsSync(filePath)) {
19
+ try {
20
+ const parsed = JSON.parse(readFileSync(filePath, 'utf-8'));
21
+ if (typeof parsed === 'object' && parsed !== null && 'tasks' in parsed && Array.isArray(parsed.tasks)) {
22
+ return parsed;
23
+ }
24
+ }
25
+ catch {
26
+ /* corrupt — start fresh */
27
+ }
28
+ }
29
+ return { $schema: 'tasks.schema.json', version: 1, tasks: [] };
30
+ }
31
+ function saveTasksFile(data, filePath) {
32
+ const dir = dirname(filePath);
33
+ if (!existsSync(dir)) {
34
+ mkdirSync(dir, { recursive: true });
35
+ }
36
+ writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // TaskManager class
40
+ // ---------------------------------------------------------------------------
41
+ export class TaskManager {
42
+ data;
43
+ /** TTL for pruning completed tasks. */
44
+ ttlMs;
45
+ /** File path for persistence. */
46
+ filePath;
47
+ /** Set of task IDs currently being executed (prevents re-firing). */
48
+ executing = new Set();
49
+ constructor(optTtlOrPath, optFilePath) {
50
+ if (typeof optTtlOrPath === 'string') {
51
+ this.filePath = optTtlOrPath;
52
+ this.ttlMs = DEFAULT_TTL_MS;
53
+ }
54
+ else {
55
+ this.ttlMs = optTtlOrPath ?? DEFAULT_TTL_MS;
56
+ this.filePath = optFilePath ?? DEFAULT_FILE;
57
+ }
58
+ this.data = loadTasksFile(this.filePath);
59
+ this.pruneOld(Date.now() - this.ttlMs);
60
+ }
61
+ /** Reload the file from disk. */
62
+ load() {
63
+ this.data = loadTasksFile(this.filePath);
64
+ return this.data;
65
+ }
66
+ /** Persist to disk. */
67
+ save() {
68
+ saveTasksFile(this.data, this.filePath);
69
+ }
70
+ // -----------------------------------------------------------------------
71
+ // Creation
72
+ // -----------------------------------------------------------------------
73
+ /** Create a new task with the given mode and scope. */
74
+ create(options) {
75
+ const defaults = createTaskDefaults(options.mode, options.scope);
76
+ const task = {
77
+ id: generateTaskId(),
78
+ title: options.title,
79
+ description: options.description ?? '',
80
+ status: 'scheduled_at' in options && options.scheduled_at ? (options.mode === 'manual' ? 'todo' : 'pending') : defaults.status,
81
+ priority: options.priority ?? 'medium',
82
+ tags: options.tags ?? [],
83
+ mode: options.mode,
84
+ scheduled_at: options.scheduled_at,
85
+ frequency: options.frequency ?? null,
86
+ scope: options.scope,
87
+ metadata: options.metadata,
88
+ order: this.data.tasks.length,
89
+ created_at: taskTimestamp(),
90
+ completed_at: undefined,
91
+ };
92
+ if (task.status === 'done' || task.status === 'canceled') {
93
+ task.completed_at = taskTimestamp();
94
+ }
95
+ this.data.tasks.push(task);
96
+ this.save();
97
+ return task;
98
+ }
99
+ // -----------------------------------------------------------------------
100
+ // Status updates
101
+ // -----------------------------------------------------------------------
102
+ /** Update a task's status and set completed_at if terminal. */
103
+ updateTaskStatus(id, status) {
104
+ const task = this.findTask(id);
105
+ if (!task)
106
+ return false;
107
+ const oldStatus = task.status;
108
+ task.status = status;
109
+ const terminalStatuses = ['done', 'canceled', 'completed', 'failed'];
110
+ if (terminalStatuses.includes(status)) {
111
+ task.completed_at = taskTimestamp();
112
+ }
113
+ // For recurring auto tasks with frequency, reset to pending instead of done
114
+ if (task.frequency && status === 'done') {
115
+ task.status = 'pending';
116
+ delete task.completed_at;
117
+ }
118
+ this.save();
119
+ return true;
120
+ }
121
+ /** Advance through the manual task lifecycle (todo → in_progress → done). */
122
+ setTaskStatus(id, status) {
123
+ return this.updateTaskStatus(id, status);
124
+ }
125
+ // -----------------------------------------------------------------------
126
+ // Query
127
+ // -----------------------------------------------------------------------
128
+ /** Find a single task by ID. */
129
+ findTask(id) {
130
+ return this.data.tasks.find((t) => t.id === id);
131
+ }
132
+ /** List tasks with optional filters. */
133
+ list(options) {
134
+ let tasks = [...this.data.tasks];
135
+ if (options?.status)
136
+ tasks = tasks.filter((t) => t.status === options.status);
137
+ if (options?.mode)
138
+ tasks = tasks.filter((t) => t.mode === options.mode);
139
+ if (options?.scope)
140
+ tasks = tasks.filter((t) => t.scope === options.scope);
141
+ if (options?.priority)
142
+ tasks = tasks.filter((t) => t.priority === options.priority);
143
+ // Sort: active first (backlog/todo/in_progress/pending), then done/canceled
144
+ const activeStatuses = new Set(['backlog', 'todo', 'in_progress', 'pending']);
145
+ tasks.sort((a, b) => {
146
+ const aActive = activeStatuses.has(a.status) ? 0 : 1;
147
+ const bActive = activeStatuses.has(b.status) ? 0 : 1;
148
+ if (aActive !== bActive)
149
+ return aActive - bActive;
150
+ return a.order - b.order;
151
+ });
152
+ return tasks;
153
+ }
154
+ /** Get pending scheduled tasks that are due (mode=auto or notify with scheduled_at <= now). */
155
+ getNextTasks(now) {
156
+ const reference = now ?? Date.now();
157
+ return this.data.tasks.filter((t) => {
158
+ if (t.status !== 'pending')
159
+ return false;
160
+ if (!t.scheduled_at)
161
+ return false;
162
+ if (this.executing.has(t.id))
163
+ return false;
164
+ return t.scheduled_at <= reference;
165
+ });
166
+ }
167
+ // -----------------------------------------------------------------------
168
+ // Lifecycle helpers (for daemon integration)
169
+ // -----------------------------------------------------------------------
170
+ /** Mark a task as currently executing. */
171
+ markExecuting(id) {
172
+ const task = this.findTask(id);
173
+ if (!task)
174
+ return false;
175
+ task.status = 'executing';
176
+ this.executing.add(id);
177
+ this.save();
178
+ return true;
179
+ }
180
+ /** Clear executing flag for a task. */
181
+ clearExecuting(id) {
182
+ this.executing.delete(id);
183
+ }
184
+ // -----------------------------------------------------------------------
185
+ // Deletion
186
+ // -----------------------------------------------------------------------
187
+ /** Cancel (soft-delete) a pending/fired task. */
188
+ cancelTask(id) {
189
+ const task = this.findTask(id);
190
+ if (!task)
191
+ return false;
192
+ task.status = 'canceled';
193
+ task.completed_at = taskTimestamp();
194
+ this.save();
195
+ return true;
196
+ }
197
+ /** Remove completed/fired/failed tasks (hard-delete). */
198
+ clearCompleted() {
199
+ const before = this.data.tasks.length;
200
+ this.data.tasks = this.data.tasks.filter((t) => t.status !== 'done' && t.status !== 'canceled' && t.status !== 'completed' && t.status !== 'failed');
201
+ const removed = before - this.data.tasks.length;
202
+ if (removed > 0) {
203
+ // Renormalize orders after removal
204
+ this.renormalizeOrders();
205
+ this.save();
206
+ }
207
+ return removed;
208
+ }
209
+ /** Remove a task permanently. */
210
+ removeTask(id) {
211
+ const idx = this.data.tasks.findIndex((t) => t.id === id);
212
+ if (idx === -1)
213
+ return false;
214
+ this.data.tasks.splice(idx, 1);
215
+ this.renormalizeOrders();
216
+ this.save();
217
+ return true;
218
+ }
219
+ /** Renormalize the `order` field for all tasks in scope. */
220
+ renormalizeOrders() {
221
+ let order = 0;
222
+ for (const task of this.data.tasks) {
223
+ task.order = order++;
224
+ }
225
+ }
226
+ // -----------------------------------------------------------------------
227
+ // Pruning
228
+ // -----------------------------------------------------------------------
229
+ /** Remove completed tasks older than the cutoff. Pending/pending-like tasks always kept. */
230
+ pruneOld(cutoff) {
231
+ const before = this.data.tasks.length;
232
+ this.data.tasks = this.data.tasks.filter((t) => t.status === 'pending' || (t.scheduled_at && t.scheduled_at > cutoff) || t.created_at > new Date(cutoff).toISOString());
233
+ // Actually, prune by timestamp: keep pending tasks forever, remove old completed ones
234
+ this.data.tasks = this.data.tasks.filter((t) => {
235
+ if (t.status === 'pending')
236
+ return true;
237
+ if (!t.completed_at)
238
+ return t.created_at > new Date(cutoff).toISOString();
239
+ const completedTime = new Date(t.completed_at).getTime();
240
+ return completedTime >= cutoff;
241
+ });
242
+ const removed = before - this.data.tasks.length;
243
+ if (removed > 0) {
244
+ this.renormalizeOrders();
245
+ this.save();
246
+ }
247
+ return removed;
248
+ }
249
+ /** Count of pending tasks. */
250
+ get pendingCount() {
251
+ return this.data.tasks.filter((t) => t.status === 'pending').length;
252
+ }
253
+ // -----------------------------------------------------------------------
254
+ // Heartbeat helpers
255
+ // -----------------------------------------------------------------------
256
+ /** Check if a task is a recurring heartbeat (auto mode with frequency). */
257
+ isHeartbeat(task) {
258
+ return task.mode === 'auto' && task.frequency !== null;
259
+ }
260
+ /** Get all pending heartbeat tasks. */
261
+ getHeartbeats() {
262
+ return this.data.tasks.filter((t) => t.mode === 'auto' && t.frequency !== null && t.status === 'pending');
263
+ }
264
+ // -----------------------------------------------------------------------
265
+ // Heartbeat schedule management
266
+ // -----------------------------------------------------------------------
267
+ /**
268
+ * Evaluate all five heartbeat schedule settings and ensure exactly one
269
+ * pending auto+frequency task exists in the store. Called after settings change.
270
+ */
271
+ rescheduleFromSettings(settings, now) {
272
+ const ref = now ?? Date.now();
273
+ const picked = pickNextSchedule(settings, ref);
274
+ if (!picked)
275
+ return;
276
+ // Find existing heartbeat task for this schedule type
277
+ let existing = this.getHeartbeats().find(t => t.frequency?.type === picked.type);
278
+ if (existing) {
279
+ existing.frequency = picked;
280
+ existing.scheduled_at = computeNextFire(picked, ref);
281
+ this.save();
282
+ }
283
+ else {
284
+ this.create({
285
+ title: `Heartbeat: ${scheduleLabel(picked.type)}`,
286
+ mode: 'auto',
287
+ scope: 'personal',
288
+ scheduled_at: computeNextFire(picked, ref),
289
+ frequency: picked,
290
+ });
291
+ }
292
+ }
293
+ /** Cancel all pending heartbeat tasks. Returns count cancelled. */
294
+ cancelAllHeartbeats() {
295
+ const hbs = this.getHeartbeats();
296
+ let count = 0;
297
+ for (const hb of hbs) {
298
+ this.updateTaskStatus(hb.id, 'canceled');
299
+ count++;
300
+ }
301
+ return count;
302
+ }
303
+ }
304
+ //# sourceMappingURL=task-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-manager.js","sourceRoot":"","sources":["../../src/task-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Migration utility: reads old todo.json and cron.json, writes tasks.json.
3
+ * Runs once — if tasks.json already exists, migration is skipped.
4
+ */
5
+ import type { TasksFile } from './unified-task.js';
6
+ /**
7
+ * Main migration: merges todo.json and cron.json into tasks.json.
8
+ */
9
+ export declare function migrateTasks(oldTodoPath?: string, oldCronPath?: string, newTasksPath?: string): TasksFile | null;
10
+ //# sourceMappingURL=task-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-migration.d.ts","sourceRoot":"","sources":["../../src/task-migration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAkD,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAqGnG;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CA0EhH"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Migration utility: reads old todo.json and cron.json, writes tasks.json.
3
+ * Runs once — if tasks.json already exists, migration is skipped.
4
+ */
5
+ import { readFileSync, writeFileSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { join } from 'node:path';
8
+ import { taskTimestamp } from './unified-task.js';
9
+ // ---------------------------------------------------------------------------
10
+ // Status mappings
11
+ // ---------------------------------------------------------------------------
12
+ /** Map old todo.json status → UnifiedTask status. */
13
+ function mapTodoStatus(status) {
14
+ switch (status) {
15
+ case 'backlog': return 'backlog';
16
+ case 'todo': return 'todo';
17
+ case 'in_progress': return 'in_progress';
18
+ case 'done': return 'done';
19
+ case 'canceled': return 'canceled';
20
+ default: return 'todo';
21
+ }
22
+ }
23
+ /** Map old cron.json type → UnifiedTask mode. */
24
+ function mapCronType(type) {
25
+ switch (type) {
26
+ case 'reminder': return 'notify';
27
+ case 'task': return 'auto';
28
+ case 'heartbeat': return 'auto';
29
+ default: return 'auto';
30
+ }
31
+ }
32
+ /** Map old cron.json status → UnifiedTask status. */
33
+ function mapCronStatus(status) {
34
+ switch (status) {
35
+ case 'pending': return 'pending';
36
+ case 'fired': return 'done'; // already notified
37
+ case 'executing': return 'pending'; // still pending in new model (daemon will run it)
38
+ case 'completed': return 'done';
39
+ case 'failed': return 'canceled';
40
+ case 'cancelled': return 'canceled';
41
+ default: return 'pending';
42
+ }
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // Migration functions
46
+ // ---------------------------------------------------------------------------
47
+ function readLegacyTodo(filePath) {
48
+ if (!filePath)
49
+ return null;
50
+ try {
51
+ const raw = readFileSync(filePath, 'utf-8');
52
+ return JSON.parse(raw);
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ }
58
+ function readLegacyCron(filePath) {
59
+ if (!filePath)
60
+ return null;
61
+ try {
62
+ const raw = readFileSync(filePath, 'utf-8');
63
+ return JSON.parse(raw);
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ /**
70
+ * Main migration: merges todo.json and cron.json into tasks.json.
71
+ */
72
+ export function migrateTasks(oldTodoPath, oldCronPath, newTasksPath) {
73
+ const target = newTasksPath || join(homedir(), '.curie-agent', 'tasks.json');
74
+ // Skip if already migrated (file exists)
75
+ try {
76
+ if (readFileSync(target, 'utf-8').trim().length > 0)
77
+ return null;
78
+ }
79
+ catch {
80
+ /* target doesn't exist yet — proceed */
81
+ }
82
+ const newFile = { $schema: 'tasks.schema.json', version: 1, tasks: [] };
83
+ let order = 0;
84
+ // Migrate todo.json → manual tasks
85
+ const todoPaths = [oldTodoPath, join(homedir(), '.curie-agent', 'todo.json')].filter(Boolean);
86
+ for (const filePath of todoPaths) {
87
+ const legacy = readLegacyTodo(filePath);
88
+ if (!legacy)
89
+ continue;
90
+ const scope = filePath.includes('.curie-agent') ? 'personal' : 'project';
91
+ for (const t of legacy.tasks || []) {
92
+ newFile.tasks.push({
93
+ id: t.id,
94
+ title: t.title,
95
+ description: t.description ?? '',
96
+ status: mapTodoStatus(t.status ?? ''),
97
+ priority: t.priority ?? 'medium',
98
+ tags: t.tags ?? [],
99
+ mode: 'manual',
100
+ scheduled_at: undefined,
101
+ frequency: null,
102
+ result: undefined,
103
+ scope,
104
+ order: order++,
105
+ created_at: t.created_at ?? taskTimestamp(),
106
+ completed_at: t.status === 'done' ? new Date().toISOString() : undefined,
107
+ });
108
+ }
109
+ }
110
+ // Migrate cron.json → auto/notify tasks
111
+ const cronPaths = [oldCronPath, join(homedir(), '.curie-agent', 'cron.json')].filter(Boolean);
112
+ for (const filePath of cronPaths) {
113
+ const legacy = readLegacyCron(filePath);
114
+ if (!legacy)
115
+ continue;
116
+ for (const t of legacy.tasks || []) {
117
+ // Skip already-fired tasks from migration (they've been delivered)
118
+ const status = mapCronStatus(t.status);
119
+ if (status === 'done' && !t.message.includes('Heartbeat'))
120
+ continue;
121
+ newFile.tasks.push({
122
+ id: t.id,
123
+ title: t.message,
124
+ description: '',
125
+ status,
126
+ priority: 'medium',
127
+ tags: [],
128
+ mode: mapCronType(t.type),
129
+ scheduled_at: t.scheduledAt || undefined,
130
+ frequency: t.schedule ? { type: t.schedule.type, value: t.schedule.value } : null,
131
+ result: t.status === 'completed' ? `Completed (${t.message})` : undefined,
132
+ scope: 'personal', // cron tasks are always personal
133
+ order: order++,
134
+ created_at: new Date(t.createdAt).toISOString(),
135
+ completed_at: status === 'done' || status === 'canceled' ? new Date().toISOString() : undefined,
136
+ });
137
+ }
138
+ }
139
+ if (!newFile.tasks.length)
140
+ return null; // nothing to migrate
141
+ writeFileSync(target, JSON.stringify(newFile, null, 2), 'utf-8');
142
+ return newFile;
143
+ }
144
+ //# sourceMappingURL=task-migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-migration.js","sourceRoot":"","sources":["../../src/task-migration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared utility for reading and summarizing tasks from JSON files.
3
+ * Replaces the duplicate readTodoSummary() functions in task-executor.ts and heartbeat-executor.ts.
4
+ */
5
+ /** Format active tasks as a summary string for context prompts. */
6
+ export declare function readTaskSummary(filePath: string): string;
7
+ //# sourceMappingURL=task-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-summary.d.ts","sourceRoot":"","sources":["../../src/task-summary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA+BxD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Shared utility for reading and summarizing tasks from JSON files.
3
+ * Replaces the duplicate readTodoSummary() functions in task-executor.ts and heartbeat-executor.ts.
4
+ */
5
+ import { readFileSync } from 'node:fs';
6
+ /** Format active tasks as a summary string for context prompts. */
7
+ export function readTaskSummary(filePath) {
8
+ try {
9
+ const raw = readFileSync(filePath, 'utf-8');
10
+ const data = JSON.parse(raw);
11
+ if (typeof data !== 'object' || data === null || !('tasks' in data))
12
+ return '(corrupt tasks.json)';
13
+ const file = data;
14
+ if (!Array.isArray(file.tasks) || !file.tasks.length)
15
+ return '(empty)';
16
+ // Show non-done/non-canceled tasks sorted by order
17
+ const active = file.tasks.filter((t) => t.status && !['done', 'canceled'].includes(t.status));
18
+ active.sort((a, b) => a.order - b.order);
19
+ if (!active.length) {
20
+ const doneCount = file.tasks.filter((t) => t.status === 'done').length;
21
+ return `All ${file.tasks.length} task(s) complete (${doneCount} done).`;
22
+ }
23
+ const lines = active.map((t) => {
24
+ const icon = t.status === 'in_progress' ? '[*]' : '-';
25
+ const priority = t.priority && t.priority !== 'medium' ? ` [${t.priority}]` : '';
26
+ return `${icon} ${t.id.slice(0, 8)} ${t.title}${priority}`;
27
+ });
28
+ return lines.join('\n');
29
+ }
30
+ catch {
31
+ return '(corrupt tasks.json)';
32
+ }
33
+ }
34
+ //# sourceMappingURL=task-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-summary.js","sourceRoot":"","sources":["../../src/task-summary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAExC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC;YAAE,OAAO,sBAAsB,CAAC;QAEnG,MAAM,IAAI,GAAG,IAAiB,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAEvE,mDAAmD;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAC5D,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAEzC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;YACvE,OAAO,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,sBAAsB,SAAS,SAAS,CAAC;QAC1E,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;YACtD,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACjF,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,QAAQ,EAAE,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,sBAAsB,CAAC;IAChC,CAAC;AACH,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { type PriceTier } from './pricing.js';
2
+ export { estimateCost, PriceTier, parseTieredPricing, selectTier } from './pricing.js';
3
+ export type TokenEvent = {
4
+ type: 'context-warning';
5
+ fillPct: number;
6
+ message: string;
7
+ } | {
8
+ type: 'context-compaction-needed';
9
+ fillPct: number;
10
+ message: string;
11
+ } | {
12
+ type: 'context-forced-compaction';
13
+ fillPct: number;
14
+ message: string;
15
+ } | {
16
+ type: 'tier-warning';
17
+ threshold: number;
18
+ oldTier: PriceTier;
19
+ newTier: PriceTier;
20
+ message: string;
21
+ };
22
+ export interface TokenMonitorConfig {
23
+ contextWindowSize: number;
24
+ thresholdPct: number;
25
+ warnThresholdPct: number;
26
+ forcedThresholdPct: number;
27
+ pricingTierWarn: boolean;
28
+ /** Model name for cost estimation (e.g., 'claude-sonnet-4-6'). */
29
+ model?: string;
30
+ }
31
+ export declare class TokenMonitor {
32
+ config: TokenMonitorConfig;
33
+ cumulativeInputTokens: number;
34
+ lastTrackedTokens: number;
35
+ private acknowledged;
36
+ constructor(config: TokenMonitorConfig);
37
+ getFillPct(): number;
38
+ getStatus(): 'ok' | 'warning' | 'compaction-needed' | 'forced-compaction';
39
+ private parseTiers;
40
+ private selectTier;
41
+ checkTierCrossing(tiersRaw?: PriceTier[]): TokenEvent | null;
42
+ addTokens(inputTokens: number, outputTokens: number, tiersRaw?: PriceTier[]): TokenEvent[];
43
+ acknowledge(eventType: string): void;
44
+ reset(): void;
45
+ setContextWindowSize(size: number): void;
46
+ setThresholdPct(pct: number): void;
47
+ setWarnThresholdPct(pct: number): void;
48
+ setForcedThresholdPct(pct: number): void;
49
+ }
50
+ //# sourceMappingURL=token-monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-monitor.d.ts","sourceRoot":"","sources":["../../src/token-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgD,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEvF,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,2BAA2B,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,2BAA2B,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzG,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,YAAY;IACvB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAqB;gBAE7B,MAAM,EAAE,kBAAkB;IAMtC,UAAU,IAAI,MAAM;IAKpB,SAAS,IAAI,IAAI,GAAG,SAAS,GAAG,mBAAmB,GAAG,mBAAmB;IAQzE,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,UAAU;IAkBlB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,UAAU,GAAG,IAAI;IA0B5D,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE;IA0B1F,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIpC,KAAK,IAAI,IAAI;IAMb,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIlC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAItC,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGzC"}