@hilariouhiss/dsh-colgrep 1.1.0 → 1.2.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.md +4 -1
- package/lib/index.js +36 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
|---|---|---|
|
|
19
19
|
| `query` | string(必填) | 自然语言查询 |
|
|
20
20
|
| `command` | enum `search`(默认)/`init`/`status`/`clear` | 检索 / 建索引 / 查状态 / 清索引 |
|
|
21
|
-
| `
|
|
21
|
+
| `root` | string | 检索/索引哪个项目(默认工作区根;可绝对路径或相对工作区解析) |
|
|
22
|
+
| `path` | string | `root` 内的检索目标(默认整个 `root`)。注意:colgrep 会回落到项目索引,所以它是「聚焦」而非硬过滤 —— 要硬收窄请用 `include` / `pattern` |
|
|
22
23
|
| `top_k` | integer | 结果数(`-k`,默认 15) |
|
|
23
24
|
| `pattern` | string | 正则预筛(`-e`,hybrid:先 grep 再语义排序) |
|
|
24
25
|
| `include` | string | 只检索匹配 glob 的文件(`--include`,如 `"*.rs"`) |
|
|
@@ -29,7 +30,9 @@
|
|
|
29
30
|
|
|
30
31
|
- 结果以 `--json` 解析后折叠为紧凑可读文本(`文件:行-行 [语言, 类型, 名称] (score)` + 首行签名),不倾倒整段代码;模型可再 `read` 具体文件。解析兼容顶层数组与 `{results:[...]}` 两种 JSON 形状;`query` 为空或纯空白时返回明确错误。
|
|
31
32
|
- **索引重定位**:DSH 文件沙箱禁止写工作区之外,而 colgrep 检索需要写索引锁文件。插件把索引目录重定位到 `<工作区>/.colgrep-data`(通过 `COLGREP_DATA_DIR`),使全部写入落在沙箱允许范围内。ColBERT 模型与 ONNX runtime 从 `~/.cache` 只读加载,无需联网。
|
|
33
|
+
- **显式根目录**:`root` 只改变检索**运行的位置**(`workdir`),不改变索引位置 —— 索引数据始终留在 `<工作区>/.colgrep-data`,因为 colgrep 的索引是**按项目注册的**(`<data_dir>/indices/<项目名>-<hash>`),一个数据目录可以同时容纳多个项目的索引,跨项目检索不会把数据写到别人的仓库里。**真正限制结果范围的是 `root`**(换项目);`path` 相对 `root` 解析(无 `root` 时相对工作区,与旧行为一致),只做聚焦、不保证排他。
|
|
32
34
|
- 首次检索会自动建立索引(CPU 上大仓库可能需数分钟);可用 `command:"init"` 显式建索引,`no_update:true` 走现有索引。
|
|
35
|
+
- **主动使用**:注册 `colgrep:guidance` 提示词段(每回合重算,带上当前会话工作区路径),让模型在「按含义找代码、但说不出确切标识符」时优先用 `colgrep` 而不是 grep。
|
|
33
36
|
|
|
34
37
|
## 前置要求
|
|
35
38
|
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,30 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
1
2
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
2
3
|
|
|
3
4
|
export const name = "colgrep";
|
|
4
|
-
export const inject = ["tools", "shell", "sandboxPolicy"];
|
|
5
|
+
export const inject = ["tools", "shell", "sandboxPolicy", "systemPrompt"];
|
|
5
6
|
|
|
6
7
|
const LONG_PATH_PREFIX = String.fromCharCode(92, 92, 63, 92); // "\\?\"
|
|
7
8
|
|
|
8
|
-
const TOOL_DESCRIPTION = `Semantic code search over the workspace using the local colgrep CLI (ColBERT multi-vector search). Finds code by meaning, not exact text. Use a natural-language \`query\` such as "error handling for database connections". Defaults to \`search\`; the first
|
|
9
|
+
const TOOL_DESCRIPTION = `Semantic code search over the workspace using the local colgrep CLI (ColBERT multi-vector search). Finds code by meaning, not exact text. Use a natural-language \`query\` such as "error handling for database connections". Defaults to \`search\`; search auto-indexes, so the first run in a project builds the index and is slower. Use \`command:"status"\` to inspect the index, \`command:"init"\` to (re)build it explicitly, and \`no_update:true\` for a fast search over an existing index. Pass \`root\` to search a project other than the workspace, and \`path\` to narrow the search within it. Use \`pattern\` to pre-filter by regex, \`include\` to limit file types (e.g. "*.rs"), and \`code_only\` to skip text/config files.`;
|
|
10
|
+
|
|
11
|
+
const GUIDANCE = [
|
|
12
|
+
"Semantic code search is available through the `colgrep` tool. ",
|
|
13
|
+
"Reach for it when you want code by meaning and cannot name the exact identifier — grep is for text you can already spell out. ",
|
|
14
|
+
"It auto-indexes on demand, so the first search in a project is slower; use `pattern` for a regex pre-filter that ranks semantically after. ",
|
|
15
|
+
"Pass `root` to search a project other than the workspace. ",
|
|
16
|
+
].join("");
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Usage guidance carrying the current workspace, so the agent passes the right
|
|
20
|
+
* default root.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} cwd the session workspace path.
|
|
23
|
+
* @returns {string} prompt text for the colgrep guidance section.
|
|
24
|
+
*/
|
|
25
|
+
export function guidanceFor(cwd) {
|
|
26
|
+
return `${GUIDANCE} Current workspace: ${cwd}; the default root.`;
|
|
27
|
+
}
|
|
9
28
|
|
|
10
29
|
export function stripPathPrefix(path) {
|
|
11
30
|
const value = String(path);
|
|
@@ -30,9 +49,11 @@ export function buildArgs(args) {
|
|
|
30
49
|
if (args.include) argv.push("--include", args.include);
|
|
31
50
|
if (args.code_only) argv.push("--code-only");
|
|
32
51
|
argv.push(String(args.query || ""));
|
|
52
|
+
if (args.root) argv.push(String(args.root));
|
|
33
53
|
if (args.path) argv.push(args.path);
|
|
34
54
|
} else if (command === "init") {
|
|
35
55
|
argv.push("init", "-y");
|
|
56
|
+
if (args.root) argv.push(String(args.root));
|
|
36
57
|
if (args.path) argv.push(args.path);
|
|
37
58
|
} else if (command === "status") {
|
|
38
59
|
argv.push("status");
|
|
@@ -94,13 +115,20 @@ export function renderOutput(value) {
|
|
|
94
115
|
}
|
|
95
116
|
|
|
96
117
|
export function apply(ctx) {
|
|
118
|
+
ctx.systemPrompt.section({
|
|
119
|
+
name: "colgrep:guidance",
|
|
120
|
+
order: 100,
|
|
121
|
+
text: (context) => guidanceFor(context.scope?.session?.header?.cwd ?? process.cwd()),
|
|
122
|
+
});
|
|
123
|
+
|
|
97
124
|
ctx.tools.register(defineTool({
|
|
98
125
|
name: "colgrep",
|
|
99
126
|
description: TOOL_DESCRIPTION,
|
|
100
127
|
parameters: {
|
|
101
128
|
query: { type: "string", description: "Natural-language query (used by search).", required: true },
|
|
102
129
|
command: { type: "string", enum: ["search", "init", "status", "clear"], description: "Operation. search (default) finds code; init builds/updates the index; status reports index state; clear removes the index." },
|
|
103
|
-
|
|
130
|
+
root: { type: "string", description: "Project directory to search or index (default: the workspace root). Absolute or relative to the workspace." },
|
|
131
|
+
path: { type: "string", description: "File or directory of `root` to search (default: the whole root). colgrep searches this target and falls back to the project index, so it is a focus, not a hard filter — narrow with `include` or `pattern` instead." },
|
|
104
132
|
top_k: { type: "integer", description: "Number of results to return (-k). Default 15." },
|
|
105
133
|
pattern: { type: "string", description: "Regex pre-filter (-e): grep first, then rank semantically (hybrid)." },
|
|
106
134
|
include: { type: "string", description: "Only search files matching this glob (--include), e.g. \"*.rs\"." },
|
|
@@ -118,6 +146,10 @@ export function apply(ctx) {
|
|
|
118
146
|
const root = policy && typeof policy.workspaceRoot === "string" ? policy.workspaceRoot : "";
|
|
119
147
|
const base = root.replace(/[\\/]+$/, "");
|
|
120
148
|
const dataDir = base + "/.colgrep-data";
|
|
149
|
+
// `root` moves the run, never the index: index data stays inside the
|
|
150
|
+
// workspace so it remains under the sandbox policy and the same
|
|
151
|
+
// registry serves every root.
|
|
152
|
+
const workdir = args.root && base ? resolve(base, args.root) : base;
|
|
121
153
|
const command = buildArgs(args).map((part, index) => (index === 0 ? part : quoteArg(part))).join(" ");
|
|
122
154
|
const spec = ctx.shell.resolve({
|
|
123
155
|
command,
|
|
@@ -125,7 +157,7 @@ export function apply(ctx) {
|
|
|
125
157
|
stdoutMaxBytes: 2 * 1024 * 1024,
|
|
126
158
|
signal: exec.signal,
|
|
127
159
|
sandboxPolicy: policy,
|
|
128
|
-
...(
|
|
160
|
+
...(workdir ? { workdir, env: { COLGREP_DATA_DIR: dataDir } } : {}),
|
|
129
161
|
});
|
|
130
162
|
const run = await ctx.shell.run(spec);
|
|
131
163
|
const stdout = run.stdout && run.stdout.text ? run.stdout.text : "";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hilariouhiss/dsh-colgrep",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "colgrep — semantic code search (ColBERT multi-vector) for DeepSeek Harness. Adds a `colgrep` tool that finds code by meaning, not exact text.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|