genesis-ai-cli 7.4.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 (227) hide show
  1. package/.env.example +78 -0
  2. package/README.md +282 -0
  3. package/dist/src/active-inference/actions.d.ts +75 -0
  4. package/dist/src/active-inference/actions.js +250 -0
  5. package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
  6. package/dist/src/active-inference/autonomous-loop.js +289 -0
  7. package/dist/src/active-inference/core.d.ts +85 -0
  8. package/dist/src/active-inference/core.js +555 -0
  9. package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
  10. package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
  11. package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
  12. package/dist/src/active-inference/demo-value-integration.js +174 -0
  13. package/dist/src/active-inference/index.d.ts +32 -0
  14. package/dist/src/active-inference/index.js +88 -0
  15. package/dist/src/active-inference/integration.d.ts +114 -0
  16. package/dist/src/active-inference/integration.js +698 -0
  17. package/dist/src/active-inference/memory-integration.d.ts +51 -0
  18. package/dist/src/active-inference/memory-integration.js +232 -0
  19. package/dist/src/active-inference/observations.d.ts +67 -0
  20. package/dist/src/active-inference/observations.js +147 -0
  21. package/dist/src/active-inference/test-active-inference.d.ts +8 -0
  22. package/dist/src/active-inference/test-active-inference.js +320 -0
  23. package/dist/src/active-inference/test-value-integration.d.ts +6 -0
  24. package/dist/src/active-inference/test-value-integration.js +168 -0
  25. package/dist/src/active-inference/types.d.ts +150 -0
  26. package/dist/src/active-inference/types.js +59 -0
  27. package/dist/src/active-inference/value-integration.d.ts +164 -0
  28. package/dist/src/active-inference/value-integration.js +459 -0
  29. package/dist/src/agents/base-agent.d.ts +53 -0
  30. package/dist/src/agents/base-agent.js +178 -0
  31. package/dist/src/agents/builder.d.ts +67 -0
  32. package/dist/src/agents/builder.js +537 -0
  33. package/dist/src/agents/critic.d.ts +35 -0
  34. package/dist/src/agents/critic.js +322 -0
  35. package/dist/src/agents/ethicist.d.ts +54 -0
  36. package/dist/src/agents/ethicist.js +393 -0
  37. package/dist/src/agents/explorer.d.ts +26 -0
  38. package/dist/src/agents/explorer.js +216 -0
  39. package/dist/src/agents/feeling.d.ts +41 -0
  40. package/dist/src/agents/feeling.js +320 -0
  41. package/dist/src/agents/index.d.ts +111 -0
  42. package/dist/src/agents/index.js +222 -0
  43. package/dist/src/agents/memory.d.ts +69 -0
  44. package/dist/src/agents/memory.js +404 -0
  45. package/dist/src/agents/message-bus.d.ts +88 -0
  46. package/dist/src/agents/message-bus.js +267 -0
  47. package/dist/src/agents/narrator.d.ts +90 -0
  48. package/dist/src/agents/narrator.js +473 -0
  49. package/dist/src/agents/planner.d.ts +38 -0
  50. package/dist/src/agents/planner.js +341 -0
  51. package/dist/src/agents/predictor.d.ts +73 -0
  52. package/dist/src/agents/predictor.js +506 -0
  53. package/dist/src/agents/sensor.d.ts +88 -0
  54. package/dist/src/agents/sensor.js +377 -0
  55. package/dist/src/agents/test-agents.d.ts +6 -0
  56. package/dist/src/agents/test-agents.js +73 -0
  57. package/dist/src/agents/types.d.ts +194 -0
  58. package/dist/src/agents/types.js +7 -0
  59. package/dist/src/brain/index.d.ts +185 -0
  60. package/dist/src/brain/index.js +843 -0
  61. package/dist/src/brain/trace.d.ts +91 -0
  62. package/dist/src/brain/trace.js +327 -0
  63. package/dist/src/brain/types.d.ts +165 -0
  64. package/dist/src/brain/types.js +51 -0
  65. package/dist/src/cli/chat.d.ts +237 -0
  66. package/dist/src/cli/chat.js +1959 -0
  67. package/dist/src/cli/dispatcher.d.ts +182 -0
  68. package/dist/src/cli/dispatcher.js +718 -0
  69. package/dist/src/cli/human-loop.d.ts +170 -0
  70. package/dist/src/cli/human-loop.js +543 -0
  71. package/dist/src/cli/index.d.ts +12 -0
  72. package/dist/src/cli/index.js +28 -0
  73. package/dist/src/cli/interactive.d.ts +141 -0
  74. package/dist/src/cli/interactive.js +757 -0
  75. package/dist/src/cli/ui.d.ts +205 -0
  76. package/dist/src/cli/ui.js +632 -0
  77. package/dist/src/consciousness/attention-schema.d.ts +154 -0
  78. package/dist/src/consciousness/attention-schema.js +432 -0
  79. package/dist/src/consciousness/global-workspace.d.ts +149 -0
  80. package/dist/src/consciousness/global-workspace.js +422 -0
  81. package/dist/src/consciousness/index.d.ts +186 -0
  82. package/dist/src/consciousness/index.js +476 -0
  83. package/dist/src/consciousness/phi-calculator.d.ts +119 -0
  84. package/dist/src/consciousness/phi-calculator.js +445 -0
  85. package/dist/src/consciousness/phi-decisions.d.ts +169 -0
  86. package/dist/src/consciousness/phi-decisions.js +383 -0
  87. package/dist/src/consciousness/phi-monitor.d.ts +153 -0
  88. package/dist/src/consciousness/phi-monitor.js +465 -0
  89. package/dist/src/consciousness/types.d.ts +260 -0
  90. package/dist/src/consciousness/types.js +44 -0
  91. package/dist/src/daemon/dream-mode.d.ts +115 -0
  92. package/dist/src/daemon/dream-mode.js +470 -0
  93. package/dist/src/daemon/index.d.ts +162 -0
  94. package/dist/src/daemon/index.js +542 -0
  95. package/dist/src/daemon/maintenance.d.ts +139 -0
  96. package/dist/src/daemon/maintenance.js +549 -0
  97. package/dist/src/daemon/process.d.ts +82 -0
  98. package/dist/src/daemon/process.js +442 -0
  99. package/dist/src/daemon/scheduler.d.ts +90 -0
  100. package/dist/src/daemon/scheduler.js +494 -0
  101. package/dist/src/daemon/types.d.ts +213 -0
  102. package/dist/src/daemon/types.js +50 -0
  103. package/dist/src/epistemic/index.d.ts +74 -0
  104. package/dist/src/epistemic/index.js +225 -0
  105. package/dist/src/grounding/epistemic-stack.d.ts +100 -0
  106. package/dist/src/grounding/epistemic-stack.js +408 -0
  107. package/dist/src/grounding/feedback.d.ts +98 -0
  108. package/dist/src/grounding/feedback.js +276 -0
  109. package/dist/src/grounding/index.d.ts +123 -0
  110. package/dist/src/grounding/index.js +224 -0
  111. package/dist/src/grounding/verifier.d.ts +149 -0
  112. package/dist/src/grounding/verifier.js +484 -0
  113. package/dist/src/healing/detector.d.ts +110 -0
  114. package/dist/src/healing/detector.js +436 -0
  115. package/dist/src/healing/fixer.d.ts +138 -0
  116. package/dist/src/healing/fixer.js +572 -0
  117. package/dist/src/healing/index.d.ts +23 -0
  118. package/dist/src/healing/index.js +43 -0
  119. package/dist/src/hooks/index.d.ts +135 -0
  120. package/dist/src/hooks/index.js +317 -0
  121. package/dist/src/index.d.ts +23 -0
  122. package/dist/src/index.js +1266 -0
  123. package/dist/src/kernel/index.d.ts +155 -0
  124. package/dist/src/kernel/index.js +795 -0
  125. package/dist/src/kernel/invariants.d.ts +153 -0
  126. package/dist/src/kernel/invariants.js +355 -0
  127. package/dist/src/kernel/test-kernel.d.ts +6 -0
  128. package/dist/src/kernel/test-kernel.js +108 -0
  129. package/dist/src/kernel/test-real-mcp.d.ts +10 -0
  130. package/dist/src/kernel/test-real-mcp.js +295 -0
  131. package/dist/src/llm/index.d.ts +146 -0
  132. package/dist/src/llm/index.js +428 -0
  133. package/dist/src/llm/router.d.ts +136 -0
  134. package/dist/src/llm/router.js +510 -0
  135. package/dist/src/mcp/index.d.ts +85 -0
  136. package/dist/src/mcp/index.js +657 -0
  137. package/dist/src/mcp/resilient.d.ts +139 -0
  138. package/dist/src/mcp/resilient.js +417 -0
  139. package/dist/src/memory/cache.d.ts +118 -0
  140. package/dist/src/memory/cache.js +356 -0
  141. package/dist/src/memory/cognitive-workspace.d.ts +231 -0
  142. package/dist/src/memory/cognitive-workspace.js +521 -0
  143. package/dist/src/memory/consolidation.d.ts +99 -0
  144. package/dist/src/memory/consolidation.js +443 -0
  145. package/dist/src/memory/episodic.d.ts +114 -0
  146. package/dist/src/memory/episodic.js +394 -0
  147. package/dist/src/memory/forgetting.d.ts +134 -0
  148. package/dist/src/memory/forgetting.js +324 -0
  149. package/dist/src/memory/index.d.ts +211 -0
  150. package/dist/src/memory/index.js +367 -0
  151. package/dist/src/memory/indexer.d.ts +123 -0
  152. package/dist/src/memory/indexer.js +479 -0
  153. package/dist/src/memory/procedural.d.ts +136 -0
  154. package/dist/src/memory/procedural.js +479 -0
  155. package/dist/src/memory/semantic.d.ts +132 -0
  156. package/dist/src/memory/semantic.js +497 -0
  157. package/dist/src/memory/types.d.ts +193 -0
  158. package/dist/src/memory/types.js +15 -0
  159. package/dist/src/orchestrator.d.ts +65 -0
  160. package/dist/src/orchestrator.js +317 -0
  161. package/dist/src/persistence/index.d.ts +257 -0
  162. package/dist/src/persistence/index.js +763 -0
  163. package/dist/src/pipeline/executor.d.ts +51 -0
  164. package/dist/src/pipeline/executor.js +695 -0
  165. package/dist/src/pipeline/index.d.ts +7 -0
  166. package/dist/src/pipeline/index.js +11 -0
  167. package/dist/src/self-production.d.ts +67 -0
  168. package/dist/src/self-production.js +205 -0
  169. package/dist/src/subagents/executor.d.ts +58 -0
  170. package/dist/src/subagents/executor.js +283 -0
  171. package/dist/src/subagents/index.d.ts +37 -0
  172. package/dist/src/subagents/index.js +53 -0
  173. package/dist/src/subagents/registry.d.ts +23 -0
  174. package/dist/src/subagents/registry.js +167 -0
  175. package/dist/src/subagents/types.d.ts +79 -0
  176. package/dist/src/subagents/types.js +14 -0
  177. package/dist/src/tools/bash.d.ts +139 -0
  178. package/dist/src/tools/bash.js +583 -0
  179. package/dist/src/tools/edit.d.ts +125 -0
  180. package/dist/src/tools/edit.js +424 -0
  181. package/dist/src/tools/git.d.ts +179 -0
  182. package/dist/src/tools/git.js +504 -0
  183. package/dist/src/tools/index.d.ts +21 -0
  184. package/dist/src/tools/index.js +163 -0
  185. package/dist/src/types.d.ts +145 -0
  186. package/dist/src/types.js +7 -0
  187. package/dist/src/world-model/decoder.d.ts +163 -0
  188. package/dist/src/world-model/decoder.js +517 -0
  189. package/dist/src/world-model/digital-twin.d.ts +219 -0
  190. package/dist/src/world-model/digital-twin.js +695 -0
  191. package/dist/src/world-model/encoder.d.ts +141 -0
  192. package/dist/src/world-model/encoder.js +564 -0
  193. package/dist/src/world-model/index.d.ts +221 -0
  194. package/dist/src/world-model/index.js +772 -0
  195. package/dist/src/world-model/predictor.d.ts +161 -0
  196. package/dist/src/world-model/predictor.js +681 -0
  197. package/dist/src/world-model/test-value-jepa.d.ts +8 -0
  198. package/dist/src/world-model/test-value-jepa.js +430 -0
  199. package/dist/src/world-model/types.d.ts +341 -0
  200. package/dist/src/world-model/types.js +69 -0
  201. package/dist/src/world-model/value-jepa.d.ts +247 -0
  202. package/dist/src/world-model/value-jepa.js +622 -0
  203. package/dist/test/brain.test.d.ts +11 -0
  204. package/dist/test/brain.test.js +358 -0
  205. package/dist/test/cli/dispatcher.test.d.ts +4 -0
  206. package/dist/test/cli/dispatcher.test.js +332 -0
  207. package/dist/test/cli/human-loop.test.d.ts +4 -0
  208. package/dist/test/cli/human-loop.test.js +270 -0
  209. package/dist/test/grounding/feedback.test.d.ts +4 -0
  210. package/dist/test/grounding/feedback.test.js +462 -0
  211. package/dist/test/grounding/verifier.test.d.ts +4 -0
  212. package/dist/test/grounding/verifier.test.js +442 -0
  213. package/dist/test/grounding.test.d.ts +6 -0
  214. package/dist/test/grounding.test.js +246 -0
  215. package/dist/test/healing/detector.test.d.ts +4 -0
  216. package/dist/test/healing/detector.test.js +266 -0
  217. package/dist/test/healing/fixer.test.d.ts +4 -0
  218. package/dist/test/healing/fixer.test.js +369 -0
  219. package/dist/test/integration.test.d.ts +5 -0
  220. package/dist/test/integration.test.js +290 -0
  221. package/dist/test/tools/bash.test.d.ts +4 -0
  222. package/dist/test/tools/bash.test.js +348 -0
  223. package/dist/test/tools/edit.test.d.ts +4 -0
  224. package/dist/test/tools/edit.test.js +350 -0
  225. package/dist/test/tools/git.test.d.ts +4 -0
  226. package/dist/test/tools/git.test.js +350 -0
  227. package/package.json +60 -0
@@ -0,0 +1,583 @@
1
+ "use strict";
2
+ /**
3
+ * Genesis Secure Bash Executor
4
+ *
5
+ * Provides sandboxed command execution with:
6
+ * - Command validation (whitelist/blacklist)
7
+ * - Dangerous pattern detection
8
+ * - Timeout enforcement
9
+ * - Working directory confinement
10
+ * - Output streaming
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.BashTool = exports.DEFAULT_SANDBOX_CONFIG = void 0;
47
+ exports.getBashTool = getBashTool;
48
+ exports.resetBashTool = resetBashTool;
49
+ exports.bash = bash;
50
+ exports.validateCommand = validateCommand;
51
+ exports.exec = exec;
52
+ const child_process_1 = require("child_process");
53
+ const events_1 = require("events");
54
+ const path = __importStar(require("path"));
55
+ const fs = __importStar(require("fs"));
56
+ // ============================================================================
57
+ // Default Configuration
58
+ // ============================================================================
59
+ exports.DEFAULT_SANDBOX_CONFIG = {
60
+ allowedCommands: [
61
+ // File operations (read-only safe)
62
+ 'ls', 'cat', 'head', 'tail', 'less', 'more', 'file', 'stat', 'wc',
63
+ 'find', 'locate', 'which', 'whereis', 'tree',
64
+ // Text processing
65
+ 'grep', 'awk', 'sed', 'cut', 'sort', 'uniq', 'tr', 'diff', 'comm',
66
+ 'jq', 'yq', 'xargs',
67
+ // Development tools
68
+ 'node', 'npm', 'npx', 'yarn', 'pnpm', 'bun',
69
+ 'python', 'python3', 'pip', 'pip3',
70
+ 'git', 'gh',
71
+ 'tsc', 'tsx', 'esbuild', 'vite', 'webpack',
72
+ 'jest', 'vitest', 'mocha', 'pytest',
73
+ 'eslint', 'prettier', 'biome',
74
+ 'cargo', 'rustc', 'go', 'make', 'cmake',
75
+ // System info
76
+ 'echo', 'printf', 'date', 'time', 'whoami', 'pwd', 'env', 'printenv',
77
+ 'uname', 'hostname', 'df', 'du', 'free', 'top', 'ps', 'pgrep',
78
+ 'sleep', 'exit', 'true', 'false', 'test', '[', 'timeout',
79
+ // File management (with caution)
80
+ 'mkdir', 'touch', 'cp', 'mv', 'ln',
81
+ // Archive
82
+ 'tar', 'zip', 'unzip', 'gzip', 'gunzip',
83
+ // Network (controlled)
84
+ 'curl', 'wget', 'ping', 'dig', 'nslookup', 'host',
85
+ // Docker (common in dev)
86
+ 'docker', 'docker-compose', 'podman',
87
+ // Kubernetes
88
+ 'kubectl', 'helm', 'k9s',
89
+ // Cloud CLIs
90
+ 'aws', 'gcloud', 'az', 'vercel', 'netlify', 'fly', 'railway',
91
+ // Databases
92
+ 'psql', 'mysql', 'mongosh', 'redis-cli', 'sqlite3',
93
+ // Misc dev
94
+ 'openssl', 'ssh-keygen', 'base64', 'md5', 'shasum', 'sha256sum',
95
+ ],
96
+ blockedPatterns: [
97
+ // Destructive file operations
98
+ /\brm\s+(-[rf]+\s+)*[\/~]/, // rm with paths
99
+ /\brm\s+-rf?\s/, // rm -rf or rm -r
100
+ /\brmdir\b/, // rmdir
101
+ />\s*\/dev\/sd[a-z]/, // Write to disk devices
102
+ /\bmkfs\b/, // Format filesystem
103
+ /\bdd\s+if=/, // dd (disk destroyer)
104
+ // Privilege escalation
105
+ /\bsudo\b/, // sudo
106
+ /\bsu\s+-?\s*\w/, // su to another user
107
+ /\bchmod\s+[0-7]*777/, // chmod 777
108
+ /\bchown\b/, // chown
109
+ /\bchgrp\b/, // chgrp
110
+ // System modification
111
+ /\bsystemctl\b/, // systemctl
112
+ /\bservice\b/, // service
113
+ /\blaunchctl\b/, // macOS launchctl
114
+ /\bcrontab\b/, // crontab
115
+ /\bvisudo\b/, // visudo
116
+ // Network abuse
117
+ /\bcurl\s+.*\|\s*(ba)?sh/, // curl | sh (pipe to shell)
118
+ /\bwget\s+.*\|\s*(ba)?sh/, // wget | sh
119
+ /\bnc\s+-[el]/, // netcat listen
120
+ /\bnetcat\b/, // netcat
121
+ /\bsocat\b/, // socat
122
+ /\biptables\b/, // iptables
123
+ /\bufw\b/, // ufw
124
+ // Shell escape / injection
125
+ /;\s*sh\b/, // ; sh
126
+ /;\s*bash\b/, // ; bash
127
+ /\$\([^)]*sh\)/, // $(sh)
128
+ /`[^`]*sh`/, // `sh`
129
+ /\beval\b/, // eval
130
+ /\bexec\b/, // exec
131
+ /\bsource\b/, // source
132
+ /\b\.\s+\//, // . /path (source)
133
+ // Fork bomb / resource exhaustion
134
+ /:\(\)\{.*:\|:.*\}/, // :(){ :|:& };:
135
+ /\bfork\b/, // fork
136
+ /\bwhile\s+true.*done/, // while true; do; done (careful)
137
+ // Sensitive files
138
+ /\/etc\/passwd/, // passwd file
139
+ /\/etc\/shadow/, // shadow file
140
+ /\/etc\/sudoers/, // sudoers
141
+ /~\/\.ssh\/id_/, // SSH private keys
142
+ /\.env\b.*password/i, // .env passwords
143
+ // History manipulation
144
+ /\bhistory\s+-c/, // Clear history
145
+ /\bshred\b/, // Secure delete
146
+ // Kill signals
147
+ /\bkill\s+-9\s+1\b/, // kill -9 1 (init)
148
+ /\bkillall\b/, // killall
149
+ /\bpkill\b/, // pkill (without constraints)
150
+ ],
151
+ maxTimeout: 120000, // 2 minutes
152
+ workingDirectory: process.cwd(),
153
+ allowNetwork: true,
154
+ allowExternalWrites: false,
155
+ maxOutputSize: 1024 * 1024, // 1MB
156
+ };
157
+ // ============================================================================
158
+ // Bash Tool Class
159
+ // ============================================================================
160
+ class BashTool extends events_1.EventEmitter {
161
+ config;
162
+ backgroundTasks = new Map();
163
+ taskCounter = 0;
164
+ constructor(config) {
165
+ super();
166
+ this.config = { ...exports.DEFAULT_SANDBOX_CONFIG, ...config };
167
+ }
168
+ // --------------------------------------------------------------------------
169
+ // Validation
170
+ // --------------------------------------------------------------------------
171
+ /**
172
+ * Validate a command against security rules
173
+ */
174
+ validate(command) {
175
+ const trimmed = command.trim();
176
+ // Empty command
177
+ if (!trimmed) {
178
+ return { valid: false, reason: 'Empty command', severity: 'blocked' };
179
+ }
180
+ // Check blocked patterns first
181
+ for (const pattern of this.config.blockedPatterns) {
182
+ if (pattern.test(trimmed)) {
183
+ return {
184
+ valid: false,
185
+ reason: `Blocked pattern detected: ${pattern.toString()}`,
186
+ severity: 'blocked',
187
+ matchedPattern: pattern.toString(),
188
+ };
189
+ }
190
+ }
191
+ // Extract base command
192
+ const baseCommand = this.extractBaseCommand(trimmed);
193
+ // Check if base command is in allowed list
194
+ if (!this.config.allowedCommands.includes(baseCommand)) {
195
+ // Check if it's a path to an allowed command
196
+ const basename = path.basename(baseCommand);
197
+ if (!this.config.allowedCommands.includes(basename)) {
198
+ return {
199
+ valid: false,
200
+ reason: `Command not in allowed list: ${baseCommand}`,
201
+ severity: 'blocked',
202
+ };
203
+ }
204
+ }
205
+ // Check for pipe chains
206
+ if (trimmed.includes('|')) {
207
+ const pipedCommands = trimmed.split('|').map(c => this.extractBaseCommand(c.trim()));
208
+ for (const cmd of pipedCommands) {
209
+ if (cmd && !this.config.allowedCommands.includes(cmd)) {
210
+ const basename = path.basename(cmd);
211
+ if (!this.config.allowedCommands.includes(basename)) {
212
+ return {
213
+ valid: false,
214
+ reason: `Piped command not allowed: ${cmd}`,
215
+ severity: 'blocked',
216
+ };
217
+ }
218
+ }
219
+ }
220
+ }
221
+ // Check for command chains (&&, ||, ;)
222
+ const chainedCommands = trimmed.split(/&&|\|\||;/).map(c => this.extractBaseCommand(c.trim()));
223
+ for (const cmd of chainedCommands) {
224
+ if (cmd && !this.config.allowedCommands.includes(cmd)) {
225
+ const basename = path.basename(cmd);
226
+ if (!this.config.allowedCommands.includes(basename)) {
227
+ return {
228
+ valid: false,
229
+ reason: `Chained command not allowed: ${cmd}`,
230
+ severity: 'blocked',
231
+ };
232
+ }
233
+ }
234
+ }
235
+ // Warning for potentially dangerous but allowed
236
+ const warningPatterns = [
237
+ { pattern: /\brm\b/, reason: 'rm command - verify target' },
238
+ { pattern: />\s*[^|]/, reason: 'File redirection - verify target' },
239
+ { pattern: /\bgit\s+push\s+--force/, reason: 'Force push - verify intent' },
240
+ { pattern: /\bgit\s+reset\s+--hard/, reason: 'Hard reset - verify intent' },
241
+ ];
242
+ for (const { pattern, reason } of warningPatterns) {
243
+ if (pattern.test(trimmed)) {
244
+ return { valid: true, reason, severity: 'warning' };
245
+ }
246
+ }
247
+ return { valid: true, severity: 'safe' };
248
+ }
249
+ /**
250
+ * Extract the base command from a command string
251
+ */
252
+ extractBaseCommand(command) {
253
+ // Remove leading env vars
254
+ const withoutEnv = command.replace(/^(\w+=\S+\s+)+/, '');
255
+ // Get first word
256
+ const parts = withoutEnv.trim().split(/\s+/);
257
+ return parts[0] || '';
258
+ }
259
+ // --------------------------------------------------------------------------
260
+ // Execution
261
+ // --------------------------------------------------------------------------
262
+ /**
263
+ * Execute a command with sandboxing
264
+ */
265
+ async execute(command, options = {}) {
266
+ const startTime = Date.now();
267
+ // Validate first
268
+ const validation = this.validate(command);
269
+ if (!validation.valid) {
270
+ return {
271
+ success: false,
272
+ exitCode: -1,
273
+ stdout: '',
274
+ stderr: validation.reason || 'Command blocked by security policy',
275
+ duration: Date.now() - startTime,
276
+ truncated: false,
277
+ killed: false,
278
+ error: validation.reason,
279
+ };
280
+ }
281
+ // Emit warning if applicable
282
+ if (validation.severity === 'warning') {
283
+ this.emit('warning', { command, reason: validation.reason });
284
+ }
285
+ // Determine working directory
286
+ const cwd = options.cwd || this.config.workingDirectory;
287
+ // Verify cwd exists and is within allowed scope
288
+ if (!fs.existsSync(cwd)) {
289
+ return {
290
+ success: false,
291
+ exitCode: -1,
292
+ stdout: '',
293
+ stderr: `Working directory does not exist: ${cwd}`,
294
+ duration: Date.now() - startTime,
295
+ truncated: false,
296
+ killed: false,
297
+ error: 'Invalid working directory',
298
+ };
299
+ }
300
+ // If background mode, handle separately
301
+ if (options.background) {
302
+ return this.executeBackground(command, options);
303
+ }
304
+ // Execute synchronously with timeout
305
+ return this.executeSync(command, {
306
+ ...options,
307
+ cwd,
308
+ timeout: options.timeout || this.config.maxTimeout,
309
+ });
310
+ }
311
+ /**
312
+ * Execute command synchronously
313
+ */
314
+ executeSync(command, options) {
315
+ return new Promise((resolve) => {
316
+ const startTime = Date.now();
317
+ let stdout = '';
318
+ let stderr = '';
319
+ let killed = false;
320
+ let truncated = false;
321
+ const env = {
322
+ ...process.env,
323
+ ...options.env,
324
+ // Prevent some shell shenanigans
325
+ SHELL: '/bin/bash',
326
+ TERM: 'xterm-256color',
327
+ };
328
+ const child = (0, child_process_1.spawn)('bash', ['-c', command], {
329
+ cwd: options.cwd,
330
+ env,
331
+ stdio: ['pipe', 'pipe', 'pipe'],
332
+ });
333
+ // Set timeout
334
+ const timeoutId = setTimeout(() => {
335
+ killed = true;
336
+ child.kill('SIGTERM');
337
+ setTimeout(() => child.kill('SIGKILL'), 1000);
338
+ }, options.timeout);
339
+ // Collect stdout
340
+ child.stdout.on('data', (data) => {
341
+ const chunk = data.toString();
342
+ if (stdout.length + chunk.length > this.config.maxOutputSize) {
343
+ truncated = true;
344
+ stdout += chunk.slice(0, this.config.maxOutputSize - stdout.length);
345
+ }
346
+ else {
347
+ stdout += chunk;
348
+ }
349
+ this.emit('stdout', chunk);
350
+ });
351
+ // Collect stderr
352
+ child.stderr.on('data', (data) => {
353
+ const chunk = data.toString();
354
+ if (stderr.length + chunk.length > this.config.maxOutputSize) {
355
+ truncated = true;
356
+ stderr += chunk.slice(0, this.config.maxOutputSize - stderr.length);
357
+ }
358
+ else {
359
+ stderr += chunk;
360
+ }
361
+ this.emit('stderr', chunk);
362
+ });
363
+ // Handle completion
364
+ child.on('close', (code) => {
365
+ clearTimeout(timeoutId);
366
+ const duration = Date.now() - startTime;
367
+ resolve({
368
+ success: code === 0 && !killed,
369
+ exitCode: code ?? -1,
370
+ stdout: stdout.trim(),
371
+ stderr: stderr.trim(),
372
+ duration,
373
+ truncated,
374
+ killed,
375
+ error: killed ? 'Command killed due to timeout' : undefined,
376
+ });
377
+ });
378
+ child.on('error', (err) => {
379
+ clearTimeout(timeoutId);
380
+ resolve({
381
+ success: false,
382
+ exitCode: -1,
383
+ stdout: '',
384
+ stderr: err.message,
385
+ duration: Date.now() - startTime,
386
+ truncated: false,
387
+ killed: false,
388
+ error: err.message,
389
+ });
390
+ });
391
+ });
392
+ }
393
+ /**
394
+ * Execute command in background
395
+ */
396
+ executeBackground(command, options) {
397
+ const taskId = `task-${++this.taskCounter}-${Date.now()}`;
398
+ const startTime = Date.now();
399
+ const cwd = options.cwd || this.config.workingDirectory;
400
+ const env = {
401
+ ...process.env,
402
+ ...options.env,
403
+ };
404
+ const child = (0, child_process_1.spawn)('bash', ['-c', command], {
405
+ cwd,
406
+ env,
407
+ stdio: ['pipe', 'pipe', 'pipe'],
408
+ detached: true,
409
+ });
410
+ const task = {
411
+ id: taskId,
412
+ command,
413
+ process: child,
414
+ startTime,
415
+ stdout: '',
416
+ stderr: '',
417
+ status: 'running',
418
+ };
419
+ this.backgroundTasks.set(taskId, task);
420
+ // Collect output
421
+ child.stdout.on('data', (data) => {
422
+ task.stdout += data.toString();
423
+ this.emit('background-stdout', { taskId, data: data.toString() });
424
+ });
425
+ child.stderr.on('data', (data) => {
426
+ task.stderr += data.toString();
427
+ this.emit('background-stderr', { taskId, data: data.toString() });
428
+ });
429
+ child.on('close', (code) => {
430
+ task.status = code === 0 ? 'completed' : 'failed';
431
+ task.exitCode = code ?? -1;
432
+ this.emit('background-complete', { taskId, exitCode: code });
433
+ });
434
+ child.on('error', (err) => {
435
+ task.status = 'failed';
436
+ task.stderr += err.message;
437
+ this.emit('background-error', { taskId, error: err.message });
438
+ });
439
+ return Promise.resolve({
440
+ success: true,
441
+ exitCode: 0,
442
+ stdout: `Background task started: ${taskId}`,
443
+ stderr: '',
444
+ duration: 0,
445
+ truncated: false,
446
+ killed: false,
447
+ });
448
+ }
449
+ // --------------------------------------------------------------------------
450
+ // Background Task Management
451
+ // --------------------------------------------------------------------------
452
+ /**
453
+ * Get output from a background task
454
+ */
455
+ getTaskOutput(taskId, block = true, timeout = 30000) {
456
+ const task = this.backgroundTasks.get(taskId);
457
+ if (!task)
458
+ return Promise.resolve(null);
459
+ if (!block || task.status !== 'running') {
460
+ return Promise.resolve(task);
461
+ }
462
+ // Block until complete or timeout
463
+ return new Promise((resolve) => {
464
+ const startTime = Date.now();
465
+ const check = () => {
466
+ const t = this.backgroundTasks.get(taskId);
467
+ if (!t || t.status !== 'running' || Date.now() - startTime > timeout) {
468
+ resolve(t || null);
469
+ }
470
+ else {
471
+ setTimeout(check, 100);
472
+ }
473
+ };
474
+ check();
475
+ });
476
+ }
477
+ /**
478
+ * Kill a background task
479
+ */
480
+ killTask(taskId) {
481
+ const task = this.backgroundTasks.get(taskId);
482
+ if (!task || task.status !== 'running')
483
+ return false;
484
+ task.process.kill('SIGTERM');
485
+ setTimeout(() => {
486
+ if (task.status === 'running') {
487
+ task.process.kill('SIGKILL');
488
+ }
489
+ }, 1000);
490
+ task.status = 'killed';
491
+ return true;
492
+ }
493
+ /**
494
+ * List all background tasks
495
+ */
496
+ listTasks() {
497
+ return Array.from(this.backgroundTasks.values());
498
+ }
499
+ /**
500
+ * Clean up completed tasks
501
+ */
502
+ cleanupTasks() {
503
+ let cleaned = 0;
504
+ for (const [id, task] of this.backgroundTasks) {
505
+ if (task.status !== 'running') {
506
+ this.backgroundTasks.delete(id);
507
+ cleaned++;
508
+ }
509
+ }
510
+ return cleaned;
511
+ }
512
+ // --------------------------------------------------------------------------
513
+ // Configuration
514
+ // --------------------------------------------------------------------------
515
+ /**
516
+ * Update sandbox configuration
517
+ */
518
+ updateConfig(config) {
519
+ this.config = { ...this.config, ...config };
520
+ }
521
+ /**
522
+ * Add command to allowed list
523
+ */
524
+ allowCommand(command) {
525
+ if (!this.config.allowedCommands.includes(command)) {
526
+ this.config.allowedCommands.push(command);
527
+ }
528
+ }
529
+ /**
530
+ * Add pattern to blocked list
531
+ */
532
+ blockPattern(pattern) {
533
+ this.config.blockedPatterns.push(pattern);
534
+ }
535
+ /**
536
+ * Get current configuration
537
+ */
538
+ getConfig() {
539
+ return { ...this.config };
540
+ }
541
+ }
542
+ exports.BashTool = BashTool;
543
+ // ============================================================================
544
+ // Singleton Instance
545
+ // ============================================================================
546
+ let bashToolInstance = null;
547
+ function getBashTool(config) {
548
+ if (!bashToolInstance) {
549
+ bashToolInstance = new BashTool(config);
550
+ }
551
+ else if (config) {
552
+ bashToolInstance.updateConfig(config);
553
+ }
554
+ return bashToolInstance;
555
+ }
556
+ function resetBashTool() {
557
+ bashToolInstance = null;
558
+ }
559
+ // ============================================================================
560
+ // Convenience Functions
561
+ // ============================================================================
562
+ /**
563
+ * Execute a command with default settings
564
+ */
565
+ async function bash(command, options) {
566
+ return getBashTool().execute(command, options);
567
+ }
568
+ /**
569
+ * Validate a command without executing
570
+ */
571
+ function validateCommand(command) {
572
+ return getBashTool().validate(command);
573
+ }
574
+ /**
575
+ * Execute command and return stdout only (throws on error)
576
+ */
577
+ async function exec(command, options) {
578
+ const result = await bash(command, options);
579
+ if (!result.success) {
580
+ throw new Error(result.stderr || result.error || 'Command failed');
581
+ }
582
+ return result.stdout;
583
+ }