@probelabs/probe 0.6.0-rc308 → 0.6.0-rc309
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 +25 -0
- package/bin/binaries/{probe-v0.6.0-rc308-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc309-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc308-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc309-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc308-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc309-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc308-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc309-x86_64-pc-windows-msvc.zip} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc308-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc309-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.js +12 -2
- package/build/agent/probeTool.js +9 -0
- package/build/agent/shared/prompts.js +4 -1
- package/build/agent/tools.js +6 -0
- package/build/index.js +6 -1
- package/build/symbols.js +86 -0
- package/build/tools/common.js +4 -0
- package/build/tools/index.js +2 -1
- package/build/tools/system-message.js +4 -0
- package/build/tools/vercel.js +36 -1
- package/cjs/agent/ProbeAgent.cjs +167 -29
- package/cjs/index.cjs +175 -29
- package/index.d.ts +63 -0
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +12 -2
- package/src/agent/probeTool.js +9 -0
- package/src/agent/shared/prompts.js +4 -1
- package/src/agent/tools.js +6 -0
- package/src/index.js +6 -1
- package/src/symbols.js +86 -0
- package/src/tools/common.js +4 -0
- package/src/tools/index.js +2 -1
- package/src/tools/system-message.js +4 -0
- package/src/tools/vercel.js +36 -1
package/cjs/index.cjs
CHANGED
|
@@ -2187,6 +2187,70 @@ var init_extract = __esm({
|
|
|
2187
2187
|
}
|
|
2188
2188
|
});
|
|
2189
2189
|
|
|
2190
|
+
// src/symbols.js
|
|
2191
|
+
async function symbols(options) {
|
|
2192
|
+
if (!options) {
|
|
2193
|
+
throw new Error("Options object is required");
|
|
2194
|
+
}
|
|
2195
|
+
if (!options.files || !Array.isArray(options.files) || options.files.length === 0) {
|
|
2196
|
+
throw new Error("At least one file path is required");
|
|
2197
|
+
}
|
|
2198
|
+
const binaryPath = await getBinaryPath(options.binaryOptions || {});
|
|
2199
|
+
const cwd = await validateCwdPath(options.cwd);
|
|
2200
|
+
const args = ["symbols", "--format", "json"];
|
|
2201
|
+
if (options.allowTests) {
|
|
2202
|
+
args.push("--allow-tests");
|
|
2203
|
+
}
|
|
2204
|
+
for (const file2 of options.files) {
|
|
2205
|
+
args.push(escapeString(file2));
|
|
2206
|
+
}
|
|
2207
|
+
if (process.env.DEBUG === "1") {
|
|
2208
|
+
console.error(`
|
|
2209
|
+
Symbols: files="${options.files.join(", ")}" cwd="${cwd}"`);
|
|
2210
|
+
}
|
|
2211
|
+
return new Promise((resolve9, reject2) => {
|
|
2212
|
+
const childProcess = (0, import_child_process5.spawn)(binaryPath, args, {
|
|
2213
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
2214
|
+
cwd
|
|
2215
|
+
});
|
|
2216
|
+
let stdout = "";
|
|
2217
|
+
let stderr = "";
|
|
2218
|
+
childProcess.stdout.on("data", (data2) => {
|
|
2219
|
+
stdout += data2.toString();
|
|
2220
|
+
});
|
|
2221
|
+
childProcess.stderr.on("data", (data2) => {
|
|
2222
|
+
stderr += data2.toString();
|
|
2223
|
+
});
|
|
2224
|
+
childProcess.on("close", (code) => {
|
|
2225
|
+
if (stderr && process.env.DEBUG === "1") {
|
|
2226
|
+
console.error(`stderr: ${stderr}`);
|
|
2227
|
+
}
|
|
2228
|
+
if (code !== 0) {
|
|
2229
|
+
reject2(new Error(`Symbols command failed with exit code ${code}: ${stderr}`));
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2232
|
+
try {
|
|
2233
|
+
const result = JSON.parse(stdout);
|
|
2234
|
+
resolve9(result);
|
|
2235
|
+
} catch (error40) {
|
|
2236
|
+
reject2(new Error(`Failed to parse symbols output: ${error40.message}. Output: ${stdout.substring(0, 200)}`));
|
|
2237
|
+
}
|
|
2238
|
+
});
|
|
2239
|
+
childProcess.on("error", (error40) => {
|
|
2240
|
+
reject2(new Error(`Failed to spawn symbols process: ${error40.message}`));
|
|
2241
|
+
});
|
|
2242
|
+
});
|
|
2243
|
+
}
|
|
2244
|
+
var import_child_process5;
|
|
2245
|
+
var init_symbols = __esm({
|
|
2246
|
+
"src/symbols.js"() {
|
|
2247
|
+
"use strict";
|
|
2248
|
+
import_child_process5 = require("child_process");
|
|
2249
|
+
init_utils();
|
|
2250
|
+
init_path_validation();
|
|
2251
|
+
}
|
|
2252
|
+
});
|
|
2253
|
+
|
|
2190
2254
|
// src/grep.js
|
|
2191
2255
|
async function grep(options) {
|
|
2192
2256
|
if (!options || !options.pattern) {
|
|
@@ -2230,14 +2294,14 @@ async function grep(options) {
|
|
|
2230
2294
|
throw new Error(`Grep failed: ${errorMessage}`);
|
|
2231
2295
|
}
|
|
2232
2296
|
}
|
|
2233
|
-
var
|
|
2297
|
+
var import_child_process6, import_util5, execFileAsync2, GREP_FLAG_MAP;
|
|
2234
2298
|
var init_grep = __esm({
|
|
2235
2299
|
"src/grep.js"() {
|
|
2236
2300
|
"use strict";
|
|
2237
|
-
|
|
2301
|
+
import_child_process6 = require("child_process");
|
|
2238
2302
|
import_util5 = require("util");
|
|
2239
2303
|
init_utils();
|
|
2240
|
-
execFileAsync2 = (0, import_util5.promisify)(
|
|
2304
|
+
execFileAsync2 = (0, import_util5.promisify)(import_child_process6.execFile);
|
|
2241
2305
|
GREP_FLAG_MAP = {
|
|
2242
2306
|
ignoreCase: "-i",
|
|
2243
2307
|
lineNumbers: "-n",
|
|
@@ -27645,6 +27709,9 @@ function createTools(configOptions) {
|
|
|
27645
27709
|
if (isToolAllowed("extract")) {
|
|
27646
27710
|
tools2.extractTool = extractTool(configOptions);
|
|
27647
27711
|
}
|
|
27712
|
+
if (isToolAllowed("symbols")) {
|
|
27713
|
+
tools2.symbolsTool = symbolsTool(configOptions);
|
|
27714
|
+
}
|
|
27648
27715
|
if (configOptions.enableDelegate && isToolAllowed("delegate")) {
|
|
27649
27716
|
tools2.delegateTool = delegateTool(configOptions);
|
|
27650
27717
|
}
|
|
@@ -27813,7 +27880,7 @@ function resolveTargetPath(target, cwd) {
|
|
|
27813
27880
|
}
|
|
27814
27881
|
return filePart + suffix;
|
|
27815
27882
|
}
|
|
27816
|
-
var import_path6, searchDelegateSchema, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, listFilesSchema, searchFilesSchema, readImageSchema, readMediaSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, searchDescription, searchDelegateDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription;
|
|
27883
|
+
var import_path6, searchDelegateSchema, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, listFilesSchema, searchFilesSchema, readImageSchema, readMediaSchema, symbolsSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, searchDescription, searchDelegateDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription;
|
|
27817
27884
|
var init_common = __esm({
|
|
27818
27885
|
"src/tools/common.js"() {
|
|
27819
27886
|
"use strict";
|
|
@@ -27872,6 +27939,9 @@ var init_common = __esm({
|
|
|
27872
27939
|
readMediaSchema = external_exports2.object({
|
|
27873
27940
|
path: external_exports2.string().describe("Path to the media file to read. Supports images (png, jpg, jpeg, webp, bmp, svg) and documents (pdf).")
|
|
27874
27941
|
});
|
|
27942
|
+
symbolsSchema = external_exports2.object({
|
|
27943
|
+
file: external_exports2.string().describe("Path to the file to list symbols from. Returns a hierarchical tree of functions, classes, structs, constants, etc. with line numbers and nesting (e.g., methods inside classes/impl blocks).")
|
|
27944
|
+
});
|
|
27875
27945
|
bashSchema = external_exports2.object({
|
|
27876
27946
|
command: external_exports2.string().describe("The bash command to execute"),
|
|
27877
27947
|
workingDirectory: external_exports2.string().optional().describe("Directory to execute the command in (optional)"),
|
|
@@ -35281,14 +35351,21 @@ function createWrappedTools(baseTools) {
|
|
|
35281
35351
|
baseTools.multiEditTool.execute
|
|
35282
35352
|
);
|
|
35283
35353
|
}
|
|
35354
|
+
if (baseTools.symbolsTool) {
|
|
35355
|
+
wrappedTools.symbolsToolInstance = wrapToolWithEmitter(
|
|
35356
|
+
baseTools.symbolsTool,
|
|
35357
|
+
"symbols",
|
|
35358
|
+
baseTools.symbolsTool.execute
|
|
35359
|
+
);
|
|
35360
|
+
}
|
|
35284
35361
|
return wrappedTools;
|
|
35285
35362
|
}
|
|
35286
|
-
var
|
|
35363
|
+
var import_child_process7, import_util13, import_crypto3, import_events, import_fs6, import_fs7, import_path8, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
|
|
35287
35364
|
var init_probeTool = __esm({
|
|
35288
35365
|
"src/agent/probeTool.js"() {
|
|
35289
35366
|
"use strict";
|
|
35290
35367
|
init_index();
|
|
35291
|
-
|
|
35368
|
+
import_child_process7 = require("child_process");
|
|
35292
35369
|
import_util13 = require("util");
|
|
35293
35370
|
import_crypto3 = require("crypto");
|
|
35294
35371
|
import_events = require("events");
|
|
@@ -73938,6 +74015,7 @@ CRITICAL - ALWAYS search before answering:
|
|
|
73938
74015
|
You must NEVER answer questions about the codebase from memory or general knowledge. ALWAYS use the search and extract tools first to find the actual code, then base your answer ONLY on what you found. Even if you think you know the answer, you MUST verify it against the actual code. Your answers must be grounded in code evidence, not assumptions.
|
|
73939
74016
|
|
|
73940
74017
|
When exploring code:
|
|
74018
|
+
- Use the symbols tool to get a quick overview of a file's structure (functions, classes, constants) before diving into details with extract
|
|
73941
74019
|
- Provide clear, concise explanations based on user request
|
|
73942
74020
|
- Find and highlight the most relevant code snippets, if required
|
|
73943
74021
|
- Trace function calls and data flow through the system \u2014 follow the FULL call chain, not just the entry point
|
|
@@ -73968,6 +74046,7 @@ You think like a code explorer \u2014 you understand that codebases have layers:
|
|
|
73968
74046
|
|
|
73969
74047
|
When searching:
|
|
73970
74048
|
- Search for the MAIN concept first, then think: "what RELATED subsystems would a real codebase have?"
|
|
74049
|
+
- Use symbols to get a file's table of contents (functions, classes, constants with line numbers) before extracting \u2014 it helps you pick the right symbols to extract
|
|
73971
74050
|
- Use extract to READ the code you find \u2014 look for function calls, type references, and imports that point to OTHER relevant code
|
|
73972
74051
|
- If you find middleware, check: are there org-level or tenant-level variants?
|
|
73973
74052
|
- If you find algorithms, check: are there different storage backends?
|
|
@@ -74011,6 +74090,7 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
74011
74090
|
- Do not add code comments unless the logic is genuinely complex and non-obvious.
|
|
74012
74091
|
|
|
74013
74092
|
# Before Implementation
|
|
74093
|
+
- Use symbols to get a quick overview of file structure (functions, classes, constants with line numbers) before reading or editing files.
|
|
74014
74094
|
- Read tests first \u2014 find existing test files for the module you're changing. They reveal expected behavior, edge cases, and the project's testing patterns.
|
|
74015
74095
|
- Read neighboring files \u2014 understand naming conventions, error handling patterns, import style, and existing utilities before creating new ones.
|
|
74016
74096
|
- Trace the call chain \u2014 follow how the code you're changing is called and what depends on it. Check interfaces, types, and consumers.
|
|
@@ -74047,7 +74127,7 @@ Use the right tool:
|
|
|
74047
74127
|
1. To MODIFY existing code \u2192 \`edit\` tool (old_string \u2192 new_string, or start_line/end_line)
|
|
74048
74128
|
2. To CREATE a new file \u2192 \`create\` tool
|
|
74049
74129
|
3. To CHANGE multiple files at once \u2192 \`multi_edit\` tool
|
|
74050
|
-
4. To READ code \u2192 \`extract\` or \`search\` tools
|
|
74130
|
+
4. To READ code \u2192 \`extract\` or \`search\` tools. Use \`symbols\` to get a file's table of contents (functions, classes, constants with line numbers) before extracting.
|
|
74051
74131
|
5. If \`edit\` fails with "file has not been read yet" \u2192 use \`extract\` with the EXACT same file path you will pass to \`edit\`. Relative vs absolute path mismatch causes this error. Use the same path format consistently. If it still fails, use bash \`cat\` to read the file, then use \`create\` to write the entire modified file. Do NOT fall back to sed.
|
|
74052
74132
|
|
|
74053
74133
|
Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands, git operations, and read-only file inspection (cat, head, tail). sed/awk should ONLY be used for trivial non-code tasks (e.g., config file tweaks) where the replacement is a simple literal string swap.
|
|
@@ -76501,6 +76581,7 @@ var require_stringify = __commonJS({
|
|
|
76501
76581
|
nullStr: "null",
|
|
76502
76582
|
simpleKeys: false,
|
|
76503
76583
|
singleQuote: null,
|
|
76584
|
+
trailingComma: false,
|
|
76504
76585
|
trueStr: "true",
|
|
76505
76586
|
verifyAliasOrder: true
|
|
76506
76587
|
}, doc.schema.toStringOptions, options);
|
|
@@ -77018,12 +77099,19 @@ ${indent}${line}` : "\n";
|
|
|
77018
77099
|
if (comment)
|
|
77019
77100
|
reqNewline = true;
|
|
77020
77101
|
let str = stringify.stringify(item, itemCtx, () => comment = null);
|
|
77021
|
-
|
|
77102
|
+
reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n"));
|
|
77103
|
+
if (i < items.length - 1) {
|
|
77022
77104
|
str += ",";
|
|
77105
|
+
} else if (ctx.options.trailingComma) {
|
|
77106
|
+
if (ctx.options.lineWidth > 0) {
|
|
77107
|
+
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth);
|
|
77108
|
+
}
|
|
77109
|
+
if (reqNewline) {
|
|
77110
|
+
str += ",";
|
|
77111
|
+
}
|
|
77112
|
+
}
|
|
77023
77113
|
if (comment)
|
|
77024
77114
|
str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
|
|
77025
|
-
if (!reqNewline && (lines.length > linesAtValue || str.includes("\n")))
|
|
77026
|
-
reqNewline = true;
|
|
77027
77115
|
lines.push(str);
|
|
77028
77116
|
linesAtValue = lines.length;
|
|
77029
77117
|
}
|
|
@@ -80037,17 +80125,22 @@ var require_compose_node = __commonJS({
|
|
|
80037
80125
|
case "block-map":
|
|
80038
80126
|
case "block-seq":
|
|
80039
80127
|
case "flow-collection":
|
|
80040
|
-
|
|
80041
|
-
|
|
80042
|
-
|
|
80128
|
+
try {
|
|
80129
|
+
node = composeCollection.composeCollection(CN, ctx, token, props, onError);
|
|
80130
|
+
if (anchor)
|
|
80131
|
+
node.anchor = anchor.source.substring(1);
|
|
80132
|
+
} catch (error40) {
|
|
80133
|
+
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
80134
|
+
onError(token, "RESOURCE_EXHAUSTION", message);
|
|
80135
|
+
}
|
|
80043
80136
|
break;
|
|
80044
80137
|
default: {
|
|
80045
80138
|
const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`;
|
|
80046
80139
|
onError(token, "UNEXPECTED_TOKEN", message);
|
|
80047
|
-
node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
|
|
80048
80140
|
isSrcToken = false;
|
|
80049
80141
|
}
|
|
80050
80142
|
}
|
|
80143
|
+
node ?? (node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError));
|
|
80051
80144
|
if (anchor && node.anchor === "")
|
|
80052
80145
|
onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
|
|
80053
80146
|
if (atKey && ctx.options.stringKeys && (!identity2.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
|
|
@@ -95036,7 +95129,7 @@ async function executeBashCommand(command, options = {}) {
|
|
|
95036
95129
|
[cmd, ...cmdArgs] = args;
|
|
95037
95130
|
useShell = false;
|
|
95038
95131
|
}
|
|
95039
|
-
const child = (0,
|
|
95132
|
+
const child = (0, import_child_process8.spawn)(cmd, cmdArgs, {
|
|
95040
95133
|
cwd,
|
|
95041
95134
|
env: processEnv,
|
|
95042
95135
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -95232,11 +95325,11 @@ function validateExecutionOptions(options = {}) {
|
|
|
95232
95325
|
warnings
|
|
95233
95326
|
};
|
|
95234
95327
|
}
|
|
95235
|
-
var
|
|
95328
|
+
var import_child_process8, import_path13, import_fs10;
|
|
95236
95329
|
var init_bashExecutor = __esm({
|
|
95237
95330
|
"src/agent/bashExecutor.js"() {
|
|
95238
95331
|
"use strict";
|
|
95239
|
-
|
|
95332
|
+
import_child_process8 = require("child_process");
|
|
95240
95333
|
import_path13 = require("path");
|
|
95241
95334
|
import_fs10 = require("fs");
|
|
95242
95335
|
init_bashCommandUtils();
|
|
@@ -96762,7 +96855,7 @@ ${opts.schema}`;
|
|
|
96762
96855
|
}
|
|
96763
96856
|
}
|
|
96764
96857
|
const toolCollector = [];
|
|
96765
|
-
const proc2 = (0,
|
|
96858
|
+
const proc2 = (0, import_child_process9.spawn)("sh", ["-c", shellCmd], {
|
|
96766
96859
|
env: { ...process.env, FORCE_COLOR: "0" },
|
|
96767
96860
|
stdio: ["ignore", "pipe", "pipe"]
|
|
96768
96861
|
// Ignore stdin since echo handles it
|
|
@@ -97117,11 +97210,11 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
|
|
|
97117
97210
|
}
|
|
97118
97211
|
return systemPrompt || "";
|
|
97119
97212
|
}
|
|
97120
|
-
var
|
|
97213
|
+
var import_child_process9, import_crypto6, import_promises5, import_path15, import_os5, import_events3;
|
|
97121
97214
|
var init_enhanced_claude_code = __esm({
|
|
97122
97215
|
"src/agent/engines/enhanced-claude-code.js"() {
|
|
97123
97216
|
"use strict";
|
|
97124
|
-
|
|
97217
|
+
import_child_process9 = require("child_process");
|
|
97125
97218
|
import_crypto6 = require("crypto");
|
|
97126
97219
|
import_promises5 = __toESM(require("fs/promises"), 1);
|
|
97127
97220
|
import_path15 = __toESM(require("path"), 1);
|
|
@@ -97163,7 +97256,7 @@ async function createCodexEngine(options = {}) {
|
|
|
97163
97256
|
if (debug) {
|
|
97164
97257
|
console.log("[DEBUG] Starting Codex MCP server...");
|
|
97165
97258
|
}
|
|
97166
|
-
const codexProcess = (0,
|
|
97259
|
+
const codexProcess = (0, import_child_process10.spawn)("codex", ["mcp-server"], {
|
|
97167
97260
|
stdio: ["pipe", "pipe", "pipe"]
|
|
97168
97261
|
});
|
|
97169
97262
|
let requestId = 0;
|
|
@@ -97395,11 +97488,11 @@ function combinePrompts2(systemPrompt, customPrompt, agent) {
|
|
|
97395
97488
|
}
|
|
97396
97489
|
return systemPrompt || "";
|
|
97397
97490
|
}
|
|
97398
|
-
var
|
|
97491
|
+
var import_child_process10, import_crypto7, import_readline;
|
|
97399
97492
|
var init_codex = __esm({
|
|
97400
97493
|
"src/agent/engines/codex.js"() {
|
|
97401
97494
|
"use strict";
|
|
97402
|
-
|
|
97495
|
+
import_child_process10 = require("child_process");
|
|
97403
97496
|
import_crypto7 = require("crypto");
|
|
97404
97497
|
import_readline = require("readline");
|
|
97405
97498
|
init_built_in_server();
|
|
@@ -98165,6 +98258,9 @@ var init_ProbeAgent = __esm({
|
|
|
98165
98258
|
if (isToolAllowed("searchFiles")) {
|
|
98166
98259
|
this.toolImplementations.searchFiles = searchFilesToolInstance;
|
|
98167
98260
|
}
|
|
98261
|
+
if (wrappedTools.symbolsToolInstance && isToolAllowed("symbols")) {
|
|
98262
|
+
this.toolImplementations.symbols = wrappedTools.symbolsToolInstance;
|
|
98263
|
+
}
|
|
98168
98264
|
if (this.enableSkills) {
|
|
98169
98265
|
const registry2 = this._getSkillsRegistry();
|
|
98170
98266
|
const { listSkillsToolInstance, useSkillToolInstance } = createSkillToolInstances({
|
|
@@ -99196,6 +99292,10 @@ var init_ProbeAgent = __esm({
|
|
|
99196
99292
|
schema: searchFilesSchema,
|
|
99197
99293
|
description: "Find files matching a glob pattern with recursive search capability."
|
|
99198
99294
|
},
|
|
99295
|
+
symbols: {
|
|
99296
|
+
schema: symbolsSchema,
|
|
99297
|
+
description: "List all symbols (functions, classes, structs, constants, etc.) in a file. Returns a hierarchical tree with line numbers \u2014 like a table of contents for code."
|
|
99298
|
+
},
|
|
99199
99299
|
readMedia: {
|
|
99200
99300
|
schema: readMediaSchema,
|
|
99201
99301
|
description: "Read and load a media file (image or PDF document) for AI analysis. Supports: png, jpg, jpeg, webp, bmp, svg, pdf."
|
|
@@ -99851,7 +99951,8 @@ ${this.architectureContext.content}
|
|
|
99851
99951
|
${searchToolDesc1}
|
|
99852
99952
|
- extract: Extract specific code sections with context
|
|
99853
99953
|
- listFiles: Browse directory contents
|
|
99854
|
-
- searchFiles: Find files by name patterns
|
|
99954
|
+
- searchFiles: Find files by name patterns
|
|
99955
|
+
- symbols: List all symbols in a file (functions, classes, constants, etc.) with line numbers`;
|
|
99855
99956
|
if (this.enableBash) {
|
|
99856
99957
|
systemPrompt += `
|
|
99857
99958
|
- bash: Execute bash commands for system operations (building, running tests, git, etc.). NEVER use bash for code exploration (no grep, cat, find, head, tail) \u2014 always use search and extract tools instead, they are faster and more accurate.`;
|
|
@@ -99906,7 +100007,8 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
99906
100007
|
${searchToolDesc2}
|
|
99907
100008
|
- extract: Extract specific code sections with context
|
|
99908
100009
|
- listFiles: Browse directory contents
|
|
99909
|
-
- searchFiles: Find files by name patterns
|
|
100010
|
+
- searchFiles: Find files by name patterns
|
|
100011
|
+
- symbols: List all symbols in a file (functions, classes, constants, etc.) with line numbers`;
|
|
99910
100012
|
if (this.enableBash) {
|
|
99911
100013
|
systemPrompt += `
|
|
99912
100014
|
- bash: Execute bash commands for system operations (building, running tests, git, etc.). NEVER use bash for code exploration (no grep, cat, find, head, tail) \u2014 always use search and extract tools instead, they are faster and more accurate.`;
|
|
@@ -103351,7 +103453,7 @@ The "searches" field helps the caller understand what was attempted.
|
|
|
103351
103453
|
- Deduplicate files across groups.
|
|
103352
103454
|
</output-rules>`;
|
|
103353
103455
|
}
|
|
103354
|
-
var import_ai5, import_fs12, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
|
|
103456
|
+
var import_ai5, import_fs12, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool, symbolsTool;
|
|
103355
103457
|
var init_vercel = __esm({
|
|
103356
103458
|
"src/tools/vercel.js"() {
|
|
103357
103459
|
"use strict";
|
|
@@ -103359,6 +103461,7 @@ var init_vercel = __esm({
|
|
|
103359
103461
|
init_search();
|
|
103360
103462
|
init_query();
|
|
103361
103463
|
init_extract();
|
|
103464
|
+
init_symbols();
|
|
103362
103465
|
init_delegate();
|
|
103363
103466
|
init_analyzeAll();
|
|
103364
103467
|
init_common();
|
|
@@ -104081,6 +104184,36 @@ Do NOT search for analogies or loosely related concepts. If the feature does not
|
|
|
104081
104184
|
}
|
|
104082
104185
|
});
|
|
104083
104186
|
};
|
|
104187
|
+
symbolsTool = (options = {}) => {
|
|
104188
|
+
return (0, import_ai5.tool)({
|
|
104189
|
+
name: "symbols",
|
|
104190
|
+
description: "List all symbols (functions, classes, structs, constants, etc.) in a file. Returns a hierarchical tree with line numbers \u2014 like a table of contents for code files.",
|
|
104191
|
+
inputSchema: symbolsSchema,
|
|
104192
|
+
execute: async ({ file: file2 }) => {
|
|
104193
|
+
try {
|
|
104194
|
+
let filePath = file2;
|
|
104195
|
+
if (options.cwd) {
|
|
104196
|
+
const resolvedPaths = parseAndResolvePaths(file2, options.cwd);
|
|
104197
|
+
if (resolvedPaths.length > 0) {
|
|
104198
|
+
filePath = resolvedPaths[0];
|
|
104199
|
+
}
|
|
104200
|
+
}
|
|
104201
|
+
const result = await symbols({
|
|
104202
|
+
files: [filePath],
|
|
104203
|
+
cwd: options.cwd,
|
|
104204
|
+
binaryOptions: options.binaryOptions
|
|
104205
|
+
});
|
|
104206
|
+
if (result && result.length > 0) {
|
|
104207
|
+
return JSON.stringify(result[0], null, 2);
|
|
104208
|
+
}
|
|
104209
|
+
return JSON.stringify({ file: file2, symbols: [] }, null, 2);
|
|
104210
|
+
} catch (error40) {
|
|
104211
|
+
console.error("Error executing symbols:", error40);
|
|
104212
|
+
return formatErrorForAI(error40);
|
|
104213
|
+
}
|
|
104214
|
+
}
|
|
104215
|
+
});
|
|
104216
|
+
};
|
|
104084
104217
|
}
|
|
104085
104218
|
});
|
|
104086
104219
|
|
|
@@ -105241,6 +105374,10 @@ You are Probe, a specialized code intelligence assistant. Your objective is to a
|
|
|
105241
105374
|
* **Purpose:** Retrieve specific code blocks or entire files *after* \`search\` or \`query\` identifies the target.
|
|
105242
105375
|
* **Syntax:** Optional \`#symbol\` (e.g., \`#MyClass\`), \`#Lstart-Lend\` (e.g., \`#L50-L75\`).
|
|
105243
105376
|
* **Mandatory Argument:** \`path\` (specific file path, e.g., \`"src/utils/helpers.go"\`, or dependency file like \`"go:github.com/gin-gonic/gin/context.go"\`).
|
|
105377
|
+
* \`symbols\`
|
|
105378
|
+
* **Purpose:** List all symbols (functions, classes, structs, constants, etc.) in a file \u2014 a table of contents with line numbers and nesting.
|
|
105379
|
+
* **Syntax:** \`file\` (path to the file to list symbols from).
|
|
105380
|
+
* **Use When:** You need to understand a file's structure before extracting specific parts, or to find the right symbol name/line number for \`extract\`.
|
|
105244
105381
|
|
|
105245
105382
|
[Examples]
|
|
105246
105383
|
|
|
@@ -105375,6 +105512,8 @@ __export(tools_exports, {
|
|
|
105375
105512
|
searchFilesSchema: () => searchFilesSchema,
|
|
105376
105513
|
searchSchema: () => searchSchema,
|
|
105377
105514
|
searchTool: () => searchTool,
|
|
105515
|
+
symbolsSchema: () => symbolsSchema,
|
|
105516
|
+
symbolsTool: () => symbolsTool,
|
|
105378
105517
|
tools: () => tools,
|
|
105379
105518
|
useSkillSchema: () => useSkillSchema
|
|
105380
105519
|
});
|
|
@@ -105498,16 +105637,16 @@ function shouldIgnore(filePath, ignorePatterns) {
|
|
|
105498
105637
|
}
|
|
105499
105638
|
return false;
|
|
105500
105639
|
}
|
|
105501
|
-
var import_fs15, import_path18, import_util14,
|
|
105640
|
+
var import_fs15, import_path18, import_util14, import_child_process11, execAsync3;
|
|
105502
105641
|
var init_file_lister = __esm({
|
|
105503
105642
|
"src/utils/file-lister.js"() {
|
|
105504
105643
|
"use strict";
|
|
105505
105644
|
import_fs15 = __toESM(require("fs"), 1);
|
|
105506
105645
|
import_path18 = __toESM(require("path"), 1);
|
|
105507
105646
|
import_util14 = require("util");
|
|
105508
|
-
|
|
105647
|
+
import_child_process11 = require("child_process");
|
|
105509
105648
|
init_symlink_utils();
|
|
105510
|
-
execAsync3 = (0, import_util14.promisify)(
|
|
105649
|
+
execAsync3 = (0, import_util14.promisify)(import_child_process11.exec);
|
|
105511
105650
|
}
|
|
105512
105651
|
});
|
|
105513
105652
|
|
|
@@ -105583,6 +105722,9 @@ __export(index_exports, {
|
|
|
105583
105722
|
searchSchema: () => searchSchema,
|
|
105584
105723
|
searchTool: () => searchTool,
|
|
105585
105724
|
setBinaryPath: () => setBinaryPath,
|
|
105725
|
+
symbols: () => symbols,
|
|
105726
|
+
symbolsSchema: () => symbolsSchema,
|
|
105727
|
+
symbolsTool: () => symbolsTool,
|
|
105586
105728
|
taskSchema: () => taskSchema,
|
|
105587
105729
|
taskSystemPrompt: () => taskSystemPrompt,
|
|
105588
105730
|
tools: () => tools_exports,
|
|
@@ -105596,6 +105738,7 @@ var init_index = __esm({
|
|
|
105596
105738
|
init_search();
|
|
105597
105739
|
init_query();
|
|
105598
105740
|
init_extract();
|
|
105741
|
+
init_symbols();
|
|
105599
105742
|
init_grep();
|
|
105600
105743
|
init_delegate();
|
|
105601
105744
|
init_utils();
|
|
@@ -105673,6 +105816,9 @@ init_index();
|
|
|
105673
105816
|
searchSchema,
|
|
105674
105817
|
searchTool,
|
|
105675
105818
|
setBinaryPath,
|
|
105819
|
+
symbols,
|
|
105820
|
+
symbolsSchema,
|
|
105821
|
+
symbolsTool,
|
|
105676
105822
|
taskSchema,
|
|
105677
105823
|
taskSystemPrompt,
|
|
105678
105824
|
tools,
|
package/index.d.ts
CHANGED
|
@@ -408,6 +408,58 @@ export interface QueryParams {
|
|
|
408
408
|
sessionId?: string;
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
+
/**
|
|
412
|
+
* Symbols tool parameters
|
|
413
|
+
*/
|
|
414
|
+
export interface SymbolsParams {
|
|
415
|
+
/** Files to list symbols from */
|
|
416
|
+
files: string[];
|
|
417
|
+
/** Working directory for resolving relative paths */
|
|
418
|
+
cwd?: string;
|
|
419
|
+
/** Include test functions/methods */
|
|
420
|
+
allowTests?: boolean;
|
|
421
|
+
/** Binary options */
|
|
422
|
+
binaryOptions?: {
|
|
423
|
+
forceDownload?: boolean;
|
|
424
|
+
version?: string;
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* A node in the symbol tree
|
|
430
|
+
*/
|
|
431
|
+
export interface SymbolNode {
|
|
432
|
+
/** Symbol name */
|
|
433
|
+
name: string;
|
|
434
|
+
/** Symbol kind (function, struct, class, const, etc.) */
|
|
435
|
+
kind: string;
|
|
436
|
+
/** Clean signature without body */
|
|
437
|
+
signature: string;
|
|
438
|
+
/** Start line (1-indexed) */
|
|
439
|
+
line: number;
|
|
440
|
+
/** End line (1-indexed) */
|
|
441
|
+
end_line: number;
|
|
442
|
+
/** Nested symbols (methods inside classes/impl blocks, etc.) */
|
|
443
|
+
children?: SymbolNode[];
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Symbols extracted from a single file
|
|
448
|
+
*/
|
|
449
|
+
export interface FileSymbols {
|
|
450
|
+
/** File path */
|
|
451
|
+
file: string;
|
|
452
|
+
/** Top-level symbols with optional nesting */
|
|
453
|
+
symbols: SymbolNode[];
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Symbols tool function type
|
|
458
|
+
*/
|
|
459
|
+
export type SymbolsTool = (options?: SearchOptions) => {
|
|
460
|
+
execute(params: { file: string }): Promise<string>;
|
|
461
|
+
};
|
|
462
|
+
|
|
411
463
|
/**
|
|
412
464
|
* Extract tool parameters
|
|
413
465
|
*/
|
|
@@ -537,6 +589,11 @@ export declare function grep(options: {
|
|
|
537
589
|
};
|
|
538
590
|
}): Promise<string>;
|
|
539
591
|
|
|
592
|
+
/**
|
|
593
|
+
* List symbols (functions, structs, classes, constants, etc.) in files
|
|
594
|
+
*/
|
|
595
|
+
export declare function symbols(options: SymbolsParams): Promise<FileSymbols[]>;
|
|
596
|
+
|
|
540
597
|
/**
|
|
541
598
|
* Extract code blocks from files
|
|
542
599
|
*/
|
|
@@ -564,6 +621,11 @@ export declare function queryTool(options?: SearchOptions): ReturnType<QueryTool
|
|
|
564
621
|
*/
|
|
565
622
|
export declare function extractTool(options?: SearchOptions): ReturnType<ExtractTool>;
|
|
566
623
|
|
|
624
|
+
/**
|
|
625
|
+
* Create symbols tool instance
|
|
626
|
+
*/
|
|
627
|
+
export declare function symbolsTool(options?: SearchOptions): ReturnType<SymbolsTool>;
|
|
628
|
+
|
|
567
629
|
/**
|
|
568
630
|
* Get the path to the probe binary
|
|
569
631
|
*/
|
|
@@ -778,6 +840,7 @@ export declare function createTool(options?: EditToolOptions): {
|
|
|
778
840
|
export declare const searchSchema: any;
|
|
779
841
|
export declare const querySchema: any;
|
|
780
842
|
export declare const extractSchema: any;
|
|
843
|
+
export declare const symbolsSchema: any;
|
|
781
844
|
export declare const editSchema: any;
|
|
782
845
|
export declare const createSchema: any;
|
|
783
846
|
export declare const attemptCompletionSchema: any;
|
package/package.json
CHANGED
package/src/agent/ProbeAgent.js
CHANGED
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
searchFilesSchema,
|
|
57
57
|
readImageSchema,
|
|
58
58
|
readMediaSchema,
|
|
59
|
+
symbolsSchema,
|
|
59
60
|
listSkillsSchema,
|
|
60
61
|
useSkillSchema
|
|
61
62
|
} from './tools.js';
|
|
@@ -945,6 +946,9 @@ export class ProbeAgent {
|
|
|
945
946
|
if (isToolAllowed('searchFiles')) {
|
|
946
947
|
this.toolImplementations.searchFiles = searchFilesToolInstance;
|
|
947
948
|
}
|
|
949
|
+
if (wrappedTools.symbolsToolInstance && isToolAllowed('symbols')) {
|
|
950
|
+
this.toolImplementations.symbols = wrappedTools.symbolsToolInstance;
|
|
951
|
+
}
|
|
948
952
|
|
|
949
953
|
if (this.enableSkills) {
|
|
950
954
|
const registry = this._getSkillsRegistry();
|
|
@@ -2225,6 +2229,10 @@ export class ProbeAgent {
|
|
|
2225
2229
|
schema: searchFilesSchema,
|
|
2226
2230
|
description: 'Find files matching a glob pattern with recursive search capability.'
|
|
2227
2231
|
},
|
|
2232
|
+
symbols: {
|
|
2233
|
+
schema: symbolsSchema,
|
|
2234
|
+
description: 'List all symbols (functions, classes, structs, constants, etc.) in a file. Returns a hierarchical tree with line numbers — like a table of contents for code.'
|
|
2235
|
+
},
|
|
2228
2236
|
readMedia: {
|
|
2229
2237
|
schema: readMediaSchema,
|
|
2230
2238
|
description: 'Read and load a media file (image or PDF document) for AI analysis. Supports: png, jpg, jpeg, webp, bmp, svg, pdf.'
|
|
@@ -3019,7 +3027,8 @@ export class ProbeAgent {
|
|
|
3019
3027
|
${searchToolDesc1}
|
|
3020
3028
|
- extract: Extract specific code sections with context
|
|
3021
3029
|
- listFiles: Browse directory contents
|
|
3022
|
-
- searchFiles: Find files by name patterns
|
|
3030
|
+
- searchFiles: Find files by name patterns
|
|
3031
|
+
- symbols: List all symbols in a file (functions, classes, constants, etc.) with line numbers`;
|
|
3023
3032
|
|
|
3024
3033
|
if (this.enableBash) {
|
|
3025
3034
|
systemPrompt += `\n- bash: Execute bash commands for system operations (building, running tests, git, etc.). NEVER use bash for code exploration (no grep, cat, find, head, tail) — always use search and extract tools instead, they are faster and more accurate.`;
|
|
@@ -3085,7 +3094,8 @@ ${extractGuidance1}
|
|
|
3085
3094
|
${searchToolDesc2}
|
|
3086
3095
|
- extract: Extract specific code sections with context
|
|
3087
3096
|
- listFiles: Browse directory contents
|
|
3088
|
-
- searchFiles: Find files by name patterns
|
|
3097
|
+
- searchFiles: Find files by name patterns
|
|
3098
|
+
- symbols: List all symbols in a file (functions, classes, constants, etc.) with line numbers`;
|
|
3089
3099
|
|
|
3090
3100
|
if (this.enableBash) {
|
|
3091
3101
|
systemPrompt += `\n- bash: Execute bash commands for system operations (building, running tests, git, etc.). NEVER use bash for code exploration (no grep, cat, find, head, tail) — always use search and extract tools instead, they are faster and more accurate.`;
|
package/src/agent/probeTool.js
CHANGED
|
@@ -265,6 +265,15 @@ export function createWrappedTools(baseTools) {
|
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
// Wrap symbols tool
|
|
269
|
+
if (baseTools.symbolsTool) {
|
|
270
|
+
wrappedTools.symbolsToolInstance = wrapToolWithEmitter(
|
|
271
|
+
baseTools.symbolsTool,
|
|
272
|
+
'symbols',
|
|
273
|
+
baseTools.symbolsTool.execute
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
268
277
|
return wrappedTools;
|
|
269
278
|
}
|
|
270
279
|
|
|
@@ -12,6 +12,7 @@ CRITICAL - ALWAYS search before answering:
|
|
|
12
12
|
You must NEVER answer questions about the codebase from memory or general knowledge. ALWAYS use the search and extract tools first to find the actual code, then base your answer ONLY on what you found. Even if you think you know the answer, you MUST verify it against the actual code. Your answers must be grounded in code evidence, not assumptions.
|
|
13
13
|
|
|
14
14
|
When exploring code:
|
|
15
|
+
- Use the symbols tool to get a quick overview of a file's structure (functions, classes, constants) before diving into details with extract
|
|
15
16
|
- Provide clear, concise explanations based on user request
|
|
16
17
|
- Find and highlight the most relevant code snippets, if required
|
|
17
18
|
- Trace function calls and data flow through the system — follow the FULL call chain, not just the entry point
|
|
@@ -43,6 +44,7 @@ You think like a code explorer — you understand that codebases have layers:
|
|
|
43
44
|
|
|
44
45
|
When searching:
|
|
45
46
|
- Search for the MAIN concept first, then think: "what RELATED subsystems would a real codebase have?"
|
|
47
|
+
- Use symbols to get a file's table of contents (functions, classes, constants with line numbers) before extracting — it helps you pick the right symbols to extract
|
|
46
48
|
- Use extract to READ the code you find — look for function calls, type references, and imports that point to OTHER relevant code
|
|
47
49
|
- If you find middleware, check: are there org-level or tenant-level variants?
|
|
48
50
|
- If you find algorithms, check: are there different storage backends?
|
|
@@ -90,6 +92,7 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
90
92
|
- Do not add code comments unless the logic is genuinely complex and non-obvious.
|
|
91
93
|
|
|
92
94
|
# Before Implementation
|
|
95
|
+
- Use symbols to get a quick overview of file structure (functions, classes, constants with line numbers) before reading or editing files.
|
|
93
96
|
- Read tests first — find existing test files for the module you're changing. They reveal expected behavior, edge cases, and the project's testing patterns.
|
|
94
97
|
- Read neighboring files — understand naming conventions, error handling patterns, import style, and existing utilities before creating new ones.
|
|
95
98
|
- Trace the call chain — follow how the code you're changing is called and what depends on it. Check interfaces, types, and consumers.
|
|
@@ -126,7 +129,7 @@ Use the right tool:
|
|
|
126
129
|
1. To MODIFY existing code → \`edit\` tool (old_string → new_string, or start_line/end_line)
|
|
127
130
|
2. To CREATE a new file → \`create\` tool
|
|
128
131
|
3. To CHANGE multiple files at once → \`multi_edit\` tool
|
|
129
|
-
4. To READ code → \`extract\` or \`search\` tools
|
|
132
|
+
4. To READ code → \`extract\` or \`search\` tools. Use \`symbols\` to get a file's table of contents (functions, classes, constants with line numbers) before extracting.
|
|
130
133
|
5. If \`edit\` fails with "file has not been read yet" → use \`extract\` with the EXACT same file path you will pass to \`edit\`. Relative vs absolute path mismatch causes this error. Use the same path format consistently. If it still fails, use bash \`cat\` to read the file, then use \`create\` to write the entire modified file. Do NOT fall back to sed.
|
|
131
134
|
|
|
132
135
|
Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands, git operations, and read-only file inspection (cat, head, tail). sed/awk should ONLY be used for trivial non-code tasks (e.g., config file tweaks) where the replacement is a simple literal string swap.
|