Current section
Files
Jump to
Current section
Files
lib/cmdc/tool/glob.ex
defmodule CMDC.Tool.Glob do
@moduledoc """
文件名模式匹配,对标 DeepAgents `glob` 工具。
- 有 Sandbox 时走 `sandbox.glob/3`(返回结构化路径列表)
- 无 Sandbox 时走 `CMDC.Sandbox.Local.glob/3`
支持标准 glob 语法(`*`、`**`、`?`、`{a,b}` 等)。
"""
@behaviour CMDC.Tool
alias CMDC.Sandbox.Local, as: SandboxLocal
@impl true
def name, do: "glob"
@impl true
def description do
"Find files matching a glob pattern. " <>
"Supports wildcards: * (any chars), ** (any path), ? (single char), {a,b} (alternation). " <>
"Returns matching file paths relative to working_dir."
end
@impl true
def meta(%{"pattern" => pattern}), do: "glob #{pattern}"
def meta(_), do: "glob"
@impl true
def parameters do
%{
"type" => "object",
"properties" => %{
"pattern" => %{
"type" => "string",
"description" =>
"Glob pattern to match. Examples: \"**/*.ex\", \"lib/**/*.exs\", \"*.{md,txt}\"."
},
"path" => %{
"type" => "string",
"description" =>
"Base directory to search in, relative to working_dir. " <>
"Defaults to working_dir root (\".\")."
}
},
"required" => ["pattern"]
}
end
@impl true
def execute(%{"pattern" => pattern} = args, %CMDC.Context{} = ctx) do
path = Map.get(args, "path", ".")
opts = [working_dir: ctx.working_dir]
result =
if ctx.sandbox do
ctx.sandbox.glob(pattern, path, opts)
else
SandboxLocal.glob(pattern, path, opts)
end
case result do
{:ok, matches} -> {:ok, format_matches(matches, pattern)}
{:error, reason} -> {:error, reason}
end
end
def execute(_args, _ctx), do: {:error, "Missing required parameter: pattern"}
# ==========================================================================
# 私有辅助
# ==========================================================================
defp format_matches([], pattern), do: "No files matched pattern: #{pattern}"
defp format_matches(matches, pattern) do
header = "#{length(matches)} file(s) matched \"#{pattern}\":"
lines =
Enum.map(matches, fn match ->
case match.type do
:directory -> " #{match.path}/"
:file -> " #{match.path}"
end
end)
([header] ++ lines) |> Enum.join("\n")
end
end