trailhound 0.2.1
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 +118 -0
- package/README.md +325 -0
- package/dist/adapters/claude-code.d.ts +25 -0
- package/dist/adapters/claude-code.d.ts.map +1 -0
- package/dist/adapters/claude-code.js +88 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +25 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +72 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/openclaw.d.ts +49 -0
- package/dist/adapters/openclaw.d.ts.map +1 -0
- package/dist/adapters/openclaw.js +180 -0
- package/dist/adapters/openclaw.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +226 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/run-store.d.ts +15 -0
- package/dist/core/run-store.d.ts.map +1 -0
- package/dist/core/run-store.js +88 -0
- package/dist/core/run-store.js.map +1 -0
- package/dist/core/trace-writer.d.ts +22 -0
- package/dist/core/trace-writer.d.ts.map +1 -0
- package/dist/core/trace-writer.js +91 -0
- package/dist/core/trace-writer.js.map +1 -0
- package/dist/core/trailhound.d.ts +42 -0
- package/dist/core/trailhound.d.ts.map +1 -0
- package/dist/core/trailhound.js +351 -0
- package/dist/core/trailhound.js.map +1 -0
- package/dist/policies/policy-engine.d.ts +15 -0
- package/dist/policies/policy-engine.d.ts.map +1 -0
- package/dist/policies/policy-engine.js +205 -0
- package/dist/policies/policy-engine.js.map +1 -0
- package/dist/recorders/filesystem-monitor.d.ts +33 -0
- package/dist/recorders/filesystem-monitor.d.ts.map +1 -0
- package/dist/recorders/filesystem-monitor.js +262 -0
- package/dist/recorders/filesystem-monitor.js.map +1 -0
- package/dist/recorders/git-snapshotter.d.ts +17 -0
- package/dist/recorders/git-snapshotter.d.ts.map +1 -0
- package/dist/recorders/git-snapshotter.js +116 -0
- package/dist/recorders/git-snapshotter.js.map +1 -0
- package/dist/recorders/network-monitor.d.ts +18 -0
- package/dist/recorders/network-monitor.d.ts.map +1 -0
- package/dist/recorders/network-monitor.js +67 -0
- package/dist/recorders/network-monitor.js.map +1 -0
- package/dist/recorders/network-proxy.d.ts +31 -0
- package/dist/recorders/network-proxy.d.ts.map +1 -0
- package/dist/recorders/network-proxy.js +163 -0
- package/dist/recorders/network-proxy.js.map +1 -0
- package/dist/recorders/process-monitor.d.ts +14 -0
- package/dist/recorders/process-monitor.d.ts.map +1 -0
- package/dist/recorders/process-monitor.js +47 -0
- package/dist/recorders/process-monitor.js.map +1 -0
- package/dist/recorders/process-wrapper.d.ts +37 -0
- package/dist/recorders/process-wrapper.d.ts.map +1 -0
- package/dist/recorders/process-wrapper.js +152 -0
- package/dist/recorders/process-wrapper.js.map +1 -0
- package/dist/recorders/secret-detector.d.ts +26 -0
- package/dist/recorders/secret-detector.d.ts.map +1 -0
- package/dist/recorders/secret-detector.js +148 -0
- package/dist/recorders/secret-detector.js.map +1 -0
- package/dist/reports/report-generator.d.ts +19 -0
- package/dist/reports/report-generator.d.ts.map +1 -0
- package/dist/reports/report-generator.js +274 -0
- package/dist/reports/report-generator.js.map +1 -0
- package/dist/types/index.d.ts +132 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/exec.d.ts +6 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +10 -0
- package/dist/utils/exec.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Policy Engine
|
|
4
|
+
* Evaluates events against policies and makes decisions
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.PolicyEngine = void 0;
|
|
41
|
+
const fs = __importStar(require("fs/promises"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const yaml = __importStar(require("yaml"));
|
|
44
|
+
const DEFAULT_POLICY = {
|
|
45
|
+
mode: "record",
|
|
46
|
+
secrets: { warn: true },
|
|
47
|
+
};
|
|
48
|
+
const BLOCKED_COMMANDS = [
|
|
49
|
+
/^rm\s+-rf\s+\/$/,
|
|
50
|
+
/^rm\s+-rf\s+\/\s/,
|
|
51
|
+
/^curl\s+.*\|\s*(bash|sh)$/,
|
|
52
|
+
/^wget\s+.*\|\s*(bash|sh)$/,
|
|
53
|
+
/^curl\s+.*\|\s*sudo/,
|
|
54
|
+
/^chmod\s+777/,
|
|
55
|
+
];
|
|
56
|
+
const REQUIRE_APPROVAL_COMMANDS = [
|
|
57
|
+
/^npm\s+install/,
|
|
58
|
+
/^pip\s+install/,
|
|
59
|
+
/^brew\s+install/,
|
|
60
|
+
/^docker\s+run/,
|
|
61
|
+
/^gh\s+secret/,
|
|
62
|
+
];
|
|
63
|
+
class PolicyEngine {
|
|
64
|
+
policy = DEFAULT_POLICY;
|
|
65
|
+
async load() {
|
|
66
|
+
try {
|
|
67
|
+
const policyPath = path.join(process.cwd(), ".trailhound", "policy.yml");
|
|
68
|
+
const content = await fs.readFile(policyPath, "utf-8");
|
|
69
|
+
this.policy = yaml.parse(content);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Use defaults if no policy file
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
evaluateFilesystem(event) {
|
|
76
|
+
if (this.policy.mode === "record") {
|
|
77
|
+
return { action: "allow" };
|
|
78
|
+
}
|
|
79
|
+
// Check blocked paths
|
|
80
|
+
if (this.policy.blockedPaths) {
|
|
81
|
+
for (const blocked of this.policy.blockedPaths) {
|
|
82
|
+
if (this.matchPattern(event.path, blocked)) {
|
|
83
|
+
return {
|
|
84
|
+
action: this.policy.mode === "enforce" ? "block" : "warn",
|
|
85
|
+
reason: `Access to blocked path: ${blocked}`,
|
|
86
|
+
rule: "blocked_paths",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Check allowed paths (if whitelist mode)
|
|
92
|
+
if (this.policy.allowedPaths) {
|
|
93
|
+
let allowed = false;
|
|
94
|
+
for (const allowedPath of this.policy.allowedPaths) {
|
|
95
|
+
if (this.matchPattern(event.path, allowedPath)) {
|
|
96
|
+
allowed = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!allowed) {
|
|
101
|
+
return {
|
|
102
|
+
action: this.policy.mode === "enforce" ? "block" : "warn",
|
|
103
|
+
reason: "Path not in allowed_paths",
|
|
104
|
+
rule: "allowed_paths",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { action: "allow" };
|
|
109
|
+
}
|
|
110
|
+
evaluateCommand(event) {
|
|
111
|
+
if (this.policy.mode === "record") {
|
|
112
|
+
return { action: "allow" };
|
|
113
|
+
}
|
|
114
|
+
const command = event.argv.join(" ");
|
|
115
|
+
// Check blocked commands
|
|
116
|
+
for (const pattern of BLOCKED_COMMANDS) {
|
|
117
|
+
if (pattern.test(command)) {
|
|
118
|
+
return {
|
|
119
|
+
action: this.policy.mode === "enforce" ? "block" : "warn",
|
|
120
|
+
reason: `Blocked command pattern matched`,
|
|
121
|
+
rule: "commands.block",
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Check require_approval commands
|
|
126
|
+
if (this.policy.commands?.requireApproval) {
|
|
127
|
+
for (const pattern of this.policy.commands.requireApproval) {
|
|
128
|
+
if (this.matchGlobs(pattern, command)) {
|
|
129
|
+
return {
|
|
130
|
+
action: "require_approval",
|
|
131
|
+
reason: `Command requires approval: ${pattern}`,
|
|
132
|
+
rule: "commands.require_approval",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Check block list
|
|
138
|
+
if (this.policy.commands?.block) {
|
|
139
|
+
for (const blocked of this.policy.commands.block) {
|
|
140
|
+
if (this.matchGlobs(blocked, command)) {
|
|
141
|
+
return {
|
|
142
|
+
action: this.policy.mode === "enforce" ? "block" : "warn",
|
|
143
|
+
reason: `Command matches blocked pattern: ${blocked}`,
|
|
144
|
+
rule: "commands.block",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Also check generic blocked patterns
|
|
150
|
+
for (const pattern of REQUIRE_APPROVAL_COMMANDS) {
|
|
151
|
+
if (pattern.test(command)) {
|
|
152
|
+
return {
|
|
153
|
+
action: "warn",
|
|
154
|
+
reason: `Potentially risky command detected`,
|
|
155
|
+
rule: "commands.suspicious",
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { action: "allow" };
|
|
160
|
+
}
|
|
161
|
+
evaluateNetwork(event) {
|
|
162
|
+
if (this.policy.mode === "record") {
|
|
163
|
+
return { action: "allow" };
|
|
164
|
+
}
|
|
165
|
+
if (!event.host) {
|
|
166
|
+
return { action: "allow" };
|
|
167
|
+
}
|
|
168
|
+
const isAllowed = this.policy.network?.allow?.some(pattern => this.matchPattern(event.host, pattern)) ?? false;
|
|
169
|
+
if (isAllowed) {
|
|
170
|
+
return { action: "allow" };
|
|
171
|
+
}
|
|
172
|
+
const isBlocked = this.policy.network?.block?.some(pattern => this.matchPattern(event.host, pattern)) ?? false;
|
|
173
|
+
if (isBlocked) {
|
|
174
|
+
return {
|
|
175
|
+
action: this.policy.mode === "enforce" ? "block" : "warn",
|
|
176
|
+
reason: `Host is blocked: ${event.host}`,
|
|
177
|
+
rule: "network.block",
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// Unknown domain handling
|
|
181
|
+
if (this.policy.network?.unknownDomains === "warn") {
|
|
182
|
+
return {
|
|
183
|
+
action: "warn",
|
|
184
|
+
reason: `Unknown external domain: ${event.host}`,
|
|
185
|
+
rule: "network.unknown",
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return { action: "allow" };
|
|
189
|
+
}
|
|
190
|
+
matchPattern(value, pattern) {
|
|
191
|
+
// Support glob patterns
|
|
192
|
+
const regex = new RegExp("^" + pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
193
|
+
return regex.test(value);
|
|
194
|
+
}
|
|
195
|
+
matchGlobs(pattern, value) {
|
|
196
|
+
// Simple glob matching
|
|
197
|
+
const regex = pattern
|
|
198
|
+
.replace(/\*\*/g, ".*")
|
|
199
|
+
.replace(/\*/g, "[^ ]*")
|
|
200
|
+
.replace(/\?/g, ".");
|
|
201
|
+
return new RegExp(regex).test(value);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.PolicyEngine = PolicyEngine;
|
|
205
|
+
//# sourceMappingURL=policy-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-engine.js","sourceRoot":"","sources":["../../src/policies/policy-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem Monitor
|
|
3
|
+
* Smart file tracking using fd (find) for efficiency
|
|
4
|
+
*/
|
|
5
|
+
import { AgentEvent } from "../types/index.js";
|
|
6
|
+
export declare class FilesystemMonitor {
|
|
7
|
+
private watcher?;
|
|
8
|
+
private eventHandler?;
|
|
9
|
+
private runId;
|
|
10
|
+
private fileHashes;
|
|
11
|
+
private watchedFiles;
|
|
12
|
+
private rootPath;
|
|
13
|
+
start(rootPath: string, runId: string, onEvent: (event: AgentEvent) => void): Promise<void>;
|
|
14
|
+
stop(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Get list of paths to watch using fd (if available) or git
|
|
17
|
+
*/
|
|
18
|
+
private getWatchPaths;
|
|
19
|
+
private shouldIgnore;
|
|
20
|
+
private captureInitialState;
|
|
21
|
+
private handleFileChange;
|
|
22
|
+
private handleFileDelete;
|
|
23
|
+
private getFileSize;
|
|
24
|
+
private getFileHash;
|
|
25
|
+
/**
|
|
26
|
+
* Get list of files modified during this session
|
|
27
|
+
*/
|
|
28
|
+
getModifiedFiles(): Array<{
|
|
29
|
+
path: string;
|
|
30
|
+
hash?: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=filesystem-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-monitor.d.ts","sourceRoot":"","sources":["../../src/recorders/filesystem-monitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAa,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI1D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAC,CAAqB;IACrC,OAAO,CAAC,YAAY,CAAC,CAA8B;IACnD,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAc;IAExB,KAAK,CACT,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GACnC,OAAO,CAAC,IAAI,CAAC;IA8DV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B;;OAEG;YACW,aAAa;IAkD3B,OAAO,CAAC,YAAY;YAgBN,mBAAmB;YA0BnB,gBAAgB;IA2B9B,OAAO,CAAC,gBAAgB;YAeV,WAAW;YASX,WAAW;IAWzB;;OAEG;IACH,gBAAgB,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAM3D"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Filesystem Monitor
|
|
4
|
+
* Smart file tracking using fd (find) for efficiency
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.FilesystemMonitor = void 0;
|
|
41
|
+
const chokidar = __importStar(require("chokidar"));
|
|
42
|
+
const fs = __importStar(require("fs/promises"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const child_process_1 = require("child_process");
|
|
45
|
+
const util_1 = require("util");
|
|
46
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
47
|
+
class FilesystemMonitor {
|
|
48
|
+
watcher;
|
|
49
|
+
eventHandler;
|
|
50
|
+
runId = "";
|
|
51
|
+
fileHashes = new Map();
|
|
52
|
+
watchedFiles = new Set();
|
|
53
|
+
rootPath = "";
|
|
54
|
+
async start(rootPath, runId, onEvent) {
|
|
55
|
+
this.eventHandler = onEvent;
|
|
56
|
+
this.runId = runId;
|
|
57
|
+
this.rootPath = rootPath;
|
|
58
|
+
// Capture initial state of git-tracked and recently modified files
|
|
59
|
+
await this.captureInitialState(rootPath);
|
|
60
|
+
// Watch only specific files/dirs, not everything
|
|
61
|
+
const watchPaths = await this.getWatchPaths(rootPath);
|
|
62
|
+
if (watchPaths.length === 0) {
|
|
63
|
+
console.log("⚠️ No files to watch - running without file monitoring");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log(`📁 Watching ${watchPaths.length} paths...`);
|
|
67
|
+
this.watcher = chokidar.watch(watchPaths, {
|
|
68
|
+
ignored: [
|
|
69
|
+
/(^|[/\\])\../, // dotfiles
|
|
70
|
+
"**/node_modules/**",
|
|
71
|
+
"**/.git/**",
|
|
72
|
+
"**/dist/**",
|
|
73
|
+
"**/build/**",
|
|
74
|
+
"**/.trailhound/**",
|
|
75
|
+
"**/*.log",
|
|
76
|
+
"**/*.tmp",
|
|
77
|
+
"**/*.temp",
|
|
78
|
+
"**/.DS_Store",
|
|
79
|
+
"**/Thumbs.db",
|
|
80
|
+
],
|
|
81
|
+
persistent: true,
|
|
82
|
+
ignoreInitial: true,
|
|
83
|
+
followSymlinks: false,
|
|
84
|
+
awaitWriteFinish: {
|
|
85
|
+
stabilityThreshold: 100,
|
|
86
|
+
pollInterval: 50,
|
|
87
|
+
},
|
|
88
|
+
ignorePermissionErrors: true,
|
|
89
|
+
});
|
|
90
|
+
// Handle file events
|
|
91
|
+
this.watcher.on("add", (filePath) => this.handleFileChange(filePath, "add"));
|
|
92
|
+
this.watcher.on("change", (filePath) => this.handleFileChange(filePath, "change"));
|
|
93
|
+
this.watcher.on("unlink", (filePath) => this.handleFileDelete(filePath));
|
|
94
|
+
// Silent error handling
|
|
95
|
+
this.watcher.on("error", () => {
|
|
96
|
+
// Silently ignore - EMFILE etc handled by ignorePermissionErrors
|
|
97
|
+
});
|
|
98
|
+
// Wait for ready
|
|
99
|
+
await new Promise((resolve) => {
|
|
100
|
+
const timeout = setTimeout(() => resolve(), 3000);
|
|
101
|
+
this.watcher?.on("ready", () => {
|
|
102
|
+
clearTimeout(timeout);
|
|
103
|
+
resolve();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async stop() {
|
|
108
|
+
await this.watcher?.close();
|
|
109
|
+
this.watchedFiles.clear();
|
|
110
|
+
this.fileHashes.clear();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get list of paths to watch using fd (if available) or git
|
|
114
|
+
*/
|
|
115
|
+
async getWatchPaths(rootPath) {
|
|
116
|
+
const paths = [];
|
|
117
|
+
const maxFiles = 500; // Limit to prevent EMFILE
|
|
118
|
+
try {
|
|
119
|
+
// Try fd command first (fastest)
|
|
120
|
+
const { stdout: fdOutput } = await execAsync(`fd --type f --changed-within 1h --max-results ${maxFiles} . "${rootPath}" 2>/dev/null || echo ""`, { timeout: 5000 });
|
|
121
|
+
const fdFiles = fdOutput.split("\n").filter(f => f.trim() && !this.shouldIgnore(f));
|
|
122
|
+
paths.push(...fdFiles.slice(0, maxFiles));
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// fd not available, try git
|
|
126
|
+
try {
|
|
127
|
+
const { stdout: gitOutput } = await execAsync(`git ls-files --others --exclude-standard --modified 2>/dev/null | head -${maxFiles}`, { cwd: rootPath, timeout: 5000 });
|
|
128
|
+
const gitFiles = gitOutput.split("\n")
|
|
129
|
+
.filter(f => f.trim())
|
|
130
|
+
.map(f => path.join(rootPath, f));
|
|
131
|
+
paths.push(...gitFiles);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Not a git repo - fall back to watching nothing
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// If still empty, try to find recently modified files manually
|
|
138
|
+
if (paths.length === 0) {
|
|
139
|
+
try {
|
|
140
|
+
const entries = await fs.readdir(rootPath, { withFileTypes: true });
|
|
141
|
+
for (const entry of entries.slice(0, 50)) {
|
|
142
|
+
if (entry.isFile() && !this.shouldIgnore(entry.name)) {
|
|
143
|
+
paths.push(path.join(rootPath, entry.name));
|
|
144
|
+
}
|
|
145
|
+
else if (entry.isDirectory() && !this.shouldIgnore(entry.name)) {
|
|
146
|
+
// Add top-level dirs only
|
|
147
|
+
paths.push(path.join(rootPath, entry.name));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Can't read dir
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return [...new Set(paths)].slice(0, maxFiles);
|
|
156
|
+
}
|
|
157
|
+
shouldIgnore(filePath) {
|
|
158
|
+
const ignorePatterns = [
|
|
159
|
+
/node_modules/,
|
|
160
|
+
/\.git/,
|
|
161
|
+
/\.trailhound/,
|
|
162
|
+
/dist/,
|
|
163
|
+
/build/,
|
|
164
|
+
/Library/,
|
|
165
|
+
/Applications/,
|
|
166
|
+
/\.log$/,
|
|
167
|
+
/\.tmp$/,
|
|
168
|
+
/\.DS_Store$/,
|
|
169
|
+
];
|
|
170
|
+
return ignorePatterns.some(p => p.test(filePath));
|
|
171
|
+
}
|
|
172
|
+
async captureInitialState(rootPath) {
|
|
173
|
+
try {
|
|
174
|
+
// Get git-tracked files with hashes
|
|
175
|
+
const { stdout } = await execAsync("git ls-files | head -200", { cwd: rootPath, timeout: 3000 });
|
|
176
|
+
const files = stdout.split("\n").filter(f => f.trim());
|
|
177
|
+
for (const file of files) {
|
|
178
|
+
const fullPath = path.join(rootPath, file);
|
|
179
|
+
try {
|
|
180
|
+
const hash = await this.getFileHash(fullPath);
|
|
181
|
+
if (hash) {
|
|
182
|
+
this.fileHashes.set(fullPath, hash);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// Skip files we can't read
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
// Not a git repo
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async handleFileChange(filePath, eventType) {
|
|
195
|
+
try {
|
|
196
|
+
const relativePath = path.relative(this.rootPath, filePath);
|
|
197
|
+
const size = await this.getFileSize(filePath);
|
|
198
|
+
const hash = await this.getFileHash(filePath);
|
|
199
|
+
const beforeHash = this.fileHashes.get(filePath);
|
|
200
|
+
const event = {
|
|
201
|
+
ts: new Date().toISOString(),
|
|
202
|
+
type: eventType === "add" ? "file.write" : "file.write",
|
|
203
|
+
runId: this.runId,
|
|
204
|
+
path: relativePath,
|
|
205
|
+
size,
|
|
206
|
+
hash_after: hash,
|
|
207
|
+
hash_before: beforeHash,
|
|
208
|
+
};
|
|
209
|
+
if (hash) {
|
|
210
|
+
this.fileHashes.set(filePath, hash);
|
|
211
|
+
}
|
|
212
|
+
this.watchedFiles.add(filePath);
|
|
213
|
+
this.eventHandler?.(event);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Silently skip files we can't process
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
handleFileDelete(filePath) {
|
|
220
|
+
const relativePath = path.relative(this.rootPath, filePath);
|
|
221
|
+
const event = {
|
|
222
|
+
ts: new Date().toISOString(),
|
|
223
|
+
type: "file.delete",
|
|
224
|
+
runId: this.runId,
|
|
225
|
+
path: relativePath,
|
|
226
|
+
};
|
|
227
|
+
this.watchedFiles.delete(filePath);
|
|
228
|
+
this.fileHashes.delete(filePath);
|
|
229
|
+
this.eventHandler?.(event);
|
|
230
|
+
}
|
|
231
|
+
async getFileSize(filePath) {
|
|
232
|
+
try {
|
|
233
|
+
const stats = await fs.stat(filePath);
|
|
234
|
+
return stats.size;
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async getFileHash(filePath) {
|
|
241
|
+
try {
|
|
242
|
+
const content = await fs.readFile(filePath);
|
|
243
|
+
// Use crypto for proper hashing
|
|
244
|
+
const crypto = await import("crypto");
|
|
245
|
+
return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Get list of files modified during this session
|
|
253
|
+
*/
|
|
254
|
+
getModifiedFiles() {
|
|
255
|
+
return Array.from(this.watchedFiles).map(filePath => ({
|
|
256
|
+
path: path.relative(this.rootPath, filePath),
|
|
257
|
+
hash: this.fileHashes.get(filePath),
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
exports.FilesystemMonitor = FilesystemMonitor;
|
|
262
|
+
//# sourceMappingURL=filesystem-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem-monitor.js","sourceRoot":"","sources":["../../src/recorders/filesystem-monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Snapshotter
|
|
3
|
+
* Captures git state before and after agent runs
|
|
4
|
+
*/
|
|
5
|
+
import { GitInfo } from "../types/index.js";
|
|
6
|
+
export declare class GitSnapshotter {
|
|
7
|
+
private beforePatch?;
|
|
8
|
+
private afterPatch?;
|
|
9
|
+
private workspacePath?;
|
|
10
|
+
setWorkspace(path: string): void;
|
|
11
|
+
captureBefore(): Promise<void>;
|
|
12
|
+
captureAfter(): Promise<void>;
|
|
13
|
+
getInfo(): Promise<GitInfo>;
|
|
14
|
+
private getGitDiff;
|
|
15
|
+
private isGitRepo;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=git-snapshotter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-snapshotter.d.ts","sourceRoot":"","sources":["../../src/recorders/git-snapshotter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAC,CAAS;IAE/B,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI1B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAc9B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAc7B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IA6BjC,OAAO,CAAC,UAAU;YAQJ,SAAS;CAQxB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Git Snapshotter
|
|
4
|
+
* Captures git state before and after agent runs
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.GitSnapshotter = void 0;
|
|
41
|
+
const child_process_1 = require("child_process");
|
|
42
|
+
const fs = __importStar(require("fs/promises"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
class GitSnapshotter {
|
|
45
|
+
beforePatch;
|
|
46
|
+
afterPatch;
|
|
47
|
+
workspacePath;
|
|
48
|
+
setWorkspace(path) {
|
|
49
|
+
this.workspacePath = path;
|
|
50
|
+
}
|
|
51
|
+
async captureBefore() {
|
|
52
|
+
if (!this.workspacePath)
|
|
53
|
+
return;
|
|
54
|
+
const isRepo = await this.isGitRepo();
|
|
55
|
+
if (!isRepo)
|
|
56
|
+
return;
|
|
57
|
+
this.beforePatch = this.getGitDiff();
|
|
58
|
+
await fs.writeFile(path.join(this.workspacePath, "git-before.patch"), this.beforePatch || "");
|
|
59
|
+
}
|
|
60
|
+
async captureAfter() {
|
|
61
|
+
if (!this.workspacePath)
|
|
62
|
+
return;
|
|
63
|
+
const isRepo = await this.isGitRepo();
|
|
64
|
+
if (!isRepo)
|
|
65
|
+
return;
|
|
66
|
+
this.afterPatch = this.getGitDiff();
|
|
67
|
+
await fs.writeFile(path.join(this.workspacePath, "git-after.patch"), this.afterPatch || "");
|
|
68
|
+
}
|
|
69
|
+
async getInfo() {
|
|
70
|
+
const isRepo = await this.isGitRepo();
|
|
71
|
+
if (!isRepo) {
|
|
72
|
+
return { isRepo: false };
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const branch = (0, child_process_1.execSync)("git branch --show-current", { encoding: "utf-8" }).trim();
|
|
76
|
+
const commit = (0, child_process_1.execSync)("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
77
|
+
const status = (0, child_process_1.execSync)("git status --porcelain", { encoding: "utf-8" }).trim();
|
|
78
|
+
let remote;
|
|
79
|
+
try {
|
|
80
|
+
remote = (0, child_process_1.execSync)("git remote get-url origin", { encoding: "utf-8" }).trim();
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
remote = undefined;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
isRepo: true,
|
|
87
|
+
branch,
|
|
88
|
+
commit,
|
|
89
|
+
dirty: status.length > 0,
|
|
90
|
+
remoteUrl: remote,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return { isRepo: true };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
getGitDiff() {
|
|
98
|
+
try {
|
|
99
|
+
return (0, child_process_1.execSync)("git diff", { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return "";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async isGitRepo() {
|
|
106
|
+
try {
|
|
107
|
+
(0, child_process_1.execSync)("git rev-parse --git-dir", { stdio: "pipe" });
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.GitSnapshotter = GitSnapshotter;
|
|
116
|
+
//# sourceMappingURL=git-snapshotter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-snapshotter.js","sourceRoot":"","sources":["../../src/recorders/git-snapshotter.ts"],"names":[],"mappings":"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"}
|