@renxqoo/renx-code 0.0.4 → 0.0.6

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 (210) hide show
  1. package/README.md +82 -51
  2. package/bin/renx.cjs +16 -0
  3. package/package.json +2 -45
  4. package/src/agent/runtime/runtime.context-usage.test.ts +4 -5
  5. package/src/agent/runtime/runtime.error-handling.test.ts +4 -5
  6. package/src/agent/runtime/runtime.test.ts +7 -4
  7. package/src/agent/runtime/runtime.ts +3 -9
  8. package/src/agent/runtime/runtime.usage-forwarding.test.ts +4 -5
  9. package/src/agent/runtime/source-modules.test.ts +16 -35
  10. package/src/agent/runtime/source-modules.ts +17 -0
  11. package/vendor/agent-root/src/agent/ENTERPRISE_ACCEPTANCE_CHECKLIST.md +95 -0
  12. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.html +1345 -0
  13. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.md +1353 -0
  14. package/vendor/agent-root/src/agent/ERROR_CONTRACT.md +60 -0
  15. package/vendor/agent-root/src/agent/TEST_COVERAGE_ANALYSIS.md +278 -0
  16. package/vendor/agent-root/src/agent/__test__/error-contract.test.ts +72 -0
  17. package/vendor/agent-root/src/agent/__test__/types.test.ts +137 -0
  18. package/vendor/agent-root/src/agent/agent/__test__/abort-runtime.test.ts +83 -0
  19. package/vendor/agent-root/src/agent/agent/__test__/callback-safety.test.ts +34 -0
  20. package/vendor/agent-root/src/agent/agent/__test__/compaction.test.ts +323 -0
  21. package/vendor/agent-root/src/agent/agent/__test__/concurrency.test.ts +290 -0
  22. package/vendor/agent-root/src/agent/agent/__test__/error-normalizer.test.ts +377 -0
  23. package/vendor/agent-root/src/agent/agent/__test__/error.test.ts +212 -0
  24. package/vendor/agent-root/src/agent/agent/__test__/fault-injection.test.ts +295 -0
  25. package/vendor/agent-root/src/agent/agent/__test__/index.test.ts +3607 -0
  26. package/vendor/agent-root/src/agent/agent/__test__/logger.test.ts +35 -0
  27. package/vendor/agent-root/src/agent/agent/__test__/message-utils.test.ts +517 -0
  28. package/vendor/agent-root/src/agent/agent/__test__/telemetry.test.ts +97 -0
  29. package/vendor/agent-root/src/agent/agent/__test__/timeout-budget.test.ts +479 -0
  30. package/vendor/agent-root/src/agent/agent/__test__/tool-call-merge.test.ts +80 -0
  31. package/vendor/agent-root/src/agent/agent/__test__/tool-execution-ledger.test.ts +76 -0
  32. package/vendor/agent-root/src/agent/agent/__test__/write-buffer.test.ts +173 -0
  33. package/vendor/agent-root/src/agent/agent/__test__/write-file-session.test.ts +109 -0
  34. package/vendor/agent-root/src/agent/agent/abort-runtime.ts +71 -0
  35. package/vendor/agent-root/src/agent/agent/callback-safety.ts +33 -0
  36. package/vendor/agent-root/src/agent/agent/compaction.ts +291 -0
  37. package/vendor/agent-root/src/agent/agent/concurrency.ts +103 -0
  38. package/vendor/agent-root/src/agent/agent/error-normalizer.ts +190 -0
  39. package/vendor/agent-root/src/agent/agent/error.ts +198 -0
  40. package/vendor/agent-root/src/agent/agent/index.ts +1772 -0
  41. package/vendor/agent-root/src/agent/agent/logger.ts +65 -0
  42. package/vendor/agent-root/src/agent/agent/message-utils.ts +101 -0
  43. package/vendor/agent-root/src/agent/agent/stream-events.ts +61 -0
  44. package/vendor/agent-root/src/agent/agent/telemetry.ts +123 -0
  45. package/vendor/agent-root/src/agent/agent/timeout-budget.ts +227 -0
  46. package/vendor/agent-root/src/agent/agent/tool-call-merge.ts +111 -0
  47. package/vendor/agent-root/src/agent/agent/tool-execution-ledger.ts +164 -0
  48. package/vendor/agent-root/src/agent/agent/write-buffer.ts +188 -0
  49. package/vendor/agent-root/src/agent/agent/write-file-session.ts +238 -0
  50. package/vendor/agent-root/src/agent/app/__test__/agent-app-service.test.ts +1053 -0
  51. package/vendor/agent-root/src/agent/app/__test__/minimal-agent-application.test.ts +158 -0
  52. package/vendor/agent-root/src/agent/app/__test__/sqlite-agent-app-store.test.ts +437 -0
  53. package/vendor/agent-root/src/agent/app/agent-app-service.ts +748 -0
  54. package/vendor/agent-root/src/agent/app/contracts.ts +109 -0
  55. package/vendor/agent-root/src/agent/app/index.ts +5 -0
  56. package/vendor/agent-root/src/agent/app/minimal-agent-application.ts +151 -0
  57. package/vendor/agent-root/src/agent/app/ports.ts +72 -0
  58. package/vendor/agent-root/src/agent/app/sqlite-agent-app-store.ts +1182 -0
  59. package/vendor/agent-root/src/agent/app/sqlite-client.ts +177 -0
  60. package/vendor/agent-root/src/agent/docs/cli-app-layer/00-README.md +36 -0
  61. package/vendor/agent-root/src/agent/docs/cli-app-layer/01-scope-and-goals.md +33 -0
  62. package/vendor/agent-root/src/agent/docs/cli-app-layer/02-architecture-overview.md +40 -0
  63. package/vendor/agent-root/src/agent/docs/cli-app-layer/03-domain-model-and-contracts.md +91 -0
  64. package/vendor/agent-root/src/agent/docs/cli-app-layer/04-ports-and-interfaces.md +116 -0
  65. package/vendor/agent-root/src/agent/docs/cli-app-layer/05-run-orchestration-and-state-machine.md +52 -0
  66. package/vendor/agent-root/src/agent/docs/cli-app-layer/06-cli-commands-and-ux.md +53 -0
  67. package/vendor/agent-root/src/agent/docs/cli-app-layer/07-storage-design-local.md +52 -0
  68. package/vendor/agent-root/src/agent/docs/cli-app-layer/08-error-and-observability.md +40 -0
  69. package/vendor/agent-root/src/agent/docs/cli-app-layer/09-security-and-policy-boundary.md +19 -0
  70. package/vendor/agent-root/src/agent/docs/cli-app-layer/10-test-plan-and-acceptance.md +28 -0
  71. package/vendor/agent-root/src/agent/docs/cli-app-layer/11-implementation-phases.md +26 -0
  72. package/vendor/agent-root/src/agent/docs/cli-app-layer/12-open-questions-and-risks.md +30 -0
  73. package/vendor/agent-root/src/agent/docs/cli-app-layer/13-sqlite-schema-fields-and-rationale.md +567 -0
  74. package/vendor/agent-root/src/agent/docs/cli-app-layer/14-project-flow-mermaid.md +583 -0
  75. package/vendor/agent-root/src/agent/docs/cli-app-layer/15-openclaw-style-project-blueprint.md +972 -0
  76. package/vendor/agent-root/src/agent/error-contract.ts +154 -0
  77. package/vendor/agent-root/src/agent/prompts/system.ts +246 -0
  78. package/vendor/agent-root/src/agent/prompts/system1.ts +208 -0
  79. package/vendor/agent-root/src/agent/storage/__test__/file-history-store.test.ts +98 -0
  80. package/vendor/agent-root/src/agent/storage/file-history-store.ts +313 -0
  81. package/vendor/agent-root/src/agent/storage/file-storage-config.ts +94 -0
  82. package/vendor/agent-root/src/agent/storage/file-system.ts +31 -0
  83. package/vendor/agent-root/src/agent/storage/file-write-service.ts +21 -0
  84. package/vendor/agent-root/src/agent/tool/__test__/base-tool.test.ts +413 -0
  85. package/vendor/agent-root/src/agent/tool/__test__/bash-policy.test.ts +356 -0
  86. package/vendor/agent-root/src/agent/tool/__test__/bash.mocked-coverage.test.ts +375 -0
  87. package/vendor/agent-root/src/agent/tool/__test__/bash.test.ts +372 -0
  88. package/vendor/agent-root/src/agent/tool/__test__/error.test.ts +108 -0
  89. package/vendor/agent-root/src/agent/tool/__test__/file-edit-tool.test.ts +258 -0
  90. package/vendor/agent-root/src/agent/tool/__test__/file-history-tools.test.ts +121 -0
  91. package/vendor/agent-root/src/agent/tool/__test__/file-read-tool.test.ts +210 -0
  92. package/vendor/agent-root/src/agent/tool/__test__/glob.test.ts +139 -0
  93. package/vendor/agent-root/src/agent/tool/__test__/grep.mocked-coverage.test.ts +456 -0
  94. package/vendor/agent-root/src/agent/tool/__test__/grep.test.ts +192 -0
  95. package/vendor/agent-root/src/agent/tool/__test__/lsp.test.ts +300 -0
  96. package/vendor/agent-root/src/agent/tool/__test__/outside-workspace-confirmation.test.ts +214 -0
  97. package/vendor/agent-root/src/agent/tool/__test__/path-security.test.ts +336 -0
  98. package/vendor/agent-root/src/agent/tool/__test__/skill-loader.test.ts +494 -0
  99. package/vendor/agent-root/src/agent/tool/__test__/skill-parser.test.ts +543 -0
  100. package/vendor/agent-root/src/agent/tool/__test__/skill-tool.test.ts +172 -0
  101. package/vendor/agent-root/src/agent/tool/__test__/task-concurrency-and-version.test.ts +116 -0
  102. package/vendor/agent-root/src/agent/tool/__test__/task-create-get-list-update.test.ts +267 -0
  103. package/vendor/agent-root/src/agent/tool/__test__/task-create.test.ts +519 -0
  104. package/vendor/agent-root/src/agent/tool/__test__/task-errors.test.ts +225 -0
  105. package/vendor/agent-root/src/agent/tool/__test__/task-output-blocking.test.ts +223 -0
  106. package/vendor/agent-root/src/agent/tool/__test__/task-output.test.ts +184 -0
  107. package/vendor/agent-root/src/agent/tool/__test__/task-parent-abort.test.ts +287 -0
  108. package/vendor/agent-root/src/agent/tool/__test__/task-real-runner-adapter.test.ts +190 -0
  109. package/vendor/agent-root/src/agent/tool/__test__/task-run-lifecycle.test.ts +352 -0
  110. package/vendor/agent-root/src/agent/tool/__test__/task-store-runner-branches.test.ts +395 -0
  111. package/vendor/agent-root/src/agent/tool/__test__/task-store.test.ts +391 -0
  112. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config-integration.test.ts +176 -0
  113. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config.test.ts +68 -0
  114. package/vendor/agent-root/src/agent/tool/__test__/task-tools-core-edges.test.ts +630 -0
  115. package/vendor/agent-root/src/agent/tool/__test__/task-tools-runtime-edges.test.ts +732 -0
  116. package/vendor/agent-root/src/agent/tool/__test__/task-types.test.ts +494 -0
  117. package/vendor/agent-root/src/agent/tool/__test__/task-utils-branches.test.ts +175 -0
  118. package/vendor/agent-root/src/agent/tool/__test__/tool-manager.test.ts +505 -0
  119. package/vendor/agent-root/src/agent/tool/__test__/types.test.ts +55 -0
  120. package/vendor/agent-root/src/agent/tool/__test__/web-fetch.test.ts +244 -0
  121. package/vendor/agent-root/src/agent/tool/__test__/web-search.test.ts +290 -0
  122. package/vendor/agent-root/src/agent/tool/__test__/write-file.test.ts +368 -0
  123. package/vendor/agent-root/src/agent/tool/base-tool.ts +345 -0
  124. package/vendor/agent-root/src/agent/tool/bash-policy.ts +636 -0
  125. package/vendor/agent-root/src/agent/tool/bash.ts +688 -0
  126. package/vendor/agent-root/src/agent/tool/error.ts +131 -0
  127. package/vendor/agent-root/src/agent/tool/file-edit-tool.ts +264 -0
  128. package/vendor/agent-root/src/agent/tool/file-history-list.ts +103 -0
  129. package/vendor/agent-root/src/agent/tool/file-history-restore.ts +149 -0
  130. package/vendor/agent-root/src/agent/tool/file-read-tool.ts +211 -0
  131. package/vendor/agent-root/src/agent/tool/glob.ts +171 -0
  132. package/vendor/agent-root/src/agent/tool/grep.ts +496 -0
  133. package/vendor/agent-root/src/agent/tool/lsp.ts +481 -0
  134. package/vendor/agent-root/src/agent/tool/path-security.ts +117 -0
  135. package/vendor/agent-root/src/agent/tool/search/common.ts +153 -0
  136. package/vendor/agent-root/src/agent/tool/skill/index.ts +13 -0
  137. package/vendor/agent-root/src/agent/tool/skill/loader.ts +229 -0
  138. package/vendor/agent-root/src/agent/tool/skill/parser.ts +124 -0
  139. package/vendor/agent-root/src/agent/tool/skill/types.ts +27 -0
  140. package/vendor/agent-root/src/agent/tool/skill-tool.ts +143 -0
  141. package/vendor/agent-root/src/agent/tool/task-create.ts +186 -0
  142. package/vendor/agent-root/src/agent/tool/task-errors.ts +42 -0
  143. package/vendor/agent-root/src/agent/tool/task-get.ts +116 -0
  144. package/vendor/agent-root/src/agent/tool/task-graph.ts +78 -0
  145. package/vendor/agent-root/src/agent/tool/task-list.ts +141 -0
  146. package/vendor/agent-root/src/agent/tool/task-mock-runner-adapter.ts +232 -0
  147. package/vendor/agent-root/src/agent/tool/task-output.ts +223 -0
  148. package/vendor/agent-root/src/agent/tool/task-parent-abort.ts +115 -0
  149. package/vendor/agent-root/src/agent/tool/task-real-runner-adapter.ts +336 -0
  150. package/vendor/agent-root/src/agent/tool/task-runner-adapter.ts +55 -0
  151. package/vendor/agent-root/src/agent/tool/task-stop.ts +187 -0
  152. package/vendor/agent-root/src/agent/tool/task-store.ts +217 -0
  153. package/vendor/agent-root/src/agent/tool/task-subagent-config.ts +149 -0
  154. package/vendor/agent-root/src/agent/tool/task-types.ts +264 -0
  155. package/vendor/agent-root/src/agent/tool/task-update.ts +315 -0
  156. package/vendor/agent-root/src/agent/tool/task.ts +209 -0
  157. package/vendor/agent-root/src/agent/tool/tool-manager.ts +362 -0
  158. package/vendor/agent-root/src/agent/tool/tool-prompts.ts +242 -0
  159. package/vendor/agent-root/src/agent/tool/types.ts +116 -0
  160. package/vendor/agent-root/src/agent/tool/web-fetch.ts +227 -0
  161. package/vendor/agent-root/src/agent/tool/web-search.ts +208 -0
  162. package/vendor/agent-root/src/agent/tool/write-file.ts +497 -0
  163. package/vendor/agent-root/src/agent/types.ts +232 -0
  164. package/vendor/agent-root/src/agent/utils/__tests__/index.test.ts +18 -0
  165. package/vendor/agent-root/src/agent/utils/__tests__/message-utils.test.ts +610 -0
  166. package/vendor/agent-root/src/agent/utils/__tests__/message.test.ts +223 -0
  167. package/vendor/agent-root/src/agent/utils/__tests__/token.test.ts +42 -0
  168. package/vendor/agent-root/src/agent/utils/index.ts +16 -0
  169. package/vendor/agent-root/src/agent/utils/message.ts +171 -0
  170. package/vendor/agent-root/src/agent/utils/token.ts +28 -0
  171. package/vendor/agent-root/src/config/__tests__/load-config-to-env.test.ts +129 -0
  172. package/vendor/agent-root/src/config/__tests__/loader.test.ts +247 -0
  173. package/vendor/agent-root/src/config/__tests__/runtime.test.ts +88 -0
  174. package/vendor/agent-root/src/config/index.ts +54 -0
  175. package/vendor/agent-root/src/config/loader.ts +431 -0
  176. package/vendor/agent-root/src/config/paths.ts +30 -0
  177. package/vendor/agent-root/src/config/runtime.ts +163 -0
  178. package/vendor/agent-root/src/config/types.ts +70 -0
  179. package/vendor/agent-root/src/logger/index.ts +57 -0
  180. package/vendor/agent-root/src/logger/logger.ts +819 -0
  181. package/vendor/agent-root/src/logger/types.ts +150 -0
  182. package/vendor/agent-root/src/providers/__tests__/errors.test.ts +441 -0
  183. package/vendor/agent-root/src/providers/__tests__/index.test.ts +16 -0
  184. package/vendor/agent-root/src/providers/__tests__/openai-compatible.options.test.ts +318 -0
  185. package/vendor/agent-root/src/providers/__tests__/openai-compatible.test.ts +600 -0
  186. package/vendor/agent-root/src/providers/__tests__/registry.test.ts +449 -0
  187. package/vendor/agent-root/src/providers/__tests__/responses-adapter.test.ts +298 -0
  188. package/vendor/agent-root/src/providers/adapters/__tests__/anthropic.test.ts +354 -0
  189. package/vendor/agent-root/src/providers/adapters/__tests__/kimi.test.ts +58 -0
  190. package/vendor/agent-root/src/providers/adapters/__tests__/standard.test.ts +261 -0
  191. package/vendor/agent-root/src/providers/adapters/anthropic.ts +572 -0
  192. package/vendor/agent-root/src/providers/adapters/base.ts +131 -0
  193. package/vendor/agent-root/src/providers/adapters/kimi.ts +48 -0
  194. package/vendor/agent-root/src/providers/adapters/responses.ts +732 -0
  195. package/vendor/agent-root/src/providers/adapters/standard.ts +120 -0
  196. package/vendor/agent-root/src/providers/http/__tests__/client.timeout.test.ts +313 -0
  197. package/vendor/agent-root/src/providers/http/client.ts +289 -0
  198. package/vendor/agent-root/src/providers/http/stream-parser.ts +109 -0
  199. package/vendor/agent-root/src/providers/index.ts +76 -0
  200. package/vendor/agent-root/src/providers/kimi-headers.ts +177 -0
  201. package/vendor/agent-root/src/providers/openai-compatible.ts +387 -0
  202. package/vendor/agent-root/src/providers/registry/model-config.ts +230 -0
  203. package/vendor/agent-root/src/providers/registry/provider-factory.ts +123 -0
  204. package/vendor/agent-root/src/providers/registry.ts +135 -0
  205. package/vendor/agent-root/src/providers/types/api.ts +284 -0
  206. package/vendor/agent-root/src/providers/types/config.ts +58 -0
  207. package/vendor/agent-root/src/providers/types/errors.ts +323 -0
  208. package/vendor/agent-root/src/providers/types/index.ts +72 -0
  209. package/vendor/agent-root/src/providers/types/provider.ts +45 -0
  210. package/vendor/agent-root/src/providers/types/registry.ts +88 -0
@@ -0,0 +1,636 @@
1
+ import * as path from 'node:path';
2
+ import { parse } from 'shell-quote';
3
+
4
+ export type BashPolicyMode = 'guarded' | 'permissive';
5
+ export type BashPolicyEffect = 'allow' | 'ask' | 'deny';
6
+
7
+ export interface BashDangerousPattern {
8
+ pattern: RegExp;
9
+ reason: string;
10
+ }
11
+
12
+ export interface EvaluateBashPolicyOptions {
13
+ platform?: NodeJS.Platform;
14
+ mode?: BashPolicyMode;
15
+ allowlistMissEffect?: Extract<BashPolicyEffect, 'ask' | 'deny'>;
16
+ allowlistMissReason?: (commandName: string) => string;
17
+ allowlistBypassed?: boolean;
18
+ }
19
+
20
+ export interface EvaluateBashPolicyResult {
21
+ effect: BashPolicyEffect;
22
+ reason?: string;
23
+ commands: string[];
24
+ }
25
+
26
+ const MAX_POLICY_RECURSION_DEPTH = 4;
27
+
28
+ const COMMON_DANGEROUS_COMMANDS = new Set([
29
+ 'sudo',
30
+ 'su',
31
+ 'passwd',
32
+ 'visudo',
33
+ 'useradd',
34
+ 'userdel',
35
+ 'groupadd',
36
+ 'groupdel',
37
+ 'shutdown',
38
+ 'reboot',
39
+ 'halt',
40
+ 'poweroff',
41
+ 'mkfs',
42
+ 'fdisk',
43
+ 'diskutil',
44
+ 'mount',
45
+ 'umount',
46
+ 'systemctl',
47
+ 'service',
48
+ 'launchctl',
49
+ ]);
50
+
51
+ const WINDOWS_DANGEROUS_COMMANDS = new Set([
52
+ 'format',
53
+ 'diskpart',
54
+ 'bcdedit',
55
+ 'vssadmin',
56
+ 'wbadmin',
57
+ 'reg',
58
+ 'sc',
59
+ ]);
60
+
61
+ const COMMON_ALLOWED_COMMANDS = new Set([
62
+ 'ls',
63
+ 'pwd',
64
+ 'cat',
65
+ 'head',
66
+ 'tail',
67
+ 'echo',
68
+ 'printf',
69
+ 'wc',
70
+ 'sort',
71
+ 'uniq',
72
+ 'cut',
73
+ 'awk',
74
+ 'sed',
75
+ 'grep',
76
+ 'egrep',
77
+ 'fgrep',
78
+ 'rg',
79
+ 'find',
80
+ 'stat',
81
+ 'du',
82
+ 'df',
83
+ 'tree',
84
+ 'which',
85
+ 'whereis',
86
+ 'dirname',
87
+ 'basename',
88
+ 'realpath',
89
+ 'readlink',
90
+ 'file',
91
+ 'env',
92
+ 'printenv',
93
+ 'date',
94
+ 'uname',
95
+ 'whoami',
96
+ 'id',
97
+ 'hostname',
98
+ 'ps',
99
+ 'top',
100
+ 'uptime',
101
+ 'git',
102
+ 'gh',
103
+ 'npm',
104
+ 'pnpm',
105
+ 'yarn',
106
+ 'bun',
107
+ 'node',
108
+ 'npx',
109
+ 'tsx',
110
+ 'ts-node',
111
+ 'tsc',
112
+ 'python',
113
+ 'python3',
114
+ 'pip',
115
+ 'pip3',
116
+ 'uv',
117
+ 'poetry',
118
+ 'pytest',
119
+ 'go',
120
+ 'cargo',
121
+ 'rustc',
122
+ 'rustup',
123
+ 'javac',
124
+ 'java',
125
+ 'mvn',
126
+ 'gradle',
127
+ 'dotnet',
128
+ 'docker-compose',
129
+ 'helm',
130
+ 'make',
131
+ 'cmake',
132
+ 'ninja',
133
+ 'cp',
134
+ 'mv',
135
+ 'mkdir',
136
+ 'touch',
137
+ 'ln',
138
+ 'chmod',
139
+ 'chown',
140
+ 'tar',
141
+ 'zip',
142
+ 'unzip',
143
+ 'gzip',
144
+ 'gunzip',
145
+ 'rsync',
146
+ 'sh',
147
+ 'bash',
148
+ 'zsh',
149
+ 'true',
150
+ 'false',
151
+ 'test',
152
+ 'cd',
153
+ 'export',
154
+ 'unset',
155
+ 'set',
156
+ 'source',
157
+ 'curl',
158
+ 'wget',
159
+ 'ping',
160
+ 'nc',
161
+ 'ssh',
162
+ 'scp',
163
+ 'jq',
164
+ 'yq',
165
+ 'fzf',
166
+ 'bat',
167
+ 'exa',
168
+ 'fd',
169
+ 'ripgrep',
170
+ 'code',
171
+ 'vim',
172
+ 'nvim',
173
+ ]);
174
+
175
+ const WINDOWS_ALLOWED_COMMANDS = new Set([
176
+ 'dir',
177
+ 'type',
178
+ 'more',
179
+ 'findstr',
180
+ 'where',
181
+ 'copy',
182
+ 'move',
183
+ 'attrib',
184
+ 'icacls',
185
+ 'mklink',
186
+ 'powershell',
187
+ 'pwsh',
188
+ 'cmd',
189
+ ]);
190
+
191
+ const MACOS_ALLOWED_COMMANDS = new Set(['open', 'pbcopy', 'pbpaste', 'launchctl']);
192
+
193
+ const COMMON_DANGEROUS_PATTERNS: BashDangerousPattern[] = [
194
+ { pattern: /\brm\s+-rf\s+\/(\s|$)/i, reason: 'Refusing destructive root deletion command' },
195
+ {
196
+ pattern: /\brm\s+-rf\s+--no-preserve-root\b/i,
197
+ reason: 'Refusing destructive root deletion command',
198
+ },
199
+ { pattern: /:\(\)\s*\{\s*:\|:&\s*\};:/, reason: 'Refusing fork bomb pattern' },
200
+ {
201
+ pattern: /\b(curl|wget)[^|\n]*\|\s*(sh|bash|zsh)\b/i,
202
+ reason: 'Refusing remote script pipe execution',
203
+ },
204
+ {
205
+ pattern: /\b(eval|source)\s+<\s*\((curl|wget)\b/i,
206
+ reason: 'Refusing remote script evaluation',
207
+ },
208
+ {
209
+ pattern: /\bdd\s+[^|\n]*\bof=\/dev\/(sd|disk|nvme|rdisk)/i,
210
+ reason: 'Refusing raw disk write command',
211
+ },
212
+ {
213
+ pattern:
214
+ />{1,2}\s*\/(etc|bin|sbin|usr|boot|proc|sys)\b|>{1,2}\s*\/dev(?:\/(?!null\b|stdout\b|stderr\b)[^\s;|&]+|(?=[\s;|&]|$))/i,
215
+ reason: 'Refusing write redirection to protected system path',
216
+ },
217
+ {
218
+ pattern:
219
+ /\btee\s+\/(etc|bin|sbin|usr|boot|proc|sys)\b|\btee\s+\/dev(?:\/(?!null\b|stdout\b|stderr\b)[^\s;|&]+|(?=[\s;|&]|$))/i,
220
+ reason: 'Refusing write to protected system path',
221
+ },
222
+ {
223
+ pattern: /\b(sh|bash|zsh)\s+-[a-z]*c[a-z]*\b/i,
224
+ reason: 'Nested shell execution is blocked by policy',
225
+ },
226
+ {
227
+ pattern: /\b(sh|bash|zsh)\s+--command\b/i,
228
+ reason: 'Nested shell execution is blocked by policy',
229
+ },
230
+ {
231
+ pattern: /\beval\s+/i,
232
+ reason: 'eval command is blocked for security reasons',
233
+ },
234
+ {
235
+ pattern: /\bexec\s+/i,
236
+ reason: 'exec command is blocked for security reasons',
237
+ },
238
+ {
239
+ pattern: /\bpython(?:3)?\s+-[a-z]*c[a-z]*\b/i,
240
+ reason: 'Inline Python execution is blocked for security reasons',
241
+ },
242
+ {
243
+ pattern: /\b(node|nodejs)\s+(?:--eval|-e)\b/i,
244
+ reason: 'Inline Node.js execution is blocked for security reasons',
245
+ },
246
+ ];
247
+
248
+ const WINDOWS_DANGEROUS_PATTERNS: BashDangerousPattern[] = [
249
+ {
250
+ pattern: /\b(rd|rmdir)\s+\/s\s+\/q\s+[a-z]:\\\s*$/i,
251
+ reason: 'Refusing recursive drive root deletion command',
252
+ },
253
+ {
254
+ pattern: /\b(del|erase)\s+\/[a-z]*\s+[a-z]:\\\*\s*$/i,
255
+ reason: 'Refusing destructive drive wildcard deletion command',
256
+ },
257
+ {
258
+ pattern: />{1,2}\s*[a-z]:\\(windows|program files|programdata)\\?/i,
259
+ reason: 'Refusing write redirection to protected Windows path',
260
+ },
261
+ {
262
+ pattern: /\breg\s+(add|delete)\s+hk(lm|cu)\\(software|system)(\\|$)/i,
263
+ reason: 'Refusing registry mutation on critical hive',
264
+ },
265
+ ];
266
+
267
+ const WINDOWS_EXECUTABLE_EXTENSIONS = new Set(['.exe', '.cmd', '.bat', '.com', '.ps1']);
268
+
269
+ function normalizeCommandToken(token: string): string {
270
+ const trimmed = token.trim();
271
+ if (!trimmed) {
272
+ return '';
273
+ }
274
+
275
+ const unixLikePath = trimmed.replace(/\\/g, '/');
276
+ const basename = path.posix.basename(unixLikePath);
277
+ const lower = basename.toLowerCase();
278
+ const extension = path.posix.extname(lower);
279
+
280
+ if (WINDOWS_EXECUTABLE_EXTENSIONS.has(extension)) {
281
+ return lower.slice(0, -extension.length);
282
+ }
283
+
284
+ return lower;
285
+ }
286
+
287
+ function collectParenthesizedSubcommands(command: string, marker: '$(' | '<(' | '>('): string[] {
288
+ const snippets: string[] = [];
289
+ const markerLength = marker.length;
290
+ const length = command.length;
291
+ let inSingleQuote = false;
292
+ let inDoubleQuote = false;
293
+ let escaped = false;
294
+
295
+ for (let i = 0; i < length; i += 1) {
296
+ const char = command[i];
297
+ if (escaped) {
298
+ escaped = false;
299
+ continue;
300
+ }
301
+
302
+ if (char === '\\' && !inSingleQuote) {
303
+ escaped = true;
304
+ continue;
305
+ }
306
+
307
+ if (char === "'" && !inDoubleQuote) {
308
+ inSingleQuote = !inSingleQuote;
309
+ continue;
310
+ }
311
+
312
+ if (char === '"' && !inSingleQuote) {
313
+ inDoubleQuote = !inDoubleQuote;
314
+ continue;
315
+ }
316
+
317
+ if (inSingleQuote) {
318
+ continue;
319
+ }
320
+
321
+ if (!command.startsWith(marker, i)) {
322
+ continue;
323
+ }
324
+
325
+ const contentStart = i + markerLength;
326
+ let depth = 1;
327
+ let innerSingleQuote = false;
328
+ let innerDoubleQuote = false;
329
+ let innerEscaped = false;
330
+ let closedAt = -1;
331
+
332
+ for (let j = contentStart; j < length; j += 1) {
333
+ const innerChar = command[j];
334
+ if (innerEscaped) {
335
+ innerEscaped = false;
336
+ continue;
337
+ }
338
+
339
+ if (innerChar === '\\' && !innerSingleQuote) {
340
+ innerEscaped = true;
341
+ continue;
342
+ }
343
+
344
+ if (innerChar === "'" && !innerDoubleQuote) {
345
+ innerSingleQuote = !innerSingleQuote;
346
+ continue;
347
+ }
348
+
349
+ if (innerChar === '"' && !innerSingleQuote) {
350
+ innerDoubleQuote = !innerDoubleQuote;
351
+ continue;
352
+ }
353
+
354
+ if (innerSingleQuote || innerDoubleQuote) {
355
+ continue;
356
+ }
357
+
358
+ if (
359
+ j + 1 < length &&
360
+ (command[j] === '$' || command[j] === '<' || command[j] === '>') &&
361
+ command[j + 1] === '('
362
+ ) {
363
+ depth += 1;
364
+ j += 1;
365
+ continue;
366
+ }
367
+
368
+ if (innerChar === ')') {
369
+ depth -= 1;
370
+ if (depth === 0) {
371
+ closedAt = j;
372
+ break;
373
+ }
374
+ }
375
+ }
376
+
377
+ if (closedAt > contentStart) {
378
+ const snippet = command.slice(contentStart, closedAt).trim();
379
+ if (snippet) {
380
+ snippets.push(snippet);
381
+ }
382
+ i = closedAt;
383
+ }
384
+ }
385
+
386
+ return snippets;
387
+ }
388
+
389
+ function collectBacktickSubcommands(command: string): string[] {
390
+ const snippets: string[] = [];
391
+ const length = command.length;
392
+ let inSingleQuote = false;
393
+ let inDoubleQuote = false;
394
+ let escaped = false;
395
+ let captureStart = -1;
396
+
397
+ for (let i = 0; i < length; i += 1) {
398
+ const char = command[i];
399
+
400
+ if (escaped) {
401
+ escaped = false;
402
+ continue;
403
+ }
404
+
405
+ if (char === '\\' && !inSingleQuote) {
406
+ escaped = true;
407
+ continue;
408
+ }
409
+
410
+ if (char === "'" && captureStart === -1 && !inDoubleQuote) {
411
+ inSingleQuote = !inSingleQuote;
412
+ continue;
413
+ }
414
+
415
+ if (char === '"' && captureStart === -1 && !inSingleQuote) {
416
+ inDoubleQuote = !inDoubleQuote;
417
+ continue;
418
+ }
419
+
420
+ if (inSingleQuote) {
421
+ continue;
422
+ }
423
+
424
+ if (char !== '`') {
425
+ continue;
426
+ }
427
+
428
+ if (captureStart === -1) {
429
+ captureStart = i + 1;
430
+ continue;
431
+ }
432
+
433
+ if (i > captureStart) {
434
+ const snippet = command.slice(captureStart, i).trim();
435
+ if (snippet) {
436
+ snippets.push(snippet);
437
+ }
438
+ }
439
+ captureStart = -1;
440
+ }
441
+
442
+ return snippets;
443
+ }
444
+
445
+ function extractNestedCommands(command: string): string[] {
446
+ return [
447
+ ...collectParenthesizedSubcommands(command, '$('),
448
+ ...collectParenthesizedSubcommands(command, '<('),
449
+ ...collectParenthesizedSubcommands(command, '>('),
450
+ ...collectBacktickSubcommands(command),
451
+ ];
452
+ }
453
+
454
+ function isOperatorToken(token: unknown): token is { op: string } {
455
+ return typeof token === 'object' && token !== null && 'op' in token;
456
+ }
457
+
458
+ function evaluateBashPolicyInternal(
459
+ command: string,
460
+ options: EvaluateBashPolicyOptions = {},
461
+ depth = 0
462
+ ): EvaluateBashPolicyResult {
463
+ if (depth > MAX_POLICY_RECURSION_DEPTH) {
464
+ return {
465
+ effect: 'deny',
466
+ reason: 'Command nesting depth exceeded policy limit',
467
+ commands: [],
468
+ };
469
+ }
470
+
471
+ const normalizedCommand = command.trim();
472
+ const mode = options.mode ?? 'guarded';
473
+ const allowlistMissEffect = options.allowlistMissEffect ?? 'deny';
474
+ const allowlistMissReason =
475
+ options.allowlistMissReason ??
476
+ ((commandName: string) =>
477
+ `Command "${commandName}" is not in allowed command list (set BASH_TOOL_POLICY=permissive to bypass)`);
478
+ const platform = options.platform ?? process.platform;
479
+
480
+ if (!normalizedCommand) {
481
+ return { effect: 'allow', commands: [] };
482
+ }
483
+
484
+ for (const rule of getBashDangerousPatterns(platform)) {
485
+ if (rule.pattern.test(normalizedCommand)) {
486
+ return {
487
+ effect: 'deny',
488
+ reason: rule.reason,
489
+ commands: [],
490
+ };
491
+ }
492
+ }
493
+
494
+ const nestedCommands = extractNestedCommands(normalizedCommand);
495
+ const nestedExtractedCommands: string[] = [];
496
+
497
+ for (const nestedCommand of nestedCommands) {
498
+ const nestedResult = evaluateBashPolicyInternal(nestedCommand, options, depth + 1);
499
+ nestedExtractedCommands.push(...nestedResult.commands);
500
+
501
+ if (nestedResult.effect !== 'allow') {
502
+ return {
503
+ effect: nestedResult.effect,
504
+ reason:
505
+ nestedResult.reason ?? `Nested command "${nestedCommand}" is blocked by security policy`,
506
+ commands: nestedExtractedCommands,
507
+ };
508
+ }
509
+ }
510
+
511
+ const commands = extractSegmentCommands(normalizedCommand);
512
+ if (commands.length === 0) {
513
+ return {
514
+ effect: 'deny',
515
+ reason: 'Unable to parse executable command',
516
+ commands: nestedExtractedCommands,
517
+ };
518
+ }
519
+
520
+ const allCommands = [...nestedExtractedCommands, ...commands];
521
+
522
+ const dangerousCommands = getBashDangerousCommands(platform);
523
+ for (const commandName of allCommands) {
524
+ if (dangerousCommands.has(commandName)) {
525
+ return {
526
+ effect: 'deny',
527
+ reason: `Command "${commandName}" is blocked by security policy`,
528
+ commands: allCommands,
529
+ };
530
+ }
531
+ }
532
+
533
+ if (mode === 'guarded' && !options.allowlistBypassed) {
534
+ const allowedCommands = getBashAllowedCommands(platform);
535
+ for (const commandName of allCommands) {
536
+ if (!allowedCommands.has(commandName)) {
537
+ return {
538
+ effect: allowlistMissEffect,
539
+ reason: allowlistMissReason(commandName),
540
+ commands: allCommands,
541
+ };
542
+ }
543
+ }
544
+ }
545
+
546
+ return { effect: 'allow', commands: allCommands };
547
+ }
548
+
549
+ export function extractSegmentCommands(command: string): string[] {
550
+ const tokens = parse(command);
551
+ const commands: string[] = [];
552
+ let expectingCommand = true;
553
+
554
+ for (const token of tokens) {
555
+ if (isOperatorToken(token)) {
556
+ const operator = String(token.op || '');
557
+ if (
558
+ operator === '|' ||
559
+ operator === '||' ||
560
+ operator === '&&' ||
561
+ operator === ';' ||
562
+ operator === '&' ||
563
+ operator === '\n'
564
+ ) {
565
+ expectingCommand = true;
566
+ }
567
+ continue;
568
+ }
569
+
570
+ if (typeof token !== 'string' || !expectingCommand) {
571
+ continue;
572
+ }
573
+
574
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(token)) {
575
+ continue;
576
+ }
577
+
578
+ const normalized = normalizeCommandToken(token);
579
+ if (!normalized) {
580
+ continue;
581
+ }
582
+
583
+ commands.push(normalized);
584
+ expectingCommand = false;
585
+ }
586
+
587
+ return commands;
588
+ }
589
+
590
+ export function getBashAllowedCommands(platform: NodeJS.Platform = process.platform): Set<string> {
591
+ const commands = new Set(COMMON_ALLOWED_COMMANDS);
592
+
593
+ if (platform === 'win32') {
594
+ for (const commandName of WINDOWS_ALLOWED_COMMANDS) {
595
+ commands.add(commandName);
596
+ }
597
+ }
598
+
599
+ if (platform === 'darwin') {
600
+ for (const commandName of MACOS_ALLOWED_COMMANDS) {
601
+ commands.add(commandName);
602
+ }
603
+ }
604
+
605
+ return commands;
606
+ }
607
+
608
+ export function getBashDangerousCommands(
609
+ platform: NodeJS.Platform = process.platform
610
+ ): Set<string> {
611
+ const commands = new Set(COMMON_DANGEROUS_COMMANDS);
612
+
613
+ if (platform === 'win32') {
614
+ for (const commandName of WINDOWS_DANGEROUS_COMMANDS) {
615
+ commands.add(commandName);
616
+ }
617
+ }
618
+
619
+ return commands;
620
+ }
621
+
622
+ export function getBashDangerousPatterns(
623
+ platform: NodeJS.Platform = process.platform
624
+ ): BashDangerousPattern[] {
625
+ if (platform === 'win32') {
626
+ return [...COMMON_DANGEROUS_PATTERNS, ...WINDOWS_DANGEROUS_PATTERNS];
627
+ }
628
+ return [...COMMON_DANGEROUS_PATTERNS];
629
+ }
630
+
631
+ export function evaluateBashPolicy(
632
+ command: string,
633
+ options: EvaluateBashPolicyOptions = {}
634
+ ): EvaluateBashPolicyResult {
635
+ return evaluateBashPolicyInternal(command, options);
636
+ }