@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.
- package/LICENSE +45 -0
- package/README.md +51 -0
- package/dist/goals/DependencyResolver.d.ts +54 -0
- package/dist/goals/DependencyResolver.js +329 -0
- package/dist/goals/ErrorRecovery.d.ts +133 -0
- package/dist/goals/ErrorRecovery.js +489 -0
- package/dist/goals/GoalApiClient.d.ts +81 -0
- package/dist/goals/GoalApiClient.js +743 -0
- package/dist/goals/GoalCache.d.ts +65 -0
- package/dist/goals/GoalCache.js +243 -0
- package/dist/goals/GoalCommsHandler.d.ts +150 -0
- package/dist/goals/GoalCommsHandler.js +378 -0
- package/dist/goals/GoalExporter.d.ts +164 -0
- package/dist/goals/GoalExporter.js +318 -0
- package/dist/goals/GoalImporter.d.ts +107 -0
- package/dist/goals/GoalImporter.js +345 -0
- package/dist/goals/GoalManager.d.ts +110 -0
- package/dist/goals/GoalManager.js +535 -0
- package/dist/goals/GoalReporter.d.ts +105 -0
- package/dist/goals/GoalReporter.js +534 -0
- package/dist/goals/GoalScheduler.d.ts +102 -0
- package/dist/goals/GoalScheduler.js +209 -0
- package/dist/goals/GoalValidator.d.ts +72 -0
- package/dist/goals/GoalValidator.js +657 -0
- package/dist/goals/MetaGoalEnforcer.d.ts +111 -0
- package/dist/goals/MetaGoalEnforcer.js +536 -0
- package/dist/goals/MilestoneBreaker.d.ts +74 -0
- package/dist/goals/MilestoneBreaker.js +348 -0
- package/dist/goals/PermissionBridge.d.ts +109 -0
- package/dist/goals/PermissionBridge.js +326 -0
- package/dist/goals/ProgressTracker.d.ts +113 -0
- package/dist/goals/ProgressTracker.js +324 -0
- package/dist/goals/ReviewScheduler.d.ts +106 -0
- package/dist/goals/ReviewScheduler.js +360 -0
- package/dist/goals/TaskExecutor.d.ts +116 -0
- package/dist/goals/TaskExecutor.js +370 -0
- package/dist/goals/TaskFeedback.d.ts +126 -0
- package/dist/goals/TaskFeedback.js +402 -0
- package/dist/goals/TaskGenerator.d.ts +75 -0
- package/dist/goals/TaskGenerator.js +329 -0
- package/dist/goals/TaskQueue.d.ts +84 -0
- package/dist/goals/TaskQueue.js +331 -0
- package/dist/goals/TaskSanitizer.d.ts +61 -0
- package/dist/goals/TaskSanitizer.js +464 -0
- package/dist/goals/errors.d.ts +116 -0
- package/dist/goals/errors.js +299 -0
- package/dist/goals/index.d.ts +24 -0
- package/dist/goals/index.js +23 -0
- package/dist/goals/types.d.ts +395 -0
- package/dist/goals/types.js +230 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/loop/DaemonIPC.d.ts +67 -0
- package/dist/loop/DaemonIPC.js +358 -0
- package/dist/loop/IntervalParser.d.ts +39 -0
- package/dist/loop/IntervalParser.js +217 -0
- package/dist/loop/LoopDaemon.d.ts +123 -0
- package/dist/loop/LoopDaemon.js +1821 -0
- package/dist/loop/LoopExecutor.d.ts +93 -0
- package/dist/loop/LoopExecutor.js +326 -0
- package/dist/loop/LoopManager.d.ts +79 -0
- package/dist/loop/LoopManager.js +476 -0
- package/dist/loop/LoopScheduler.d.ts +69 -0
- package/dist/loop/LoopScheduler.js +329 -0
- package/dist/loop/LoopStore.d.ts +57 -0
- package/dist/loop/LoopStore.js +406 -0
- package/dist/loop/LoopValidator.d.ts +55 -0
- package/dist/loop/LoopValidator.js +603 -0
- package/dist/loop/errors.d.ts +115 -0
- package/dist/loop/errors.js +312 -0
- package/dist/loop/index.d.ts +11 -0
- package/dist/loop/index.js +10 -0
- package/dist/loop/notifications/Notifier.d.ts +28 -0
- package/dist/loop/notifications/Notifier.js +78 -0
- package/dist/loop/notifications/SlackNotifier.d.ts +28 -0
- package/dist/loop/notifications/SlackNotifier.js +203 -0
- package/dist/loop/notifications/TerminalNotifier.d.ts +18 -0
- package/dist/loop/notifications/TerminalNotifier.js +72 -0
- package/dist/loop/notifications/WebhookNotifier.d.ts +24 -0
- package/dist/loop/notifications/WebhookNotifier.js +123 -0
- package/dist/loop/notifications/index.d.ts +24 -0
- package/dist/loop/notifications/index.js +109 -0
- package/dist/loop/types.d.ts +280 -0
- package/dist/loop/types.js +222 -0
- package/package.json +92 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
function getPriorityWeight(priority) {
|
|
3
|
+
switch (priority) {
|
|
4
|
+
case 'high': return 10;
|
|
5
|
+
case 'medium': return 5;
|
|
6
|
+
case 'low': return 1;
|
|
7
|
+
default: return 5;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
import { GoalError } from './errors.js';
|
|
11
|
+
const DEFAULT_MAX_TASKS_PER_DAY = 20;
|
|
12
|
+
const DEFAULT_QUIET_HOURS = {
|
|
13
|
+
start: 22,
|
|
14
|
+
end: 6,
|
|
15
|
+
};
|
|
16
|
+
const noopLogger = {
|
|
17
|
+
debug: () => { },
|
|
18
|
+
info: () => { },
|
|
19
|
+
warn: () => { },
|
|
20
|
+
error: () => { },
|
|
21
|
+
};
|
|
22
|
+
export class TaskQueueError extends GoalError {
|
|
23
|
+
constructor(message, cause) {
|
|
24
|
+
super('TASK_EXECUTION_ERROR', message, cause ? { cause } : {});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class QuotaExceededError extends GoalError {
|
|
28
|
+
constructor(executed, max) {
|
|
29
|
+
super('TASK_QUOTA_EXCEEDED', `Daily task quota exceeded (${executed}/${max})`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class TaskQueue extends EventEmitter {
|
|
33
|
+
maxTasksPerDay;
|
|
34
|
+
quietHours;
|
|
35
|
+
enforceQuietHours;
|
|
36
|
+
typeWeights;
|
|
37
|
+
logger;
|
|
38
|
+
tasks;
|
|
39
|
+
executedToday = 0;
|
|
40
|
+
lastResetDate = '';
|
|
41
|
+
quietHoursTimer = null;
|
|
42
|
+
constructor(options = {}) {
|
|
43
|
+
super();
|
|
44
|
+
this.maxTasksPerDay = options.maxTasksPerDay ?? DEFAULT_MAX_TASKS_PER_DAY;
|
|
45
|
+
this.quietHours = options.quietHours ?? DEFAULT_QUIET_HOURS;
|
|
46
|
+
this.enforceQuietHours = options.enforceQuietHours ?? true;
|
|
47
|
+
this.logger = options.logger ?? noopLogger;
|
|
48
|
+
this.typeWeights = new Map([
|
|
49
|
+
['research', 1.0],
|
|
50
|
+
['draft', 1.2],
|
|
51
|
+
['code', 1.5],
|
|
52
|
+
['execute', 2.0],
|
|
53
|
+
['recipe', 1.8],
|
|
54
|
+
['loop', 1.0],
|
|
55
|
+
['notify', 0.5],
|
|
56
|
+
]);
|
|
57
|
+
if (options.typeWeights) {
|
|
58
|
+
for (const [type, weight] of Object.entries(options.typeWeights)) {
|
|
59
|
+
this.typeWeights.set(type, weight);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
this.tasks = new Map();
|
|
63
|
+
this.resetDailyCounterIfNeeded();
|
|
64
|
+
}
|
|
65
|
+
addTask(task, goalHash) {
|
|
66
|
+
if (!this.tasks.has(goalHash)) {
|
|
67
|
+
this.tasks.set(goalHash, new Map());
|
|
68
|
+
}
|
|
69
|
+
const goalTasks = this.tasks.get(goalHash);
|
|
70
|
+
goalTasks.set(task.id, task);
|
|
71
|
+
this.logger.debug('TASK_QUEUE', 'Task added', {
|
|
72
|
+
taskId: task.id,
|
|
73
|
+
goalHash,
|
|
74
|
+
type: task.taskType,
|
|
75
|
+
priority: task.priority,
|
|
76
|
+
});
|
|
77
|
+
this.emit('taskAdded', task, goalHash);
|
|
78
|
+
}
|
|
79
|
+
addTasks(tasks, goalHash) {
|
|
80
|
+
for (const task of tasks) {
|
|
81
|
+
this.addTask(task, goalHash);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
removeTask(taskId, goalHash, reason = 'removed') {
|
|
85
|
+
const goalTasks = this.tasks.get(goalHash);
|
|
86
|
+
if (!goalTasks) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
const removed = goalTasks.delete(taskId);
|
|
90
|
+
if (removed) {
|
|
91
|
+
this.logger.debug('TASK_QUEUE', 'Task removed', {
|
|
92
|
+
taskId,
|
|
93
|
+
goalHash,
|
|
94
|
+
reason,
|
|
95
|
+
});
|
|
96
|
+
this.emit('taskRemoved', taskId, goalHash, reason);
|
|
97
|
+
if (goalTasks.size === 0) {
|
|
98
|
+
this.tasks.delete(goalHash);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return removed;
|
|
102
|
+
}
|
|
103
|
+
getNextTask(options = {}) {
|
|
104
|
+
this.resetDailyCounterIfNeeded();
|
|
105
|
+
this.pruneExpiredTasks();
|
|
106
|
+
if (this.executedToday >= this.maxTasksPerDay) {
|
|
107
|
+
this.logger.debug('TASK_QUEUE', 'Quota reached, no tasks available');
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const readyTasks = this.getReadyTasks(options);
|
|
111
|
+
if (readyTasks.length === 0) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return readyTasks[0];
|
|
115
|
+
}
|
|
116
|
+
getTasks(options = {}) {
|
|
117
|
+
this.pruneExpiredTasks();
|
|
118
|
+
const result = [];
|
|
119
|
+
for (const [goalHash, goalTasks] of this.tasks) {
|
|
120
|
+
if (options.goalHash && goalHash !== options.goalHash) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
for (const task of goalTasks.values()) {
|
|
124
|
+
if (options.type && task.taskType !== options.type) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (options.status && task.status !== options.status) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const queued = this.createQueuedTask(task, goalHash);
|
|
131
|
+
if (options.readyOnly && !queued.isReady) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
result.push(queued);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
result.sort((a, b) => b.priorityScore - a.priorityScore);
|
|
138
|
+
if (options.limit && options.limit > 0) {
|
|
139
|
+
return result.slice(0, options.limit);
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
getReadyTasks(options = {}) {
|
|
144
|
+
return this.getTasks({ ...options, readyOnly: true });
|
|
145
|
+
}
|
|
146
|
+
markTaskStarted(taskId, goalHash) {
|
|
147
|
+
this.resetDailyCounterIfNeeded();
|
|
148
|
+
this.executedToday++;
|
|
149
|
+
this.logger.debug('TASK_QUEUE', 'Task started', {
|
|
150
|
+
taskId,
|
|
151
|
+
goalHash,
|
|
152
|
+
executedToday: this.executedToday,
|
|
153
|
+
});
|
|
154
|
+
if (this.executedToday >= this.maxTasksPerDay) {
|
|
155
|
+
this.emit('quotaReached', this.executedToday);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
clearGoal(goalHash) {
|
|
159
|
+
const goalTasks = this.tasks.get(goalHash);
|
|
160
|
+
if (!goalTasks) {
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
const count = goalTasks.size;
|
|
164
|
+
this.tasks.delete(goalHash);
|
|
165
|
+
this.logger.info('TASK_QUEUE', 'Goal cleared', { goalHash, count });
|
|
166
|
+
this.emit('queueCleared', goalHash);
|
|
167
|
+
return count;
|
|
168
|
+
}
|
|
169
|
+
clearAll() {
|
|
170
|
+
let total = 0;
|
|
171
|
+
for (const goalTasks of this.tasks.values()) {
|
|
172
|
+
total += goalTasks.size;
|
|
173
|
+
}
|
|
174
|
+
this.tasks.clear();
|
|
175
|
+
this.logger.info('TASK_QUEUE', 'Queue cleared', { count: total });
|
|
176
|
+
this.emit('queueCleared');
|
|
177
|
+
return total;
|
|
178
|
+
}
|
|
179
|
+
getStats() {
|
|
180
|
+
this.resetDailyCounterIfNeeded();
|
|
181
|
+
let totalPending = 0;
|
|
182
|
+
let readyCount = 0;
|
|
183
|
+
let scheduledCount = 0;
|
|
184
|
+
let expiredCount = 0;
|
|
185
|
+
const byGoal = new Map();
|
|
186
|
+
const byType = new Map();
|
|
187
|
+
const now = new Date();
|
|
188
|
+
for (const [goalHash, goalTasks] of this.tasks) {
|
|
189
|
+
byGoal.set(goalHash, goalTasks.size);
|
|
190
|
+
for (const task of goalTasks.values()) {
|
|
191
|
+
totalPending++;
|
|
192
|
+
byType.set(task.taskType, (byType.get(task.taskType) ?? 0) + 1);
|
|
193
|
+
if (task.expiresAt && new Date(task.expiresAt) < now) {
|
|
194
|
+
expiredCount++;
|
|
195
|
+
}
|
|
196
|
+
else if (task.scheduledFor && new Date(task.scheduledFor) > now) {
|
|
197
|
+
scheduledCount++;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
readyCount++;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
totalPending,
|
|
206
|
+
readyCount,
|
|
207
|
+
scheduledCount,
|
|
208
|
+
expiredCount,
|
|
209
|
+
executedToday: this.executedToday,
|
|
210
|
+
remainingQuota: Math.max(0, this.maxTasksPerDay - this.executedToday),
|
|
211
|
+
inQuietHours: this.isInQuietHours(),
|
|
212
|
+
byGoal,
|
|
213
|
+
byType,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
isInQuietHours() {
|
|
217
|
+
if (!this.enforceQuietHours) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
const now = new Date();
|
|
221
|
+
const hour = now.getHours();
|
|
222
|
+
if (this.quietHours.start > this.quietHours.end) {
|
|
223
|
+
return hour >= this.quietHours.start || hour < this.quietHours.end;
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
return hour >= this.quietHours.start && hour < this.quietHours.end;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
hasQuota() {
|
|
230
|
+
this.resetDailyCounterIfNeeded();
|
|
231
|
+
return this.executedToday < this.maxTasksPerDay;
|
|
232
|
+
}
|
|
233
|
+
stop() {
|
|
234
|
+
if (this.quietHoursTimer) {
|
|
235
|
+
clearTimeout(this.quietHoursTimer);
|
|
236
|
+
this.quietHoursTimer = null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
createQueuedTask(task, goalHash) {
|
|
240
|
+
const now = new Date();
|
|
241
|
+
const priorityScore = this.calculatePriorityScore(task);
|
|
242
|
+
let isReady = true;
|
|
243
|
+
let notReadyReason;
|
|
244
|
+
if (task.expiresAt && new Date(task.expiresAt) < now) {
|
|
245
|
+
isReady = false;
|
|
246
|
+
notReadyReason = 'Task has expired';
|
|
247
|
+
}
|
|
248
|
+
if (task.scheduledFor && new Date(task.scheduledFor) > now) {
|
|
249
|
+
isReady = false;
|
|
250
|
+
notReadyReason = `Scheduled for ${task.scheduledFor}`;
|
|
251
|
+
}
|
|
252
|
+
if (this.isInQuietHours()) {
|
|
253
|
+
isReady = false;
|
|
254
|
+
notReadyReason = 'Currently in quiet hours';
|
|
255
|
+
}
|
|
256
|
+
if (this.executedToday >= this.maxTasksPerDay) {
|
|
257
|
+
isReady = false;
|
|
258
|
+
notReadyReason = 'Daily quota reached';
|
|
259
|
+
}
|
|
260
|
+
if (task.status !== 'pending' && task.status !== 'awaiting_approval') {
|
|
261
|
+
isReady = false;
|
|
262
|
+
notReadyReason = `Task status is ${task.status}`;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
task,
|
|
266
|
+
goalHash,
|
|
267
|
+
queuedAt: new Date(task.createdAt),
|
|
268
|
+
priorityScore,
|
|
269
|
+
isReady,
|
|
270
|
+
notReadyReason,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
calculatePriorityScore(task) {
|
|
274
|
+
let score = getPriorityWeight(task.priority);
|
|
275
|
+
const typeWeight = this.typeWeights.get(task.taskType) ?? 1.0;
|
|
276
|
+
score *= typeWeight;
|
|
277
|
+
if (task.expiresAt) {
|
|
278
|
+
const now = new Date();
|
|
279
|
+
const expires = new Date(task.expiresAt);
|
|
280
|
+
const hoursUntilExpiry = (expires.getTime() - now.getTime()) / (1000 * 60 * 60);
|
|
281
|
+
if (hoursUntilExpiry > 0 && hoursUntilExpiry < 24) {
|
|
282
|
+
score *= 1.5;
|
|
283
|
+
}
|
|
284
|
+
else if (hoursUntilExpiry > 0 && hoursUntilExpiry < 4) {
|
|
285
|
+
score *= 2.0;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const ageHours = (Date.now() - new Date(task.createdAt).getTime()) / (1000 * 60 * 60);
|
|
289
|
+
if (ageHours > 24) {
|
|
290
|
+
score *= 1.1;
|
|
291
|
+
}
|
|
292
|
+
return score;
|
|
293
|
+
}
|
|
294
|
+
pruneExpiredTasks() {
|
|
295
|
+
const now = new Date();
|
|
296
|
+
for (const [goalHash, goalTasks] of this.tasks) {
|
|
297
|
+
const expired = [];
|
|
298
|
+
for (const task of goalTasks.values()) {
|
|
299
|
+
if (task.expiresAt && new Date(task.expiresAt) < now) {
|
|
300
|
+
expired.push(task.id);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
for (const taskId of expired) {
|
|
304
|
+
const task = goalTasks.get(taskId);
|
|
305
|
+
goalTasks.delete(taskId);
|
|
306
|
+
if (task) {
|
|
307
|
+
this.logger.info('TASK_QUEUE', 'Task expired', {
|
|
308
|
+
taskId,
|
|
309
|
+
goalHash,
|
|
310
|
+
title: task.title,
|
|
311
|
+
});
|
|
312
|
+
this.emit('taskExpired', task, goalHash);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (goalTasks.size === 0) {
|
|
316
|
+
this.tasks.delete(goalHash);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
resetDailyCounterIfNeeded() {
|
|
321
|
+
const today = new Date().toISOString().split('T')[0];
|
|
322
|
+
if (this.lastResetDate !== today) {
|
|
323
|
+
this.executedToday = 0;
|
|
324
|
+
this.lastResetDate = today;
|
|
325
|
+
this.logger.debug('TASK_QUEUE', 'Daily counter reset', { date: today });
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
export function createTaskQueue(options = {}) {
|
|
330
|
+
return new TaskQueue(options);
|
|
331
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { CreateTaskInput, Logger } from './types.js';
|
|
2
|
+
import { GoalError } from './errors.js';
|
|
3
|
+
export interface SanitizationResult {
|
|
4
|
+
readonly isValid: boolean;
|
|
5
|
+
readonly sanitizedInput: CreateTaskInput | null;
|
|
6
|
+
readonly warnings: string[];
|
|
7
|
+
readonly blocked: boolean;
|
|
8
|
+
readonly blockReason?: string;
|
|
9
|
+
readonly securityIssues: SecurityIssue[];
|
|
10
|
+
readonly modifications: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface SecurityIssue {
|
|
13
|
+
readonly type: SecurityIssueType;
|
|
14
|
+
readonly severity: 'low' | 'medium' | 'high' | 'critical';
|
|
15
|
+
readonly description: string;
|
|
16
|
+
readonly location?: string;
|
|
17
|
+
readonly matchedPattern?: string;
|
|
18
|
+
}
|
|
19
|
+
export type SecurityIssueType = 'prompt_injection' | 'command_injection' | 'path_traversal' | 'sensitive_path' | 'dangerous_command' | 'control_character' | 'excessive_length' | 'suspicious_pattern' | 'encoding_attack';
|
|
20
|
+
export interface TaskSanitizerOptions {
|
|
21
|
+
readonly allowedPaths?: string[];
|
|
22
|
+
readonly deniedPaths?: string[];
|
|
23
|
+
readonly allowedCommands?: string[];
|
|
24
|
+
readonly deniedCommands?: string[];
|
|
25
|
+
readonly maxTitleLength?: number;
|
|
26
|
+
readonly maxDescriptionLength?: number;
|
|
27
|
+
readonly strictMode?: boolean;
|
|
28
|
+
readonly customBlockedPatterns?: RegExp[];
|
|
29
|
+
readonly logger?: Logger;
|
|
30
|
+
}
|
|
31
|
+
export interface PathValidationResult {
|
|
32
|
+
isValid: boolean;
|
|
33
|
+
normalizedPath: string;
|
|
34
|
+
issues: SecurityIssue[];
|
|
35
|
+
}
|
|
36
|
+
export declare class TaskSanitizationError extends GoalError {
|
|
37
|
+
readonly issues: SecurityIssue[];
|
|
38
|
+
constructor(message: string, issues: SecurityIssue[]);
|
|
39
|
+
}
|
|
40
|
+
export declare class TaskSanitizer {
|
|
41
|
+
private readonly allowedPaths;
|
|
42
|
+
private readonly deniedPaths;
|
|
43
|
+
private readonly allowedCommands;
|
|
44
|
+
private readonly deniedCommands;
|
|
45
|
+
private readonly maxTitleLength;
|
|
46
|
+
private readonly maxDescriptionLength;
|
|
47
|
+
private readonly strictMode;
|
|
48
|
+
private readonly customBlockedPatterns;
|
|
49
|
+
private readonly logger;
|
|
50
|
+
constructor(options?: TaskSanitizerOptions);
|
|
51
|
+
sanitize(input: CreateTaskInput): SanitizationResult;
|
|
52
|
+
validatePath(path: string): PathValidationResult;
|
|
53
|
+
validateCommand(command: string): SecurityIssue[];
|
|
54
|
+
private checkPromptInjection;
|
|
55
|
+
private checkDangerousCommands;
|
|
56
|
+
private checkCustomPatterns;
|
|
57
|
+
private sanitizeText;
|
|
58
|
+
private matchesGlob;
|
|
59
|
+
}
|
|
60
|
+
export declare function createTaskSanitizer(options?: TaskSanitizerOptions): TaskSanitizer;
|
|
61
|
+
export declare function createSecureTaskSanitizer(logger?: Logger): TaskSanitizer;
|