Files
oh-my-opencode/src/tools/glob/tools.ts
T
ismeth 418cf8529f fix(glob): use cwd-relative search for ripgrep to fix directory prefix patterns
Ripgrep's --glob flag silently returns zero results when the search target
is an absolute path and the pattern contains directory prefixes (e.g.
'apps/backend/**/*.ts' with '/project'). This is a known ripgrep behavior
where glob matching fails against paths rooted at absolute arguments.

Fix by running ripgrep with cwd set to the search path and '.' as the
search target, matching how the find backend already operates. Ripgrep
then sees relative paths internally, so directory-prefixed globs match
correctly. Output paths are resolved back to absolute via resolve().
2026-02-28 13:26:30 +09:00

50 lines
1.9 KiB
TypeScript

import { resolve } from "node:path"
import type { PluginInput } from "@opencode-ai/plugin"
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
import { runRgFiles } from "./cli"
import { resolveGrepCliWithAutoInstall } from "./constants"
import { formatGlobResult } from "./result-formatter"
export function createGlobTools(ctx: PluginInput): Record<string, ToolDefinition> {
const glob: ToolDefinition = tool({
description:
"Fast file pattern matching tool with safety limits (60s timeout, 100 file limit). " +
"Supports glob patterns like \"**/*.js\" or \"src/**/*.ts\". " +
"Returns matching file paths sorted by modification time. " +
"Use this tool when you need to find files by name patterns.",
args: {
pattern: tool.schema.string().describe("The glob pattern to match files against"),
path: tool.schema
.string()
.optional()
.describe(
"The directory to search in. If not specified, the current working directory will be used. " +
"IMPORTANT: Omit this field to use the default directory. DO NOT enter \"undefined\" or \"null\" - " +
"simply omit it for the default behavior. Must be a valid directory path if provided."
),
},
execute: async (args, context) => {
try {
const cli = await resolveGrepCliWithAutoInstall()
const runtimeCtx = context as Record<string, unknown>
const dir = typeof runtimeCtx.directory === "string" ? runtimeCtx.directory : ctx.directory
const searchPath = args.path ? resolve(dir, args.path) : dir
const result = await runRgFiles(
{
pattern: args.pattern,
paths: [searchPath],
},
cli
)
return formatGlobResult(result)
} catch (e) {
return `Error: ${e instanceof Error ? e.message : String(e)}`
}
},
})
return { glob }
}