headlesscode 1.0.2

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 (232) hide show
  1. package/ATTRIBUTION.md +53 -0
  2. package/CODE_OF_CONDUCT.md +130 -0
  3. package/CONTRIBUTING.md +107 -0
  4. package/LICENSE +202 -0
  5. package/README.md +486 -0
  6. package/SECURITY.md +211 -0
  7. package/bin/headlesscode.mjs +83 -0
  8. package/package.json +63 -0
  9. package/shared/prompts/review-mode-prompt-short.md +93 -0
  10. package/shared/prompts/review-mode-prompt.md +281 -0
  11. package/shared/rules-code/rules.md +22 -0
  12. package/shared/stacks/cpp/rules.md +30 -0
  13. package/shared/stacks/fastapi/rules.md +30 -0
  14. package/shared/stacks/javascript/rules.md +37 -0
  15. package/shared/stacks/postgresql/rules.md +31 -0
  16. package/shared/stacks/python/rules.md +35 -0
  17. package/shared/stacks/react/rules.md +11 -0
  18. package/shared/stacks/typescript/rules.md +10 -0
  19. package/src/budget/budget.ts +221 -0
  20. package/src/budget/concurrency.ts +126 -0
  21. package/src/budget/cost.ts +309 -0
  22. package/src/budget/index.ts +8 -0
  23. package/src/checkpoints/cli.ts +256 -0
  24. package/src/checkpoints/service.ts +227 -0
  25. package/src/cli.ts +1535 -0
  26. package/src/cloud/docker-provider.ts +334 -0
  27. package/src/cloud/provider.ts +300 -0
  28. package/src/codeintel/call-graph.ts +78 -0
  29. package/src/codeintel/find-references.ts +123 -0
  30. package/src/codeintel/go-to-definition.ts +193 -0
  31. package/src/codeintel/handlers.ts +190 -0
  32. package/src/codeintel/import-graph.ts +173 -0
  33. package/src/codeintel/outline.ts +180 -0
  34. package/src/codeintel/position.ts +77 -0
  35. package/src/codeintel/program.ts +350 -0
  36. package/src/codeintel/rename-symbol.ts +213 -0
  37. package/src/codeintel/tools.ts +280 -0
  38. package/src/codemap/build.ts +135 -0
  39. package/src/codemap/cli.ts +190 -0
  40. package/src/codemap/extract.ts +339 -0
  41. package/src/codemap/files.ts +236 -0
  42. package/src/codemap/fingerprint.ts +65 -0
  43. package/src/codemap/flows.ts +62 -0
  44. package/src/codemap/html.ts +451 -0
  45. package/src/codemap/lock.ts +80 -0
  46. package/src/codemap/types.ts +101 -0
  47. package/src/codesearch/airunner-embedder.ts +185 -0
  48. package/src/codesearch/chunk.ts +339 -0
  49. package/src/codesearch/cli.ts +223 -0
  50. package/src/codesearch/embedder.ts +332 -0
  51. package/src/codesearch/files.ts +280 -0
  52. package/src/codesearch/index.ts +469 -0
  53. package/src/codesearch/ollama-embedder.ts +205 -0
  54. package/src/codesearch/search.ts +141 -0
  55. package/src/codesearch/types.ts +100 -0
  56. package/src/config/mode-models.ts +218 -0
  57. package/src/dashboard/aggregate.ts +364 -0
  58. package/src/dashboard/chat-thread.ts +141 -0
  59. package/src/dashboard/checkpoints.ts +124 -0
  60. package/src/dashboard/cli.ts +193 -0
  61. package/src/dashboard/codemap.ts +44 -0
  62. package/src/dashboard/files.ts +121 -0
  63. package/src/dashboard/page.ts +2803 -0
  64. package/src/dashboard/self-improvement-metrics.ts +282 -0
  65. package/src/dashboard/server.ts +1103 -0
  66. package/src/dashboard/session-launch.ts +310 -0
  67. package/src/dashboard/timeline.ts +273 -0
  68. package/src/dashboard/tool-exec.ts +107 -0
  69. package/src/dashboard/trend-cli.ts +141 -0
  70. package/src/dashboard/trend.ts +413 -0
  71. package/src/decision-proxy/cli.ts +261 -0
  72. package/src/decision-proxy/proxy.ts +569 -0
  73. package/src/deploy/gate-cli.ts +147 -0
  74. package/src/deploy/gate.ts +254 -0
  75. package/src/engine/condense.ts +512 -0
  76. package/src/engine/events.ts +428 -0
  77. package/src/engine/handoff.ts +71 -0
  78. package/src/engine/lazy-tools.ts +160 -0
  79. package/src/engine/local-explore.ts +653 -0
  80. package/src/engine/logger.ts +96 -0
  81. package/src/engine/loop.ts +5517 -0
  82. package/src/engine/parser.ts +347 -0
  83. package/src/engine/prompt.ts +860 -0
  84. package/src/engine/reports.ts +47 -0
  85. package/src/engine/stacks.ts +448 -0
  86. package/src/engine/types.ts +291 -0
  87. package/src/engine/usage.ts +186 -0
  88. package/src/github/app-auth.ts +161 -0
  89. package/src/github/cli.ts +448 -0
  90. package/src/github/installations.ts +133 -0
  91. package/src/github/pr.ts +321 -0
  92. package/src/github/provision.ts +118 -0
  93. package/src/github/push.ts +122 -0
  94. package/src/index-util.ts +50 -0
  95. package/src/index.ts +81 -0
  96. package/src/init/cli.ts +248 -0
  97. package/src/init/gitignore.ts +74 -0
  98. package/src/llm/ollama.ts +308 -0
  99. package/src/llm/openrouter.ts +868 -0
  100. package/src/llm/preflight.ts +367 -0
  101. package/src/llm/transcript-capture.ts +84 -0
  102. package/src/memory/embed.ts +110 -0
  103. package/src/memory/index.ts +22 -0
  104. package/src/memory/local.ts +259 -0
  105. package/src/memory/summarizer.ts +283 -0
  106. package/src/memory/types.ts +153 -0
  107. package/src/memory/uwuchat.ts +157 -0
  108. package/src/migrate/cli.ts +115 -0
  109. package/src/orchestrator/analyze-cli.ts +104 -0
  110. package/src/orchestrator/auto-split.ts +206 -0
  111. package/src/orchestrator/cleanup.ts +1003 -0
  112. package/src/orchestrator/cli.ts +3571 -0
  113. package/src/orchestrator/cost-estimate.ts +564 -0
  114. package/src/orchestrator/cost-history-cli.ts +242 -0
  115. package/src/orchestrator/cost-history.ts +397 -0
  116. package/src/orchestrator/git-sync.ts +250 -0
  117. package/src/orchestrator/index.ts +153 -0
  118. package/src/orchestrator/log-analysis.ts +0 -0
  119. package/src/orchestrator/merge-check.ts +108 -0
  120. package/src/orchestrator/pipeline.ts +411 -0
  121. package/src/orchestrator/resume.ts +1940 -0
  122. package/src/orchestrator/reviewer.ts +503 -0
  123. package/src/orchestrator/split.ts +296 -0
  124. package/src/orchestrator/state.ts +542 -0
  125. package/src/orchestrator/status.ts +697 -0
  126. package/src/orchestrator/verification-gate.ts +134 -0
  127. package/src/orchestrator/watch.ts +898 -0
  128. package/src/permissions/commands.ts +1083 -0
  129. package/src/permissions/config.ts +241 -0
  130. package/src/permissions/index.ts +12 -0
  131. package/src/permissions/protected-files.ts +96 -0
  132. package/src/permissions/store-protection.ts +272 -0
  133. package/src/project-store.ts +648 -0
  134. package/src/projects/cli.ts +382 -0
  135. package/src/qa/qa.ts +487 -0
  136. package/src/tools/browser/handler.ts +346 -0
  137. package/src/tools/browser/service.ts +406 -0
  138. package/src/tools/browser/smoke.ts +78 -0
  139. package/src/tools/browser/tool.ts +99 -0
  140. package/src/tools/executor.ts +2575 -0
  141. package/src/tools/language-detect.ts +183 -0
  142. package/src/tools/output-summarizer.ts +369 -0
  143. package/src/tools/run-tests.ts +302 -0
  144. package/src/tools/set-indentation-tool.ts +49 -0
  145. package/src/tools/test-selection.ts +160 -0
  146. package/src/vendor/tests/smoke.ts +103 -0
  147. package/src/vendor/zoo-code/VENDOR-NOTES.md +213 -0
  148. package/src/vendor/zoo-code/shim/anthropic.ts +71 -0
  149. package/src/vendor/zoo-code/shim/openai.d.ts +60 -0
  150. package/src/vendor/zoo-code/shim/os-name.ts +18 -0
  151. package/src/vendor/zoo-code/shim/strip-bom.ts +14 -0
  152. package/src/vendor/zoo-code/shim/vscode.ts +76 -0
  153. package/src/vendor/zoo-code/src/core/config/CustomModesManager.ts +1015 -0
  154. package/src/vendor/zoo-code/src/core/diff/strategies/multi-search-replace.ts +670 -0
  155. package/src/vendor/zoo-code/src/core/prompts/sections/capabilities.ts +46 -0
  156. package/src/vendor/zoo-code/src/core/prompts/sections/custom-instructions.ts +559 -0
  157. package/src/vendor/zoo-code/src/core/prompts/sections/index.ts +10 -0
  158. package/src/vendor/zoo-code/src/core/prompts/sections/markdown-formatting.ts +7 -0
  159. package/src/vendor/zoo-code/src/core/prompts/sections/modes.ts +35 -0
  160. package/src/vendor/zoo-code/src/core/prompts/sections/objective.ts +13 -0
  161. package/src/vendor/zoo-code/src/core/prompts/sections/rules.ts +95 -0
  162. package/src/vendor/zoo-code/src/core/prompts/sections/skills.ts +105 -0
  163. package/src/vendor/zoo-code/src/core/prompts/sections/system-info.ts +30 -0
  164. package/src/vendor/zoo-code/src/core/prompts/sections/tool-use-guidelines.ts +9 -0
  165. package/src/vendor/zoo-code/src/core/prompts/sections/tool-use.ts +7 -0
  166. package/src/vendor/zoo-code/src/core/prompts/system.ts +176 -0
  167. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/access_mcp_resource.ts +41 -0
  168. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/apply_diff.ts +40 -0
  169. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/apply_patch.ts +61 -0
  170. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/ask_followup_question.ts +62 -0
  171. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/attempt_completion.ts +33 -0
  172. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/codebase_search.ts +43 -0
  173. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/converters.ts +109 -0
  174. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/edit.ts +48 -0
  175. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/edit_file.ts +72 -0
  176. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/execute_command.ts +54 -0
  177. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/generate_image.ts +51 -0
  178. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/index.ts +75 -0
  179. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/list_files.ts +41 -0
  180. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/mcp_server.ts +75 -0
  181. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/new_task.ts +39 -0
  182. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/read_command_output.ts +81 -0
  183. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/read_file.ts +169 -0
  184. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/run_slash_command.ts +31 -0
  185. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/search_files.ts +50 -0
  186. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/search_replace.ts +51 -0
  187. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/skill.ts +33 -0
  188. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/switch_mode.ts +31 -0
  189. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/update_todo_list.ts +54 -0
  190. package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/write_to_file.ts +40 -0
  191. package/src/vendor/zoo-code/src/core/prompts/types.ts +12 -0
  192. package/src/vendor/zoo-code/src/i18n/index.ts +19 -0
  193. package/src/vendor/zoo-code/src/integrations/misc/extract-text.ts +81 -0
  194. package/src/vendor/zoo-code/src/services/checkpoints/RepoPerTaskCheckpointService.ts +15 -0
  195. package/src/vendor/zoo-code/src/services/checkpoints/ShadowCheckpointService.ts +553 -0
  196. package/src/vendor/zoo-code/src/services/checkpoints/excludes.ts +212 -0
  197. package/src/vendor/zoo-code/src/services/checkpoints/index.ts +3 -0
  198. package/src/vendor/zoo-code/src/services/checkpoints/types.ts +35 -0
  199. package/src/vendor/zoo-code/src/services/code-index/manager.ts +19 -0
  200. package/src/vendor/zoo-code/src/services/mcp/McpHub.ts +36 -0
  201. package/src/vendor/zoo-code/src/services/roo-config/index.ts +441 -0
  202. package/src/vendor/zoo-code/src/services/search/file-search.ts +143 -0
  203. package/src/vendor/zoo-code/src/services/skills/SkillsManager.ts +20 -0
  204. package/src/vendor/zoo-code/src/shared/globalFileNames.ts +9 -0
  205. package/src/vendor/zoo-code/src/shared/language.ts +43 -0
  206. package/src/vendor/zoo-code/src/shared/modes.ts +257 -0
  207. package/src/vendor/zoo-code/src/shared/tools.ts +385 -0
  208. package/src/vendor/zoo-code/src/utils/fs.ts +39 -0
  209. package/src/vendor/zoo-code/src/utils/globalContext.ts +22 -0
  210. package/src/vendor/zoo-code/src/utils/json-schema.ts +16 -0
  211. package/src/vendor/zoo-code/src/utils/logging.ts +21 -0
  212. package/src/vendor/zoo-code/src/utils/mcp-name.ts +190 -0
  213. package/src/vendor/zoo-code/src/utils/object.ts +18 -0
  214. package/src/vendor/zoo-code/src/utils/path.ts +94 -0
  215. package/src/vendor/zoo-code/src/utils/shell.ts +376 -0
  216. package/src/vendor/zoo-code/src/utils/text-normalization.ts +99 -0
  217. package/src/vendor/zoo-code/types/global-settings.ts +19 -0
  218. package/src/vendor/zoo-code/types/index.ts +22 -0
  219. package/src/vendor/zoo-code/types/message.ts +375 -0
  220. package/src/vendor/zoo-code/types/mode.ts +241 -0
  221. package/src/vendor/zoo-code/types/todo.ts +19 -0
  222. package/src/vendor/zoo-code/types/tool-params.ts +116 -0
  223. package/src/vendor/zoo-code/types/tool.ts +67 -0
  224. package/src/vendor/zoo-code/types/vscode.ts +84 -0
  225. package/src/vision/describe.ts +242 -0
  226. package/src/vision/tool.ts +91 -0
  227. package/src/watcher/cli.ts +369 -0
  228. package/src/watcher/github.ts +304 -0
  229. package/src/watcher/index.ts +59 -0
  230. package/src/watcher/state.ts +254 -0
  231. package/src/watcher/watch.ts +562 -0
  232. package/tsconfig.json +18 -0
@@ -0,0 +1,376 @@
1
+ import * as vscode from "../../shim/vscode"
2
+ import { existsSync } from "fs"
3
+ import { userInfo } from "os"
4
+ import * as path from "path"
5
+
6
+ // Security: Allowlist of approved shell executables to prevent arbitrary command execution
7
+ const SHELL_ALLOWLIST = new Set<string>([
8
+ // Windows PowerShell variants
9
+ "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
10
+ "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
11
+ "C:\\Program Files\\PowerShell\\6\\pwsh.exe",
12
+ "C:\\Program Files\\PowerShell\\5\\pwsh.exe",
13
+
14
+ // Windows Command Prompt
15
+ "C:\\Windows\\System32\\cmd.exe",
16
+
17
+ // Windows WSL
18
+ "C:\\Windows\\System32\\wsl.exe",
19
+
20
+ // Git Bash on Windows
21
+ "C:\\Program Files\\Git\\bin\\bash.exe",
22
+ "C:\\Program Files\\Git\\usr\\bin\\bash.exe",
23
+ "C:\\Program Files (x86)\\Git\\bin\\bash.exe",
24
+ "C:\\Program Files (x86)\\Git\\usr\\bin\\bash.exe",
25
+
26
+ // MSYS2/MinGW/Cygwin on Windows
27
+ "C:\\msys64\\usr\\bin\\bash.exe",
28
+ "C:\\msys32\\usr\\bin\\bash.exe",
29
+ "C:\\MinGW\\msys\\1.0\\bin\\bash.exe",
30
+ "C:\\cygwin64\\bin\\bash.exe",
31
+ "C:\\cygwin\\bin\\bash.exe",
32
+
33
+ // Unix/Linux/macOS - Bourne-compatible shells
34
+ "/bin/sh",
35
+ "/usr/bin/sh",
36
+ "/bin/bash",
37
+ "/usr/bin/bash",
38
+ "/usr/local/bin/bash",
39
+ "/opt/homebrew/bin/bash",
40
+ "/opt/local/bin/bash",
41
+
42
+ // Z Shell
43
+ "/bin/zsh",
44
+ "/usr/bin/zsh",
45
+ "/usr/local/bin/zsh",
46
+ "/opt/homebrew/bin/zsh",
47
+ "/opt/local/bin/zsh",
48
+
49
+ // Dash
50
+ "/bin/dash",
51
+ "/usr/bin/dash",
52
+
53
+ // Ash
54
+ "/bin/ash",
55
+ "/usr/bin/ash",
56
+
57
+ // C Shells
58
+ "/bin/csh",
59
+ "/usr/bin/csh",
60
+ "/bin/tcsh",
61
+ "/usr/bin/tcsh",
62
+ "/usr/local/bin/tcsh",
63
+
64
+ // Korn Shells
65
+ "/bin/ksh",
66
+ "/usr/bin/ksh",
67
+ "/bin/ksh93",
68
+ "/usr/bin/ksh93",
69
+ "/bin/mksh",
70
+ "/usr/bin/mksh",
71
+ "/bin/pdksh",
72
+ "/usr/bin/pdksh",
73
+
74
+ // Fish Shell
75
+ "/usr/bin/fish",
76
+ "/usr/local/bin/fish",
77
+ "/opt/homebrew/bin/fish",
78
+ "/opt/local/bin/fish",
79
+
80
+ // Modern shells
81
+ "/usr/bin/elvish",
82
+ "/usr/local/bin/elvish",
83
+ "/usr/bin/xonsh",
84
+ "/usr/local/bin/xonsh",
85
+ "/usr/bin/nu",
86
+ "/usr/local/bin/nu",
87
+ "/usr/bin/nushell",
88
+ "/usr/local/bin/nushell",
89
+ "/usr/bin/ion",
90
+ "/usr/local/bin/ion",
91
+
92
+ // BusyBox
93
+ "/bin/busybox",
94
+ "/usr/bin/busybox",
95
+ ])
96
+
97
+ const SHELL_PATHS = {
98
+ // Windows paths
99
+ POWERSHELL_7: "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
100
+ POWERSHELL_LEGACY: "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
101
+ CMD: "C:\\Windows\\System32\\cmd.exe",
102
+ WSL_BASH: "/bin/bash",
103
+ // Unix paths
104
+ MAC_DEFAULT: "/bin/zsh",
105
+ LINUX_DEFAULT: "/bin/bash",
106
+ CSH: "/bin/csh",
107
+ BASH: "/bin/bash",
108
+ KSH: "/bin/ksh",
109
+ SH: "/bin/sh",
110
+ ZSH: "/bin/zsh",
111
+ DASH: "/bin/dash",
112
+ TCSH: "/bin/tcsh",
113
+ FALLBACK: "/bin/sh",
114
+ } as const
115
+
116
+ interface MacTerminalProfile {
117
+ path?: string | string[]
118
+ }
119
+
120
+ type MacTerminalProfiles = Record<string, MacTerminalProfile>
121
+
122
+ interface WindowsTerminalProfile {
123
+ path?: string | string[]
124
+ source?: "PowerShell" | "WSL"
125
+ }
126
+
127
+ type WindowsTerminalProfiles = Record<string, WindowsTerminalProfile>
128
+
129
+ interface LinuxTerminalProfile {
130
+ path?: string | string[]
131
+ }
132
+
133
+ type LinuxTerminalProfiles = Record<string, LinuxTerminalProfile>
134
+
135
+ // -----------------------------------------------------
136
+ // 1) VS Code Terminal Configuration Helpers
137
+ // -----------------------------------------------------
138
+
139
+ type PlatformProfilesMap = {
140
+ windows: WindowsTerminalProfiles
141
+ osx: MacTerminalProfiles
142
+ linux: LinuxTerminalProfiles
143
+ }
144
+
145
+ /**
146
+ * Reads the VS Code terminal profile configuration for the given platform.
147
+ *
148
+ * The key must be one of `"windows"`, `"osx"`, or `"linux"` — the exact strings
149
+ * VS Code uses in `terminal.integrated.defaultProfile.<key>` and
150
+ * `terminal.integrated.profiles.<key>`. Passing any other value is a compile-time
151
+ * error, which prevents silent mismatches such as `"darwin"` returning empty config.
152
+ *
153
+ * The return type (`defaultProfileName` and `profiles`) is inferred from `K` via
154
+ * `PlatformProfilesMap`, so callers don't need an explicit type parameter.
155
+ *
156
+ * Returns `{ defaultProfileName: null, profiles: {} }` on any VS Code API error.
157
+ */
158
+ function getTerminalConfig<K extends keyof PlatformProfilesMap>(
159
+ platformKey: K,
160
+ ): { defaultProfileName: string | null; profiles: PlatformProfilesMap[K] } {
161
+ try {
162
+ const config = vscode.workspace.getConfiguration("terminal.integrated")
163
+ const rawProfileName = config.get<string>(`defaultProfile.${platformKey}`)
164
+ const defaultProfileName = typeof rawProfileName === "string" ? rawProfileName : null
165
+ const profiles = config.get<PlatformProfilesMap[K]>(`profiles.${platformKey}`) ?? ({} as PlatformProfilesMap[K])
166
+ return { defaultProfileName, profiles }
167
+ } catch {
168
+ return { defaultProfileName: null, profiles: {} as PlatformProfilesMap[K] }
169
+ }
170
+ }
171
+
172
+ // -----------------------------------------------------
173
+ // 2) Platform-Specific VS Code Shell Retrieval
174
+ // -----------------------------------------------------
175
+
176
+ /**
177
+ * Normalizes a path that can be either a string or an array of strings.
178
+ * If it's an array, returns the first element. Otherwise returns the string.
179
+ */
180
+ function normalizeShellPath(path: string | string[] | undefined): string | null {
181
+ if (!path) return null
182
+ if (Array.isArray(path)) {
183
+ return path.length > 0 ? path[0] : null
184
+ }
185
+ return path
186
+ }
187
+
188
+ /** Attempts to retrieve a shell path from VS Code config on Windows. */
189
+ function getWindowsShellFromVSCode(): string | null {
190
+ const { defaultProfileName, profiles } = getTerminalConfig("windows")
191
+ if (!defaultProfileName) {
192
+ // No explicit Windows terminal profile is configured. VS Code auto-detects
193
+ // the default on modern Windows and prefers PowerShell 7 (pwsh.exe) when it
194
+ // is installed, otherwise the always-present Windows PowerShell 5.1. Mirror
195
+ // that here so the system prompt advertises the real shell instead of falling
196
+ // through to COMSPEC (cmd.exe). See issue #82.
197
+ return existsSync(SHELL_PATHS.POWERSHELL_7) ? SHELL_PATHS.POWERSHELL_7 : SHELL_PATHS.POWERSHELL_LEGACY
198
+ }
199
+
200
+ const profile = profiles[defaultProfileName]
201
+
202
+ // If the profile name indicates PowerShell, do version-based detection.
203
+ // In testing it was found these typically do not have a path, and this
204
+ // implementation manages to deductively get the correct version of PowerShell
205
+ if (defaultProfileName.toLowerCase().includes("powershell")) {
206
+ const normalizedPath = normalizeShellPath(profile?.path)
207
+ if (normalizedPath) {
208
+ // If there's an explicit PowerShell path, return that
209
+ return normalizedPath
210
+ } else if (profile?.source === "PowerShell") {
211
+ // If the profile is sourced from PowerShell, assume the newest
212
+ return SHELL_PATHS.POWERSHELL_7
213
+ }
214
+ // Otherwise, assume legacy Windows PowerShell
215
+ return SHELL_PATHS.POWERSHELL_LEGACY
216
+ }
217
+
218
+ // If there's a specific path, return that immediately
219
+ const normalizedPath = normalizeShellPath(profile?.path)
220
+ if (normalizedPath) {
221
+ return normalizedPath
222
+ }
223
+
224
+ // If the profile indicates WSL
225
+ if (profile?.source === "WSL" || defaultProfileName.toLowerCase().includes("wsl")) {
226
+ return SHELL_PATHS.WSL_BASH
227
+ }
228
+
229
+ // If nothing special detected, we assume cmd
230
+ return SHELL_PATHS.CMD
231
+ }
232
+
233
+ /** Attempts to retrieve a shell path from VS Code config on macOS. */
234
+ function getMacShellFromVSCode(): string | null {
235
+ const { defaultProfileName, profiles } = getTerminalConfig("osx")
236
+ if (!defaultProfileName) {
237
+ return null
238
+ }
239
+
240
+ const profile = profiles[defaultProfileName]
241
+ return normalizeShellPath(profile?.path)
242
+ }
243
+
244
+ /** Attempts to retrieve a shell path from VS Code config on Linux. */
245
+ function getLinuxShellFromVSCode(): string | null {
246
+ const { defaultProfileName, profiles } = getTerminalConfig("linux")
247
+ if (!defaultProfileName) {
248
+ return null
249
+ }
250
+
251
+ const profile = profiles[defaultProfileName]
252
+ return normalizeShellPath(profile?.path)
253
+ }
254
+
255
+ // -----------------------------------------------------
256
+ // 3) General Fallback Helpers
257
+ // -----------------------------------------------------
258
+
259
+ /**
260
+ * Tries to get a user’s shell from os.userInfo() (works on Unix if the
261
+ * underlying system call is supported). Returns null on error or if not found.
262
+ */
263
+ function getShellFromUserInfo(): string | null {
264
+ try {
265
+ const { shell } = userInfo()
266
+ return shell || null
267
+ } catch {
268
+ return null
269
+ }
270
+ }
271
+
272
+ /** Returns the environment-based shell variable, or null if not set. */
273
+ function getShellFromEnv(): string | null {
274
+ const { env } = process
275
+
276
+ if (process.platform === "win32") {
277
+ // On Windows, COMSPEC typically holds cmd.exe
278
+ return env.COMSPEC || "C:\\Windows\\System32\\cmd.exe"
279
+ }
280
+
281
+ if (process.platform === "darwin") {
282
+ // On macOS/Linux, SHELL is commonly the environment variable
283
+ return env.SHELL || "/bin/zsh"
284
+ }
285
+
286
+ if (process.platform === "linux") {
287
+ // On Linux, SHELL is commonly the environment variable
288
+ return env.SHELL || "/bin/bash"
289
+ }
290
+ return null
291
+ }
292
+
293
+ // -----------------------------------------------------
294
+ // 4) Shell Validation Functions
295
+ // -----------------------------------------------------
296
+
297
+ /**
298
+ * Validates if a shell path is in the allowlist to prevent arbitrary command execution
299
+ */
300
+ function isShellAllowed(shellPath: string): boolean {
301
+ if (!shellPath) return false
302
+
303
+ const normalizedPath = path.normalize(shellPath)
304
+
305
+ // Direct lookup first
306
+ if (SHELL_ALLOWLIST.has(normalizedPath)) {
307
+ return true
308
+ }
309
+
310
+ // On Windows, try case-insensitive comparison
311
+ if (process.platform === "win32") {
312
+ const lowerPath = normalizedPath.toLowerCase()
313
+ for (const allowedPath of SHELL_ALLOWLIST) {
314
+ if (allowedPath.toLowerCase() === lowerPath) {
315
+ return true
316
+ }
317
+ }
318
+ }
319
+
320
+ return false
321
+ }
322
+
323
+ /**
324
+ * Returns a safe fallback shell based on the platform
325
+ */
326
+ function getSafeFallbackShell(): string {
327
+ if (process.platform === "win32") {
328
+ return SHELL_PATHS.CMD
329
+ } else if (process.platform === "darwin") {
330
+ return SHELL_PATHS.MAC_DEFAULT
331
+ } else {
332
+ return SHELL_PATHS.LINUX_DEFAULT
333
+ }
334
+ }
335
+
336
+ // -----------------------------------------------------
337
+ // 5) Publicly Exposed Shell Getter
338
+ // -----------------------------------------------------
339
+
340
+ export function getShell(): string {
341
+ let shell: string | null = null
342
+
343
+ // 1. Check VS Code config first.
344
+ if (process.platform === "win32") {
345
+ // Special logic for Windows
346
+ shell = getWindowsShellFromVSCode()
347
+ } else if (process.platform === "darwin") {
348
+ // macOS from VS Code
349
+ shell = getMacShellFromVSCode()
350
+ } else if (process.platform === "linux") {
351
+ // Linux from VS Code
352
+ shell = getLinuxShellFromVSCode()
353
+ }
354
+
355
+ // 2. If no shell from VS Code, try userInfo()
356
+ if (!shell) {
357
+ shell = getShellFromUserInfo()
358
+ }
359
+
360
+ // 3. If still nothing, try environment variable
361
+ if (!shell) {
362
+ shell = getShellFromEnv()
363
+ }
364
+
365
+ // 4. Finally, fall back to a default
366
+ if (!shell) {
367
+ shell = getSafeFallbackShell()
368
+ }
369
+
370
+ // 5. Validate the shell against allowlist
371
+ if (!isShellAllowed(shell)) {
372
+ shell = getSafeFallbackShell()
373
+ }
374
+
375
+ return shell
376
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Common character mappings for normalization
3
+ */
4
+ export const NORMALIZATION_MAPS = {
5
+ // Smart quotes to regular quotes
6
+ SMART_QUOTES: {
7
+ "\u201C": '"', // Left double quote (U+201C)
8
+ "\u201D": '"', // Right double quote (U+201D)
9
+ "\u2018": "'", // Left single quote (U+2018)
10
+ "\u2019": "'", // Right single quote (U+2019)
11
+ },
12
+ // Other typographic characters
13
+ TYPOGRAPHIC: {
14
+ "\u2026": "...", // Ellipsis
15
+ "\u2014": "-", // Em dash
16
+ "\u2013": "-", // En dash
17
+ "\u00A0": " ", // Non-breaking space
18
+ },
19
+ }
20
+
21
+ /**
22
+ * Options for string normalization
23
+ */
24
+ export interface NormalizeOptions {
25
+ smartQuotes?: boolean // Replace smart quotes with straight quotes
26
+ typographicChars?: boolean // Replace typographic characters
27
+ extraWhitespace?: boolean // Collapse multiple whitespace to single space
28
+ trim?: boolean // Trim whitespace from start and end
29
+ }
30
+
31
+ /**
32
+ * Default options for normalization
33
+ */
34
+ const DEFAULT_OPTIONS: NormalizeOptions = {
35
+ smartQuotes: true,
36
+ typographicChars: true,
37
+ extraWhitespace: true,
38
+ trim: true,
39
+ }
40
+
41
+ /**
42
+ * Normalizes a string based on the specified options
43
+ *
44
+ * @param str The string to normalize
45
+ * @param options Normalization options
46
+ * @returns The normalized string
47
+ */
48
+ export function normalizeString(str: string, options: NormalizeOptions = DEFAULT_OPTIONS): string {
49
+ const opts = { ...DEFAULT_OPTIONS, ...options }
50
+ let normalized = str
51
+
52
+ // Replace smart quotes
53
+ if (opts.smartQuotes) {
54
+ for (const [smart, regular] of Object.entries(NORMALIZATION_MAPS.SMART_QUOTES)) {
55
+ normalized = normalized.replace(new RegExp(smart, "g"), regular)
56
+ }
57
+ }
58
+
59
+ // Replace typographic characters
60
+ if (opts.typographicChars) {
61
+ for (const [typographic, regular] of Object.entries(NORMALIZATION_MAPS.TYPOGRAPHIC)) {
62
+ normalized = normalized.replace(new RegExp(typographic, "g"), regular)
63
+ }
64
+ }
65
+
66
+ // Normalize whitespace
67
+ if (opts.extraWhitespace) {
68
+ normalized = normalized.replace(/\s+/g, " ")
69
+ }
70
+
71
+ // Trim whitespace
72
+ if (opts.trim) {
73
+ normalized = normalized.trim()
74
+ }
75
+
76
+ return normalized
77
+ }
78
+
79
+ /**
80
+ * Unescapes common HTML entities in a string
81
+ *
82
+ * @param text The string containing HTML entities to unescape
83
+ * @returns The unescaped string with HTML entities converted to their literal characters
84
+ */
85
+ export function unescapeHtmlEntities(text: string): string {
86
+ if (!text) return text
87
+
88
+ return text
89
+ .replace(/&lt;/g, "<")
90
+ .replace(/&gt;/g, ">")
91
+ .replace(/&quot;/g, '"')
92
+ .replace(/&#39;/g, "'")
93
+ .replace(/&apos;/g, "'")
94
+ .replace(/&#91;/g, "[")
95
+ .replace(/&#93;/g, "]")
96
+ .replace(/&lsqb;/g, "[")
97
+ .replace(/&rsqb;/g, "]")
98
+ .replace(/&amp;/g, "&")
99
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Vendored subset of `zoo-code/packages/types/src/global-settings.ts`.
3
+ *
4
+ * Only `DEFAULT_DIFF_FUZZY_THRESHOLD` is carried here (verbatim value) — it is
5
+ * the one global-setting constant the vendored diff strategy imports. The full
6
+ * upstream file also defines dozens of settings-related constants + zod schemas
7
+ * that pull in `codebase-index`, `experiment`, `history`, `provider-settings`,
8
+ * `telemetry` and `type-fu` modules, none of which the headless harness needs.
9
+ */
10
+
11
+ /**
12
+ * Default fuzzy matching threshold for the multi-search-replace diff strategy.
13
+ * A value of 1.0 (exact match) is used by default for safety, especially when
14
+ * auto-approval for writes is enabled. This prevents unintended changes from
15
+ * being applied due to minor mismatches. Users can lower this threshold manually
16
+ * in settings to reduce "Edit Unsuccessful" errors caused by minor whitespace
17
+ * or formatting differences, accepting a higher risk of unintended edits.
18
+ */
19
+ export const DEFAULT_DIFF_FUZZY_THRESHOLD = 1.0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Vendored `@roo-code/types` barrel.
3
+ *
4
+ * The harness does not depend on the published `@roo-code/types` package. The
5
+ * type modules below are copied verbatim from `packages/types/src/`, and this
6
+ * barrel re-exports exactly the surface the vendored core imports. Vendored
7
+ * files' `@roo-code/types` imports are rewritten to import this barrel by
8
+ * relative path (issue #99 rework).
9
+ *
10
+ * Files: tool.ts, mode.ts, todo.ts, vscode.ts are verbatim copies.
11
+ * message.ts and tool-params.ts are also verbatim copies; only the two types
12
+ * each of them contributes to the vendored core are re-exported here.
13
+ */
14
+
15
+ export * from "./tool.js"
16
+ export * from "./mode.js"
17
+ export * from "./todo.js"
18
+ export * from "./vscode.js"
19
+ export * from "./global-settings.js"
20
+
21
+ export type { ClineAsk, ToolProgressStatus } from "./message.js"
22
+ export type { GenerateImageParams, ReadFileToolParams } from "./tool-params.js"