bashbros 0.1.3 → 0.1.5

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 (79) hide show
  1. package/README.md +734 -271
  2. package/dist/adapters-JAZGGNVP.js +9 -0
  3. package/dist/chunk-25TREQ6V.js +465 -0
  4. package/dist/chunk-25TREQ6V.js.map +1 -0
  5. package/dist/{chunk-A535VV7N.js → chunk-2CI2MRKI.js} +23 -6
  6. package/dist/chunk-2CI2MRKI.js.map +1 -0
  7. package/dist/chunk-4XZ64P4V.js +47 -0
  8. package/dist/chunk-4XZ64P4V.js.map +1 -0
  9. package/dist/chunk-5BBPRDWL.js +186 -0
  10. package/dist/chunk-5BBPRDWL.js.map +1 -0
  11. package/dist/{chunk-2RPTM6EQ.js → chunk-6QVMBCSX.js} +719 -902
  12. package/dist/chunk-6QVMBCSX.js.map +1 -0
  13. package/dist/{chunk-JYWQT2B4.js → chunk-6SLR5WPD.js} +657 -14
  14. package/dist/chunk-6SLR5WPD.js.map +1 -0
  15. package/dist/{chunk-EYO44OMN.js → chunk-AZVT6AZY.js} +78 -17
  16. package/dist/chunk-AZVT6AZY.js.map +1 -0
  17. package/dist/{chunk-WPJJZLT6.js → chunk-C4GZNBFF.js} +3 -2
  18. package/dist/chunk-C4GZNBFF.js.map +1 -0
  19. package/dist/chunk-IUUBCPMV.js +166 -0
  20. package/dist/chunk-IUUBCPMV.js.map +1 -0
  21. package/dist/chunk-J6ONXY6N.js +146 -0
  22. package/dist/chunk-J6ONXY6N.js.map +1 -0
  23. package/dist/{chunk-DLP2O6PN.js → chunk-JOIAG54E.js} +83 -88
  24. package/dist/chunk-JOIAG54E.js.map +1 -0
  25. package/dist/chunk-LJE4EPIU.js +56 -0
  26. package/dist/chunk-LJE4EPIU.js.map +1 -0
  27. package/dist/{chunk-QWZGB4V3.js → chunk-PAZIDRXK.js} +42 -181
  28. package/dist/chunk-PAZIDRXK.js.map +1 -0
  29. package/dist/chunk-PLSHJHHR.js +293 -0
  30. package/dist/chunk-PLSHJHHR.js.map +1 -0
  31. package/dist/chunk-R5I5DEXE.js +228 -0
  32. package/dist/chunk-R5I5DEXE.js.map +1 -0
  33. package/dist/chunk-SDN6TAGD.js +157 -0
  34. package/dist/chunk-SDN6TAGD.js.map +1 -0
  35. package/dist/chunk-T5ONCUHZ.js +198 -0
  36. package/dist/chunk-T5ONCUHZ.js.map +1 -0
  37. package/dist/cli.js +1204 -188
  38. package/dist/cli.js.map +1 -1
  39. package/dist/{config-43SK6SFI.js → config-IXBXMIUA.js} +2 -2
  40. package/dist/copilot-cli-5WJWK5YT.js +9 -0
  41. package/dist/{db-SWJUUSFX.js → db-GJALN3R7.js} +2 -2
  42. package/dist/db-checks-2YOVECD4.js +133 -0
  43. package/dist/db-checks-2YOVECD4.js.map +1 -0
  44. package/dist/{display-HFIFXOOL.js → display-UDIACHTP.js} +3 -3
  45. package/dist/{engine-EGPAS2EX.js → engine-4WNPXVMS.js} +3 -2
  46. package/dist/gemini-cli-3563EELZ.js +9 -0
  47. package/dist/gemini-cli-3563EELZ.js.map +1 -0
  48. package/dist/index.d.ts +205 -101
  49. package/dist/index.js +132 -402
  50. package/dist/index.js.map +1 -1
  51. package/dist/{ollama-HY35OHW4.js → ollama-TNMD5WHW.js} +2 -2
  52. package/dist/ollama-TNMD5WHW.js.map +1 -0
  53. package/dist/opencode-DRCY275R.js +9 -0
  54. package/dist/opencode-DRCY275R.js.map +1 -0
  55. package/dist/profiles-7CLN6TAT.js +9 -0
  56. package/dist/profiles-7CLN6TAT.js.map +1 -0
  57. package/dist/server-3CMTP4W4.js +13 -0
  58. package/dist/server-3CMTP4W4.js.map +1 -0
  59. package/dist/setup-U4R5QJMV.js +124 -0
  60. package/dist/setup-U4R5QJMV.js.map +1 -0
  61. package/dist/static/index.html +4862 -2007
  62. package/dist/store-WJ5Y7MOE.js +9 -0
  63. package/dist/store-WJ5Y7MOE.js.map +1 -0
  64. package/dist/{writer-4ZEAKUFD.js → writer-OMHUMJR5.js} +3 -3
  65. package/dist/writer-OMHUMJR5.js.map +1 -0
  66. package/package.json +78 -68
  67. package/dist/chunk-2RPTM6EQ.js.map +0 -1
  68. package/dist/chunk-A535VV7N.js.map +0 -1
  69. package/dist/chunk-DLP2O6PN.js.map +0 -1
  70. package/dist/chunk-EYO44OMN.js.map +0 -1
  71. package/dist/chunk-JYWQT2B4.js.map +0 -1
  72. package/dist/chunk-QWZGB4V3.js.map +0 -1
  73. package/dist/chunk-WPJJZLT6.js.map +0 -1
  74. /package/dist/{config-43SK6SFI.js.map → adapters-JAZGGNVP.js.map} +0 -0
  75. /package/dist/{db-SWJUUSFX.js.map → config-IXBXMIUA.js.map} +0 -0
  76. /package/dist/{display-HFIFXOOL.js.map → copilot-cli-5WJWK5YT.js.map} +0 -0
  77. /package/dist/{engine-EGPAS2EX.js.map → db-GJALN3R7.js.map} +0 -0
  78. /package/dist/{ollama-HY35OHW4.js.map → display-UDIACHTP.js.map} +0 -0
  79. /package/dist/{writer-4ZEAKUFD.js.map → engine-4WNPXVMS.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,38 +1,54 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ startMCPServer
4
+ } from "./chunk-PLSHJHHR.js";
5
+ import {
6
+ AnomalyDetector,
3
7
  BackgroundWorker,
4
8
  BashBro,
5
9
  BashBros,
6
10
  BashgymIntegration,
7
- ClaudeCodeHooks,
8
- CommandSuggester,
9
11
  CostEstimator,
10
12
  LoopDetector,
11
- MetricsCollector,
13
+ OutputScanner,
12
14
  ReportGenerator,
13
15
  SystemProfiler,
14
16
  TaskRouter,
15
17
  UndoStack,
16
- gateCommand,
17
18
  getBashgymIntegration,
18
19
  resetBashgymIntegration
19
- } from "./chunk-2RPTM6EQ.js";
20
+ } from "./chunk-6QVMBCSX.js";
21
+ import {
22
+ CommandSuggester
23
+ } from "./chunk-5BBPRDWL.js";
24
+ import {
25
+ ClaudeCodeHooks,
26
+ gateCommand
27
+ } from "./chunk-25TREQ6V.js";
28
+ import {
29
+ MoltbotHooks,
30
+ getMoltbotHooks
31
+ } from "./chunk-J37RHCFJ.js";
20
32
  import {
21
33
  AuditLogger
22
34
  } from "./chunk-SG752FZC.js";
23
35
  import {
24
36
  OllamaClient
25
- } from "./chunk-DLP2O6PN.js";
37
+ } from "./chunk-JOIAG54E.js";
38
+ import "./chunk-4XZ64P4V.js";
39
+ import "./chunk-LJE4EPIU.js";
26
40
  import {
27
41
  loadConfig
28
- } from "./chunk-A535VV7N.js";
42
+ } from "./chunk-2CI2MRKI.js";
29
43
  import {
30
44
  CommandFilter,
31
45
  PathSandbox,
32
46
  PolicyEngine,
33
- RateLimiter,
47
+ RateLimiter
48
+ } from "./chunk-PAZIDRXK.js";
49
+ import {
34
50
  SecretsGuard
35
- } from "./chunk-QWZGB4V3.js";
51
+ } from "./chunk-R5I5DEXE.js";
36
52
  import {
37
53
  allowForSession,
38
54
  clearSessionAllowlist,
@@ -42,438 +58,151 @@ import {
42
58
  import {
43
59
  RiskScorer
44
60
  } from "./chunk-DEAF6PYM.js";
45
- import {
46
- MoltbotHooks,
47
- getMoltbotHooks
48
- } from "./chunk-J37RHCFJ.js";
61
+ import "./chunk-6SLR5WPD.js";
49
62
  import "./chunk-7OCVIDC7.js";
50
63
 
51
- // src/policy/anomaly-detector.ts
52
- var DEFAULT_CONFIG = {
53
- workingHours: [6, 22],
54
- // 6 AM to 10 PM
55
- typicalCommandsPerMinute: 30,
56
- knownPaths: [],
57
- suspiciousPatterns: [],
58
- enabled: true
59
- };
60
- var DEFAULT_SUSPICIOUS_PATTERNS = [
61
- /\bpasswd\b/,
62
- /\bshadow\b/,
63
- /\/root\//,
64
- /\.ssh\//,
65
- /\.gnupg\//,
66
- /\.aws\//,
67
- /\.kube\//,
68
- /wallet/i,
69
- /crypto/i,
70
- /bitcoin/i,
71
- /ethereum/i,
72
- /private.*key/i
73
- ];
74
- var AnomalyDetector = class {
75
- config;
64
+ // src/observability/metrics.ts
65
+ var MetricsCollector = class {
66
+ sessionId;
67
+ startTime;
76
68
  commands = [];
77
- baselinePaths = /* @__PURE__ */ new Set();
78
- baselineCommands = /* @__PURE__ */ new Set();
79
- learningMode = true;
80
- learningCount = 0;
81
- LEARNING_THRESHOLD = 50;
82
- constructor(config = {}) {
83
- this.config = { ...DEFAULT_CONFIG, ...config };
69
+ filesModified = /* @__PURE__ */ new Set();
70
+ pathsAccessed = /* @__PURE__ */ new Set();
71
+ constructor() {
72
+ this.sessionId = this.generateSessionId();
73
+ this.startTime = /* @__PURE__ */ new Date();
84
74
  }
85
- /**
86
- * Check a command for anomalies
87
- */
88
- check(command, cwd) {
89
- if (!this.config.enabled) return [];
90
- const anomalies = [];
91
- const now = Date.now();
92
- this.commands.push({ command, timestamp: now, path: cwd });
93
- if (this.commands.length > 1e3) {
94
- this.commands = this.commands.slice(-500);
95
- }
96
- if (this.learningMode) {
97
- this.learn(command, cwd);
98
- if (this.learningCount >= this.LEARNING_THRESHOLD) {
99
- this.learningMode = false;
100
- }
101
- return anomalies;
102
- }
103
- const timingAnomaly = this.checkTiming(now);
104
- if (timingAnomaly) anomalies.push(timingAnomaly);
105
- const freqAnomaly = this.checkFrequency(now);
106
- if (freqAnomaly) anomalies.push(freqAnomaly);
107
- if (cwd) {
108
- const pathAnomaly = this.checkPath(cwd);
109
- if (pathAnomaly) anomalies.push(pathAnomaly);
110
- }
111
- const patternAnomalies = this.checkPatterns(command);
112
- anomalies.push(...patternAnomalies);
113
- const behaviorAnomaly = this.checkBehavior(command);
114
- if (behaviorAnomaly) anomalies.push(behaviorAnomaly);
115
- return anomalies;
116
- }
117
- /**
118
- * Learn from command (build baseline)
119
- */
120
- learn(command, cwd) {
121
- this.learningCount++;
122
- const baseCmd = command.split(/\s+/)[0];
123
- this.baselineCommands.add(baseCmd);
124
- if (cwd) {
125
- this.baselinePaths.add(cwd);
126
- const parts = cwd.split(/[/\\]/);
127
- for (let i = 1; i <= parts.length; i++) {
128
- this.baselinePaths.add(parts.slice(0, i).join("/"));
129
- }
130
- }
131
- }
132
- /**
133
- * Check for timing anomalies
134
- */
135
- checkTiming(now) {
136
- const hour = new Date(now).getHours();
137
- const [start, end] = this.config.workingHours;
138
- if (hour < start || hour >= end) {
139
- return {
140
- type: "timing",
141
- severity: "info",
142
- message: `Activity outside normal hours (${hour}:00)`,
143
- details: { hour, workingHours: this.config.workingHours }
144
- };
145
- }
146
- return null;
75
+ generateSessionId() {
76
+ const now = /* @__PURE__ */ new Date();
77
+ const date = now.toISOString().slice(0, 10).replace(/-/g, "");
78
+ const time = now.toTimeString().slice(0, 8).replace(/:/g, "");
79
+ const rand = Math.random().toString(36).slice(2, 6);
80
+ return `${date}-${time}-${rand}`;
147
81
  }
148
82
  /**
149
- * Check for frequency anomalies
83
+ * Record a command execution
150
84
  */
151
- checkFrequency(now) {
152
- const oneMinuteAgo = now - 6e4;
153
- const recentCommands = this.commands.filter((c) => c.timestamp > oneMinuteAgo);
154
- const rate = recentCommands.length;
155
- if (rate > this.config.typicalCommandsPerMinute * 2) {
156
- return {
157
- type: "frequency",
158
- severity: "warning",
159
- message: `High command rate: ${rate}/min (typical: ${this.config.typicalCommandsPerMinute})`,
160
- details: { rate, typical: this.config.typicalCommandsPerMinute }
161
- };
85
+ record(metric) {
86
+ this.commands.push(metric);
87
+ const paths = this.extractPaths(metric.command);
88
+ for (const path of paths) {
89
+ this.pathsAccessed.add(path);
162
90
  }
163
- const fiveSecondsAgo = now - 5e3;
164
- const burstCommands = this.commands.filter((c) => c.timestamp > fiveSecondsAgo);
165
- if (burstCommands.length > 10) {
166
- return {
167
- type: "frequency",
168
- severity: "alert",
169
- message: `Burst detected: ${burstCommands.length} commands in 5 seconds`,
170
- details: { count: burstCommands.length, window: "5s" }
171
- };
172
- }
173
- return null;
174
- }
175
- /**
176
- * Check for unusual path access
177
- */
178
- checkPath(path) {
179
- if (this.config.knownPaths.length > 0) {
180
- const isKnown = this.config.knownPaths.some(
181
- (p) => path.startsWith(p) || path.includes(p)
182
- );
183
- if (!isKnown) {
184
- return {
185
- type: "path",
186
- severity: "warning",
187
- message: `Access to unexpected path: ${path}`,
188
- details: { path, knownPaths: this.config.knownPaths }
189
- };
91
+ if (this.isWriteCommand(metric.command)) {
92
+ for (const path of paths) {
93
+ this.filesModified.add(path);
190
94
  }
191
95
  }
192
- if (!this.learningMode && this.baselinePaths.size > 0) {
193
- const isBaseline = this.baselinePaths.has(path) || [...this.baselinePaths].some((p) => path.startsWith(p));
194
- if (!isBaseline) {
195
- return {
196
- type: "path",
197
- severity: "info",
198
- message: `New path accessed: ${path}`,
199
- details: { path, isNew: true }
200
- };
201
- }
202
- }
203
- return null;
204
96
  }
205
97
  /**
206
- * Check for suspicious patterns
98
+ * Get current session metrics
207
99
  */
208
- checkPatterns(command) {
209
- const anomalies = [];
210
- const allPatterns = [...DEFAULT_SUSPICIOUS_PATTERNS, ...this.config.suspiciousPatterns];
211
- for (const pattern of allPatterns) {
212
- if (pattern.test(command)) {
213
- anomalies.push({
214
- type: "pattern",
215
- severity: "warning",
216
- message: `Suspicious pattern detected: ${pattern.source}`,
217
- details: { command: command.slice(0, 100), pattern: pattern.source }
218
- });
219
- }
100
+ getMetrics() {
101
+ const now = /* @__PURE__ */ new Date();
102
+ const duration = now.getTime() - this.startTime.getTime();
103
+ const riskDist = { safe: 0, caution: 0, dangerous: 0, critical: 0 };
104
+ let totalRisk = 0;
105
+ for (const cmd of this.commands) {
106
+ riskDist[cmd.riskScore.level]++;
107
+ totalRisk += cmd.riskScore.score;
220
108
  }
221
- return anomalies;
222
- }
223
- /**
224
- * Check for behavioral anomalies
225
- */
226
- checkBehavior(command) {
227
- const baseCmd = command.split(/\s+/)[0];
228
- if (!this.learningMode && this.baselineCommands.size > 0) {
229
- if (!this.baselineCommands.has(baseCmd)) {
230
- const sensitiveCommands = /* @__PURE__ */ new Set([
231
- "curl",
232
- "wget",
233
- "nc",
234
- "netcat",
235
- "ssh",
236
- "scp",
237
- "rsync",
238
- "sudo",
239
- "su",
240
- "chmod",
241
- "chown",
242
- "mount",
243
- "umount"
244
- ]);
245
- if (sensitiveCommands.has(baseCmd)) {
246
- return {
247
- type: "behavior",
248
- severity: "warning",
249
- message: `New sensitive command type: ${baseCmd}`,
250
- details: { command: baseCmd, isNew: true }
251
- };
252
- }
109
+ const cmdFreq = /* @__PURE__ */ new Map();
110
+ for (const cmd of this.commands) {
111
+ const base = cmd.command.split(/\s+/)[0];
112
+ cmdFreq.set(base, (cmdFreq.get(base) || 0) + 1);
113
+ }
114
+ const topCommands = [...cmdFreq.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10);
115
+ const violationsByType = {};
116
+ for (const cmd of this.commands) {
117
+ for (const v of cmd.violations) {
118
+ violationsByType[v.type] = (violationsByType[v.type] || 0) + 1;
253
119
  }
254
120
  }
255
- return null;
256
- }
257
- /**
258
- * Get anomaly stats
259
- */
260
- getStats() {
261
- const now = Date.now();
262
- const oneMinuteAgo = now - 6e4;
263
- const recentRate = this.commands.filter((c) => c.timestamp > oneMinuteAgo).length;
121
+ const totalExecTime = this.commands.reduce((sum, c) => sum + c.duration, 0);
122
+ const avgExecTime = this.commands.length > 0 ? totalExecTime / this.commands.length : 0;
264
123
  return {
265
- learningMode: this.learningMode,
266
- learningProgress: Math.min(100, Math.round(this.learningCount / this.LEARNING_THRESHOLD * 100)),
267
- baselineCommands: this.baselineCommands.size,
268
- baselinePaths: this.baselinePaths.size,
269
- recentCommandRate: recentRate
124
+ sessionId: this.sessionId,
125
+ startTime: this.startTime,
126
+ duration,
127
+ commandCount: this.commands.length,
128
+ blockedCount: this.commands.filter((c) => !c.allowed).length,
129
+ uniqueCommands: cmdFreq.size,
130
+ topCommands,
131
+ riskDistribution: riskDist,
132
+ avgRiskScore: this.commands.length > 0 ? totalRisk / this.commands.length : 0,
133
+ avgExecutionTime: avgExecTime,
134
+ totalExecutionTime: totalExecTime,
135
+ filesModified: [...this.filesModified],
136
+ pathsAccessed: [...this.pathsAccessed],
137
+ violationsByType
270
138
  };
271
139
  }
272
140
  /**
273
- * Force end learning mode
274
- */
275
- endLearning() {
276
- this.learningMode = false;
277
- }
278
- /**
279
- * Reset and restart learning
141
+ * Extract paths from a command
280
142
  */
281
- reset() {
282
- this.commands = [];
283
- this.baselinePaths.clear();
284
- this.baselineCommands.clear();
285
- this.learningMode = true;
286
- this.learningCount = 0;
287
- }
288
- };
289
-
290
- // src/policy/output-scanner.ts
291
- var SECRET_PATTERNS = [
292
- // API Keys
293
- { pattern: /sk-[A-Za-z0-9]{20,}/, name: "OpenAI API Key" },
294
- { pattern: /sk-ant-[A-Za-z0-9\-]{20,}/, name: "Anthropic API Key" },
295
- { pattern: /ghp_[A-Za-z0-9]{36}/, name: "GitHub Token" },
296
- { pattern: /gho_[A-Za-z0-9]{36}/, name: "GitHub OAuth Token" },
297
- { pattern: /github_pat_[A-Za-z0-9_]{22,}/, name: "GitHub PAT" },
298
- { pattern: /glpat-[A-Za-z0-9\-]{20,}/, name: "GitLab Token" },
299
- { pattern: /xox[baprs]-[A-Za-z0-9\-]{10,}/, name: "Slack Token" },
300
- { pattern: /sk_live_[A-Za-z0-9]{24,}/, name: "Stripe Secret Key" },
301
- { pattern: /sq0atp-[A-Za-z0-9\-_]{22,}/, name: "Square Token" },
302
- { pattern: /AKIA[A-Z0-9]{16}/, name: "AWS Access Key" },
303
- { pattern: /amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/, name: "Amazon MWS Key" },
304
- // OAuth/JWT
305
- { pattern: /Bearer\s+[A-Za-z0-9\-._~+/]+=*/, name: "Bearer Token" },
306
- { pattern: /eyJ[A-Za-z0-9\-_]+\.eyJ[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/, name: "JWT Token" },
307
- // Credentials in output
308
- { pattern: /password\s*[=:]\s*['"]?[^\s'"]{4,}['"]?/i, name: "Password" },
309
- { pattern: /passwd\s*[=:]\s*['"]?[^\s'"]{4,}['"]?/i, name: "Password" },
310
- { pattern: /api[_-]?key\s*[=:]\s*['"]?[^\s'"]{8,}['"]?/i, name: "API Key" },
311
- { pattern: /secret\s*[=:]\s*['"]?[^\s'"]{8,}['"]?/i, name: "Secret" },
312
- { pattern: /token\s*[=:]\s*['"]?[^\s'"]{8,}['"]?/i, name: "Token" },
313
- // Private keys
314
- { pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----/, name: "Private Key" },
315
- { pattern: /-----BEGIN\s+EC\s+PRIVATE\s+KEY-----/, name: "EC Private Key" },
316
- { pattern: /-----BEGIN\s+OPENSSH\s+PRIVATE\s+KEY-----/, name: "SSH Private Key" },
317
- { pattern: /-----BEGIN\s+PGP\s+PRIVATE\s+KEY\s+BLOCK-----/, name: "PGP Private Key" },
318
- // Database URLs
319
- { pattern: /mongodb(\+srv)?:\/\/[^:]+:[^@]+@/, name: "MongoDB Connection String" },
320
- { pattern: /postgres(ql)?:\/\/[^:]+:[^@]+@/, name: "PostgreSQL Connection String" },
321
- { pattern: /mysql:\/\/[^:]+:[^@]+@/, name: "MySQL Connection String" },
322
- { pattern: /redis:\/\/[^:]+:[^@]+@/, name: "Redis Connection String" },
323
- // SSH
324
- { pattern: /ssh-rsa\s+[A-Za-z0-9+/]+[=]{0,2}/, name: "SSH Public Key" },
325
- { pattern: /ssh-ed25519\s+[A-Za-z0-9+/]+/, name: "SSH ED25519 Key" }
326
- ];
327
- var ERROR_PATTERNS = [
328
- { pattern: /EACCES|EPERM|permission denied/i, name: "Permission Error" },
329
- { pattern: /ENOENT|no such file|not found/i, name: "File Not Found" },
330
- { pattern: /ECONNREFUSED|connection refused/i, name: "Connection Refused" },
331
- { pattern: /ETIMEDOUT|timed out/i, name: "Timeout Error" },
332
- { pattern: /segmentation fault|core dumped/i, name: "Crash" },
333
- { pattern: /out of memory|OOM|cannot allocate/i, name: "Memory Error" },
334
- { pattern: /stack trace|traceback|at\s+\S+:\d+:\d+/i, name: "Stack Trace" },
335
- { pattern: /error:|fatal:|failed:/i, name: "Error Message" }
336
- ];
337
- var OutputScanner = class {
338
- secretPatterns;
339
- redactPatterns;
340
- policy;
341
- constructor(policy) {
342
- this.policy = policy;
343
- this.secretPatterns = SECRET_PATTERNS.map((p) => p.pattern);
344
- this.redactPatterns = (policy.redactPatterns || []).map((p) => {
345
- try {
346
- return new RegExp(p, "gi");
347
- } catch {
348
- return null;
143
+ extractPaths(command) {
144
+ const paths = [];
145
+ const tokens = command.split(/\s+/);
146
+ for (const token of tokens) {
147
+ if (token.startsWith("-")) continue;
148
+ if (token.startsWith("/") || token.startsWith("./") || token.startsWith("../") || token.startsWith("~/") || token.includes(".")) {
149
+ paths.push(token);
349
150
  }
350
- }).filter((p) => p !== null);
151
+ }
152
+ return paths;
351
153
  }
352
154
  /**
353
- * Scan output for secrets and sensitive data
155
+ * Check if command modifies files
354
156
  */
355
- scan(output) {
356
- if (!this.policy.enabled) {
357
- return {
358
- hasSecrets: false,
359
- hasErrors: false,
360
- redactedOutput: output,
361
- findings: []
362
- };
363
- }
364
- const findings = [];
365
- let hasSecrets = false;
366
- let hasErrors = false;
367
- let processedOutput = output;
368
- if (output.length > this.policy.maxOutputLength) {
369
- processedOutput = output.slice(0, this.policy.maxOutputLength) + "\n... [truncated]";
370
- }
371
- if (this.policy.scanForSecrets) {
372
- const secretFindings = this.scanForSecrets(processedOutput);
373
- if (secretFindings.length > 0) {
374
- hasSecrets = true;
375
- findings.push(...secretFindings);
376
- }
377
- }
378
- if (this.policy.scanForErrors) {
379
- const errorFindings = this.scanForErrors(processedOutput);
380
- if (errorFindings.length > 0) {
381
- hasErrors = true;
382
- findings.push(...errorFindings);
383
- }
384
- }
385
- const redactedOutput = this.redact(processedOutput);
386
- return {
387
- hasSecrets,
388
- hasErrors,
389
- redactedOutput,
390
- findings
391
- };
157
+ isWriteCommand(command) {
158
+ const writePatterns = [
159
+ /^(vim|vi|nano|emacs|code)\s/,
160
+ /^(touch|mkdir|cp|mv|rm)\s/,
161
+ /^(echo|cat|printf).*>/,
162
+ /^(git\s+(add|commit|checkout|reset))/,
163
+ /^(npm|yarn|pnpm)\s+(install|uninstall)/,
164
+ /^(pip|pip3)\s+(install|uninstall)/,
165
+ /^chmod\s/,
166
+ /^chown\s/
167
+ ];
168
+ return writePatterns.some((p) => p.test(command));
392
169
  }
393
170
  /**
394
- * Scan for secrets in output
171
+ * Get recent commands
395
172
  */
396
- scanForSecrets(output) {
397
- const findings = [];
398
- const lines = output.split("\n");
399
- for (let i = 0; i < lines.length; i++) {
400
- const line = lines[i];
401
- for (const { pattern, name } of SECRET_PATTERNS) {
402
- if (pattern.test(line)) {
403
- findings.push({
404
- type: "secret",
405
- pattern: name,
406
- message: `Potential ${name} found in output`,
407
- line: i + 1
408
- });
409
- }
410
- }
411
- }
412
- return findings;
173
+ getRecentCommands(n = 10) {
174
+ return this.commands.slice(-n);
413
175
  }
414
176
  /**
415
- * Scan for error patterns in output
177
+ * Get blocked commands
416
178
  */
417
- scanForErrors(output) {
418
- const findings = [];
419
- const lines = output.split("\n");
420
- for (let i = 0; i < lines.length; i++) {
421
- const line = lines[i];
422
- for (const { pattern, name } of ERROR_PATTERNS) {
423
- if (pattern.test(line)) {
424
- findings.push({
425
- type: "error",
426
- pattern: name,
427
- message: `${name} detected`,
428
- line: i + 1
429
- });
430
- break;
431
- }
432
- }
433
- }
434
- return findings;
179
+ getBlockedCommands() {
180
+ return this.commands.filter((c) => !c.allowed);
435
181
  }
436
182
  /**
437
- * Redact sensitive data from output
183
+ * Get high-risk commands
438
184
  */
439
- redact(output) {
440
- let redacted = output;
441
- for (const { pattern, name } of SECRET_PATTERNS) {
442
- redacted = redacted.replace(new RegExp(pattern.source, "g"), `[REDACTED ${name}]`);
443
- }
444
- for (const pattern of this.redactPatterns) {
445
- redacted = redacted.replace(pattern, "[REDACTED]");
446
- }
447
- return redacted;
185
+ getHighRiskCommands(threshold = 6) {
186
+ return this.commands.filter((c) => c.riskScore.score >= threshold);
448
187
  }
449
188
  /**
450
- * Check if output contains any secrets
189
+ * Format duration for display
451
190
  */
452
- hasSecrets(output) {
453
- for (const pattern of this.secretPatterns) {
454
- if (pattern.test(output)) {
455
- return true;
456
- }
457
- }
458
- return false;
191
+ static formatDuration(ms) {
192
+ if (ms < 1e3) return `${ms}ms`;
193
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
194
+ if (ms < 36e5) return `${Math.floor(ms / 6e4)}m ${Math.floor(ms % 6e4 / 1e3)}s`;
195
+ return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
459
196
  }
460
197
  /**
461
- * Get summary of findings
198
+ * Reset collector
462
199
  */
463
- static summarize(findings) {
464
- if (findings.length === 0) {
465
- return "No issues found";
466
- }
467
- const secrets = findings.filter((f) => f.type === "secret");
468
- const errors = findings.filter((f) => f.type === "error");
469
- const parts = [];
470
- if (secrets.length > 0) {
471
- parts.push(`${secrets.length} potential secret(s)`);
472
- }
473
- if (errors.length > 0) {
474
- parts.push(`${errors.length} error(s)`);
475
- }
476
- return parts.join(", ");
200
+ reset() {
201
+ this.sessionId = this.generateSessionId();
202
+ this.startTime = /* @__PURE__ */ new Date();
203
+ this.commands = [];
204
+ this.filesModified.clear();
205
+ this.pathsAccessed.clear();
477
206
  }
478
207
  };
479
208
 
@@ -549,6 +278,7 @@ export {
549
278
  isInMoltbotSession,
550
279
  isSandboxEnabled,
551
280
  loadConfig,
552
- resetBashgymIntegration
281
+ resetBashgymIntegration,
282
+ startMCPServer
553
283
  };
554
284
  //# sourceMappingURL=index.js.map