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.
Files changed (75) hide show
  1. package/LICENSE +118 -0
  2. package/README.md +325 -0
  3. package/dist/adapters/claude-code.d.ts +25 -0
  4. package/dist/adapters/claude-code.d.ts.map +1 -0
  5. package/dist/adapters/claude-code.js +88 -0
  6. package/dist/adapters/claude-code.js.map +1 -0
  7. package/dist/adapters/codex.d.ts +25 -0
  8. package/dist/adapters/codex.d.ts.map +1 -0
  9. package/dist/adapters/codex.js +72 -0
  10. package/dist/adapters/codex.js.map +1 -0
  11. package/dist/adapters/openclaw.d.ts +49 -0
  12. package/dist/adapters/openclaw.d.ts.map +1 -0
  13. package/dist/adapters/openclaw.js +180 -0
  14. package/dist/adapters/openclaw.js.map +1 -0
  15. package/dist/cli.d.ts +7 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +226 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/core/run-store.d.ts +15 -0
  20. package/dist/core/run-store.d.ts.map +1 -0
  21. package/dist/core/run-store.js +88 -0
  22. package/dist/core/run-store.js.map +1 -0
  23. package/dist/core/trace-writer.d.ts +22 -0
  24. package/dist/core/trace-writer.d.ts.map +1 -0
  25. package/dist/core/trace-writer.js +91 -0
  26. package/dist/core/trace-writer.js.map +1 -0
  27. package/dist/core/trailhound.d.ts +42 -0
  28. package/dist/core/trailhound.d.ts.map +1 -0
  29. package/dist/core/trailhound.js +351 -0
  30. package/dist/core/trailhound.js.map +1 -0
  31. package/dist/policies/policy-engine.d.ts +15 -0
  32. package/dist/policies/policy-engine.d.ts.map +1 -0
  33. package/dist/policies/policy-engine.js +205 -0
  34. package/dist/policies/policy-engine.js.map +1 -0
  35. package/dist/recorders/filesystem-monitor.d.ts +33 -0
  36. package/dist/recorders/filesystem-monitor.d.ts.map +1 -0
  37. package/dist/recorders/filesystem-monitor.js +262 -0
  38. package/dist/recorders/filesystem-monitor.js.map +1 -0
  39. package/dist/recorders/git-snapshotter.d.ts +17 -0
  40. package/dist/recorders/git-snapshotter.d.ts.map +1 -0
  41. package/dist/recorders/git-snapshotter.js +116 -0
  42. package/dist/recorders/git-snapshotter.js.map +1 -0
  43. package/dist/recorders/network-monitor.d.ts +18 -0
  44. package/dist/recorders/network-monitor.d.ts.map +1 -0
  45. package/dist/recorders/network-monitor.js +67 -0
  46. package/dist/recorders/network-monitor.js.map +1 -0
  47. package/dist/recorders/network-proxy.d.ts +31 -0
  48. package/dist/recorders/network-proxy.d.ts.map +1 -0
  49. package/dist/recorders/network-proxy.js +163 -0
  50. package/dist/recorders/network-proxy.js.map +1 -0
  51. package/dist/recorders/process-monitor.d.ts +14 -0
  52. package/dist/recorders/process-monitor.d.ts.map +1 -0
  53. package/dist/recorders/process-monitor.js +47 -0
  54. package/dist/recorders/process-monitor.js.map +1 -0
  55. package/dist/recorders/process-wrapper.d.ts +37 -0
  56. package/dist/recorders/process-wrapper.d.ts.map +1 -0
  57. package/dist/recorders/process-wrapper.js +152 -0
  58. package/dist/recorders/process-wrapper.js.map +1 -0
  59. package/dist/recorders/secret-detector.d.ts +26 -0
  60. package/dist/recorders/secret-detector.d.ts.map +1 -0
  61. package/dist/recorders/secret-detector.js +148 -0
  62. package/dist/recorders/secret-detector.js.map +1 -0
  63. package/dist/reports/report-generator.d.ts +19 -0
  64. package/dist/reports/report-generator.d.ts.map +1 -0
  65. package/dist/reports/report-generator.js +274 -0
  66. package/dist/reports/report-generator.js.map +1 -0
  67. package/dist/types/index.d.ts +132 -0
  68. package/dist/types/index.d.ts.map +1 -0
  69. package/dist/types/index.js +7 -0
  70. package/dist/types/index.js.map +1 -0
  71. package/dist/utils/exec.d.ts +6 -0
  72. package/dist/utils/exec.d.ts.map +1 -0
  73. package/dist/utils/exec.js +10 -0
  74. package/dist/utils/exec.js.map +1 -0
  75. 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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"}