promptscout 1.3.2 → 1.4.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 +98 -55
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -2
- package/dist/constants.js.map +1 -1
- package/dist/core/rewriter.js +6 -6
- package/dist/core/rewriter.js.map +1 -1
- package/dist/llm/prompts/tool-calling.d.ts +1 -1
- package/dist/llm/prompts/tool-calling.js +86 -21
- package/dist/llm/prompts/tool-calling.js.map +1 -1
- package/dist/tools/implementations.d.ts +4 -5
- package/dist/tools/implementations.js +17 -19
- package/dist/tools/implementations.js.map +1 -1
- package/dist/tools/index.d.ts +2 -20
- package/dist/tools/index.js +6 -106
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/search-utils.d.ts +2 -4
- package/dist/tools/search-utils.js +61 -43
- package/dist/tools/search-utils.js.map +1 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A CLI tool that enriches your coding agent prompts with codebase context using a
|
|
|
8
8
|
|
|
9
9
|
When you ask a coding agent like Claude Code, Cursor, or Copilot to work on your codebase, the agent spends time and tokens discovering which files matter. It greps, reads, explores, all on your dime.
|
|
10
10
|
|
|
11
|
-
promptscout does that discovery locally, for free. A small local LLM reads your prompt, searches your codebase with `
|
|
11
|
+
promptscout does that discovery locally, for free. A small local LLM reads your prompt, searches your codebase with `ripgrep` and `git`, and appends the results to your original prompt. The paid agent gets a prompt that already contains the relevant file paths, code snippets, and commit history. It can skip straight to the actual work.
|
|
12
12
|
|
|
13
13
|
Your original prompt is never modified. promptscout only appends context.
|
|
14
14
|
|
|
@@ -17,16 +17,22 @@ Your original prompt is never modified. promptscout only appends context.
|
|
|
17
17
|
```mermaid
|
|
18
18
|
flowchart LR
|
|
19
19
|
A["Raw Prompt"] --> B["Local LLM<br/>(Qwen 3 4B)"]
|
|
20
|
-
B -->|"tool calls"| C["
|
|
21
|
-
C --> D["
|
|
22
|
-
|
|
20
|
+
B -->|"tool calls"| C["ripgrep / git"]
|
|
21
|
+
C --> D["Original Prompt<br/>+ Discovered Context"]
|
|
22
|
+
|
|
23
|
+
subgraph B_ctx[" "]
|
|
24
|
+
direction TB
|
|
25
|
+
T["Project Tree<br/>(git ls-files)"]
|
|
26
|
+
end
|
|
27
|
+
T -.->|"context"| B
|
|
23
28
|
```
|
|
24
29
|
|
|
25
30
|
1. You run `promptscout "check the auth module, there might be a token refresh bug"`
|
|
26
|
-
2. The local LLM
|
|
27
|
-
3.
|
|
28
|
-
4.
|
|
29
|
-
5. The
|
|
31
|
+
2. The local LLM sees your prompt along with the project file tree (`git ls-files`) and decides which search tools to call
|
|
32
|
+
3. The LLM outputs tool calls directly as JSON (e.g. `file_finder("auth")`, `section_finder("token")`, `git_history("refresh")`)
|
|
33
|
+
4. Each tool runs against your codebase using `ripgrep` and `git`
|
|
34
|
+
5. The output is your original prompt unchanged, followed by the discovered context
|
|
35
|
+
6. The result is copied to your clipboard, ready to paste into your coding agent
|
|
30
36
|
|
|
31
37
|
## Installation
|
|
32
38
|
|
|
@@ -34,6 +40,8 @@ flowchart LR
|
|
|
34
40
|
|
|
35
41
|
- Node.js >= 20
|
|
36
42
|
- C++ compiler (Xcode Command Line Tools on macOS, `build-essential` on Linux)
|
|
43
|
+
- [ripgrep](https://github.com/BurntSushi/ripgrep) (`rg`) for fast codebase search
|
|
44
|
+
- `git` (for project tree generation and commit history search)
|
|
37
45
|
- ~3GB disk space for the model
|
|
38
46
|
|
|
39
47
|
### Install
|
|
@@ -94,13 +102,13 @@ If `promptscout` is not installed or fails for any reason, the plugin falls back
|
|
|
94
102
|
promptscout uses `Qwen 3 4B` (`Q4_K_M` quantization) running locally via [node-llama-cpp](https://github.com/withcatai/node-llama-cpp). The model uses GPU acceleration automatically when available (Metal on macOS, CUDA on Linux).
|
|
95
103
|
|
|
96
104
|
- Size: ~2.5GB (`GGUF Q4_K_M`)
|
|
97
|
-
- Context:
|
|
105
|
+
- Context: 8192 tokens
|
|
98
106
|
- Latency: ~2s per prompt (Metal, Apple Silicon)
|
|
99
|
-
- Purpose: Decides which search tools to call based on your prompt. Does not rewrite your text.
|
|
107
|
+
- Purpose: Decides which search tools to call based on your prompt and the project file tree. Does not rewrite your text.
|
|
100
108
|
|
|
101
109
|
## Tools
|
|
102
110
|
|
|
103
|
-
promptscout has 5 built-in tools
|
|
111
|
+
promptscout has 5 built-in search tools. The LLM picks which ones to call and with what keywords:
|
|
104
112
|
|
|
105
113
|
| Tool | What it does |
|
|
106
114
|
|---|---|
|
|
@@ -110,7 +118,7 @@ promptscout has 5 built-in tools that the LLM can invoke:
|
|
|
110
118
|
| `import_tracer` | Finds import/require/include statements referencing a module. |
|
|
111
119
|
| `git_history` | Finds recent commits that added or removed code matching a keyword. |
|
|
112
120
|
|
|
113
|
-
All
|
|
121
|
+
All search tools use `ripgrep`, which respects `.gitignore` and skips binary files automatically.
|
|
114
122
|
|
|
115
123
|
## Usage
|
|
116
124
|
|
|
@@ -188,26 +196,35 @@ Context from codebase:
|
|
|
188
196
|
<file_finder query="audio">
|
|
189
197
|
Sources/Core/AudioCaptureSession.swift
|
|
190
198
|
Sources/Core/AudioTapManager.swift
|
|
191
|
-
|
|
199
|
+
Sources/Info.plist
|
|
200
|
+
Sources/main.swift
|
|
201
|
+
Sources/CLI/ArgumentParser.swift
|
|
202
|
+
Sources/CLI/ExitCodes.swift
|
|
192
203
|
README.md
|
|
193
|
-
|
|
204
|
+
entitlements.plist
|
|
194
205
|
Sources/IO/RingBuffer.swift
|
|
195
|
-
|
|
196
|
-
Sources/CLI/ExitCodes.swift
|
|
206
|
+
Package.swift
|
|
197
207
|
</file_finder>
|
|
198
208
|
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
</
|
|
209
|
+
<definition_finder query="format">
|
|
210
|
+
Sources/main.swift:49: let tapFormat = tapManager.tapFormat else {
|
|
211
|
+
Sources/main.swift:53: let outputSampleRate = UInt32(tapFormat.mSampleRate)
|
|
212
|
+
Sources/main.swift:55: let sourceChannels = Int(tapFormat.mChannelsPerFrame)
|
|
213
|
+
Sources/Core/InputDeviceQuery.swift:41: var formatAddress = AudioObjectPropertyAddress(
|
|
214
|
+
Sources/Core/InputDeviceQuery.swift:46: var format = AudioStreamBasicDescription()
|
|
215
|
+
Sources/Core/AudioTapManager.swift:23: case .formatQueryFailed(let status):
|
|
216
|
+
Sources/Core/AudioTapManager.swift:34: private(set) var tapFormat: AudioStreamBasicDescription?
|
|
217
|
+
Sources/Core/AudioTapManager.swift:103: private func queryTapFormat(tapID: AudioObjectID) throws -> AudioStreamBasicDescription {
|
|
218
|
+
Sources/Core/AudioTapManager.swift:110: var format = AudioStreamBasicDescription()
|
|
219
|
+
Sources/Core/AudioTapManager.swift:112: let status = AudioObjectGetPropertyData(tapID, &address, 0, nil, &size, &format)
|
|
220
|
+
</definition_finder>
|
|
221
|
+
|
|
222
|
+
<import_tracer query="audio">
|
|
223
|
+
Sources/IO/RingBuffer.swift:39: /// Write bytes into the ring buffer. Called from the real-time audio thread.
|
|
224
|
+
README.md:13:Download the latest build from the releases page.
|
|
225
|
+
README.md:77:Record from the default microphone instead of system audio.
|
|
226
|
+
README.md:149:The included entitlements.plist declares com.apple.security.device.audio-input.
|
|
227
|
+
</import_tracer>
|
|
211
228
|
```
|
|
212
229
|
|
|
213
230
|
### TypeScript project (task management CLI)
|
|
@@ -223,25 +240,48 @@ I want to add task filtering by status and tags. check how tasks are stored and
|
|
|
223
240
|
Context from codebase:
|
|
224
241
|
|
|
225
242
|
<file_finder query="task">
|
|
243
|
+
src/services/task.ts
|
|
244
|
+
src/commands/task.ts
|
|
245
|
+
src/commands/subtask.ts
|
|
226
246
|
tests/commands/subtask.test.ts
|
|
227
247
|
tests/commands/task.test.ts
|
|
228
|
-
|
|
229
|
-
src/services/
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
248
|
+
package.json
|
|
249
|
+
src/services/epic.ts
|
|
250
|
+
README.md
|
|
251
|
+
CLAUDE.md
|
|
252
|
+
src/services/history.ts
|
|
233
253
|
</file_finder>
|
|
234
254
|
|
|
235
|
-
<
|
|
236
|
-
|
|
255
|
+
<section_finder query="status">
|
|
256
|
+
src/services/task.ts:9: TaskStatus,
|
|
257
|
+
src/services/task.ts:73: status?: TaskStatus;
|
|
258
|
+
src/services/task.ts:81: if (options?.status) {
|
|
259
|
+
src/services/task.ts:82: conditions.push(eq(tasks.status, options.status));
|
|
260
|
+
src/services/list.ts:56: if (options?.statuses && options.statuses.length > 0) {
|
|
261
|
+
src/services/list.ts:57: const placeholders = options.statuses.map(() => "?").join(", ");
|
|
262
|
+
src/services/list.ts:58: conditions.push(`status IN (${placeholders})`);
|
|
263
|
+
</section_finder>
|
|
264
|
+
|
|
265
|
+
<section_finder query="tag">
|
|
266
|
+
src/services/task.ts:56: tags: input.tags ?? null,
|
|
267
|
+
src/services/task.ts:140: if (input.tags !== undefined) updates.tags = input.tags;
|
|
268
|
+
src/commands/task.ts:29: .option("--tags <tags>", "Comma-separated tags")
|
|
269
|
+
src/commands/task.ts:91: .option("--tags <tags>", "New tags (comma-separated)")
|
|
270
|
+
</section_finder>
|
|
271
|
+
|
|
272
|
+
<definition_finder query="task">
|
|
273
|
+
src/services/task.ts:16:export function createTask(input: CreateTaskInput): Task {
|
|
274
|
+
src/services/task.ts:66:export function getTask(id: string): Task | undefined {
|
|
237
275
|
src/services/task.ts:72:export function listTasks(options?: {
|
|
276
|
+
src/services/task.ts:116:export function updateTask(id: string, input: UpdateTaskInput): Task {
|
|
238
277
|
</definition_finder>
|
|
239
278
|
|
|
240
|
-
<
|
|
241
|
-
src/
|
|
242
|
-
src/
|
|
243
|
-
src/services/
|
|
244
|
-
|
|
279
|
+
<import_tracer query="task">
|
|
280
|
+
src/services/task.ts:3:import { tasks, projects, epics } from "../db/schema";
|
|
281
|
+
src/services/comment.ts:3:import { comments, tasks } from "../db/schema";
|
|
282
|
+
src/services/dependency.ts:3:import { dependencies, tasks } from "../db/schema";
|
|
283
|
+
src/commands/task.ts:8:} from "../services/task";
|
|
284
|
+
</import_tracer>
|
|
245
285
|
```
|
|
246
286
|
|
|
247
287
|
### React/TypeScript project (terminal ebook downloader)
|
|
@@ -258,35 +298,38 @@ and find the related components
|
|
|
258
298
|
Context from codebase:
|
|
259
299
|
|
|
260
300
|
<file_finder query="search">
|
|
261
|
-
src/tui/layouts/search/search-input/SearchWarning.tsx
|
|
262
301
|
src/tui/layouts/search/search-input/SearchInput.tsx
|
|
302
|
+
src/tui/layouts/search/search-input/SearchWarning.tsx
|
|
263
303
|
src/tui/layouts/search/index.tsx
|
|
264
304
|
src/tui/layouts/search/search-input/index.tsx
|
|
265
|
-
|
|
266
|
-
|
|
305
|
+
src/options.ts
|
|
306
|
+
src/labels.ts
|
|
307
|
+
src/constants.ts
|
|
308
|
+
src/utils.ts
|
|
309
|
+
src/settings.ts
|
|
267
310
|
CLAUDE.md
|
|
268
|
-
src/tui/index.tsx
|
|
269
311
|
</file_finder>
|
|
270
312
|
|
|
271
|
-
<
|
|
272
|
-
src/
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
313
|
+
<definition_finder query="search">
|
|
314
|
+
src/api/data/document.ts:3:export async function getDocument(searchURL: string): Promise<Document> {
|
|
315
|
+
src/constants.ts:1:export const SEARCH_MIN_CHAR = 3;
|
|
316
|
+
src/settings.ts:11:export const SEARCH_PAGE_SIZE = 25;
|
|
317
|
+
src/tui/store/events.ts:31: const searchURL = get().mirrorAdapter?.getSearchURL(query, pageNumber, SEARCH_PAGE_SIZE);
|
|
318
|
+
src/tui/store/events.ts:68: const entries = await store.search(store.searchValue, store.currentPage);
|
|
319
|
+
src/tui/layouts/search/index.tsx:8:const Search: React.FC = () => {
|
|
320
|
+
</definition_finder>
|
|
278
321
|
```
|
|
279
322
|
|
|
280
|
-
###
|
|
323
|
+
### No-context detection
|
|
281
324
|
|
|
282
|
-
When the prompt
|
|
325
|
+
When the prompt has no technical keywords (pure acknowledgment), promptscout returns it unchanged:
|
|
283
326
|
|
|
284
327
|
```
|
|
285
|
-
$ promptscout "
|
|
328
|
+
$ promptscout "thanks, that works perfectly"
|
|
286
329
|
```
|
|
287
330
|
|
|
288
331
|
```
|
|
289
|
-
|
|
332
|
+
thanks, that works perfectly
|
|
290
333
|
```
|
|
291
334
|
|
|
292
335
|
## License
|
package/dist/constants.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare const MODEL_DIR: string;
|
|
|
4
4
|
export declare const MODEL_FILE_NAME = "Qwen3-4B-Q4_K_M.gguf";
|
|
5
5
|
export declare const MODEL_HF_URI: string;
|
|
6
6
|
export declare const MODEL_DOWNLOAD_URI = "hf:Qwen/Qwen3-4B-GGUF:Q4_K_M";
|
|
7
|
-
export declare const LLM_CONTEXT_SIZE =
|
|
7
|
+
export declare const LLM_CONTEXT_SIZE = 8192;
|
|
8
8
|
export declare const MODEL_HF_URI_KEY = "model_hf_uri";
|
|
9
9
|
export declare const MODEL_CONTEXT_SIZE_KEY = "model_context_size";
|
|
10
10
|
export declare const GPU_LAYERS: "auto";
|
package/dist/constants.js
CHANGED
|
@@ -7,8 +7,7 @@ export const MODEL_DIR = join(DATA_DIR, "models");
|
|
|
7
7
|
export const MODEL_FILE_NAME = "Qwen3-4B-Q4_K_M.gguf";
|
|
8
8
|
export const MODEL_HF_URI = join(MODEL_DIR, MODEL_FILE_NAME);
|
|
9
9
|
export const MODEL_DOWNLOAD_URI = "hf:Qwen/Qwen3-4B-GGUF:Q4_K_M";
|
|
10
|
-
|
|
11
|
-
export const LLM_CONTEXT_SIZE = 4096;
|
|
10
|
+
export const LLM_CONTEXT_SIZE = 8192;
|
|
12
11
|
export const MODEL_HF_URI_KEY = "model_hf_uri";
|
|
13
12
|
export const MODEL_CONTEXT_SIZE_KEY = "model_context_size";
|
|
14
13
|
// "auto" lets node-llama-cpp offload as many layers as fit in GPU/Metal memory
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;AAEvB,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AAEjE,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;AAEvB,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AAEjE,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAC/C,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAC3D,+EAA+E;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAG,MAAe,CAAC;AAE1C,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AACzC,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC"}
|
package/dist/core/rewriter.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { generate } from "../llm/inference.js";
|
|
2
2
|
import { buildToolCallingPrompt, parseToolCalls, } from "../llm/prompts/tool-calling.js";
|
|
3
|
-
import {
|
|
3
|
+
import { executeToolCall, buildProjectTree, } from "../tools/index.js";
|
|
4
4
|
const TOOL_CALLING_PARAMS = {
|
|
5
|
-
temperature: 0.
|
|
5
|
+
temperature: 0.3,
|
|
6
6
|
topP: 0.8,
|
|
7
7
|
topK: 20,
|
|
8
8
|
minP: 0.0,
|
|
@@ -19,7 +19,7 @@ function isEmptyResult(result) {
|
|
|
19
19
|
return NO_RESULT_PREFIXES.some((prefix) => result.startsWith(prefix));
|
|
20
20
|
}
|
|
21
21
|
function formatToolResult(call, result) {
|
|
22
|
-
const param = call.arguments.
|
|
22
|
+
const param = call.arguments.query;
|
|
23
23
|
return `<${call.name} query="${param}">\n${result}\n</${call.name}>`;
|
|
24
24
|
}
|
|
25
25
|
export class Rewriter {
|
|
@@ -35,15 +35,15 @@ export class Rewriter {
|
|
|
35
35
|
const contextSize = this.configRepo.getModelContextSize();
|
|
36
36
|
const searchDir = projectDir ?? process.cwd();
|
|
37
37
|
onStatus?.("Evaluating");
|
|
38
|
-
const
|
|
38
|
+
const tree = buildProjectTree(searchDir);
|
|
39
|
+
const systemPrompt = buildToolCallingPrompt(tree);
|
|
39
40
|
const raw = await generate(systemPrompt, rawPrompt, hfUri, contextSize, TOOL_CALLING_PARAMS);
|
|
40
41
|
const calls = parseToolCalls(raw);
|
|
41
42
|
if (calls.length === 0)
|
|
42
43
|
return rawPrompt;
|
|
43
|
-
const ig = loadIgnoreFilter(searchDir);
|
|
44
44
|
onStatus?.(`Running ${calls.length} tool calls`);
|
|
45
45
|
const settled = await Promise.all(calls.map(async (call) => {
|
|
46
|
-
const result = await executeToolCall(call, searchDir
|
|
46
|
+
const result = await executeToolCall(call, searchDir);
|
|
47
47
|
if (!result || isEmptyResult(result))
|
|
48
48
|
return null;
|
|
49
49
|
return formatToolResult(call, result);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewriter.js","sourceRoot":"","sources":["../../src/core/rewriter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EACL,sBAAsB,EACtB,cAAc,GACf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,
|
|
1
|
+
{"version":3,"file":"rewriter.js","sourceRoot":"","sources":["../../src/core/rewriter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ToolCall } from "../../tools/index.js";
|
|
2
|
-
export declare function buildToolCallingPrompt(
|
|
2
|
+
export declare function buildToolCallingPrompt(projectTree: string): string;
|
|
3
3
|
export declare function parseToolCalls(output: string): ToolCall[];
|
|
@@ -1,23 +1,89 @@
|
|
|
1
|
-
export function buildToolCallingPrompt(
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
- Do
|
|
1
|
+
export function buildToolCallingPrompt(projectTree) {
|
|
2
|
+
const treeBlock = projectTree
|
|
3
|
+
? `\nPROJECT TREE (hint only; you MUST still call tools):\n${projectTree}\n`
|
|
4
|
+
: "";
|
|
5
|
+
return `ROLE
|
|
6
|
+
You are a code search router. Your only job is to choose tool calls that help locate relevant code.
|
|
7
|
+
|
|
8
|
+
WHEN TO CALL TOOLS
|
|
9
|
+
- If the user message is technical (intent to inspect/modify code; mentions code, bug, feature, module, API, config, build, test, error, stacktrace): output 3 to 5 tool CALLS.
|
|
10
|
+
- If non-technical (e.g. "thanks", "ok", greetings, small talk) OR no intent to inspect code: output [].
|
|
11
|
+
|
|
12
|
+
OUTPUT (STRICT)
|
|
13
|
+
- Output ONLY a JSON array. No extra text.
|
|
14
|
+
- Use double quotes. No trailing commas.
|
|
15
|
+
- Format: [{"name":"tool","arguments":{"query":"keyword"}}]
|
|
16
|
+
|
|
17
|
+
KEYWORDS (STRICT)
|
|
18
|
+
- query must be ONE token: lowercase a-z0-9 only, 2-16 chars, no spaces, no punctuation.
|
|
19
|
+
- Prefer file/path-ish roots and domain nouns: auth, user, config, cache, redis, route, middleware, upload, webhook, socket, retry.
|
|
20
|
+
- Do not repeat the exact same (tool, query) pair.
|
|
21
|
+
- Prefer different queries across calls (broad coverage).
|
|
22
|
+
|
|
23
|
+
ALLOWED TOOLS (STRICT)
|
|
24
|
+
- Only use these names: file_finder, section_finder, definition_finder, import_tracer, git_history.
|
|
25
|
+
|
|
26
|
+
TOOLS
|
|
27
|
+
1) file_finder(query) REQUIRED in every technical response, and MUST be first.
|
|
28
|
+
2) section_finder(query) usage/call sites, string matches, error codes
|
|
29
|
+
3) definition_finder(query) where functions/types/classes are defined
|
|
30
|
+
4) import_tracer(query) who imports/uses a module/package
|
|
31
|
+
5) git_history(query) recent changes related to a keyword
|
|
32
|
+
|
|
33
|
+
SELECTION RULES (DETERMINISTIC)
|
|
34
|
+
- Always start: file_finder(main_topic)
|
|
35
|
+
- Use exactly 1 file_finder in most cases.
|
|
36
|
+
- Use 2 file_finder calls only if the user clearly mentions 2+ distinct topics.
|
|
37
|
+
- Then add 2-4 more calls using DIFFERENT queries to cover:
|
|
38
|
+
|
|
39
|
+
Definitions:
|
|
40
|
+
- "where is X defined?" -> definition_finder(x) + section_finder(x)
|
|
41
|
+
|
|
42
|
+
Usage/call sites:
|
|
43
|
+
- "where is X used/called?" -> section_finder(x) + import_tracer(x)
|
|
44
|
+
|
|
45
|
+
Bugs/regressions/recent change:
|
|
46
|
+
- mention of bug/regression/recent -> git_history(core_keyword) + section_finder(core_keyword)
|
|
47
|
+
|
|
48
|
+
Dependencies/module usage:
|
|
49
|
+
- "who uses module Y?" -> import_tracer(y) + section_finder(y)
|
|
50
|
+
|
|
51
|
+
Error codes / log tokens:
|
|
52
|
+
- if the user includes codes like EPIPE, ECONNRESET, ACCESSDENIED -> add section_finder(normalizedtoken)
|
|
53
|
+
|
|
54
|
+
NON-TECHNICAL = []
|
|
55
|
+
- Output [] only if there is no intent to inspect/modify code AND none of these appear:
|
|
56
|
+
error, bug, crash, stack, trace, build, deploy, ci, test, config, api, module.
|
|
57
|
+
|
|
58
|
+
COVERAGE BOOST (CHEF TOUCH)
|
|
59
|
+
- If array length is 4 or 5:
|
|
60
|
+
- Repeat EXACTLY ONE tool name once (so one tool appears twice).
|
|
61
|
+
- The repeated tool must use a DIFFERENT query (alt keyword).
|
|
62
|
+
- Prefer repeating section_finder or file_finder.
|
|
63
|
+
- If array length is 3: repetition is optional.
|
|
64
|
+
|
|
65
|
+
ALT KEYWORD RULE (FOR REPEATS)
|
|
66
|
+
- When you repeat a tool, pick an alt query that is closely related:
|
|
67
|
+
- short synonym/abbrev: auth->login, socket->ws, config->env, route->router, middleware->guard
|
|
68
|
+
- neighboring component: upload->s3, cache->redis, queue->job, db->sql
|
|
69
|
+
- Still obey query regex /^[a-z0-9]{2,16}$/ and keep queries distinct.
|
|
70
|
+
|
|
71
|
+
FINAL CHECK (MUST PASS)
|
|
72
|
+
- Output is a JSON array only.
|
|
73
|
+
- Array length is 0 OR between 3 and 5.
|
|
74
|
+
- If length > 0: first item name is "file_finder".
|
|
75
|
+
- Every query matches /^[a-z0-9]{2,16}$/.
|
|
76
|
+
- No duplicate (name, query) pairs.
|
|
77
|
+
- At least 3 distinct queries when length is 3-5.
|
|
78
|
+
- If length is 4-5:
|
|
79
|
+
- At least one tool name appears twice.
|
|
80
|
+
- At least 4 distinct queries total.
|
|
81
|
+
- No tool name appears more than twice.
|
|
82
|
+
|
|
83
|
+
EXAMPLE
|
|
84
|
+
User: "fix websocket reconnection bug"
|
|
85
|
+
[{"name":"file_finder","arguments":{"query":"websocket"}},{"name":"section_finder","arguments":{"query":"reconnect"}},{"name":"section_finder","arguments":{"query":"retry"}},{"name":"definition_finder","arguments":{"query":"socket"}},{"name":"git_history","arguments":{"query":"reconnect"}}]
|
|
86
|
+
${treeBlock}`;
|
|
21
87
|
}
|
|
22
88
|
export function parseToolCalls(output) {
|
|
23
89
|
const cleaned = output
|
|
@@ -31,7 +97,6 @@ export function parseToolCalls(output) {
|
|
|
31
97
|
return [];
|
|
32
98
|
}
|
|
33
99
|
catch {
|
|
34
|
-
// Fallback: extract JSON array from mixed output
|
|
35
100
|
const match = cleaned.match(/\[[\s\S]*\]/);
|
|
36
101
|
if (match) {
|
|
37
102
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-calling.js","sourceRoot":"","sources":["../../../src/llm/prompts/tool-calling.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,sBAAsB,CAAC,
|
|
1
|
+
{"version":3,"file":"tool-calling.js","sourceRoot":"","sources":["../../../src/llm/prompts/tool-calling.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,MAAM,SAAS,GAAG,WAAW;QAC3B,CAAC,CAAC,2DAA2D,WAAW,IAAI;QAC5E,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiFP,SAAS,EAAE,CAAC;AACd,CAAC;AAGD,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,OAAO,GAAG,MAAM;SACnB,IAAI,EAAE;SACN,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC;SACxC,IAAI,EAAE,CAAC;IAEV,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACzC,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC3C,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function importTracer(query: string, dir: string, ig: Ignore): string;
|
|
1
|
+
export declare function fileFinder(query: string, dir: string): string;
|
|
2
|
+
export declare function sectionFinder(query: string, dir: string): string;
|
|
3
|
+
export declare function definitionFinder(query: string, dir: string): string;
|
|
4
|
+
export declare function importTracer(query: string, dir: string): string;
|
|
6
5
|
export declare function gitHistory(query: string, dir: string): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { escapeRegex,
|
|
1
|
+
import { escapeRegex, stripDirPrefix, rgSync, gitSync, } from "./search-utils.js";
|
|
2
2
|
const MAX_FILES = 10;
|
|
3
3
|
const MAX_LINES = 20;
|
|
4
4
|
const MAX_COMMITS = 10;
|
|
@@ -22,54 +22,52 @@ function scoreFilePath(filePath, lowerQuery) {
|
|
|
22
22
|
score += 1;
|
|
23
23
|
return score;
|
|
24
24
|
}
|
|
25
|
-
export function fileFinder(query, dir
|
|
25
|
+
export function fileFinder(query, dir) {
|
|
26
26
|
const escaped = escapeRegex(query);
|
|
27
|
-
const output =
|
|
27
|
+
const output = rgSync(["-li", escaped], dir);
|
|
28
28
|
if (!output)
|
|
29
29
|
return "No matching files found.";
|
|
30
|
-
const
|
|
31
|
-
if (filtered.length === 0)
|
|
32
|
-
return "No matching files found.";
|
|
30
|
+
const lines = output.split("\n").filter(Boolean);
|
|
33
31
|
const lowerQuery = query.toLowerCase();
|
|
34
|
-
const scored =
|
|
32
|
+
const scored = lines
|
|
35
33
|
.map((l) => ({ path: stripDirPrefix(l, dir), score: scoreFilePath(l, lowerQuery) }))
|
|
36
34
|
.sort((a, b) => b.score - a.score)
|
|
37
35
|
.slice(0, MAX_FILES);
|
|
38
36
|
return scored.map((s) => s.path).join("\n");
|
|
39
37
|
}
|
|
40
|
-
export function sectionFinder(query, dir
|
|
38
|
+
export function sectionFinder(query, dir) {
|
|
41
39
|
const escaped = escapeRegex(query);
|
|
42
|
-
const output =
|
|
40
|
+
const output = rgSync(["-ni", escaped], dir);
|
|
43
41
|
if (!output)
|
|
44
42
|
return "No matching code found.";
|
|
45
|
-
const
|
|
46
|
-
if (filtered.length === 0)
|
|
47
|
-
return "No matching code found.";
|
|
43
|
+
const lines = output.split("\n").filter(Boolean);
|
|
48
44
|
const lowerQuery = query.toLowerCase();
|
|
49
|
-
const scored =
|
|
45
|
+
const scored = lines
|
|
50
46
|
.map((l) => ({ line: stripDirPrefix(l, dir), score: scoreFilePath(l, lowerQuery) }))
|
|
51
47
|
.sort((a, b) => b.score - a.score)
|
|
52
48
|
.slice(0, MAX_LINES);
|
|
53
49
|
return scored.map((s) => s.line).join("\n");
|
|
54
50
|
}
|
|
55
|
-
export function definitionFinder(query, dir
|
|
56
|
-
const output =
|
|
51
|
+
export function definitionFinder(query, dir) {
|
|
52
|
+
const output = rgSync(["-n", DEFINITION_PATTERN], dir);
|
|
57
53
|
if (!output)
|
|
58
54
|
return "No definitions found.";
|
|
59
55
|
const lowerQuery = query.toLowerCase();
|
|
60
|
-
const filtered =
|
|
56
|
+
const filtered = output
|
|
57
|
+
.split("\n")
|
|
58
|
+
.filter(Boolean)
|
|
61
59
|
.filter((line) => line.toLowerCase().includes(lowerQuery))
|
|
62
60
|
.slice(0, MAX_LINES);
|
|
63
61
|
if (filtered.length === 0)
|
|
64
62
|
return "No matching definitions found.";
|
|
65
63
|
return filtered.map((l) => stripDirPrefix(l, dir)).join("\n");
|
|
66
64
|
}
|
|
67
|
-
export function importTracer(query, dir
|
|
65
|
+
export function importTracer(query, dir) {
|
|
68
66
|
const escaped = escapeRegex(query);
|
|
69
|
-
const output =
|
|
67
|
+
const output = rgSync(["-n", `(import|from|require|include|use).*${escaped}`], dir);
|
|
70
68
|
if (!output)
|
|
71
69
|
return "No matching imports found.";
|
|
72
|
-
const lines =
|
|
70
|
+
const lines = output.split("\n").filter(Boolean).slice(0, MAX_LINES);
|
|
73
71
|
if (lines.length === 0)
|
|
74
72
|
return "No matching imports found.";
|
|
75
73
|
return lines.map((l) => stripDirPrefix(l, dir)).join("\n");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implementations.js","sourceRoot":"","sources":["../../src/tools/implementations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"implementations.js","sourceRoot":"","sources":["../../src/tools/implementations.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export { loadIgnoreFilter } from "./search-utils.js";
|
|
1
|
+
export { buildProjectTree } from "./search-utils.js";
|
|
3
2
|
export interface ToolCall {
|
|
4
3
|
name: string;
|
|
5
4
|
arguments: Record<string, string>;
|
|
6
5
|
}
|
|
7
|
-
export declare function executeToolCall(call: ToolCall, dir: string
|
|
8
|
-
export declare const TOOL_DEFINITIONS: {
|
|
9
|
-
type: string;
|
|
10
|
-
function: {
|
|
11
|
-
name: string;
|
|
12
|
-
description: string;
|
|
13
|
-
parameters: {
|
|
14
|
-
type: string;
|
|
15
|
-
properties: {
|
|
16
|
-
query: {
|
|
17
|
-
type: string;
|
|
18
|
-
description: string;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
required: string[];
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
}[];
|
|
6
|
+
export declare function executeToolCall(call: ToolCall, dir: string): Promise<string>;
|
package/dist/tools/index.js
CHANGED
|
@@ -1,119 +1,19 @@
|
|
|
1
1
|
import { fileFinder, sectionFinder, definitionFinder, importTracer, gitHistory, } from "./implementations.js";
|
|
2
|
-
export {
|
|
3
|
-
export async function executeToolCall(call, dir
|
|
2
|
+
export { buildProjectTree } from "./search-utils.js";
|
|
3
|
+
export async function executeToolCall(call, dir) {
|
|
4
4
|
switch (call.name) {
|
|
5
5
|
case "file_finder":
|
|
6
|
-
return fileFinder(call.arguments.query, dir
|
|
6
|
+
return fileFinder(call.arguments.query, dir);
|
|
7
7
|
case "section_finder":
|
|
8
|
-
return sectionFinder(call.arguments.query, dir
|
|
8
|
+
return sectionFinder(call.arguments.query, dir);
|
|
9
9
|
case "definition_finder":
|
|
10
|
-
return definitionFinder(call.arguments.query, dir
|
|
10
|
+
return definitionFinder(call.arguments.query, dir);
|
|
11
11
|
case "import_tracer":
|
|
12
|
-
return importTracer(call.arguments.query, dir
|
|
12
|
+
return importTracer(call.arguments.query, dir);
|
|
13
13
|
case "git_history":
|
|
14
14
|
return gitHistory(call.arguments.query, dir);
|
|
15
15
|
default:
|
|
16
16
|
return `Unknown tool: ${call.name}`;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
export const TOOL_DEFINITIONS = [
|
|
20
|
-
{
|
|
21
|
-
type: "function",
|
|
22
|
-
function: {
|
|
23
|
-
name: "file_finder",
|
|
24
|
-
description: "Find files matching a keyword. Returns file paths. " +
|
|
25
|
-
"Pair with section_finder using a different keyword to also get code snippets.",
|
|
26
|
-
parameters: {
|
|
27
|
-
type: "object",
|
|
28
|
-
properties: {
|
|
29
|
-
query: {
|
|
30
|
-
type: "string",
|
|
31
|
-
description: "A single keyword to search for in file contents. Use concise, specific terms " +
|
|
32
|
-
"(e.g., 'camera', 'auth', 'Router'). Avoid multi-word phrases.",
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
required: ["query"],
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
type: "function",
|
|
41
|
-
function: {
|
|
42
|
-
name: "section_finder",
|
|
43
|
-
description: "Find code snippets matching a keyword. Returns file:line:code entries. " +
|
|
44
|
-
"Use alongside file_finder with a different keyword for complete context.",
|
|
45
|
-
parameters: {
|
|
46
|
-
type: "object",
|
|
47
|
-
properties: {
|
|
48
|
-
query: {
|
|
49
|
-
type: "string",
|
|
50
|
-
description: "A single keyword to find in source code. Use specific identifiers " +
|
|
51
|
-
"(e.g., 'handleSubmit', 'CameraView', 'fetchUser'). Case-insensitive.",
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
required: ["query"],
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
type: "function",
|
|
60
|
-
function: {
|
|
61
|
-
name: "definition_finder",
|
|
62
|
-
description: "Find function, class, type, interface, struct, enum, and other definition declarations " +
|
|
63
|
-
"matching a keyword. Works across languages (JS/TS, Python, Go, Rust, Swift, Ruby, Java). " +
|
|
64
|
-
"Returns up to 15 results. Use this to find where something is defined, not where it is used.",
|
|
65
|
-
parameters: {
|
|
66
|
-
type: "object",
|
|
67
|
-
properties: {
|
|
68
|
-
query: {
|
|
69
|
-
type: "string",
|
|
70
|
-
description: "A single keyword matching the name of a function, class, type, or other definition " +
|
|
71
|
-
"(e.g., 'Camera', 'UserService', 'parse_config'). Case-insensitive.",
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
required: ["query"],
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
type: "function",
|
|
80
|
-
function: {
|
|
81
|
-
name: "import_tracer",
|
|
82
|
-
description: "Find import, require, include, and use statements that reference a module or keyword. " +
|
|
83
|
-
"Shows the dependency graph — which files depend on the given module. " +
|
|
84
|
-
"Returns up to 15 results. Use this to understand how modules are connected.",
|
|
85
|
-
parameters: {
|
|
86
|
-
type: "object",
|
|
87
|
-
properties: {
|
|
88
|
-
query: {
|
|
89
|
-
type: "string",
|
|
90
|
-
description: "A module name or keyword to search for in import statements " +
|
|
91
|
-
"(e.g., 'camera', 'utils', 'express'). Case-sensitive for import paths.",
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
required: ["query"],
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
type: "function",
|
|
100
|
-
function: {
|
|
101
|
-
name: "git_history",
|
|
102
|
-
description: "Search git commit history for the 10 most recent commits that added or removed " +
|
|
103
|
-
"code containing the given keyword. Use this when the user references a recent change, " +
|
|
104
|
-
"regression, or wants to understand what changed recently related to a topic.",
|
|
105
|
-
parameters: {
|
|
106
|
-
type: "object",
|
|
107
|
-
properties: {
|
|
108
|
-
query: {
|
|
109
|
-
type: "string",
|
|
110
|
-
description: "A keyword to search in commit diffs (e.g., 'camera', 'auth'). " +
|
|
111
|
-
"Git searches for commits where this string was added or removed.",
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
required: ["query"],
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
];
|
|
119
19
|
//# sourceMappingURL=index.js.map
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAOrD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAc,EACd,GAAW;IAEX,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,KAAK,gBAAgB;YACnB,OAAO,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAClD,KAAK,mBAAmB;YACtB,OAAO,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACrD,KAAK,eAAe;YAClB,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACjD,KAAK,aAAa;YAChB,OAAO,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C;YACE,OAAO,iBAAiB,IAAI,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;AACH,CAAC"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { type Ignore } from "ignore";
|
|
2
1
|
export declare function escapeRegex(str: string): string;
|
|
3
|
-
export declare function loadIgnoreFilter(dir: string): Ignore;
|
|
4
|
-
export declare function filterLines(lines: string[], dir: string, ig: Ignore): string[];
|
|
5
2
|
export declare function stripDirPrefix(line: string, dir: string): string;
|
|
6
|
-
export declare function
|
|
3
|
+
export declare function rgSync(args: string[], cwd: string): string;
|
|
7
4
|
export declare function gitSync(args: string[], cwd: string): string;
|
|
5
|
+
export declare function buildProjectTree(dir: string): string;
|
|
@@ -1,55 +1,18 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
-
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import ignore from "ignore";
|
|
5
|
-
const GREP_TIMEOUT = 5_000;
|
|
2
|
+
const RG_TIMEOUT = 5_000;
|
|
6
3
|
const GIT_TIMEOUT = 5_000;
|
|
7
|
-
// Hardcoded for grep traversal performance only.
|
|
8
|
-
// .git is never in .gitignore (git handles it internally).
|
|
9
|
-
// node_modules is virtually always gitignored and huge.
|
|
10
|
-
// -I: skip binary files (images, fonts, compiled assets)
|
|
11
|
-
// --exclude-dir: skip dirs that are huge and almost always irrelevant
|
|
12
|
-
const BASE_GREP_FLAGS = [
|
|
13
|
-
"-I",
|
|
14
|
-
"-D", "skip",
|
|
15
|
-
"--exclude-dir", ".git",
|
|
16
|
-
"--exclude-dir", "node_modules",
|
|
17
|
-
];
|
|
18
4
|
export function escapeRegex(str) {
|
|
19
5
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
20
6
|
}
|
|
21
|
-
export function loadIgnoreFilter(dir) {
|
|
22
|
-
const ig = ignore();
|
|
23
|
-
try {
|
|
24
|
-
const content = readFileSync(join(dir, ".gitignore"), "utf-8");
|
|
25
|
-
ig.add(content);
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
// No .gitignore — no extra filtering
|
|
29
|
-
}
|
|
30
|
-
return ig;
|
|
31
|
-
}
|
|
32
|
-
function extractRelativePath(line, dir) {
|
|
33
|
-
const relative = line.startsWith(dir + "/")
|
|
34
|
-
? line.slice(dir.length + 1)
|
|
35
|
-
: line;
|
|
36
|
-
const match = relative.match(/^(.+?):\d+:/);
|
|
37
|
-
return match ? match[1] : relative;
|
|
38
|
-
}
|
|
39
|
-
export function filterLines(lines, dir, ig) {
|
|
40
|
-
return lines.filter((line) => {
|
|
41
|
-
const rel = extractRelativePath(line, dir);
|
|
42
|
-
return !ig.ignores(rel);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
7
|
export function stripDirPrefix(line, dir) {
|
|
46
|
-
return line.replace(dir + "/", "");
|
|
8
|
+
return line.replace(dir + "/", "").replace(/^\.\//, "");
|
|
47
9
|
}
|
|
48
|
-
export function
|
|
10
|
+
export function rgSync(args, cwd) {
|
|
49
11
|
try {
|
|
50
|
-
|
|
12
|
+
// Explicit "." prevents rg from reading stdin when spawned by Node.js
|
|
13
|
+
return execFileSync("rg", [...args, "."], {
|
|
51
14
|
cwd,
|
|
52
|
-
timeout:
|
|
15
|
+
timeout: RG_TIMEOUT,
|
|
53
16
|
encoding: "utf-8",
|
|
54
17
|
maxBuffer: 1024 * 1024,
|
|
55
18
|
}).trim();
|
|
@@ -71,4 +34,59 @@ export function gitSync(args, cwd) {
|
|
|
71
34
|
return "";
|
|
72
35
|
}
|
|
73
36
|
}
|
|
37
|
+
const MAX_TREE_LINES = 80;
|
|
38
|
+
const MAX_TREE_DEPTH = 4;
|
|
39
|
+
export function buildProjectTree(dir) {
|
|
40
|
+
const output = gitSync(["ls-files"], dir);
|
|
41
|
+
if (!output)
|
|
42
|
+
return "";
|
|
43
|
+
const files = output.split("\n").filter(Boolean);
|
|
44
|
+
// Build nested map from flat file paths
|
|
45
|
+
const tree = new Map();
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
const parts = file.split("/");
|
|
48
|
+
let current = tree;
|
|
49
|
+
for (let i = 0; i < parts.length; i++) {
|
|
50
|
+
const part = parts[i];
|
|
51
|
+
if (i === parts.length - 1) {
|
|
52
|
+
current.set(part, null);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
if (!current.has(part))
|
|
56
|
+
current.set(part, new Map());
|
|
57
|
+
current = current.get(part);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const lines = [];
|
|
62
|
+
function render(node, indent, depth) {
|
|
63
|
+
if (lines.length >= MAX_TREE_LINES || depth > MAX_TREE_DEPTH)
|
|
64
|
+
return;
|
|
65
|
+
const entries = [...node.entries()].sort(([, av], [, bv]) => {
|
|
66
|
+
const aDir = av instanceof Map;
|
|
67
|
+
const bDir = bv instanceof Map;
|
|
68
|
+
if (aDir && !bDir)
|
|
69
|
+
return -1;
|
|
70
|
+
if (!aDir && bDir)
|
|
71
|
+
return 1;
|
|
72
|
+
return 0;
|
|
73
|
+
});
|
|
74
|
+
for (const [name, value] of entries) {
|
|
75
|
+
if (lines.length >= MAX_TREE_LINES)
|
|
76
|
+
break;
|
|
77
|
+
if (value instanceof Map) {
|
|
78
|
+
lines.push(`${indent}${name}/`);
|
|
79
|
+
render(value, indent + " ", depth + 1);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
lines.push(`${indent}${name}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
render(tree, "", 0);
|
|
87
|
+
if (files.length > lines.length) {
|
|
88
|
+
lines.push(`... (${files.length} files total)`);
|
|
89
|
+
}
|
|
90
|
+
return lines.join("\n");
|
|
91
|
+
}
|
|
74
92
|
//# sourceMappingURL=search-utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-utils.js","sourceRoot":"","sources":["../../src/tools/search-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"search-utils.js","sourceRoot":"","sources":["../../src/tools/search-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,GAAG,KAAK,CAAC;AACzB,MAAM,WAAW,GAAG,KAAK,CAAC;AAE1B,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,GAAW;IACtD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAc,EAAE,GAAW;IAChD,IAAI,CAAC;QACH,sEAAsE;QACtE,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE;YACxC,GAAG;YACH,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,IAAI,GAAG,IAAI;SACvB,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAc,EAAE,GAAW;IACjD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;YAC/B,GAAG;YACH,OAAO,EAAE,WAAW;YACpB,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,IAAI,GAAG,IAAI;SACvB,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjD,wCAAwC;IACxC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;gBACrD,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAyB,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,MAAM,CAAC,IAA0B,EAAE,MAAc,EAAE,KAAa;QACvE,IAAI,KAAK,CAAC,MAAM,IAAI,cAAc,IAAI,KAAK,GAAG,cAAc;YAAE,OAAO;QAErE,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;YAC1D,MAAM,IAAI,GAAG,EAAE,YAAY,GAAG,CAAC;YAC/B,MAAM,IAAI,GAAG,EAAE,YAAY,GAAG,CAAC;YAC/B,IAAI,IAAI,IAAI,CAAC,IAAI;gBAAE,OAAO,CAAC,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI,IAAI,IAAI;gBAAE,OAAO,CAAC,CAAC;YAC5B,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,MAAM,IAAI,cAAc;gBAAE,MAAM;YAC1C,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC;gBAChC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAEpB,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,eAAe,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "promptscout",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Enrich coding agent prompts with codebase context using a local LLM",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
"clipboardy": "^5.2.1",
|
|
51
51
|
"commander": "^14.0.3",
|
|
52
52
|
"drizzle-orm": "^0.45.1",
|
|
53
|
-
"ignore": "^7.0.5",
|
|
54
53
|
"node-llama-cpp": "^3.15.1",
|
|
55
54
|
"ora": "^9.3.0"
|
|
56
55
|
},
|