oh-my-opencode 4.2.3 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/README.ja.md +1 -0
  2. package/README.ko.md +1 -0
  3. package/README.md +3 -2
  4. package/README.zh-cn.md +1 -0
  5. package/dist/agents/atlas/default-prompt-sections.d.ts +1 -1
  6. package/dist/agents/builtin-agents/available-skills.d.ts +1 -1
  7. package/dist/agents/builtin-agents/model-resolution.d.ts +1 -1
  8. package/dist/agents/prometheus/plan-generation.d.ts +1 -1
  9. package/dist/agents/prometheus/plan-template.d.ts +1 -1
  10. package/dist/agents/prometheus/spec-driven-mode.d.ts +7 -0
  11. package/dist/cli/doctor/checks/system-binary.d.ts +1 -1
  12. package/dist/cli/doctor/checks/tui-plugin-config.d.ts +14 -0
  13. package/dist/cli/doctor/constants.d.ts +1 -0
  14. package/dist/cli/index.js +3203 -2368
  15. package/dist/cli/provider-model-id-transform.d.ts +1 -1
  16. package/dist/config/index.d.ts +1 -1
  17. package/dist/config/schema/agent-overrides.d.ts +147 -1
  18. package/dist/config/schema/background-task.d.ts +1 -0
  19. package/dist/config/schema/default-mode.d.ts +6 -0
  20. package/dist/config/schema/hooks.d.ts +2 -0
  21. package/dist/config/schema/i18n.d.ts +5 -0
  22. package/dist/config/schema/keyword-detector.d.ts +8 -0
  23. package/dist/config/schema/oh-my-opencode-config.d.ts +163 -1
  24. package/dist/config/schema.d.ts +2 -0
  25. package/dist/create-hooks.d.ts +2 -0
  26. package/dist/features/background-agent/fallback-retry-handler.d.ts +3 -0
  27. package/dist/features/background-agent/manager.d.ts +0 -1
  28. package/dist/features/background-agent/parent-wake-notifier.d.ts +5 -0
  29. package/dist/features/background-agent/session-activity.d.ts +12 -0
  30. package/dist/features/background-agent/session-existence.d.ts +2 -0
  31. package/dist/features/background-agent/session-stream-activity.d.ts +18 -0
  32. package/dist/features/background-agent/task-activity-refresh.d.ts +11 -0
  33. package/dist/features/background-agent/task-poller.d.ts +2 -0
  34. package/dist/features/boulder-state/constants.d.ts +1 -10
  35. package/dist/features/boulder-state/format-duration.d.ts +1 -1
  36. package/dist/features/boulder-state/storage.d.ts +1 -83
  37. package/dist/features/boulder-state/top-level-task.d.ts +1 -2
  38. package/dist/features/boulder-state/types.d.ts +1 -100
  39. package/dist/features/task-toast-manager/manager.d.ts +1 -1
  40. package/dist/features/team-mode/team-state-store/locks.d.ts +7 -4
  41. package/dist/features/tmux-subagent/manager.d.ts +2 -0
  42. package/dist/hooks/atlas/system-reminder-templates.d.ts +1 -1
  43. package/dist/hooks/claude-code-hooks/config-loader.d.ts +7 -0
  44. package/dist/hooks/claude-code-hooks/config.d.ts +4 -1
  45. package/dist/hooks/claude-code-hooks/types.d.ts +17 -1
  46. package/dist/hooks/comment-checker/cli.d.ts +2 -22
  47. package/dist/hooks/comment-checker/types.d.ts +1 -31
  48. package/dist/hooks/directory-agents-injector/finder.d.ts +2 -7
  49. package/dist/hooks/directory-agents-injector/injector.d.ts +1 -18
  50. package/dist/hooks/index.d.ts +2 -0
  51. package/dist/hooks/keyword-detector/analyze/default.d.ts +1 -1
  52. package/dist/hooks/keyword-detector/constants.d.ts +10 -5
  53. package/dist/hooks/keyword-detector/detector.d.ts +2 -2
  54. package/dist/hooks/keyword-detector/hook.d.ts +2 -1
  55. package/dist/hooks/keyword-detector/hyperplan/default.d.ts +5 -0
  56. package/dist/hooks/notepad-write-guard/index.d.ts +2 -0
  57. package/dist/hooks/plan-format-validator/hook.d.ts +21 -0
  58. package/dist/hooks/plan-format-validator/index.d.ts +1 -0
  59. package/dist/hooks/prometheus-md-only/constants.d.ts +8 -0
  60. package/dist/hooks/rules-injector/constants.d.ts +1 -7
  61. package/dist/hooks/rules-injector/matcher.d.ts +2 -2
  62. package/dist/hooks/rules-injector/parser.d.ts +2 -2
  63. package/dist/hooks/rules-injector/project-root-finder.d.ts +1 -1
  64. package/dist/hooks/rules-injector/rule-distance.d.ts +1 -1
  65. package/dist/hooks/rules-injector/rule-file-finder.d.ts +2 -2
  66. package/dist/hooks/rules-injector/rule-file-scanner.d.ts +1 -1
  67. package/dist/hooks/rules-injector/rule-scan-cache.d.ts +2 -2
  68. package/dist/hooks/rules-injector/types.d.ts +1 -1
  69. package/dist/hooks/session-todo-status.d.ts +1 -0
  70. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  71. package/dist/hooks/start-work/context-info-builder.d.ts +1 -0
  72. package/dist/hooks/start-work/session-plan-affinity.d.ts +7 -0
  73. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  74. package/dist/index.js +18290 -16069
  75. package/dist/locales/en.d.ts +18 -0
  76. package/dist/locales/index.d.ts +6 -0
  77. package/dist/locales/zh.d.ts +17 -0
  78. package/dist/mcp/ast-grep.d.ts +2 -0
  79. package/dist/mcp/cli-suffix.d.ts +1 -0
  80. package/dist/mcp/index.d.ts +2 -0
  81. package/dist/mcp/lsp.d.ts +2 -0
  82. package/dist/mcp/runtime-executable.d.ts +11 -0
  83. package/dist/oh-my-opencode.schema.json +449 -1
  84. package/dist/plugin/hooks/create-core-hooks.d.ts +2 -0
  85. package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +3 -1
  86. package/dist/plugin/system-transform.d.ts +2 -1
  87. package/dist/plugin/tool-definition.d.ts +9 -0
  88. package/dist/plugin-handlers/agent-key-remapper.d.ts +5 -1
  89. package/dist/plugin-handlers/hook-config-handler.d.ts +7 -0
  90. package/dist/plugin-handlers/index.d.ts +1 -0
  91. package/dist/plugin-handlers/plugin-components-loader.d.ts +2 -3
  92. package/dist/shared/agent-display-names.d.ts +10 -2
  93. package/dist/shared/bun-spawn-shim.d.ts +3 -0
  94. package/dist/shared/command-executor/execute-hook-command.d.ts +2 -0
  95. package/dist/shared/contains-path.d.ts +1 -2
  96. package/dist/shared/context-limit-resolver.d.ts +2 -5
  97. package/dist/shared/deep-merge.d.ts +1 -13
  98. package/dist/shared/disabled-providers.d.ts +14 -0
  99. package/dist/shared/extract-semver.d.ts +1 -1
  100. package/dist/shared/fallback-chain-from-models.d.ts +1 -12
  101. package/dist/shared/file-utils.d.ts +1 -7
  102. package/dist/shared/frontmatter.d.ts +1 -7
  103. package/dist/shared/i18n.d.ts +9 -0
  104. package/dist/shared/index.d.ts +0 -1
  105. package/dist/shared/jsonc-parser.d.ts +1 -23
  106. package/dist/shared/model-availability.d.ts +18 -5
  107. package/dist/shared/model-capabilities/index.d.ts +6 -3
  108. package/dist/shared/model-capabilities-cache.d.ts +4 -8
  109. package/dist/shared/model-error-classifier.d.ts +4 -33
  110. package/dist/shared/model-format-normalizer.d.ts +1 -7
  111. package/dist/shared/model-normalization.d.ts +1 -2
  112. package/dist/shared/model-requirements.d.ts +2 -22
  113. package/dist/shared/model-resolution-pipeline.d.ts +5 -30
  114. package/dist/shared/model-resolution-types.d.ts +1 -36
  115. package/dist/shared/model-resolver.d.ts +8 -35
  116. package/dist/shared/model-sanitizer.d.ts +1 -3
  117. package/dist/shared/model-settings-compatibility.d.ts +2 -40
  118. package/dist/shared/model-string-parser.d.ts +1 -9
  119. package/dist/shared/model-suggestion-retry.d.ts +3 -7
  120. package/dist/shared/opencode-config-dir.d.ts +1 -0
  121. package/dist/shared/port-utils.d.ts +1 -9
  122. package/dist/shared/process-stream-reader.d.ts +3 -0
  123. package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +9 -0
  124. package/dist/shared/prompt-async-gate/queue.d.ts +8 -0
  125. package/dist/shared/prompt-async-gate/reservations.d.ts +9 -0
  126. package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +15 -0
  127. package/dist/shared/prompt-async-gate/timing.d.ts +8 -0
  128. package/dist/shared/prompt-async-gate/types.d.ts +120 -0
  129. package/dist/shared/prompt-async-gate.d.ts +3 -90
  130. package/dist/shared/provider-model-id-transform.d.ts +1 -1
  131. package/dist/shared/record-type-guard.d.ts +1 -1
  132. package/dist/shared/replace-tool-args.d.ts +1 -13
  133. package/dist/shared/session-idle-settle.d.ts +2 -1
  134. package/dist/shared/shell-env.d.ts +7 -5
  135. package/dist/shared/snake-case.d.ts +1 -5
  136. package/dist/shared/tool-name.d.ts +1 -1
  137. package/dist/testing/create-plugin-module.d.ts +2 -0
  138. package/dist/tools/delegate-task/constants.d.ts +19 -0
  139. package/dist/tools/delegate-task/skill-resolver.d.ts +9 -2
  140. package/dist/tools/delegate-task/types.d.ts +32 -0
  141. package/dist/tools/glob/cli.d.ts +3 -1
  142. package/dist/tools/glob/constants.d.ts +1 -1
  143. package/dist/tools/grep/cli.d.ts +4 -2
  144. package/dist/tools/grep/constants.d.ts +1 -1
  145. package/dist/tools/hashline-edit/autocorrect-replacement-lines.d.ts +1 -6
  146. package/dist/tools/hashline-edit/constants.d.ts +1 -4
  147. package/dist/tools/hashline-edit/diff-utils.d.ts +1 -6
  148. package/dist/tools/hashline-edit/edit-deduplication.d.ts +1 -5
  149. package/dist/tools/hashline-edit/edit-operation-primitives.d.ts +1 -10
  150. package/dist/tools/hashline-edit/edit-operations.d.ts +2 -8
  151. package/dist/tools/hashline-edit/edit-ordering.d.ts +1 -4
  152. package/dist/tools/hashline-edit/edit-text-normalization.d.ts +1 -7
  153. package/dist/tools/hashline-edit/file-text-canonicalization.d.ts +2 -7
  154. package/dist/tools/hashline-edit/hash-computation.d.ts +2 -11
  155. package/dist/tools/hashline-edit/hashline-chunk-formatter.d.ts +2 -10
  156. package/dist/tools/hashline-edit/hashline-edit-diff.d.ts +1 -1
  157. package/dist/tools/hashline-edit/normalize-edits.d.ts +2 -10
  158. package/dist/tools/hashline-edit/types.d.ts +1 -17
  159. package/dist/tools/hashline-edit/validation.d.ts +2 -20
  160. package/dist/tools/look-at/assistant-message-extractor.d.ts +7 -0
  161. package/dist/tools/look-at/session-poller.d.ts +9 -1
  162. package/dist/tools/shared/search-process-output.d.ts +7 -0
  163. package/dist/tools/skill/tools.d.ts +1 -1
  164. package/dist/tools/skill/types.d.ts +2 -0
  165. package/package.json +31 -16
  166. package/packages/ast-grep-mcp/dist/cli.js +272 -248
  167. package/dist/hooks/comment-checker/apply-patch-edits.d.ts +0 -2
  168. package/dist/shared/known-variants.d.ts +0 -6
  169. package/dist/shared/model-capabilities/bundled-snapshot.d.ts +0 -2
  170. package/dist/shared/model-capabilities/get-model-capabilities.d.ts +0 -2
  171. package/dist/shared/model-capabilities/runtime-model-readers.d.ts +0 -11
  172. package/dist/shared/model-capabilities/supplemental-entries.d.ts +0 -2
  173. package/dist/shared/model-capabilities/types.d.ts +0 -94
  174. package/dist/shared/model-capability-aliases.d.ts +0 -21
  175. package/dist/shared/model-capability-guardrails.d.ts +0 -38
  176. package/dist/shared/model-capability-heuristics.d.ts +0 -11
@@ -6,7 +6,7 @@ import { argv, stderr } from "node:process";
6
6
  // src/mcp.ts
7
7
  import { createInterface } from "node:readline";
8
8
 
9
- // src/language-support.ts
9
+ // ../ast-grep-core/src/language-support.ts
10
10
  var CLI_LANGUAGES = [
11
11
  "bash",
12
12
  "c",
@@ -37,81 +37,7 @@ var CLI_LANGUAGES = [
37
37
  var DEFAULT_TIMEOUT_MS = 300000;
38
38
  var DEFAULT_MAX_OUTPUT_BYTES = 1 * 1024 * 1024;
39
39
  var DEFAULT_MAX_MATCHES = 500;
40
- // src/sg-cli-path.ts
41
- import { createRequire } from "module";
42
- import { dirname, join } from "path";
43
- import { existsSync, statSync } from "fs";
44
- function isValidBinary(filePath) {
45
- try {
46
- return statSync(filePath).size > 1e4;
47
- } catch {
48
- return false;
49
- }
50
- }
51
- function getPlatformPackageName() {
52
- const platform = process.platform;
53
- const arch = process.arch;
54
- const platformMap = {
55
- "darwin-arm64": "@ast-grep/cli-darwin-arm64",
56
- "darwin-x64": "@ast-grep/cli-darwin-x64",
57
- "linux-arm64": "@ast-grep/cli-linux-arm64-gnu",
58
- "linux-x64": "@ast-grep/cli-linux-x64-gnu",
59
- "win32-x64": "@ast-grep/cli-win32-x64-msvc",
60
- "win32-arm64": "@ast-grep/cli-win32-arm64-msvc",
61
- "win32-ia32": "@ast-grep/cli-win32-ia32-msvc"
62
- };
63
- return platformMap[`${platform}-${arch}`] ?? null;
64
- }
65
- function findSgCliPathSync() {
66
- const binaryName = process.platform === "win32" ? "sg.exe" : "sg";
67
- try {
68
- const require2 = createRequire(import.meta.url);
69
- const cliPackageJsonPath = require2.resolve("@ast-grep/cli/package.json");
70
- const cliDirectory = dirname(cliPackageJsonPath);
71
- const sgPath = join(cliDirectory, binaryName);
72
- if (existsSync(sgPath) && isValidBinary(sgPath)) {
73
- return sgPath;
74
- }
75
- } catch {}
76
- const platformPackage = getPlatformPackageName();
77
- if (platformPackage) {
78
- try {
79
- const require2 = createRequire(import.meta.url);
80
- const packageJsonPath = require2.resolve(`${platformPackage}/package.json`);
81
- const packageDirectory = dirname(packageJsonPath);
82
- const astGrepBinaryName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
83
- const binaryPath = join(packageDirectory, astGrepBinaryName);
84
- if (existsSync(binaryPath) && isValidBinary(binaryPath)) {
85
- return binaryPath;
86
- }
87
- } catch {}
88
- }
89
- if (process.platform === "darwin") {
90
- const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
91
- for (const path of homebrewPaths) {
92
- if (existsSync(path) && isValidBinary(path)) {
93
- return path;
94
- }
95
- }
96
- }
97
- return null;
98
- }
99
- var resolvedCliPath = null;
100
- function getSgCliPath() {
101
- if (resolvedCliPath !== null) {
102
- return resolvedCliPath;
103
- }
104
- const syncPath = findSgCliPathSync();
105
- if (syncPath) {
106
- resolvedCliPath = syncPath;
107
- return syncPath;
108
- }
109
- return null;
110
- }
111
- function setSgCliPath(path) {
112
- resolvedCliPath = path;
113
- }
114
- // src/pattern-hints.ts
40
+ // ../ast-grep-core/src/pattern-hints.ts
115
41
  function detectRegexMisuse(pattern) {
116
42
  const src = pattern.trim();
117
43
  if (/\\[wWdDsSbB]/.test(src)) {
@@ -158,8 +84,7 @@ function detectLanguageSpecificMistake(pattern, lang) {
158
84
  function getPatternHint(pattern, lang) {
159
85
  return detectRegexMisuse(pattern) ?? detectLanguageSpecificMistake(pattern, lang);
160
86
  }
161
-
162
- // src/result-formatter.ts
87
+ // ../ast-grep-core/src/result-formatter.ts
163
88
  function formatSearchResult(result) {
164
89
  if (result.error) {
165
90
  return `Error: ${result.error}`;
@@ -212,6 +137,253 @@ function formatReplaceResult(result, isDryRun) {
212
137
  return lines.join(`
213
138
  `);
214
139
  }
140
+ // ../ast-grep-core/src/sg-compact-json-output.ts
141
+ function createSgResultFromStdout(stdout) {
142
+ if (!stdout.trim()) {
143
+ return { matches: [], totalMatches: 0, truncated: false };
144
+ }
145
+ const outputTruncated = stdout.length >= DEFAULT_MAX_OUTPUT_BYTES;
146
+ const outputToProcess = outputTruncated ? stdout.substring(0, DEFAULT_MAX_OUTPUT_BYTES) : stdout;
147
+ let matches = [];
148
+ try {
149
+ matches = JSON.parse(outputToProcess);
150
+ } catch {
151
+ if (outputTruncated) {
152
+ try {
153
+ const lastValidIndex = outputToProcess.lastIndexOf("}");
154
+ if (lastValidIndex > 0) {
155
+ const bracketIndex = outputToProcess.lastIndexOf("},", lastValidIndex);
156
+ if (bracketIndex > 0) {
157
+ const truncatedJson = outputToProcess.substring(0, bracketIndex + 1) + "]";
158
+ matches = JSON.parse(truncatedJson);
159
+ }
160
+ }
161
+ } catch {
162
+ return {
163
+ matches: [],
164
+ totalMatches: 0,
165
+ truncated: true,
166
+ truncatedReason: "max_output_bytes",
167
+ error: "Output too large and could not be parsed"
168
+ };
169
+ }
170
+ } else {
171
+ return { matches: [], totalMatches: 0, truncated: false };
172
+ }
173
+ }
174
+ const totalMatches = matches.length;
175
+ const matchesTruncated = totalMatches > DEFAULT_MAX_MATCHES;
176
+ const finalMatches = matchesTruncated ? matches.slice(0, DEFAULT_MAX_MATCHES) : matches;
177
+ return {
178
+ matches: finalMatches,
179
+ totalMatches,
180
+ truncated: outputTruncated || matchesTruncated,
181
+ truncatedReason: outputTruncated ? "max_output_bytes" : matchesTruncated ? "max_matches" : undefined
182
+ };
183
+ }
184
+ // ../ast-grep-core/src/runner.ts
185
+ var SG_BINARY_NOT_FOUND_MESSAGE = `ast-grep (sg) binary not found.
186
+
187
+ ` + `Install options:
188
+ ` + ` bun add -D @ast-grep/cli
189
+ ` + ` cargo install ast-grep --locked
190
+ ` + ` brew install ast-grep`;
191
+ function buildSgArgs(options, flags) {
192
+ const args = ["run", "-p", options.pattern, "--lang", options.lang];
193
+ if (flags.includeJson) {
194
+ args.push("--json=compact");
195
+ }
196
+ if (options.rewrite) {
197
+ args.push("-r", options.rewrite);
198
+ if (flags.includeUpdateAll) {
199
+ args.push("--update-all");
200
+ }
201
+ }
202
+ if (typeof options.context === "number" && options.context > 0) {
203
+ args.push("-C", String(options.context));
204
+ }
205
+ if (options.globs) {
206
+ for (const glob of options.globs) {
207
+ args.push("--globs", glob);
208
+ }
209
+ }
210
+ const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
211
+ args.push("--", ...paths);
212
+ return args;
213
+ }
214
+ async function runSg(options, deps) {
215
+ const shouldSeparateWritePass = Boolean(options.rewrite && options.updateAll);
216
+ const args = buildSgArgs(options, { includeJson: true, includeUpdateAll: false });
217
+ let binary;
218
+ try {
219
+ binary = await deps.resolveBinary();
220
+ } catch (error) {
221
+ return {
222
+ matches: [],
223
+ totalMatches: 0,
224
+ truncated: false,
225
+ error: isNoEntryError(error) ? SG_BINARY_NOT_FOUND_MESSAGE : `Failed to resolve ast-grep binary: ${errorMessage(error)}`
226
+ };
227
+ }
228
+ const searchResult = await trySpawn(binary, args, options.cwd, deps);
229
+ if (searchResult.error) {
230
+ return searchResult.error;
231
+ }
232
+ const output = searchResult.value;
233
+ if (output.exitCode !== 0 && output.stdout.trim() === "") {
234
+ if (output.stderr.includes("No files found")) {
235
+ return { matches: [], totalMatches: 0, truncated: false };
236
+ }
237
+ if (output.stderr.trim()) {
238
+ return { matches: [], totalMatches: 0, truncated: false, error: output.stderr.trim() };
239
+ }
240
+ return { matches: [], totalMatches: 0, truncated: false };
241
+ }
242
+ const jsonResult = createSgResultFromStdout(output.stdout);
243
+ if (!(shouldSeparateWritePass && jsonResult.matches.length > 0)) {
244
+ return jsonResult;
245
+ }
246
+ const writeArgs = buildSgArgs(options, { includeJson: false, includeUpdateAll: true });
247
+ const writeResult = await trySpawn(binary, writeArgs, options.cwd, deps);
248
+ if (writeResult.error) {
249
+ return { ...jsonResult, error: `Replace failed: ${writeResult.error.error ?? "unknown error"}` };
250
+ }
251
+ if (writeResult.value.exitCode !== 0) {
252
+ const errorDetail = writeResult.value.stderr.trim() || `ast-grep exited with code ${writeResult.value.exitCode}`;
253
+ return { ...jsonResult, error: `Replace failed: ${errorDetail}` };
254
+ }
255
+ return jsonResult;
256
+ }
257
+ async function trySpawn(binary, args, cwd, deps) {
258
+ try {
259
+ const value = await deps.spawnProcess(binary, args, {
260
+ cwd,
261
+ stdout: "pipe",
262
+ stderr: "pipe"
263
+ });
264
+ return { value };
265
+ } catch (error) {
266
+ if (error instanceof Error && error.message.includes("timeout")) {
267
+ return {
268
+ error: {
269
+ matches: [],
270
+ totalMatches: 0,
271
+ truncated: true,
272
+ truncatedReason: "timeout",
273
+ error: error.message
274
+ }
275
+ };
276
+ }
277
+ if (isNoEntryError(error)) {
278
+ return {
279
+ error: {
280
+ matches: [],
281
+ totalMatches: 0,
282
+ truncated: false,
283
+ error: SG_BINARY_NOT_FOUND_MESSAGE
284
+ }
285
+ };
286
+ }
287
+ return {
288
+ error: {
289
+ matches: [],
290
+ totalMatches: 0,
291
+ truncated: false,
292
+ error: `Failed to spawn ast-grep: ${errorMessage(error)}`
293
+ }
294
+ };
295
+ }
296
+ }
297
+ function isNoEntryError(error) {
298
+ if (typeof error !== "object" || error === null) {
299
+ return false;
300
+ }
301
+ const code = Reflect.get(error, "code");
302
+ const message = errorMessage(error);
303
+ return code === "ENOENT" || message.includes("ENOENT") || message.includes("not found");
304
+ }
305
+ function errorMessage(error) {
306
+ if (error instanceof Error) {
307
+ return error.message;
308
+ }
309
+ return String(error);
310
+ }
311
+ // src/sg-cli-path.ts
312
+ import { createRequire } from "module";
313
+ import { dirname, join } from "path";
314
+ import { existsSync, statSync } from "fs";
315
+ function isValidBinary(filePath) {
316
+ try {
317
+ return statSync(filePath).size > 1e4;
318
+ } catch {
319
+ return false;
320
+ }
321
+ }
322
+ function getPlatformPackageName() {
323
+ const platform = process.platform;
324
+ const arch = process.arch;
325
+ const platformMap = {
326
+ "darwin-arm64": "@ast-grep/cli-darwin-arm64",
327
+ "darwin-x64": "@ast-grep/cli-darwin-x64",
328
+ "linux-arm64": "@ast-grep/cli-linux-arm64-gnu",
329
+ "linux-x64": "@ast-grep/cli-linux-x64-gnu",
330
+ "win32-x64": "@ast-grep/cli-win32-x64-msvc",
331
+ "win32-arm64": "@ast-grep/cli-win32-arm64-msvc",
332
+ "win32-ia32": "@ast-grep/cli-win32-ia32-msvc"
333
+ };
334
+ return platformMap[`${platform}-${arch}`] ?? null;
335
+ }
336
+ function findSgCliPathSync() {
337
+ const binaryName = process.platform === "win32" ? "sg.exe" : "sg";
338
+ try {
339
+ const require2 = createRequire(import.meta.url);
340
+ const cliPackageJsonPath = require2.resolve("@ast-grep/cli/package.json");
341
+ const cliDirectory = dirname(cliPackageJsonPath);
342
+ const sgPath = join(cliDirectory, binaryName);
343
+ if (existsSync(sgPath) && isValidBinary(sgPath)) {
344
+ return sgPath;
345
+ }
346
+ } catch {}
347
+ const platformPackage = getPlatformPackageName();
348
+ if (platformPackage) {
349
+ try {
350
+ const require2 = createRequire(import.meta.url);
351
+ const packageJsonPath = require2.resolve(`${platformPackage}/package.json`);
352
+ const packageDirectory = dirname(packageJsonPath);
353
+ const astGrepBinaryName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
354
+ const binaryPath = join(packageDirectory, astGrepBinaryName);
355
+ if (existsSync(binaryPath) && isValidBinary(binaryPath)) {
356
+ return binaryPath;
357
+ }
358
+ } catch {}
359
+ }
360
+ if (process.platform === "darwin") {
361
+ const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
362
+ for (const path of homebrewPaths) {
363
+ if (existsSync(path) && isValidBinary(path)) {
364
+ return path;
365
+ }
366
+ }
367
+ }
368
+ return null;
369
+ }
370
+ var resolvedCliPath = null;
371
+ function getSgCliPath() {
372
+ if (resolvedCliPath !== null) {
373
+ return resolvedCliPath;
374
+ }
375
+ const syncPath = findSgCliPathSync();
376
+ if (syncPath) {
377
+ resolvedCliPath = syncPath;
378
+ return syncPath;
379
+ }
380
+ return null;
381
+ }
382
+ function setSgCliPath(path) {
383
+ resolvedCliPath = path;
384
+ }
385
+ // src/runner.ts
386
+ import { existsSync as existsSync3 } from "node:fs";
215
387
 
216
388
  // src/bun-spawn-shim.ts
217
389
  import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
@@ -325,9 +497,6 @@ function spawn(cmdOrOpts, opts) {
325
497
  }));
326
498
  }
327
499
 
328
- // src/runner.ts
329
- import { existsSync as existsSync3 } from "fs";
330
-
331
500
  // src/cli-binary-path-resolution.ts
332
501
  import { existsSync as existsSync2 } from "fs";
333
502
  var resolvedCliPath2 = null;
@@ -368,178 +537,33 @@ async function collectProcessOutputWithTimeout(process2, timeoutMs) {
368
537
  return { stdout, stderr, exitCode };
369
538
  }
370
539
 
371
- // src/sg-compact-json-output.ts
372
- function createSgResultFromStdout(stdout) {
373
- if (!stdout.trim()) {
374
- return { matches: [], totalMatches: 0, truncated: false };
375
- }
376
- const outputTruncated = stdout.length >= DEFAULT_MAX_OUTPUT_BYTES;
377
- const outputToProcess = outputTruncated ? stdout.substring(0, DEFAULT_MAX_OUTPUT_BYTES) : stdout;
378
- let matches = [];
379
- try {
380
- matches = JSON.parse(outputToProcess);
381
- } catch {
382
- if (outputTruncated) {
383
- try {
384
- const lastValidIndex = outputToProcess.lastIndexOf("}");
385
- if (lastValidIndex > 0) {
386
- const bracketIndex = outputToProcess.lastIndexOf("},", lastValidIndex);
387
- if (bracketIndex > 0) {
388
- const truncatedJson = outputToProcess.substring(0, bracketIndex + 1) + "]";
389
- matches = JSON.parse(truncatedJson);
390
- }
391
- }
392
- } catch {
393
- return {
394
- matches: [],
395
- totalMatches: 0,
396
- truncated: true,
397
- truncatedReason: "max_output_bytes",
398
- error: "Output too large and could not be parsed"
399
- };
400
- }
401
- } else {
402
- return { matches: [], totalMatches: 0, truncated: false };
403
- }
404
- }
405
- const totalMatches = matches.length;
406
- const matchesTruncated = totalMatches > DEFAULT_MAX_MATCHES;
407
- const finalMatches = matchesTruncated ? matches.slice(0, DEFAULT_MAX_MATCHES) : matches;
408
- return {
409
- matches: finalMatches,
410
- totalMatches,
411
- truncated: outputTruncated || matchesTruncated,
412
- truncatedReason: outputTruncated ? "max_output_bytes" : matchesTruncated ? "max_matches" : undefined
413
- };
414
- }
415
-
416
540
  // src/runner.ts
417
- async function runSg(options) {
418
- const shouldSeparateWritePass = !!(options.rewrite && options.updateAll);
419
- const args = createSgArgs(options, { includeJson: true, includeUpdateAll: false });
420
- let cliPath = getSgCliPath();
421
- if (!cliPath || !existsSync3(cliPath)) {
422
- const resolvedPath = await getAstGrepPath();
423
- if (resolvedPath) {
424
- cliPath = resolvedPath;
425
- } else {
426
- return {
427
- matches: [],
428
- totalMatches: 0,
429
- truncated: false,
430
- error: `ast-grep (sg) binary not found.
431
-
432
- ` + `Install options:
433
- ` + ` bun add -D @ast-grep/cli
434
- ` + ` cargo install ast-grep --locked
435
- ` + ` brew install ast-grep`
436
- };
437
- }
438
- }
439
- const timeout = DEFAULT_TIMEOUT_MS;
440
- const proc = spawn([cliPath, ...args], {
441
- cwd: options.cwd,
442
- stdout: "pipe",
443
- stderr: "pipe"
541
+ async function runSg2(options) {
542
+ return runSg(options, {
543
+ resolveBinary: resolveBinaryPath,
544
+ spawnProcess
444
545
  });
445
- let stdout;
446
- let stderr;
447
- let exitCode;
448
- try {
449
- const output = await collectProcessOutputWithTimeout(proc, timeout);
450
- stdout = output.stdout;
451
- stderr = output.stderr;
452
- exitCode = output.exitCode;
453
- } catch (error) {
454
- if (error instanceof Error && error.message.includes("timeout")) {
455
- return {
456
- matches: [],
457
- totalMatches: 0,
458
- truncated: true,
459
- truncatedReason: "timeout",
460
- error: error.message
461
- };
462
- }
463
- const errorMessage = error instanceof Error ? error.message : String(error);
464
- const errorCode = errorCodeFrom(error);
465
- const isNoEntry = errorCode === "ENOENT" || errorMessage.includes("ENOENT") || errorMessage.includes("not found");
466
- if (isNoEntry) {
467
- return {
468
- matches: [],
469
- totalMatches: 0,
470
- truncated: false,
471
- error: `ast-grep CLI binary not found.
472
-
473
- ` + `Install options:
474
- ` + ` bun add -D @ast-grep/cli
475
- ` + ` cargo install ast-grep --locked
476
- ` + ` brew install ast-grep`
477
- };
478
- }
479
- return {
480
- matches: [],
481
- totalMatches: 0,
482
- truncated: false,
483
- error: `Failed to spawn ast-grep: ${errorMessage}`
484
- };
485
- }
486
- if (exitCode !== 0 && stdout.trim() === "") {
487
- if (stderr.includes("No files found")) {
488
- return { matches: [], totalMatches: 0, truncated: false };
489
- }
490
- if (stderr.trim()) {
491
- return { matches: [], totalMatches: 0, truncated: false, error: stderr.trim() };
492
- }
493
- return { matches: [], totalMatches: 0, truncated: false };
494
- }
495
- const jsonResult = createSgResultFromStdout(stdout);
496
- if (shouldSeparateWritePass && jsonResult.matches.length > 0) {
497
- const writeArgs = createSgArgs(options, { includeJson: false, includeUpdateAll: true });
498
- const writeProc = spawn([cliPath, ...writeArgs], {
499
- cwd: options.cwd,
500
- stdout: "pipe",
501
- stderr: "pipe"
502
- });
503
- try {
504
- const writeOutput = await collectProcessOutputWithTimeout(writeProc, timeout);
505
- if (writeOutput.exitCode !== 0) {
506
- const errorDetail = writeOutput.stderr.trim() || `ast-grep exited with code ${writeOutput.exitCode}`;
507
- return { ...jsonResult, error: `Replace failed: ${errorDetail}` };
508
- }
509
- } catch (error) {
510
- const errorMessage = error instanceof Error ? error.message : String(error);
511
- return { ...jsonResult, error: `Replace failed: ${errorMessage}` };
512
- }
513
- }
514
- return jsonResult;
515
546
  }
516
- function createSgArgs(options, flags) {
517
- const args = ["run", "-p", options.pattern, "--lang", options.lang];
518
- if (flags.includeJson) {
519
- args.push("--json=compact");
520
- }
521
- if (options.rewrite) {
522
- args.push("-r", options.rewrite);
523
- if (flags.includeUpdateAll) {
524
- args.push("--update-all");
525
- }
526
- }
527
- if (options.context && options.context > 0) {
528
- args.push("-C", String(options.context));
547
+ async function resolveBinaryPath() {
548
+ const cliPath = getSgCliPath();
549
+ if (cliPath && existsSync3(cliPath)) {
550
+ return cliPath;
529
551
  }
530
- if (options.globs) {
531
- for (const glob of options.globs) {
532
- args.push("--globs", glob);
533
- }
552
+ const resolvedPath = await getAstGrepPath();
553
+ if (!resolvedPath) {
554
+ const noEntryError = new Error("ENOENT: ast-grep binary not found");
555
+ Reflect.set(noEntryError, "code", "ENOENT");
556
+ throw noEntryError;
534
557
  }
535
- const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
536
- args.push("--", ...paths);
537
- return args;
558
+ return resolvedPath;
538
559
  }
539
- function errorCodeFrom(error) {
540
- if (typeof error !== "object" || error === null || !("code" in error))
541
- return;
542
- return Reflect.get(error, "code");
560
+ async function spawnProcess(binary, args, options) {
561
+ const proc = spawn([binary, ...args], {
562
+ cwd: options?.cwd,
563
+ stdout: options?.stdout ?? "pipe",
564
+ stderr: options?.stderr ?? "pipe"
565
+ });
566
+ return collectProcessOutputWithTimeout(proc, DEFAULT_TIMEOUT_MS);
543
567
  }
544
568
 
545
569
  // src/tool-descriptions.ts
@@ -720,7 +744,7 @@ async function handleToolCall(id, params, options) {
720
744
  async function executeAstGrepTool(name, args, options) {
721
745
  if (disabledToolNames(options).has(name))
722
746
  throw new Error(`ast-grep tool is disabled: ${name}`);
723
- const runner = options.runSg ?? runSg;
747
+ const runner = options.runSg ?? runSg2;
724
748
  const workspaceDirectory = normalizeWorkspaceDirectory(options.workspaceDirectory ?? process.env.OMO_AST_GREP_WORKSPACE ?? process.cwd());
725
749
  if (name === "search") {
726
750
  const input = parseSearchArgs(args, workspaceDirectory);
@@ -1,2 +0,0 @@
1
- import type { ApplyPatchEdit } from "./cli-runner";
2
- export declare function extractApplyPatchEdits(details: unknown, args?: Record<string, unknown>): ApplyPatchEdit[];
@@ -1,6 +0,0 @@
1
- /**
2
- * Canonical set of recognised variant / effort tokens.
3
- * Used by parseFallbackModelEntry (space-suffix detection) and
4
- * flattenToFallbackModelStrings (inline-variant stripping).
5
- */
6
- export declare const KNOWN_VARIANTS: Set<string>;
@@ -1,2 +0,0 @@
1
- import type { ModelCapabilitiesSnapshot } from "./types";
2
- export declare function getBundledModelCapabilitiesSnapshot(): ModelCapabilitiesSnapshot;
@@ -1,2 +0,0 @@
1
- import type { GetModelCapabilitiesInput, ModelCapabilities } from "./types";
2
- export declare function getModelCapabilities(input: GetModelCapabilitiesInput): ModelCapabilities;
@@ -1,11 +0,0 @@
1
- import type { ModelMetadata } from "../connected-providers-cache";
2
- import type { ModelCapabilities } from "./types";
3
- export declare function readRuntimeModel(runtimeModel: ModelMetadata | Record<string, unknown> | undefined): Record<string, unknown> | undefined;
4
- export declare function readRuntimeModelVariants(runtimeModel: Record<string, unknown> | undefined): string[] | undefined;
5
- export declare function readRuntimeModelModalities(runtimeModel: Record<string, unknown> | undefined): ModelCapabilities["modalities"] | undefined;
6
- export declare function readRuntimeModelReasoningSupport(runtimeModel: Record<string, unknown> | undefined): boolean | undefined;
7
- export declare function readRuntimeModelThinkingSupport(runtimeModel: Record<string, unknown> | undefined): boolean | undefined;
8
- export declare function readRuntimeModelTemperatureSupport(runtimeModel: Record<string, unknown> | undefined): boolean | undefined;
9
- export declare function readRuntimeModelTopPSupport(runtimeModel: Record<string, unknown> | undefined): boolean | undefined;
10
- export declare function readRuntimeModelToolCallSupport(runtimeModel: Record<string, unknown> | undefined): boolean | undefined;
11
- export declare function readRuntimeModelLimitOutput(runtimeModel: Record<string, unknown> | undefined): number | undefined;
@@ -1,2 +0,0 @@
1
- import type { ModelCapabilitiesSnapshotEntry } from "./types";
2
- export declare const SUPPLEMENTAL_MODEL_CAPABILITIES: Record<string, ModelCapabilitiesSnapshotEntry>;