watchfix 0.2.1 → 0.2.2
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/dist/config/schema.d.ts +13 -0
- package/dist/config/schema.js +5 -0
- package/dist/watcher/index.js +17 -0
- package/dist/watcher/sources/file.js +4 -6
- package/package.json +15 -1
package/dist/config/schema.d.ts
CHANGED
|
@@ -259,6 +259,13 @@ declare const configSchema: z.ZodObject<{
|
|
|
259
259
|
context_max_age_days?: number | undefined;
|
|
260
260
|
context_max_size_kb?: number | undefined;
|
|
261
261
|
}>>;
|
|
262
|
+
deduplication: z.ZodDefault<z.ZodObject<{
|
|
263
|
+
fixed_grace_period: z.ZodDefault<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
264
|
+
}, "strip", z.ZodTypeAny, {
|
|
265
|
+
fixed_grace_period: string;
|
|
266
|
+
}, {
|
|
267
|
+
fixed_grace_period?: string | undefined;
|
|
268
|
+
}>>;
|
|
262
269
|
patterns: z.ZodDefault<z.ZodObject<{
|
|
263
270
|
match: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
264
271
|
ignore: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -315,6 +322,9 @@ declare const configSchema: z.ZodObject<{
|
|
|
315
322
|
context_max_age_days: number;
|
|
316
323
|
context_max_size_kb: number;
|
|
317
324
|
};
|
|
325
|
+
deduplication: {
|
|
326
|
+
fixed_grace_period: string;
|
|
327
|
+
};
|
|
318
328
|
patterns: {
|
|
319
329
|
ignore: string[];
|
|
320
330
|
match: string[];
|
|
@@ -365,6 +375,9 @@ declare const configSchema: z.ZodObject<{
|
|
|
365
375
|
context_max_age_days?: number | undefined;
|
|
366
376
|
context_max_size_kb?: number | undefined;
|
|
367
377
|
} | undefined;
|
|
378
|
+
deduplication?: {
|
|
379
|
+
fixed_grace_period?: string | undefined;
|
|
380
|
+
} | undefined;
|
|
368
381
|
patterns?: {
|
|
369
382
|
ignore?: string[] | undefined;
|
|
370
383
|
match?: string[] | undefined;
|
package/dist/config/schema.js
CHANGED
|
@@ -89,6 +89,11 @@ const configSchema = z.object({
|
|
|
89
89
|
context_max_size_kb: z.number().int().min(64).default(256),
|
|
90
90
|
})
|
|
91
91
|
.default({}),
|
|
92
|
+
deduplication: z
|
|
93
|
+
.object({
|
|
94
|
+
fixed_grace_period: durationSchema.default('10m'),
|
|
95
|
+
})
|
|
96
|
+
.default({}),
|
|
92
97
|
patterns: z
|
|
93
98
|
.object({
|
|
94
99
|
match: z.array(patternSchema).default([]),
|
package/dist/watcher/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import { getErrorByHash, insertError, logActivity } from '../db/queries.js';
|
|
3
|
+
import { parseDuration } from '../utils/duration.js';
|
|
3
4
|
import { Logger } from '../utils/logger.js';
|
|
4
5
|
import { ErrorParser } from './parser.js';
|
|
5
6
|
import { CommandSource } from './sources/command.js';
|
|
@@ -186,6 +187,22 @@ export class WatcherOrchestrator {
|
|
|
186
187
|
});
|
|
187
188
|
return;
|
|
188
189
|
}
|
|
190
|
+
// Deduplicate fixed errors within grace period to prevent re-detection
|
|
191
|
+
// after a fix when the log file is re-read
|
|
192
|
+
if (existing && existing.status === 'fixed') {
|
|
193
|
+
const gracePeriodMs = parseDuration(this.config.deduplication.fixed_grace_period);
|
|
194
|
+
const fixedAt = new Date(existing.updatedAt).getTime();
|
|
195
|
+
if (Date.now() - fixedAt < gracePeriodMs) {
|
|
196
|
+
logActivity(this.db, 'error_deduplicated', existing.id, `status=${existing.status} grace_period=true`);
|
|
197
|
+
this.logger.info(`Deduplicated error ${error.hash} (within grace period after fix)`);
|
|
198
|
+
this.emitter.emit('error_deduplicated', {
|
|
199
|
+
errorId: existing.id,
|
|
200
|
+
error,
|
|
201
|
+
status: existing.status,
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
189
206
|
const newId = insertError(this.db, {
|
|
190
207
|
hash: error.hash,
|
|
191
208
|
source: error.source,
|
|
@@ -125,14 +125,12 @@ export class FileSource {
|
|
|
125
125
|
}
|
|
126
126
|
const inode = typeof stats.ino === 'number' ? stats.ino : null;
|
|
127
127
|
const mtimeMs = stats.mtimeMs;
|
|
128
|
-
const shouldForceRead = this.forceRead;
|
|
129
128
|
this.forceRead = false;
|
|
130
129
|
const inodeChanged = this.lastInode !== null && inode !== null && inode !== this.lastInode;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
(mtimeChanged && stats.size === this.position && this.position > 0)) {
|
|
130
|
+
// Only reset position on actual file replacement (inode change) or truncation (size shrunk)
|
|
131
|
+
// Do NOT reset on mtime changes without content changes - this prevents re-reading
|
|
132
|
+
// old errors when the file is touched but no new content is added
|
|
133
|
+
if (inodeChanged || stats.size < this.position) {
|
|
136
134
|
this.position = 0;
|
|
137
135
|
this.partialLine = '';
|
|
138
136
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "watchfix",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "CLI tool that watches logs, detects errors, and dispatches AI agents to fix them",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cli",
|
|
7
|
+
"log-watcher",
|
|
8
|
+
"error-detection",
|
|
9
|
+
"ai",
|
|
10
|
+
"ai-agent",
|
|
11
|
+
"automation",
|
|
12
|
+
"auto-fix",
|
|
13
|
+
"llm",
|
|
14
|
+
"devtools",
|
|
15
|
+
"monitoring",
|
|
16
|
+
"logs",
|
|
17
|
+
"debugging"
|
|
18
|
+
],
|
|
5
19
|
"type": "module",
|
|
6
20
|
"bin": {
|
|
7
21
|
"watchfix": "./dist/cli/index.js"
|