@flowdot.ai/daemon 1.0.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 (85) hide show
  1. package/LICENSE +45 -0
  2. package/README.md +51 -0
  3. package/dist/goals/DependencyResolver.d.ts +54 -0
  4. package/dist/goals/DependencyResolver.js +329 -0
  5. package/dist/goals/ErrorRecovery.d.ts +133 -0
  6. package/dist/goals/ErrorRecovery.js +489 -0
  7. package/dist/goals/GoalApiClient.d.ts +81 -0
  8. package/dist/goals/GoalApiClient.js +743 -0
  9. package/dist/goals/GoalCache.d.ts +65 -0
  10. package/dist/goals/GoalCache.js +243 -0
  11. package/dist/goals/GoalCommsHandler.d.ts +150 -0
  12. package/dist/goals/GoalCommsHandler.js +378 -0
  13. package/dist/goals/GoalExporter.d.ts +164 -0
  14. package/dist/goals/GoalExporter.js +318 -0
  15. package/dist/goals/GoalImporter.d.ts +107 -0
  16. package/dist/goals/GoalImporter.js +345 -0
  17. package/dist/goals/GoalManager.d.ts +110 -0
  18. package/dist/goals/GoalManager.js +535 -0
  19. package/dist/goals/GoalReporter.d.ts +105 -0
  20. package/dist/goals/GoalReporter.js +534 -0
  21. package/dist/goals/GoalScheduler.d.ts +102 -0
  22. package/dist/goals/GoalScheduler.js +209 -0
  23. package/dist/goals/GoalValidator.d.ts +72 -0
  24. package/dist/goals/GoalValidator.js +657 -0
  25. package/dist/goals/MetaGoalEnforcer.d.ts +111 -0
  26. package/dist/goals/MetaGoalEnforcer.js +536 -0
  27. package/dist/goals/MilestoneBreaker.d.ts +74 -0
  28. package/dist/goals/MilestoneBreaker.js +348 -0
  29. package/dist/goals/PermissionBridge.d.ts +109 -0
  30. package/dist/goals/PermissionBridge.js +326 -0
  31. package/dist/goals/ProgressTracker.d.ts +113 -0
  32. package/dist/goals/ProgressTracker.js +324 -0
  33. package/dist/goals/ReviewScheduler.d.ts +106 -0
  34. package/dist/goals/ReviewScheduler.js +360 -0
  35. package/dist/goals/TaskExecutor.d.ts +116 -0
  36. package/dist/goals/TaskExecutor.js +370 -0
  37. package/dist/goals/TaskFeedback.d.ts +126 -0
  38. package/dist/goals/TaskFeedback.js +402 -0
  39. package/dist/goals/TaskGenerator.d.ts +75 -0
  40. package/dist/goals/TaskGenerator.js +329 -0
  41. package/dist/goals/TaskQueue.d.ts +84 -0
  42. package/dist/goals/TaskQueue.js +331 -0
  43. package/dist/goals/TaskSanitizer.d.ts +61 -0
  44. package/dist/goals/TaskSanitizer.js +464 -0
  45. package/dist/goals/errors.d.ts +116 -0
  46. package/dist/goals/errors.js +299 -0
  47. package/dist/goals/index.d.ts +24 -0
  48. package/dist/goals/index.js +23 -0
  49. package/dist/goals/types.d.ts +395 -0
  50. package/dist/goals/types.js +230 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.js +3 -0
  53. package/dist/loop/DaemonIPC.d.ts +67 -0
  54. package/dist/loop/DaemonIPC.js +358 -0
  55. package/dist/loop/IntervalParser.d.ts +39 -0
  56. package/dist/loop/IntervalParser.js +217 -0
  57. package/dist/loop/LoopDaemon.d.ts +123 -0
  58. package/dist/loop/LoopDaemon.js +1821 -0
  59. package/dist/loop/LoopExecutor.d.ts +93 -0
  60. package/dist/loop/LoopExecutor.js +326 -0
  61. package/dist/loop/LoopManager.d.ts +79 -0
  62. package/dist/loop/LoopManager.js +476 -0
  63. package/dist/loop/LoopScheduler.d.ts +69 -0
  64. package/dist/loop/LoopScheduler.js +329 -0
  65. package/dist/loop/LoopStore.d.ts +57 -0
  66. package/dist/loop/LoopStore.js +406 -0
  67. package/dist/loop/LoopValidator.d.ts +55 -0
  68. package/dist/loop/LoopValidator.js +603 -0
  69. package/dist/loop/errors.d.ts +115 -0
  70. package/dist/loop/errors.js +312 -0
  71. package/dist/loop/index.d.ts +11 -0
  72. package/dist/loop/index.js +10 -0
  73. package/dist/loop/notifications/Notifier.d.ts +28 -0
  74. package/dist/loop/notifications/Notifier.js +78 -0
  75. package/dist/loop/notifications/SlackNotifier.d.ts +28 -0
  76. package/dist/loop/notifications/SlackNotifier.js +203 -0
  77. package/dist/loop/notifications/TerminalNotifier.d.ts +18 -0
  78. package/dist/loop/notifications/TerminalNotifier.js +72 -0
  79. package/dist/loop/notifications/WebhookNotifier.d.ts +24 -0
  80. package/dist/loop/notifications/WebhookNotifier.js +123 -0
  81. package/dist/loop/notifications/index.d.ts +24 -0
  82. package/dist/loop/notifications/index.js +109 -0
  83. package/dist/loop/types.d.ts +280 -0
  84. package/dist/loop/types.js +222 -0
  85. package/package.json +92 -0
@@ -0,0 +1,402 @@
1
+ import { EventEmitter } from 'events';
2
+ const DEFAULT_MAX_ENTRIES = 10000;
3
+ const DEFAULT_PATTERN_THRESHOLD = 5;
4
+ const DEFAULT_TREND_WINDOW_DAYS = 7;
5
+ export class TaskFeedback extends EventEmitter {
6
+ logger;
7
+ maxEntries;
8
+ patternThreshold;
9
+ trendWindowDays;
10
+ feedback = new Map();
11
+ patterns = new Map();
12
+ feedbackCounter = 0;
13
+ patternCounter = 0;
14
+ constructor(options = {}) {
15
+ super();
16
+ this.logger = options.logger ?? console;
17
+ this.maxEntries = options.maxFeedbackEntries ?? DEFAULT_MAX_ENTRIES;
18
+ this.patternThreshold =
19
+ options.patternDetectionThreshold ?? DEFAULT_PATTERN_THRESHOLD;
20
+ this.trendWindowDays = options.trendWindowDays ?? DEFAULT_TREND_WINDOW_DAYS;
21
+ }
22
+ submitFeedback(input) {
23
+ const sentiment = this.deriveSentiment(input.rating);
24
+ const entry = {
25
+ id: `feedback_${++this.feedbackCounter}_${Date.now()}`,
26
+ taskId: input.taskId,
27
+ goalHash: input.goalHash,
28
+ taskType: input.taskType,
29
+ rating: input.rating,
30
+ category: input.category ?? 'quality',
31
+ sentiment,
32
+ comment: input.comment,
33
+ tags: input.tags,
34
+ wasTaskModified: input.wasTaskModified ?? false,
35
+ wasTaskRetried: input.wasTaskRetried ?? false,
36
+ createdAt: new Date(),
37
+ metadata: input.metadata,
38
+ };
39
+ this.feedback.set(entry.id, entry);
40
+ this.enforceMaxEntries();
41
+ this.emit('feedback:submitted', entry);
42
+ this.logger.debug('TASK_FEEDBACK', `Feedback submitted for task ${input.taskId}: ${input.rating}/5`);
43
+ this.detectPatterns();
44
+ this.checkQualityTrends();
45
+ return entry;
46
+ }
47
+ getFeedback(feedbackId) {
48
+ return this.feedback.get(feedbackId);
49
+ }
50
+ queryFeedback(options = {}) {
51
+ let results = Array.from(this.feedback.values());
52
+ if (options.goalHash) {
53
+ results = results.filter((f) => f.goalHash === options.goalHash);
54
+ }
55
+ if (options.taskType) {
56
+ results = results.filter((f) => f.taskType === options.taskType);
57
+ }
58
+ if (options.category) {
59
+ results = results.filter((f) => f.category === options.category);
60
+ }
61
+ if (options.sentiment) {
62
+ results = results.filter((f) => f.sentiment === options.sentiment);
63
+ }
64
+ if (options.minRating) {
65
+ results = results.filter((f) => f.rating >= options.minRating);
66
+ }
67
+ if (options.maxRating) {
68
+ results = results.filter((f) => f.rating <= options.maxRating);
69
+ }
70
+ if (options.startDate) {
71
+ results = results.filter((f) => f.createdAt >= options.startDate);
72
+ }
73
+ if (options.endDate) {
74
+ results = results.filter((f) => f.createdAt <= options.endDate);
75
+ }
76
+ results.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
77
+ if (options.offset) {
78
+ results = results.slice(options.offset);
79
+ }
80
+ if (options.limit) {
81
+ results = results.slice(0, options.limit);
82
+ }
83
+ return results;
84
+ }
85
+ getTaskFeedback(taskId) {
86
+ return Array.from(this.feedback.values()).filter((f) => f.taskId === taskId);
87
+ }
88
+ getGoalFeedback(goalHash) {
89
+ return this.queryFeedback({ goalHash });
90
+ }
91
+ calculateStatistics(options = {}) {
92
+ const entries = this.queryFeedback(options);
93
+ if (entries.length === 0) {
94
+ return this.emptyStatistics();
95
+ }
96
+ const ratingDistribution = {
97
+ 1: 0,
98
+ 2: 0,
99
+ 3: 0,
100
+ 4: 0,
101
+ 5: 0,
102
+ };
103
+ const categoryBreakdown = {
104
+ quality: 0,
105
+ accuracy: 0,
106
+ completeness: 0,
107
+ relevance: 0,
108
+ safety: 0,
109
+ performance: 0,
110
+ other: 0,
111
+ };
112
+ const sentimentBreakdown = {
113
+ positive: 0,
114
+ neutral: 0,
115
+ negative: 0,
116
+ };
117
+ const taskTypeData = new Map();
118
+ let totalRating = 0;
119
+ for (const entry of entries) {
120
+ totalRating += entry.rating;
121
+ ratingDistribution[entry.rating]++;
122
+ categoryBreakdown[entry.category]++;
123
+ sentimentBreakdown[entry.sentiment]++;
124
+ const taskType = entry.taskType;
125
+ const existing = taskTypeData.get(taskType) ?? { sum: 0, count: 0 };
126
+ taskTypeData.set(taskType, {
127
+ sum: existing.sum + entry.rating,
128
+ count: existing.count + 1,
129
+ });
130
+ }
131
+ const taskTypeBreakdown = {};
132
+ for (const [type, data] of taskTypeData) {
133
+ taskTypeBreakdown[type] = {
134
+ count: data.count,
135
+ avgRating: Math.round((data.sum / data.count) * 100) / 100,
136
+ };
137
+ }
138
+ return {
139
+ totalFeedback: entries.length,
140
+ averageRating: Math.round((totalRating / entries.length) * 100) / 100,
141
+ ratingDistribution,
142
+ categoryBreakdown,
143
+ sentimentBreakdown,
144
+ taskTypeBreakdown,
145
+ commonIssues: Array.from(this.patterns.values()),
146
+ trends: this.calculateTrends(entries),
147
+ };
148
+ }
149
+ getPatterns() {
150
+ return Array.from(this.patterns.values());
151
+ }
152
+ generateSuggestions() {
153
+ const stats = this.calculateStatistics();
154
+ const suggestions = [];
155
+ let suggestionCounter = 0;
156
+ if (stats.averageRating < 3 && stats.totalFeedback >= 5) {
157
+ suggestions.push({
158
+ id: `suggestion_${++suggestionCounter}`,
159
+ priority: 'high',
160
+ area: 'Overall Quality',
161
+ description: `Average rating is ${stats.averageRating}/5, below target threshold`,
162
+ basedOnFeedbackCount: stats.totalFeedback,
163
+ potentialImpact: 80,
164
+ actionItems: [
165
+ 'Review recent negative feedback',
166
+ 'Identify common failure patterns',
167
+ 'Adjust task generation prompts',
168
+ ],
169
+ });
170
+ }
171
+ for (const [category, count] of Object.entries(stats.categoryBreakdown)) {
172
+ if (count >= this.patternThreshold) {
173
+ const categoryFeedback = this.queryFeedback({
174
+ category: category,
175
+ });
176
+ const avgRating = categoryFeedback.reduce((sum, f) => sum + f.rating, 0) /
177
+ categoryFeedback.length;
178
+ if (avgRating < 3) {
179
+ suggestions.push({
180
+ id: `suggestion_${++suggestionCounter}`,
181
+ priority: avgRating < 2 ? 'high' : 'medium',
182
+ area: `${this.capitalizeFirst(category)} Issues`,
183
+ description: `${category} feedback has low average rating (${avgRating.toFixed(1)}/5)`,
184
+ basedOnFeedbackCount: count,
185
+ potentialImpact: 60,
186
+ actionItems: [
187
+ `Review ${category} feedback comments`,
188
+ `Identify specific ${category} issues`,
189
+ `Implement targeted improvements`,
190
+ ],
191
+ });
192
+ }
193
+ }
194
+ }
195
+ for (const pattern of this.patterns.values()) {
196
+ if (pattern.averageRating < 3) {
197
+ suggestions.push({
198
+ id: `suggestion_${++suggestionCounter}`,
199
+ priority: 'medium',
200
+ area: 'Recurring Pattern',
201
+ description: pattern.description,
202
+ basedOnFeedbackCount: pattern.frequency,
203
+ potentialImpact: 50,
204
+ actionItems: pattern.suggestedFix
205
+ ? [pattern.suggestedFix]
206
+ : ['Analyze pattern and develop fix'],
207
+ });
208
+ }
209
+ }
210
+ for (const [taskType, data] of Object.entries(stats.taskTypeBreakdown)) {
211
+ if (data.count >= 3 && data.avgRating < 3) {
212
+ suggestions.push({
213
+ id: `suggestion_${++suggestionCounter}`,
214
+ priority: data.avgRating < 2 ? 'high' : 'medium',
215
+ area: `Task Type: ${taskType}`,
216
+ description: `${taskType} tasks have low satisfaction (${data.avgRating}/5)`,
217
+ basedOnFeedbackCount: data.count,
218
+ potentialImpact: 40,
219
+ actionItems: [
220
+ `Review ${taskType} task generation`,
221
+ 'Analyze failure modes',
222
+ 'Improve task handling logic',
223
+ ],
224
+ });
225
+ }
226
+ }
227
+ for (const suggestion of suggestions) {
228
+ this.emit('suggestion:generated', suggestion);
229
+ }
230
+ return suggestions.sort((a, b) => b.potentialImpact - a.potentialImpact);
231
+ }
232
+ getGoalAverageRating(goalHash) {
233
+ const feedback = this.getGoalFeedback(goalHash);
234
+ if (feedback.length === 0)
235
+ return null;
236
+ const sum = feedback.reduce((acc, f) => acc + f.rating, 0);
237
+ return Math.round((sum / feedback.length) * 100) / 100;
238
+ }
239
+ clearGoalFeedback(goalHash) {
240
+ let deleted = 0;
241
+ for (const [id, entry] of this.feedback) {
242
+ if (entry.goalHash === goalHash) {
243
+ this.feedback.delete(id);
244
+ deleted++;
245
+ }
246
+ }
247
+ return deleted;
248
+ }
249
+ exportFeedback(options = {}) {
250
+ const entries = this.queryFeedback(options);
251
+ return JSON.stringify({
252
+ exportedAt: new Date().toISOString(),
253
+ count: entries.length,
254
+ statistics: this.calculateStatistics(options),
255
+ entries,
256
+ }, null, 2);
257
+ }
258
+ deriveSentiment(rating) {
259
+ if (rating >= 4)
260
+ return 'positive';
261
+ if (rating <= 2)
262
+ return 'negative';
263
+ return 'neutral';
264
+ }
265
+ enforceMaxEntries() {
266
+ if (this.feedback.size <= this.maxEntries)
267
+ return;
268
+ const entries = Array.from(this.feedback.entries()).sort(([, a], [, b]) => a.createdAt.getTime() - b.createdAt.getTime());
269
+ const toRemove = entries.slice(0, entries.length - this.maxEntries);
270
+ for (const [id] of toRemove) {
271
+ this.feedback.delete(id);
272
+ }
273
+ }
274
+ detectPatterns() {
275
+ const negativeFeedback = Array.from(this.feedback.values()).filter((f) => f.rating <= 2);
276
+ const groups = new Map();
277
+ for (const entry of negativeFeedback) {
278
+ const key = `${entry.category}:${entry.taskType}`;
279
+ const existing = groups.get(key) ?? {
280
+ entries: [],
281
+ taskTypes: new Set(),
282
+ };
283
+ existing.entries.push(entry);
284
+ existing.taskTypes.add(entry.taskType);
285
+ groups.set(key, existing);
286
+ }
287
+ for (const [key, group] of groups) {
288
+ if (group.entries.length >= this.patternThreshold) {
289
+ const [category, taskType] = key.split(':');
290
+ const patternId = `pattern_${++this.patternCounter}`;
291
+ const avgRating = group.entries.reduce((sum, e) => sum + e.rating, 0) /
292
+ group.entries.length;
293
+ const pattern = {
294
+ id: patternId,
295
+ description: `Low ratings for ${category} in ${taskType} tasks`,
296
+ frequency: group.entries.length,
297
+ affectedTaskTypes: Array.from(group.taskTypes),
298
+ averageRating: Math.round(avgRating * 100) / 100,
299
+ exampleFeedbackIds: group.entries.slice(0, 3).map((e) => e.id),
300
+ suggestedFix: this.suggestFix(category, taskType),
301
+ };
302
+ const existingPattern = Array.from(this.patterns.values()).find((p) => p.description === pattern.description ||
303
+ (p.affectedTaskTypes.includes(taskType) &&
304
+ p.description.includes(category)));
305
+ if (!existingPattern) {
306
+ this.patterns.set(patternId, pattern);
307
+ this.emit('pattern:detected', pattern);
308
+ }
309
+ }
310
+ }
311
+ }
312
+ suggestFix(category, taskType) {
313
+ const fixes = {
314
+ quality: `Review ${taskType} task generation prompts and improve output quality`,
315
+ accuracy: `Verify ${taskType} task outputs and add validation`,
316
+ completeness: `Ensure ${taskType} tasks include all required elements`,
317
+ relevance: `Review context gathering for ${taskType} tasks`,
318
+ safety: `Add safety checks for ${taskType} task execution`,
319
+ performance: `Optimize ${taskType} task execution speed`,
320
+ other: `Analyze ${taskType} task feedback for improvement areas`,
321
+ };
322
+ return fixes[category];
323
+ }
324
+ calculateTrends(entries) {
325
+ if (entries.length < 2)
326
+ return [];
327
+ const trends = [];
328
+ const now = new Date();
329
+ for (let i = 0; i < 4; i++) {
330
+ const weekEnd = new Date(now);
331
+ weekEnd.setDate(weekEnd.getDate() - i * 7);
332
+ const weekStart = new Date(weekEnd);
333
+ weekStart.setDate(weekStart.getDate() - 7);
334
+ const weekEntries = entries.filter((e) => e.createdAt >= weekStart && e.createdAt < weekEnd);
335
+ if (weekEntries.length > 0) {
336
+ const avgRating = weekEntries.reduce((sum, e) => sum + e.rating, 0) / weekEntries.length;
337
+ trends.push({
338
+ period: `Week ${i + 1}`,
339
+ averageRating: Math.round(avgRating * 100) / 100,
340
+ feedbackCount: weekEntries.length,
341
+ change: 'stable',
342
+ });
343
+ }
344
+ }
345
+ for (let i = 0; i < trends.length - 1; i++) {
346
+ const current = trends[i].averageRating;
347
+ const previous = trends[i + 1].averageRating;
348
+ const diff = current - previous;
349
+ const trendWithChange = {
350
+ ...trends[i],
351
+ change: diff > 0.2 ? 'improving' : diff < -0.2 ? 'declining' : 'stable',
352
+ };
353
+ trends[i] = trendWithChange;
354
+ }
355
+ return trends;
356
+ }
357
+ checkQualityTrends() {
358
+ const recentStats = this.calculateStatistics({
359
+ startDate: new Date(Date.now() - this.trendWindowDays * 24 * 60 * 60 * 1000),
360
+ });
361
+ if (recentStats.totalFeedback < 5)
362
+ return;
363
+ const olderStats = this.calculateStatistics({
364
+ endDate: new Date(Date.now() - this.trendWindowDays * 24 * 60 * 60 * 1000),
365
+ });
366
+ if (olderStats.totalFeedback < 5)
367
+ return;
368
+ const diff = recentStats.averageRating - olderStats.averageRating;
369
+ if (diff < -0.5) {
370
+ this.emit('quality:declining', recentStats);
371
+ }
372
+ else if (diff > 0.5) {
373
+ this.emit('quality:improving', recentStats);
374
+ }
375
+ }
376
+ capitalizeFirst(str) {
377
+ return str.charAt(0).toUpperCase() + str.slice(1);
378
+ }
379
+ emptyStatistics() {
380
+ return {
381
+ totalFeedback: 0,
382
+ averageRating: 0,
383
+ ratingDistribution: { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 },
384
+ categoryBreakdown: {
385
+ quality: 0,
386
+ accuracy: 0,
387
+ completeness: 0,
388
+ relevance: 0,
389
+ safety: 0,
390
+ performance: 0,
391
+ other: 0,
392
+ },
393
+ sentimentBreakdown: { positive: 0, neutral: 0, negative: 0 },
394
+ taskTypeBreakdown: {},
395
+ commonIssues: [],
396
+ trends: [],
397
+ };
398
+ }
399
+ }
400
+ export function createTaskFeedback(options) {
401
+ return new TaskFeedback(options);
402
+ }
@@ -0,0 +1,75 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { Goal, Milestone, Task, TaskType, MetaGoal, CreateTaskInput, Logger } from './types.js';
3
+ import { GoalError } from './errors.js';
4
+ export type TaskGeneratorLLMFunction = (prompt: string, options?: {
5
+ modelTier?: string;
6
+ maxTokens?: number;
7
+ temperature?: number;
8
+ }) => Promise<string>;
9
+ export interface TaskSuggestion {
10
+ readonly title: string;
11
+ readonly description: string;
12
+ readonly type: TaskType;
13
+ readonly priority: number;
14
+ readonly scheduledFor?: string;
15
+ readonly expiresAt?: string;
16
+ readonly milestoneId?: number;
17
+ readonly reasoning: string;
18
+ readonly estimatedCost?: number;
19
+ readonly dependsOnTasks?: string[];
20
+ }
21
+ export interface TaskGenerationResult {
22
+ readonly suggestions: TaskSuggestion[];
23
+ readonly planSummary: string;
24
+ readonly warnings: string[];
25
+ readonly estimatedEffort?: string;
26
+ readonly metadata: {
27
+ readonly generatedAt: string;
28
+ readonly modelTier: string;
29
+ readonly promptTokens?: number;
30
+ readonly responseTokens?: number;
31
+ };
32
+ }
33
+ export interface TaskGenerationOptions {
34
+ readonly maxTasks?: number;
35
+ readonly milestoneId?: number;
36
+ readonly taskTypes?: TaskType[];
37
+ readonly additionalContext?: string;
38
+ readonly metaGoals?: MetaGoal[];
39
+ readonly modelTier?: string;
40
+ readonly includeReasoning?: boolean;
41
+ }
42
+ export interface TaskGeneratorOptions {
43
+ readonly llmFunction: TaskGeneratorLLMFunction;
44
+ readonly defaultModelTier?: string;
45
+ readonly defaultMaxTasks?: number;
46
+ readonly logger?: Logger;
47
+ }
48
+ export interface TaskGeneratorEvents {
49
+ generationStarted: [goalHash: string, options: TaskGenerationOptions];
50
+ generationCompleted: [goalHash: string, result: TaskGenerationResult];
51
+ generationFailed: [goalHash: string, error: Error];
52
+ taskSuggested: [goalHash: string, suggestion: TaskSuggestion];
53
+ }
54
+ export declare class TaskGenerationError extends GoalError {
55
+ constructor(message: string, cause?: Error);
56
+ }
57
+ export declare class LLMParseError extends GoalError {
58
+ constructor(message: string, cause?: Error);
59
+ }
60
+ export declare class TaskGenerator extends EventEmitter<TaskGeneratorEvents> {
61
+ private readonly llmFunction;
62
+ private readonly defaultModelTier;
63
+ private readonly defaultMaxTasks;
64
+ private readonly logger;
65
+ constructor(options: TaskGeneratorOptions);
66
+ generateTasks(goal: Goal, milestones: Milestone[], existingTasks: Task[], options?: TaskGenerationOptions): Promise<TaskGenerationResult>;
67
+ generateDailyTasks(goal: Goal, milestones: Milestone[], existingTasks: Task[], options?: TaskGenerationOptions): Promise<TaskGenerationResult>;
68
+ suggestNextTask(goal: Goal, milestones: Milestone[], pendingTasks: Task[], options?: TaskGenerationOptions): Promise<TaskSuggestion | null>;
69
+ suggestionToInput(suggestion: TaskSuggestion, _goalHash: string): CreateTaskInput;
70
+ private buildGenerationPrompt;
71
+ private parseGenerationResponse;
72
+ private validateSuggestion;
73
+ private validateTaskType;
74
+ }
75
+ export declare function createTaskGenerator(options: TaskGeneratorOptions): TaskGenerator;