cursor-opencode-provider 0.7.1 → 0.7.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.
- package/dist/protocol/messages.js +2 -0
- package/dist/protocol/tools.js +102 -7
- package/package.json +1 -1
|
@@ -472,6 +472,8 @@ export function createMessageTypes() {
|
|
|
472
472
|
{ id: 1, name: "matches", type: "GrepFileMatch", repeated: true },
|
|
473
473
|
{ id: 2, name: "total_lines", type: "int32" },
|
|
474
474
|
{ id: 3, name: "total_matched_lines", type: "int32" },
|
|
475
|
+
{ id: 4, name: "client_truncated", type: "bool" },
|
|
476
|
+
{ id: 5, name: "ripgrep_truncated", type: "bool" },
|
|
475
477
|
]);
|
|
476
478
|
addType(root, "GrepUnionResult", [
|
|
477
479
|
{ id: 2, name: "files", type: "GrepFilesResult" },
|
package/dist/protocol/tools.js
CHANGED
|
@@ -1049,7 +1049,9 @@ export function parseExecServerMessage(msg, dialect = OPENCODE_1_TOOL_DIALECT) {
|
|
|
1049
1049
|
? shellStreamResultMetadata(rawArgs)
|
|
1050
1050
|
: execVariant === "read_args" || execVariant === "pi_read_args"
|
|
1051
1051
|
? readRequestResultMetadata(rawArgs, mapped.args)
|
|
1052
|
-
:
|
|
1052
|
+
: execVariant === "grep_args"
|
|
1053
|
+
? grepRequestResultMetadata(rawArgs)
|
|
1054
|
+
: undefined;
|
|
1053
1055
|
if (resultMetadata
|
|
1054
1056
|
&& resultMetadata.timeout_behavior !== 2
|
|
1055
1057
|
&& typeof resultMetadata.timeout_ms === "number") {
|
|
@@ -2063,6 +2065,70 @@ function rewriteShellPathLine(line, root) {
|
|
|
2063
2065
|
return resolveToolPath(trimmed, root);
|
|
2064
2066
|
return line;
|
|
2065
2067
|
}
|
|
2068
|
+
const OPENCODE_GREP_LINE = /^[ \t]+Line (\d+):[ \t]?(.*)$/;
|
|
2069
|
+
/**
|
|
2070
|
+
* OpenCode 1.x and 2.0 both render grep as `Found N matches`, a `path:` header,
|
|
2071
|
+
* and indented `Line N: text` previews. A page with no previews is not content.
|
|
2072
|
+
*/
|
|
2073
|
+
function parseOpenCodeGrepContent(output, workspaceRoot) {
|
|
2074
|
+
const lines = normalizeToolText(output).split("\n");
|
|
2075
|
+
const first = lines[0]?.trim() ?? "";
|
|
2076
|
+
if (!/^Found \d+ matches\b/.test(first))
|
|
2077
|
+
return undefined;
|
|
2078
|
+
const matches = [];
|
|
2079
|
+
let current;
|
|
2080
|
+
let truncated = /\bmore matches available\b/.test(first);
|
|
2081
|
+
let sawLine = false;
|
|
2082
|
+
for (const raw of lines.slice(1)) {
|
|
2083
|
+
if (!raw.trim())
|
|
2084
|
+
continue;
|
|
2085
|
+
const preview = OPENCODE_GREP_LINE.exec(raw);
|
|
2086
|
+
if (preview) {
|
|
2087
|
+
sawLine = true;
|
|
2088
|
+
if (!current)
|
|
2089
|
+
continue;
|
|
2090
|
+
const lineNumber = Number(preview[1]);
|
|
2091
|
+
if (!Number.isSafeInteger(lineNumber) || lineNumber < 1)
|
|
2092
|
+
continue;
|
|
2093
|
+
current.matches.push({ line_number: lineNumber, content: preview[2] ?? "" });
|
|
2094
|
+
continue;
|
|
2095
|
+
}
|
|
2096
|
+
if (raw.trimStart().startsWith("(")) {
|
|
2097
|
+
if (/truncat/i.test(raw))
|
|
2098
|
+
truncated = true;
|
|
2099
|
+
continue;
|
|
2100
|
+
}
|
|
2101
|
+
if (raw.startsWith(" ") || raw.startsWith("\t"))
|
|
2102
|
+
continue;
|
|
2103
|
+
const header = /^(.*):$/.exec(raw.trim());
|
|
2104
|
+
if (!header || !header[1] || header[1].includes("://"))
|
|
2105
|
+
continue;
|
|
2106
|
+
current = { file: resolveToolPath(header[1], workspaceRoot), matches: [] };
|
|
2107
|
+
matches.push(current);
|
|
2108
|
+
}
|
|
2109
|
+
if (!sawLine)
|
|
2110
|
+
return undefined;
|
|
2111
|
+
const withHits = matches.filter((file) => file.matches.length > 0);
|
|
2112
|
+
if (withHits.length === 0)
|
|
2113
|
+
return undefined;
|
|
2114
|
+
return {
|
|
2115
|
+
matches: withHits,
|
|
2116
|
+
truncated,
|
|
2117
|
+
totalMatchedLines: withHits.reduce((count, file) => count + file.matches.length, 0),
|
|
2118
|
+
};
|
|
2119
|
+
}
|
|
2120
|
+
function grepRequestResultMetadata(raw) {
|
|
2121
|
+
const pattern = str(raw.pattern);
|
|
2122
|
+
const outputMode = str(raw.output_mode);
|
|
2123
|
+
const searchPath = str(raw.path);
|
|
2124
|
+
if (!pattern && !outputMode && !searchPath)
|
|
2125
|
+
return undefined;
|
|
2126
|
+
return {
|
|
2127
|
+
...(pattern ? { pattern } : {}),
|
|
2128
|
+
...(outputMode ? { output_mode: outputMode } : {}),
|
|
2129
|
+
...(searchPath ? { path: searchPath } : {}),
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2066
2132
|
function extractGroundedPaths(output, workspaceRoot) {
|
|
2067
2133
|
const normalized = normalizeToolText(output);
|
|
2068
2134
|
const directory = parseOpenCode2DirectoryListing(normalized, workspaceRoot);
|
|
@@ -2231,21 +2297,50 @@ export function buildTypedExecResult(resultField, output, error, toolName, resul
|
|
|
2231
2297
|
case "grep_result": {
|
|
2232
2298
|
if (error)
|
|
2233
2299
|
return { error: { error } };
|
|
2234
|
-
// Prefer files_with_matches: OpenCode glob/grep often returns path lists.
|
|
2235
|
-
// Content-mode GrepSuccess also works but needs GrepFileMatch nesting.
|
|
2236
|
-
const files = extractGroundedPaths(output, resultRoot);
|
|
2237
2300
|
const cwd = resultRoot ?? "";
|
|
2301
|
+
const pattern = str(resultMetadata?.pattern) ?? "";
|
|
2302
|
+
const requestedPath = str(resultMetadata?.path) ?? cwd;
|
|
2303
|
+
const requestedMode = str(resultMetadata?.output_mode);
|
|
2304
|
+
// OpenCode always returns match previews. Cursor's native Grep defaults
|
|
2305
|
+
// to content; encoding that as files_with_matches drops the previews and
|
|
2306
|
+
// the model only sees paths. Keep files_with_matches for an explicit
|
|
2307
|
+
// files-only request, and for path lists (glob remaps, no matches).
|
|
2308
|
+
const parsedContent = parseOpenCodeGrepContent(output, resultRoot);
|
|
2309
|
+
const content = requestedMode === "files_with_matches"
|
|
2310
|
+
? undefined
|
|
2311
|
+
: parsedContent;
|
|
2312
|
+
if (content) {
|
|
2313
|
+
return {
|
|
2314
|
+
success: {
|
|
2315
|
+
pattern,
|
|
2316
|
+
path: requestedPath,
|
|
2317
|
+
output_mode: "content",
|
|
2318
|
+
workspace_results: {
|
|
2319
|
+
[cwd]: {
|
|
2320
|
+
content: {
|
|
2321
|
+
matches: content.matches,
|
|
2322
|
+
total_lines: content.totalMatchedLines,
|
|
2323
|
+
total_matched_lines: content.totalMatchedLines,
|
|
2324
|
+
client_truncated: content.truncated,
|
|
2325
|
+
ripgrep_truncated: false,
|
|
2326
|
+
},
|
|
2327
|
+
},
|
|
2328
|
+
},
|
|
2329
|
+
},
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
const files = extractGroundedPaths(output, resultRoot);
|
|
2238
2333
|
return {
|
|
2239
2334
|
success: {
|
|
2240
|
-
pattern
|
|
2241
|
-
path:
|
|
2335
|
+
pattern,
|
|
2336
|
+
path: requestedPath,
|
|
2242
2337
|
output_mode: "files_with_matches",
|
|
2243
2338
|
workspace_results: {
|
|
2244
2339
|
[cwd]: {
|
|
2245
2340
|
files: {
|
|
2246
2341
|
files,
|
|
2247
2342
|
total_files: files.length,
|
|
2248
|
-
client_truncated: false,
|
|
2343
|
+
client_truncated: parsedContent?.truncated ?? false,
|
|
2249
2344
|
},
|
|
2250
2345
|
},
|
|
2251
2346
|
},
|