oh-my-opencode 4.2.3 → 4.3.0
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.
- package/README.ja.md +1 -0
- package/README.ko.md +1 -0
- package/README.md +3 -2
- package/README.zh-cn.md +1 -0
- package/dist/agents/atlas/default-prompt-sections.d.ts +1 -1
- package/dist/agents/builtin-agents/available-skills.d.ts +1 -1
- package/dist/agents/builtin-agents/model-resolution.d.ts +1 -1
- package/dist/agents/prometheus/plan-generation.d.ts +1 -1
- package/dist/agents/prometheus/plan-template.d.ts +1 -1
- package/dist/agents/prometheus/spec-driven-mode.d.ts +7 -0
- package/dist/cli/doctor/checks/system-binary.d.ts +1 -1
- package/dist/cli/doctor/checks/tui-plugin-config.d.ts +14 -0
- package/dist/cli/doctor/constants.d.ts +1 -0
- package/dist/cli/index.js +3168 -2353
- package/dist/cli/provider-model-id-transform.d.ts +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schema/agent-overrides.d.ts +147 -1
- package/dist/config/schema/background-task.d.ts +1 -0
- package/dist/config/schema/default-mode.d.ts +6 -0
- package/dist/config/schema/hooks.d.ts +2 -0
- package/dist/config/schema/i18n.d.ts +5 -0
- package/dist/config/schema/keyword-detector.d.ts +8 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +163 -1
- package/dist/config/schema.d.ts +2 -0
- package/dist/create-hooks.d.ts +2 -0
- package/dist/features/background-agent/fallback-retry-handler.d.ts +3 -0
- package/dist/features/background-agent/manager.d.ts +0 -1
- package/dist/features/background-agent/parent-wake-notifier.d.ts +4 -0
- package/dist/features/background-agent/session-activity.d.ts +12 -0
- package/dist/features/background-agent/session-existence.d.ts +2 -0
- package/dist/features/background-agent/session-stream-activity.d.ts +18 -0
- package/dist/features/background-agent/task-activity-refresh.d.ts +11 -0
- package/dist/features/background-agent/task-poller.d.ts +2 -0
- package/dist/features/boulder-state/constants.d.ts +1 -10
- package/dist/features/boulder-state/format-duration.d.ts +1 -1
- package/dist/features/boulder-state/storage.d.ts +1 -83
- package/dist/features/boulder-state/top-level-task.d.ts +1 -2
- package/dist/features/boulder-state/types.d.ts +1 -100
- package/dist/features/task-toast-manager/manager.d.ts +1 -1
- package/dist/features/team-mode/team-state-store/locks.d.ts +7 -4
- package/dist/features/tmux-subagent/manager.d.ts +2 -0
- package/dist/hooks/atlas/system-reminder-templates.d.ts +1 -1
- package/dist/hooks/claude-code-hooks/config-loader.d.ts +7 -0
- package/dist/hooks/claude-code-hooks/config.d.ts +4 -1
- package/dist/hooks/claude-code-hooks/types.d.ts +17 -1
- package/dist/hooks/comment-checker/cli.d.ts +2 -22
- package/dist/hooks/comment-checker/types.d.ts +1 -31
- package/dist/hooks/directory-agents-injector/finder.d.ts +2 -7
- package/dist/hooks/directory-agents-injector/injector.d.ts +1 -18
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/keyword-detector/analyze/default.d.ts +1 -1
- package/dist/hooks/keyword-detector/constants.d.ts +10 -5
- package/dist/hooks/keyword-detector/detector.d.ts +2 -2
- package/dist/hooks/keyword-detector/hook.d.ts +2 -1
- package/dist/hooks/keyword-detector/hyperplan/default.d.ts +5 -0
- package/dist/hooks/notepad-write-guard/index.d.ts +2 -0
- package/dist/hooks/plan-format-validator/hook.d.ts +21 -0
- package/dist/hooks/plan-format-validator/index.d.ts +1 -0
- package/dist/hooks/prometheus-md-only/constants.d.ts +8 -0
- package/dist/hooks/rules-injector/constants.d.ts +1 -7
- package/dist/hooks/rules-injector/matcher.d.ts +2 -2
- package/dist/hooks/rules-injector/parser.d.ts +2 -2
- package/dist/hooks/rules-injector/project-root-finder.d.ts +1 -1
- package/dist/hooks/rules-injector/rule-distance.d.ts +1 -1
- package/dist/hooks/rules-injector/rule-file-finder.d.ts +2 -2
- package/dist/hooks/rules-injector/rule-file-scanner.d.ts +1 -1
- package/dist/hooks/rules-injector/rule-scan-cache.d.ts +2 -2
- package/dist/hooks/rules-injector/types.d.ts +1 -1
- package/dist/hooks/session-todo-status.d.ts +1 -0
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/start-work/context-info-builder.d.ts +1 -0
- package/dist/hooks/start-work/session-plan-affinity.d.ts +7 -0
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
- package/dist/index.js +17916 -15893
- package/dist/locales/en.d.ts +18 -0
- package/dist/locales/index.d.ts +6 -0
- package/dist/locales/zh.d.ts +17 -0
- package/dist/mcp/ast-grep.d.ts +2 -0
- package/dist/mcp/cli-suffix.d.ts +1 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/lsp.d.ts +2 -0
- package/dist/mcp/runtime-executable.d.ts +11 -0
- package/dist/oh-my-opencode.schema.json +449 -1
- package/dist/plugin/hooks/create-core-hooks.d.ts +2 -0
- package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +3 -1
- package/dist/plugin/system-transform.d.ts +2 -1
- package/dist/plugin/tool-definition.d.ts +9 -0
- package/dist/plugin-handlers/agent-key-remapper.d.ts +5 -1
- package/dist/plugin-handlers/hook-config-handler.d.ts +7 -0
- package/dist/plugin-handlers/index.d.ts +1 -0
- package/dist/plugin-handlers/plugin-components-loader.d.ts +2 -3
- package/dist/shared/agent-display-names.d.ts +10 -2
- package/dist/shared/command-executor/execute-hook-command.d.ts +2 -0
- package/dist/shared/contains-path.d.ts +1 -2
- package/dist/shared/context-limit-resolver.d.ts +2 -5
- package/dist/shared/deep-merge.d.ts +1 -13
- package/dist/shared/disabled-providers.d.ts +14 -0
- package/dist/shared/extract-semver.d.ts +1 -1
- package/dist/shared/fallback-chain-from-models.d.ts +1 -12
- package/dist/shared/file-utils.d.ts +1 -7
- package/dist/shared/frontmatter.d.ts +1 -7
- package/dist/shared/i18n.d.ts +9 -0
- package/dist/shared/index.d.ts +0 -1
- package/dist/shared/jsonc-parser.d.ts +1 -23
- package/dist/shared/model-availability.d.ts +18 -5
- package/dist/shared/model-capabilities/index.d.ts +6 -3
- package/dist/shared/model-capabilities-cache.d.ts +4 -8
- package/dist/shared/model-error-classifier.d.ts +4 -33
- package/dist/shared/model-format-normalizer.d.ts +1 -7
- package/dist/shared/model-normalization.d.ts +1 -2
- package/dist/shared/model-requirements.d.ts +2 -22
- package/dist/shared/model-resolution-pipeline.d.ts +5 -30
- package/dist/shared/model-resolution-types.d.ts +1 -36
- package/dist/shared/model-resolver.d.ts +8 -35
- package/dist/shared/model-sanitizer.d.ts +1 -3
- package/dist/shared/model-settings-compatibility.d.ts +2 -40
- package/dist/shared/model-string-parser.d.ts +1 -9
- package/dist/shared/model-suggestion-retry.d.ts +3 -7
- package/dist/shared/opencode-config-dir.d.ts +1 -0
- package/dist/shared/port-utils.d.ts +1 -9
- package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +9 -0
- package/dist/shared/prompt-async-gate/queue.d.ts +8 -0
- package/dist/shared/prompt-async-gate/reservations.d.ts +9 -0
- package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +15 -0
- package/dist/shared/prompt-async-gate/timing.d.ts +8 -0
- package/dist/shared/prompt-async-gate/types.d.ts +120 -0
- package/dist/shared/prompt-async-gate.d.ts +3 -90
- package/dist/shared/provider-model-id-transform.d.ts +1 -1
- package/dist/shared/record-type-guard.d.ts +1 -1
- package/dist/shared/replace-tool-args.d.ts +1 -13
- package/dist/shared/session-idle-settle.d.ts +2 -1
- package/dist/shared/shell-env.d.ts +7 -5
- package/dist/shared/snake-case.d.ts +1 -5
- package/dist/shared/tool-name.d.ts +1 -1
- package/dist/testing/create-plugin-module.d.ts +2 -0
- package/dist/tools/delegate-task/constants.d.ts +19 -0
- package/dist/tools/delegate-task/skill-resolver.d.ts +9 -2
- package/dist/tools/delegate-task/types.d.ts +32 -0
- package/dist/tools/glob/constants.d.ts +1 -1
- package/dist/tools/grep/constants.d.ts +1 -1
- package/dist/tools/hashline-edit/autocorrect-replacement-lines.d.ts +1 -6
- package/dist/tools/hashline-edit/constants.d.ts +1 -4
- package/dist/tools/hashline-edit/diff-utils.d.ts +1 -6
- package/dist/tools/hashline-edit/edit-deduplication.d.ts +1 -5
- package/dist/tools/hashline-edit/edit-operation-primitives.d.ts +1 -10
- package/dist/tools/hashline-edit/edit-operations.d.ts +2 -8
- package/dist/tools/hashline-edit/edit-ordering.d.ts +1 -4
- package/dist/tools/hashline-edit/edit-text-normalization.d.ts +1 -7
- package/dist/tools/hashline-edit/file-text-canonicalization.d.ts +2 -7
- package/dist/tools/hashline-edit/hash-computation.d.ts +2 -11
- package/dist/tools/hashline-edit/hashline-chunk-formatter.d.ts +2 -10
- package/dist/tools/hashline-edit/hashline-edit-diff.d.ts +1 -1
- package/dist/tools/hashline-edit/normalize-edits.d.ts +2 -10
- package/dist/tools/hashline-edit/types.d.ts +1 -17
- package/dist/tools/hashline-edit/validation.d.ts +2 -20
- package/dist/tools/look-at/assistant-message-extractor.d.ts +7 -0
- package/dist/tools/look-at/session-poller.d.ts +9 -1
- package/dist/tools/skill/tools.d.ts +1 -1
- package/dist/tools/skill/types.d.ts +2 -0
- package/package.json +31 -16
- package/packages/ast-grep-mcp/dist/cli.js +272 -248
- package/dist/hooks/comment-checker/apply-patch-edits.d.ts +0 -2
- package/dist/shared/known-variants.d.ts +0 -6
- package/dist/shared/model-capabilities/bundled-snapshot.d.ts +0 -2
- package/dist/shared/model-capabilities/get-model-capabilities.d.ts +0 -2
- package/dist/shared/model-capabilities/runtime-model-readers.d.ts +0 -11
- package/dist/shared/model-capabilities/supplemental-entries.d.ts +0 -2
- package/dist/shared/model-capabilities/types.d.ts +0 -94
- package/dist/shared/model-capability-aliases.d.ts +0 -21
- package/dist/shared/model-capability-guardrails.d.ts +0 -38
- 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/
|
|
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
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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
|
|
517
|
-
const
|
|
518
|
-
if (
|
|
519
|
-
|
|
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
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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
|
-
|
|
536
|
-
args.push("--", ...paths);
|
|
537
|
-
return args;
|
|
558
|
+
return resolvedPath;
|
|
538
559
|
}
|
|
539
|
-
function
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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 ??
|
|
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,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;
|