@probelabs/probe 0.6.0-rc248 → 0.6.0-rc249

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.
@@ -8,6 +8,7 @@
8
8
 
9
9
  import {
10
10
  searchSchema,
11
+ searchAllSchema,
11
12
  querySchema,
12
13
  extractSchema,
13
14
  bashSchema,
@@ -16,6 +17,7 @@ import {
16
17
  // Map of native tool names to their Zod schemas
17
18
  const NATIVE_TOOL_SCHEMAS = {
18
19
  search: searchSchema,
20
+ searchAll: searchAllSchema,
19
21
  query: querySchema,
20
22
  extract: extractSchema,
21
23
  bash: bashSchema,
@@ -23,7 +25,7 @@ const NATIVE_TOOL_SCHEMAS = {
23
25
 
24
26
  // Tools that are inherently async (make network/LLM calls)
25
27
  const ALWAYS_ASYNC = new Set([
26
- 'search', 'query', 'extract', 'listFiles', 'searchFiles', 'bash',
28
+ 'search', 'searchAll', 'query', 'extract', 'listFiles', 'searchFiles', 'bash',
27
29
  'LLM', 'map',
28
30
  ]);
29
31
 
@@ -9905,7 +9905,7 @@ function resolveTargetPath(target, cwd) {
9905
9905
  }
9906
9906
  return filePart + suffix;
9907
9907
  }
9908
- var searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
9908
+ var searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
9909
9909
  var init_common = __esm({
9910
9910
  "src/tools/common.js"() {
9911
9911
  "use strict";
@@ -9916,9 +9916,17 @@ var init_common = __esm({
9916
9916
  query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
9917
9917
  path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
9918
9918
  exact: external_exports.boolean().optional().default(false).describe('Default (false) enables stemming and keyword splitting for exploratory search - "getUserData" matches "get", "user", "data", etc. Set true for precise symbol lookup where "getUserData" matches only "getUserData". Use true when you know the exact symbol name.'),
9919
+ maxTokens: external_exports.number().nullable().optional().describe("Maximum tokens to return. Default is 20000. Set to null for unlimited results."),
9919
9920
  session: external_exports.string().optional().describe("Session ID for result caching and pagination. Pass the session ID from a previous search to get additional results (next page). Results already shown in a session are automatically excluded. Omit for a fresh search."),
9920
9921
  nextPage: external_exports.boolean().optional().default(false).describe("Set to true when requesting the next page of results. Requires passing the same session ID from the previous search output.")
9921
9922
  });
9923
+ searchAllSchema = external_exports.object({
9924
+ query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
9925
+ path: external_exports.string().optional().default(".").describe("Path to search in."),
9926
+ exact: external_exports.boolean().optional().default(false).describe("Use exact matching instead of stemming."),
9927
+ maxTokensPerPage: external_exports.number().optional().default(2e4).describe("Tokens per page when paginating. Default 20000."),
9928
+ maxPages: external_exports.number().optional().default(50).describe("Maximum pages to retrieve. Default 50 (safety limit).")
9929
+ });
9922
9930
  querySchema = external_exports.object({
9923
9931
  pattern: external_exports.string().describe("AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc."),
9924
9932
  path: external_exports.string().optional().default(".").describe("Path to search in"),
@@ -22110,12 +22118,14 @@ var init_environment = __esm({
22110
22118
  init_common();
22111
22119
  NATIVE_TOOL_SCHEMAS = {
22112
22120
  search: searchSchema,
22121
+ searchAll: searchAllSchema,
22113
22122
  query: querySchema,
22114
22123
  extract: extractSchema,
22115
22124
  bash: bashSchema
22116
22125
  };
22117
22126
  ALWAYS_ASYNC = /* @__PURE__ */ new Set([
22118
22127
  "search",
22128
+ "searchAll",
22119
22129
  "query",
22120
22130
  "extract",
22121
22131
  "listFiles",
@@ -28992,6 +29002,7 @@ function buildToolImplementations(configOptions) {
28992
29002
  if (!searchPaths || searchPaths.length === 0) {
28993
29003
  searchPaths = [cwd || "."];
28994
29004
  }
29005
+ const maxTokens = params.maxTokens !== void 0 ? params.maxTokens : 2e4;
28995
29006
  return await search({
28996
29007
  query: params.query,
28997
29008
  path: searchPaths.join(" "),
@@ -28999,7 +29010,7 @@ function buildToolImplementations(configOptions) {
28999
29010
  allowTests: true,
29000
29011
  exact: params.exact || false,
29001
29012
  json: false,
29002
- maxTokens: 2e4,
29013
+ maxTokens,
29003
29014
  session: sessionId,
29004
29015
  timeout: 60
29005
29016
  });
@@ -29008,6 +29019,56 @@ function buildToolImplementations(configOptions) {
29008
29019
  }
29009
29020
  }
29010
29021
  };
29022
+ tools2.searchAll = {
29023
+ execute: async (params) => {
29024
+ try {
29025
+ let searchPaths;
29026
+ if (params.path) {
29027
+ searchPaths = parseAndResolvePaths(params.path, cwd);
29028
+ }
29029
+ if (!searchPaths || searchPaths.length === 0) {
29030
+ searchPaths = [cwd || "."];
29031
+ }
29032
+ const pathStr = searchPaths.join(" ");
29033
+ const maxTokensPerPage = params.maxTokensPerPage || 2e4;
29034
+ const maxPages = params.maxPages || 50;
29035
+ let allResults = "";
29036
+ let pageCount = 0;
29037
+ while (pageCount < maxPages) {
29038
+ const pageResult = await search({
29039
+ query: params.query,
29040
+ path: pathStr,
29041
+ cwd,
29042
+ allowTests: true,
29043
+ exact: params.exact || false,
29044
+ json: false,
29045
+ maxTokens: maxTokensPerPage,
29046
+ session: sessionId,
29047
+ timeout: 60
29048
+ });
29049
+ pageCount++;
29050
+ if (!pageResult || pageResult.trim().length === 0) {
29051
+ break;
29052
+ }
29053
+ if (pageResult.includes("All results retrieved") || pageResult.includes("No results found") || pageResult.includes("No matching code blocks found")) {
29054
+ if (pageResult.trim().length > 50) {
29055
+ allResults += (allResults ? "\n\n" : "") + pageResult;
29056
+ }
29057
+ break;
29058
+ }
29059
+ allResults += (allResults ? "\n\n" : "") + pageResult;
29060
+ }
29061
+ if (pageCount >= maxPages) {
29062
+ allResults += `
29063
+
29064
+ [Warning: Reached maximum page limit (${maxPages}). Some results may be omitted.]`;
29065
+ }
29066
+ return allResults || "No results found.";
29067
+ } catch (e) {
29068
+ return `SearchAll error: ${e.message}`;
29069
+ }
29070
+ }
29071
+ };
29011
29072
  tools2.query = {
29012
29073
  execute: async (params) => {
29013
29074
  try {
@@ -29192,7 +29253,8 @@ ${lastError}
29192
29253
 
29193
29254
  RULES REMINDER:
29194
29255
  - search(query) is KEYWORD SEARCH \u2014 pass a search query, NOT a filename. Use extract(filepath) to read file contents.
29195
- - search(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
29256
+ - search() returns up to 20K tokens by default. Use search(query, path, {maxTokens: null}) for unlimited, or searchAll(query) to auto-paginate ALL results.
29257
+ - search(), searchAll(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
29196
29258
  - Use chunk(stringData) to split a string into an array of chunks.
29197
29259
  - Use map(array, fn) only with arrays. Do NOT pass strings to map().
29198
29260
  - Do NOT use .map(), .forEach(), .filter(), .join() \u2014 use for..of loops instead.
@@ -29493,7 +29555,8 @@ return table;
29493
29555
  ${funcList}
29494
29556
 
29495
29557
  **Return types \u2014 IMPORTANT:**
29496
- - \`search(query)\` \u2192 **keyword search** \u2014 pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets). To process parts, use \`chunk()\` to split it.
29558
+ - \`search(query)\` \u2192 **keyword search** \u2014 pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets, up to 20K tokens by default). Use \`{maxTokens: null}\` for unlimited.
29559
+ - \`searchAll(query)\` \u2192 **exhaustive keyword search** \u2014 auto-paginates to retrieve ALL matching results. Returns a **string** (all matching code snippets concatenated). Use for bulk analysis.
29497
29560
  - \`query(pattern)\` \u2192 **AST search** \u2014 pass a tree-sitter pattern. Returns a **string** (matching code elements).
29498
29561
  - \`extract(targets)\` \u2192 **read file contents** \u2014 pass a file path like "src/main.js" or "src/main.js:42". Use this to read specific files found by listFiles(). Returns a **string**.
29499
29562
  - \`listFiles(pattern)\` \u2192 **list files** \u2014 pass a glob pattern like "**/*.md". Returns an **array** of file path strings. Use directly with \`for (const f of listFiles("**/*.md"))\`.
@@ -13,10 +13,19 @@ export const searchSchema = z.object({
13
13
  query: z.string().describe('Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation.'),
14
14
  path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
15
15
  exact: z.boolean().optional().default(false).describe('Default (false) enables stemming and keyword splitting for exploratory search - "getUserData" matches "get", "user", "data", etc. Set true for precise symbol lookup where "getUserData" matches only "getUserData". Use true when you know the exact symbol name.'),
16
+ maxTokens: z.number().nullable().optional().describe('Maximum tokens to return. Default is 20000. Set to null for unlimited results.'),
16
17
  session: z.string().optional().describe('Session ID for result caching and pagination. Pass the session ID from a previous search to get additional results (next page). Results already shown in a session are automatically excluded. Omit for a fresh search.'),
17
18
  nextPage: z.boolean().optional().default(false).describe('Set to true when requesting the next page of results. Requires passing the same session ID from the previous search output.')
18
19
  });
19
20
 
21
+ export const searchAllSchema = z.object({
22
+ query: z.string().describe('Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation.'),
23
+ path: z.string().optional().default('.').describe('Path to search in.'),
24
+ exact: z.boolean().optional().default(false).describe('Use exact matching instead of stemming.'),
25
+ maxTokensPerPage: z.number().optional().default(20000).describe('Tokens per page when paginating. Default 20000.'),
26
+ maxPages: z.number().optional().default(50).describe('Maximum pages to retrieve. Default 50 (safety limit).')
27
+ });
28
+
20
29
  export const querySchema = z.object({
21
30
  pattern: z.string().describe('AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc.'),
22
31
  path: z.string().optional().default('.').describe('Path to search in'),
@@ -85,6 +85,8 @@ function buildToolImplementations(configOptions) {
85
85
  if (!searchPaths || searchPaths.length === 0) {
86
86
  searchPaths = [cwd || '.'];
87
87
  }
88
+ // Allow maxTokens to be passed through (null = unlimited, undefined = default 20000)
89
+ const maxTokens = params.maxTokens !== undefined ? params.maxTokens : 20000;
88
90
  return await search({
89
91
  query: params.query,
90
92
  path: searchPaths.join(' '),
@@ -92,7 +94,7 @@ function buildToolImplementations(configOptions) {
92
94
  allowTests: true,
93
95
  exact: params.exact || false,
94
96
  json: false,
95
- maxTokens: 20000,
97
+ maxTokens,
96
98
  session: sessionId,
97
99
  timeout: 60,
98
100
  });
@@ -102,6 +104,70 @@ function buildToolImplementations(configOptions) {
102
104
  },
103
105
  };
104
106
 
107
+ // searchAll: auto-paginating search that retrieves ALL results
108
+ // Calls search() repeatedly with same sessionId until no more results
109
+ tools.searchAll = {
110
+ execute: async (params) => {
111
+ try {
112
+ let searchPaths;
113
+ if (params.path) {
114
+ searchPaths = parseAndResolvePaths(params.path, cwd);
115
+ }
116
+ if (!searchPaths || searchPaths.length === 0) {
117
+ searchPaths = [cwd || '.'];
118
+ }
119
+ const pathStr = searchPaths.join(' ');
120
+ const maxTokensPerPage = params.maxTokensPerPage || 20000;
121
+ const maxPages = params.maxPages || 50; // Safety limit
122
+
123
+ let allResults = '';
124
+ let pageCount = 0;
125
+
126
+ while (pageCount < maxPages) {
127
+ const pageResult = await search({
128
+ query: params.query,
129
+ path: pathStr,
130
+ cwd,
131
+ allowTests: true,
132
+ exact: params.exact || false,
133
+ json: false,
134
+ maxTokens: maxTokensPerPage,
135
+ session: sessionId,
136
+ timeout: 60,
137
+ });
138
+
139
+ pageCount++;
140
+
141
+ // Check if we got results
142
+ if (!pageResult || pageResult.trim().length === 0) {
143
+ break;
144
+ }
145
+
146
+ // Check for "All results retrieved" or "No results found" signals
147
+ if (pageResult.includes('All results retrieved') ||
148
+ pageResult.includes('No results found') ||
149
+ pageResult.includes('No matching code blocks found')) {
150
+ // Include this final page if it has content beyond the message
151
+ if (pageResult.trim().length > 50) {
152
+ allResults += (allResults ? '\n\n' : '') + pageResult;
153
+ }
154
+ break;
155
+ }
156
+
157
+ allResults += (allResults ? '\n\n' : '') + pageResult;
158
+ }
159
+
160
+ if (pageCount >= maxPages) {
161
+ allResults += `\n\n[Warning: Reached maximum page limit (${maxPages}). Some results may be omitted.]`;
162
+ }
163
+
164
+ return allResults || 'No results found.';
165
+ } catch (e) {
166
+ return `SearchAll error: ${e.message}`;
167
+ }
168
+ },
169
+ };
170
+
105
171
  tools.query = {
106
172
  execute: async (params) => {
107
173
  try {
@@ -345,7 +411,8 @@ ${lastError}
345
411
 
346
412
  RULES REMINDER:
347
413
  - search(query) is KEYWORD SEARCH — pass a search query, NOT a filename. Use extract(filepath) to read file contents.
348
- - search(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
414
+ - search() returns up to 20K tokens by default. Use search(query, path, {maxTokens: null}) for unlimited, or searchAll(query) to auto-paginate ALL results.
415
+ - search(), searchAll(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
349
416
  - Use chunk(stringData) to split a string into an array of chunks.
350
417
  - Use map(array, fn) only with arrays. Do NOT pass strings to map().
351
418
  - Do NOT use .map(), .forEach(), .filter(), .join() — use for..of loops instead.
@@ -684,7 +751,8 @@ return table;
684
751
  ${funcList}
685
752
 
686
753
  **Return types — IMPORTANT:**
687
- - \`search(query)\` → **keyword search** — pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets). To process parts, use \`chunk()\` to split it.
754
+ - \`search(query)\` → **keyword search** — pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets, up to 20K tokens by default). Use \`{maxTokens: null}\` for unlimited.
755
+ - \`searchAll(query)\` → **exhaustive keyword search** — auto-paginates to retrieve ALL matching results. Returns a **string** (all matching code snippets concatenated). Use for bulk analysis.
688
756
  - \`query(pattern)\` → **AST search** — pass a tree-sitter pattern. Returns a **string** (matching code elements).
689
757
  - \`extract(targets)\` → **read file contents** — pass a file path like "src/main.js" or "src/main.js:42". Use this to read specific files found by listFiles(). Returns a **string**.
690
758
  - \`listFiles(pattern)\` → **list files** — pass a glob pattern like "**/*.md". Returns an **array** of file path strings. Use directly with \`for (const f of listFiles("**/*.md"))\`.
@@ -37037,7 +37037,7 @@ function resolveTargetPath(target, cwd) {
37037
37037
  }
37038
37038
  return filePart + suffix;
37039
37039
  }
37040
- var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
37040
+ var import_path6, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
37041
37041
  var init_common2 = __esm({
37042
37042
  "src/tools/common.js"() {
37043
37043
  "use strict";
@@ -37049,9 +37049,17 @@ var init_common2 = __esm({
37049
37049
  query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
37050
37050
  path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
37051
37051
  exact: external_exports.boolean().optional().default(false).describe('Default (false) enables stemming and keyword splitting for exploratory search - "getUserData" matches "get", "user", "data", etc. Set true for precise symbol lookup where "getUserData" matches only "getUserData". Use true when you know the exact symbol name.'),
37052
+ maxTokens: external_exports.number().nullable().optional().describe("Maximum tokens to return. Default is 20000. Set to null for unlimited results."),
37052
37053
  session: external_exports.string().optional().describe("Session ID for result caching and pagination. Pass the session ID from a previous search to get additional results (next page). Results already shown in a session are automatically excluded. Omit for a fresh search."),
37053
37054
  nextPage: external_exports.boolean().optional().default(false).describe("Set to true when requesting the next page of results. Requires passing the same session ID from the previous search output.")
37054
37055
  });
37056
+ searchAllSchema = external_exports.object({
37057
+ query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
37058
+ path: external_exports.string().optional().default(".").describe("Path to search in."),
37059
+ exact: external_exports.boolean().optional().default(false).describe("Use exact matching instead of stemming."),
37060
+ maxTokensPerPage: external_exports.number().optional().default(2e4).describe("Tokens per page when paginating. Default 20000."),
37061
+ maxPages: external_exports.number().optional().default(50).describe("Maximum pages to retrieve. Default 50 (safety limit).")
37062
+ });
37055
37063
  querySchema = external_exports.object({
37056
37064
  pattern: external_exports.string().describe("AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc."),
37057
37065
  path: external_exports.string().optional().default(".").describe("Path to search in"),
@@ -49244,12 +49252,14 @@ var init_environment = __esm({
49244
49252
  init_common2();
49245
49253
  NATIVE_TOOL_SCHEMAS = {
49246
49254
  search: searchSchema,
49255
+ searchAll: searchAllSchema,
49247
49256
  query: querySchema,
49248
49257
  extract: extractSchema,
49249
49258
  bash: bashSchema
49250
49259
  };
49251
49260
  ALWAYS_ASYNC = /* @__PURE__ */ new Set([
49252
49261
  "search",
49262
+ "searchAll",
49253
49263
  "query",
49254
49264
  "extract",
49255
49265
  "listFiles",
@@ -56125,6 +56135,7 @@ function buildToolImplementations(configOptions) {
56125
56135
  if (!searchPaths || searchPaths.length === 0) {
56126
56136
  searchPaths = [cwd || "."];
56127
56137
  }
56138
+ const maxTokens = params.maxTokens !== void 0 ? params.maxTokens : 2e4;
56128
56139
  return await search({
56129
56140
  query: params.query,
56130
56141
  path: searchPaths.join(" "),
@@ -56132,7 +56143,7 @@ function buildToolImplementations(configOptions) {
56132
56143
  allowTests: true,
56133
56144
  exact: params.exact || false,
56134
56145
  json: false,
56135
- maxTokens: 2e4,
56146
+ maxTokens,
56136
56147
  session: sessionId,
56137
56148
  timeout: 60
56138
56149
  });
@@ -56141,6 +56152,56 @@ function buildToolImplementations(configOptions) {
56141
56152
  }
56142
56153
  }
56143
56154
  };
56155
+ tools2.searchAll = {
56156
+ execute: async (params) => {
56157
+ try {
56158
+ let searchPaths;
56159
+ if (params.path) {
56160
+ searchPaths = parseAndResolvePaths(params.path, cwd);
56161
+ }
56162
+ if (!searchPaths || searchPaths.length === 0) {
56163
+ searchPaths = [cwd || "."];
56164
+ }
56165
+ const pathStr = searchPaths.join(" ");
56166
+ const maxTokensPerPage = params.maxTokensPerPage || 2e4;
56167
+ const maxPages = params.maxPages || 50;
56168
+ let allResults = "";
56169
+ let pageCount = 0;
56170
+ while (pageCount < maxPages) {
56171
+ const pageResult = await search({
56172
+ query: params.query,
56173
+ path: pathStr,
56174
+ cwd,
56175
+ allowTests: true,
56176
+ exact: params.exact || false,
56177
+ json: false,
56178
+ maxTokens: maxTokensPerPage,
56179
+ session: sessionId,
56180
+ timeout: 60
56181
+ });
56182
+ pageCount++;
56183
+ if (!pageResult || pageResult.trim().length === 0) {
56184
+ break;
56185
+ }
56186
+ if (pageResult.includes("All results retrieved") || pageResult.includes("No results found") || pageResult.includes("No matching code blocks found")) {
56187
+ if (pageResult.trim().length > 50) {
56188
+ allResults += (allResults ? "\n\n" : "") + pageResult;
56189
+ }
56190
+ break;
56191
+ }
56192
+ allResults += (allResults ? "\n\n" : "") + pageResult;
56193
+ }
56194
+ if (pageCount >= maxPages) {
56195
+ allResults += `
56196
+
56197
+ [Warning: Reached maximum page limit (${maxPages}). Some results may be omitted.]`;
56198
+ }
56199
+ return allResults || "No results found.";
56200
+ } catch (e4) {
56201
+ return `SearchAll error: ${e4.message}`;
56202
+ }
56203
+ }
56204
+ };
56144
56205
  tools2.query = {
56145
56206
  execute: async (params) => {
56146
56207
  try {
@@ -56325,7 +56386,8 @@ ${lastError}
56325
56386
 
56326
56387
  RULES REMINDER:
56327
56388
  - search(query) is KEYWORD SEARCH \u2014 pass a search query, NOT a filename. Use extract(filepath) to read file contents.
56328
- - search(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
56389
+ - search() returns up to 20K tokens by default. Use search(query, path, {maxTokens: null}) for unlimited, or searchAll(query) to auto-paginate ALL results.
56390
+ - search(), searchAll(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
56329
56391
  - Use chunk(stringData) to split a string into an array of chunks.
56330
56392
  - Use map(array, fn) only with arrays. Do NOT pass strings to map().
56331
56393
  - Do NOT use .map(), .forEach(), .filter(), .join() \u2014 use for..of loops instead.
@@ -56626,7 +56688,8 @@ return table;
56626
56688
  ${funcList}
56627
56689
 
56628
56690
  **Return types \u2014 IMPORTANT:**
56629
- - \`search(query)\` \u2192 **keyword search** \u2014 pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets). To process parts, use \`chunk()\` to split it.
56691
+ - \`search(query)\` \u2192 **keyword search** \u2014 pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets, up to 20K tokens by default). Use \`{maxTokens: null}\` for unlimited.
56692
+ - \`searchAll(query)\` \u2192 **exhaustive keyword search** \u2014 auto-paginates to retrieve ALL matching results. Returns a **string** (all matching code snippets concatenated). Use for bulk analysis.
56630
56693
  - \`query(pattern)\` \u2192 **AST search** \u2014 pass a tree-sitter pattern. Returns a **string** (matching code elements).
56631
56694
  - \`extract(targets)\` \u2192 **read file contents** \u2014 pass a file path like "src/main.js" or "src/main.js:42". Use this to read specific files found by listFiles(). Returns a **string**.
56632
56695
  - \`listFiles(pattern)\` \u2192 **list files** \u2014 pass a glob pattern like "**/*.md". Returns an **array** of file path strings. Use directly with \`for (const f of listFiles("**/*.md"))\`.
package/cjs/index.cjs CHANGED
@@ -36203,7 +36203,7 @@ function resolveTargetPath(target, cwd) {
36203
36203
  }
36204
36204
  return filePart + suffix;
36205
36205
  }
36206
- var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
36206
+ var import_path6, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
36207
36207
  var init_common2 = __esm({
36208
36208
  "src/tools/common.js"() {
36209
36209
  "use strict";
@@ -36215,9 +36215,17 @@ var init_common2 = __esm({
36215
36215
  query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
36216
36216
  path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
36217
36217
  exact: external_exports.boolean().optional().default(false).describe('Default (false) enables stemming and keyword splitting for exploratory search - "getUserData" matches "get", "user", "data", etc. Set true for precise symbol lookup where "getUserData" matches only "getUserData". Use true when you know the exact symbol name.'),
36218
+ maxTokens: external_exports.number().nullable().optional().describe("Maximum tokens to return. Default is 20000. Set to null for unlimited results."),
36218
36219
  session: external_exports.string().optional().describe("Session ID for result caching and pagination. Pass the session ID from a previous search to get additional results (next page). Results already shown in a session are automatically excluded. Omit for a fresh search."),
36219
36220
  nextPage: external_exports.boolean().optional().default(false).describe("Set to true when requesting the next page of results. Requires passing the same session ID from the previous search output.")
36220
36221
  });
36222
+ searchAllSchema = external_exports.object({
36223
+ query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
36224
+ path: external_exports.string().optional().default(".").describe("Path to search in."),
36225
+ exact: external_exports.boolean().optional().default(false).describe("Use exact matching instead of stemming."),
36226
+ maxTokensPerPage: external_exports.number().optional().default(2e4).describe("Tokens per page when paginating. Default 20000."),
36227
+ maxPages: external_exports.number().optional().default(50).describe("Maximum pages to retrieve. Default 50 (safety limit).")
36228
+ });
36221
36229
  querySchema = external_exports.object({
36222
36230
  pattern: external_exports.string().describe("AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc."),
36223
36231
  path: external_exports.string().optional().default(".").describe("Path to search in"),
@@ -102069,12 +102077,14 @@ var init_environment = __esm({
102069
102077
  init_common2();
102070
102078
  NATIVE_TOOL_SCHEMAS = {
102071
102079
  search: searchSchema,
102080
+ searchAll: searchAllSchema,
102072
102081
  query: querySchema,
102073
102082
  extract: extractSchema,
102074
102083
  bash: bashSchema
102075
102084
  };
102076
102085
  ALWAYS_ASYNC = /* @__PURE__ */ new Set([
102077
102086
  "search",
102087
+ "searchAll",
102078
102088
  "query",
102079
102089
  "extract",
102080
102090
  "listFiles",
@@ -103898,6 +103908,7 @@ function buildToolImplementations(configOptions) {
103898
103908
  if (!searchPaths || searchPaths.length === 0) {
103899
103909
  searchPaths = [cwd || "."];
103900
103910
  }
103911
+ const maxTokens = params.maxTokens !== void 0 ? params.maxTokens : 2e4;
103901
103912
  return await search({
103902
103913
  query: params.query,
103903
103914
  path: searchPaths.join(" "),
@@ -103905,7 +103916,7 @@ function buildToolImplementations(configOptions) {
103905
103916
  allowTests: true,
103906
103917
  exact: params.exact || false,
103907
103918
  json: false,
103908
- maxTokens: 2e4,
103919
+ maxTokens,
103909
103920
  session: sessionId,
103910
103921
  timeout: 60
103911
103922
  });
@@ -103914,6 +103925,56 @@ function buildToolImplementations(configOptions) {
103914
103925
  }
103915
103926
  }
103916
103927
  };
103928
+ tools2.searchAll = {
103929
+ execute: async (params) => {
103930
+ try {
103931
+ let searchPaths;
103932
+ if (params.path) {
103933
+ searchPaths = parseAndResolvePaths(params.path, cwd);
103934
+ }
103935
+ if (!searchPaths || searchPaths.length === 0) {
103936
+ searchPaths = [cwd || "."];
103937
+ }
103938
+ const pathStr = searchPaths.join(" ");
103939
+ const maxTokensPerPage = params.maxTokensPerPage || 2e4;
103940
+ const maxPages = params.maxPages || 50;
103941
+ let allResults = "";
103942
+ let pageCount = 0;
103943
+ while (pageCount < maxPages) {
103944
+ const pageResult = await search({
103945
+ query: params.query,
103946
+ path: pathStr,
103947
+ cwd,
103948
+ allowTests: true,
103949
+ exact: params.exact || false,
103950
+ json: false,
103951
+ maxTokens: maxTokensPerPage,
103952
+ session: sessionId,
103953
+ timeout: 60
103954
+ });
103955
+ pageCount++;
103956
+ if (!pageResult || pageResult.trim().length === 0) {
103957
+ break;
103958
+ }
103959
+ if (pageResult.includes("All results retrieved") || pageResult.includes("No results found") || pageResult.includes("No matching code blocks found")) {
103960
+ if (pageResult.trim().length > 50) {
103961
+ allResults += (allResults ? "\n\n" : "") + pageResult;
103962
+ }
103963
+ break;
103964
+ }
103965
+ allResults += (allResults ? "\n\n" : "") + pageResult;
103966
+ }
103967
+ if (pageCount >= maxPages) {
103968
+ allResults += `
103969
+
103970
+ [Warning: Reached maximum page limit (${maxPages}). Some results may be omitted.]`;
103971
+ }
103972
+ return allResults || "No results found.";
103973
+ } catch (e4) {
103974
+ return `SearchAll error: ${e4.message}`;
103975
+ }
103976
+ }
103977
+ };
103917
103978
  tools2.query = {
103918
103979
  execute: async (params) => {
103919
103980
  try {
@@ -104098,7 +104159,8 @@ ${lastError}
104098
104159
 
104099
104160
  RULES REMINDER:
104100
104161
  - search(query) is KEYWORD SEARCH \u2014 pass a search query, NOT a filename. Use extract(filepath) to read file contents.
104101
- - search(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
104162
+ - search() returns up to 20K tokens by default. Use search(query, path, {maxTokens: null}) for unlimited, or searchAll(query) to auto-paginate ALL results.
104163
+ - search(), searchAll(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
104102
104164
  - Use chunk(stringData) to split a string into an array of chunks.
104103
104165
  - Use map(array, fn) only with arrays. Do NOT pass strings to map().
104104
104166
  - Do NOT use .map(), .forEach(), .filter(), .join() \u2014 use for..of loops instead.
@@ -104399,7 +104461,8 @@ return table;
104399
104461
  ${funcList}
104400
104462
 
104401
104463
  **Return types \u2014 IMPORTANT:**
104402
- - \`search(query)\` \u2192 **keyword search** \u2014 pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets). To process parts, use \`chunk()\` to split it.
104464
+ - \`search(query)\` \u2192 **keyword search** \u2014 pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets, up to 20K tokens by default). Use \`{maxTokens: null}\` for unlimited.
104465
+ - \`searchAll(query)\` \u2192 **exhaustive keyword search** \u2014 auto-paginates to retrieve ALL matching results. Returns a **string** (all matching code snippets concatenated). Use for bulk analysis.
104403
104466
  - \`query(pattern)\` \u2192 **AST search** \u2014 pass a tree-sitter pattern. Returns a **string** (matching code elements).
104404
104467
  - \`extract(targets)\` \u2192 **read file contents** \u2014 pass a file path like "src/main.js" or "src/main.js:42". Use this to read specific files found by listFiles(). Returns a **string**.
104405
104468
  - \`listFiles(pattern)\` \u2192 **list files** \u2014 pass a glob pattern like "**/*.md". Returns an **array** of file path strings. Use directly with \`for (const f of listFiles("**/*.md"))\`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe",
3
- "version": "0.6.0-rc248",
3
+ "version": "0.6.0-rc249",
4
4
  "description": "Node.js wrapper for the probe code search tool",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -8,6 +8,7 @@
8
8
 
9
9
  import {
10
10
  searchSchema,
11
+ searchAllSchema,
11
12
  querySchema,
12
13
  extractSchema,
13
14
  bashSchema,
@@ -16,6 +17,7 @@ import {
16
17
  // Map of native tool names to their Zod schemas
17
18
  const NATIVE_TOOL_SCHEMAS = {
18
19
  search: searchSchema,
20
+ searchAll: searchAllSchema,
19
21
  query: querySchema,
20
22
  extract: extractSchema,
21
23
  bash: bashSchema,
@@ -23,7 +25,7 @@ const NATIVE_TOOL_SCHEMAS = {
23
25
 
24
26
  // Tools that are inherently async (make network/LLM calls)
25
27
  const ALWAYS_ASYNC = new Set([
26
- 'search', 'query', 'extract', 'listFiles', 'searchFiles', 'bash',
28
+ 'search', 'searchAll', 'query', 'extract', 'listFiles', 'searchFiles', 'bash',
27
29
  'LLM', 'map',
28
30
  ]);
29
31
 
@@ -13,10 +13,19 @@ export const searchSchema = z.object({
13
13
  query: z.string().describe('Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation.'),
14
14
  path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
15
15
  exact: z.boolean().optional().default(false).describe('Default (false) enables stemming and keyword splitting for exploratory search - "getUserData" matches "get", "user", "data", etc. Set true for precise symbol lookup where "getUserData" matches only "getUserData". Use true when you know the exact symbol name.'),
16
+ maxTokens: z.number().nullable().optional().describe('Maximum tokens to return. Default is 20000. Set to null for unlimited results.'),
16
17
  session: z.string().optional().describe('Session ID for result caching and pagination. Pass the session ID from a previous search to get additional results (next page). Results already shown in a session are automatically excluded. Omit for a fresh search.'),
17
18
  nextPage: z.boolean().optional().default(false).describe('Set to true when requesting the next page of results. Requires passing the same session ID from the previous search output.')
18
19
  });
19
20
 
21
+ export const searchAllSchema = z.object({
22
+ query: z.string().describe('Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation.'),
23
+ path: z.string().optional().default('.').describe('Path to search in.'),
24
+ exact: z.boolean().optional().default(false).describe('Use exact matching instead of stemming.'),
25
+ maxTokensPerPage: z.number().optional().default(20000).describe('Tokens per page when paginating. Default 20000.'),
26
+ maxPages: z.number().optional().default(50).describe('Maximum pages to retrieve. Default 50 (safety limit).')
27
+ });
28
+
20
29
  export const querySchema = z.object({
21
30
  pattern: z.string().describe('AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc.'),
22
31
  path: z.string().optional().default('.').describe('Path to search in'),
@@ -85,6 +85,8 @@ function buildToolImplementations(configOptions) {
85
85
  if (!searchPaths || searchPaths.length === 0) {
86
86
  searchPaths = [cwd || '.'];
87
87
  }
88
+ // Allow maxTokens to be passed through (null = unlimited, undefined = default 20000)
89
+ const maxTokens = params.maxTokens !== undefined ? params.maxTokens : 20000;
88
90
  return await search({
89
91
  query: params.query,
90
92
  path: searchPaths.join(' '),
@@ -92,7 +94,7 @@ function buildToolImplementations(configOptions) {
92
94
  allowTests: true,
93
95
  exact: params.exact || false,
94
96
  json: false,
95
- maxTokens: 20000,
97
+ maxTokens,
96
98
  session: sessionId,
97
99
  timeout: 60,
98
100
  });
@@ -102,6 +104,70 @@ function buildToolImplementations(configOptions) {
102
104
  },
103
105
  };
104
106
 
107
+ // searchAll: auto-paginating search that retrieves ALL results
108
+ // Calls search() repeatedly with same sessionId until no more results
109
+ tools.searchAll = {
110
+ execute: async (params) => {
111
+ try {
112
+ let searchPaths;
113
+ if (params.path) {
114
+ searchPaths = parseAndResolvePaths(params.path, cwd);
115
+ }
116
+ if (!searchPaths || searchPaths.length === 0) {
117
+ searchPaths = [cwd || '.'];
118
+ }
119
+ const pathStr = searchPaths.join(' ');
120
+ const maxTokensPerPage = params.maxTokensPerPage || 20000;
121
+ const maxPages = params.maxPages || 50; // Safety limit
122
+
123
+ let allResults = '';
124
+ let pageCount = 0;
125
+
126
+ while (pageCount < maxPages) {
127
+ const pageResult = await search({
128
+ query: params.query,
129
+ path: pathStr,
130
+ cwd,
131
+ allowTests: true,
132
+ exact: params.exact || false,
133
+ json: false,
134
+ maxTokens: maxTokensPerPage,
135
+ session: sessionId,
136
+ timeout: 60,
137
+ });
138
+
139
+ pageCount++;
140
+
141
+ // Check if we got results
142
+ if (!pageResult || pageResult.trim().length === 0) {
143
+ break;
144
+ }
145
+
146
+ // Check for "All results retrieved" or "No results found" signals
147
+ if (pageResult.includes('All results retrieved') ||
148
+ pageResult.includes('No results found') ||
149
+ pageResult.includes('No matching code blocks found')) {
150
+ // Include this final page if it has content beyond the message
151
+ if (pageResult.trim().length > 50) {
152
+ allResults += (allResults ? '\n\n' : '') + pageResult;
153
+ }
154
+ break;
155
+ }
156
+
157
+ allResults += (allResults ? '\n\n' : '') + pageResult;
158
+ }
159
+
160
+ if (pageCount >= maxPages) {
161
+ allResults += `\n\n[Warning: Reached maximum page limit (${maxPages}). Some results may be omitted.]`;
162
+ }
163
+
164
+ return allResults || 'No results found.';
165
+ } catch (e) {
166
+ return `SearchAll error: ${e.message}`;
167
+ }
168
+ },
169
+ };
170
+
105
171
  tools.query = {
106
172
  execute: async (params) => {
107
173
  try {
@@ -345,7 +411,8 @@ ${lastError}
345
411
 
346
412
  RULES REMINDER:
347
413
  - search(query) is KEYWORD SEARCH — pass a search query, NOT a filename. Use extract(filepath) to read file contents.
348
- - search(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
414
+ - search() returns up to 20K tokens by default. Use search(query, path, {maxTokens: null}) for unlimited, or searchAll(query) to auto-paginate ALL results.
415
+ - search(), searchAll(), query(), extract(), listFiles(), bash() all return STRINGS, not arrays.
349
416
  - Use chunk(stringData) to split a string into an array of chunks.
350
417
  - Use map(array, fn) only with arrays. Do NOT pass strings to map().
351
418
  - Do NOT use .map(), .forEach(), .filter(), .join() — use for..of loops instead.
@@ -684,7 +751,8 @@ return table;
684
751
  ${funcList}
685
752
 
686
753
  **Return types — IMPORTANT:**
687
- - \`search(query)\` → **keyword search** — pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets). To process parts, use \`chunk()\` to split it.
754
+ - \`search(query)\` → **keyword search** — pass a search query (e.g. "error handling"), NOT a filename. Returns a **string** (matching code snippets, up to 20K tokens by default). Use \`{maxTokens: null}\` for unlimited.
755
+ - \`searchAll(query)\` → **exhaustive keyword search** — auto-paginates to retrieve ALL matching results. Returns a **string** (all matching code snippets concatenated). Use for bulk analysis.
688
756
  - \`query(pattern)\` → **AST search** — pass a tree-sitter pattern. Returns a **string** (matching code elements).
689
757
  - \`extract(targets)\` → **read file contents** — pass a file path like "src/main.js" or "src/main.js:42". Use this to read specific files found by listFiles(). Returns a **string**.
690
758
  - \`listFiles(pattern)\` → **list files** — pass a glob pattern like "**/*.md". Returns an **array** of file path strings. Use directly with \`for (const f of listFiles("**/*.md"))\`.