deepagents 1.12.1 → 1.12.2

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.
@@ -530,9 +530,12 @@ function adaptBackendProtocol(backend) {
530
530
  if (typeof result === "string") return { content: result };
531
531
  return result;
532
532
  },
533
- async grep(pattern, path, glob) {
534
- const result = await ("grep" in backend ? backend.grep(pattern, path, glob) : backend.grepRaw(pattern, path, glob));
535
- if (Array.isArray(result)) return { matches: result };
533
+ async grep(pattern, path, glob, maxCount) {
534
+ const result = await ("grep" in backend ? backend.grep(pattern, path, glob, maxCount) : backend.grepRaw(pattern, path, glob));
535
+ if (Array.isArray(result)) return applyGrepMaxCount({
536
+ result: { matches: result },
537
+ maxCount
538
+ });
536
539
  if (typeof result === "string") return { error: result };
537
540
  return result;
538
541
  }
@@ -567,6 +570,21 @@ function adaptSandboxProtocol(sandbox) {
567
570
  //#endregion
568
571
  //#region src/backends/protocol.ts
569
572
  /**
573
+ * Enforce a match cap after a backend grep has completed.
574
+ *
575
+ * When `maxCount` is set and the result exceeds it, the matches are sliced
576
+ * to the cap and the result is flagged `truncated: true`.
577
+ */
578
+ function applyGrepMaxCount(params) {
579
+ const { result, maxCount } = params;
580
+ if (maxCount == null || result.matches == null || result.matches.length <= maxCount) return result;
581
+ return {
582
+ error: result.error,
583
+ matches: result.matches.slice(0, maxCount),
584
+ truncated: true
585
+ };
586
+ }
587
+ /**
570
588
  * Type guard to check if a backend supports execution.
571
589
  *
572
590
  * @param backend - Backend instance to check
@@ -847,9 +865,12 @@ var StateBackend = class {
847
865
  * Search file contents for a literal text pattern.
848
866
  * Binary files are skipped.
849
867
  */
850
- grep(pattern, path = "/", glob = null) {
868
+ grep(pattern, path = "/", glob = null, maxCount = null) {
851
869
  const files = this.files;
852
- return { matches: grepMatchesFromFiles(files, pattern, path, glob) };
870
+ return applyGrepMaxCount({
871
+ result: { matches: grepMatchesFromFiles(files, pattern, path, glob) },
872
+ maxCount
873
+ });
853
874
  }
854
875
  /**
855
876
  * Structured glob matching returning FileInfo objects.
@@ -1091,7 +1112,7 @@ var CompositeBackend = class {
1091
1112
  const results = [];
1092
1113
  const defaultResult = await this.default.ls(path);
1093
1114
  if (defaultResult.error) return defaultResult;
1094
- results.push(...defaultResult.files || []);
1115
+ for (const fi of defaultResult.files || []) results.push(fi);
1095
1116
  for (const [routePrefix] of this.sortedRoutes) results.push({
1096
1117
  path: routePrefix,
1097
1118
  is_dir: true,
@@ -1127,33 +1148,56 @@ var CompositeBackend = class {
1127
1148
  }
1128
1149
  /**
1129
1150
  * Structured search results or error string for invalid input.
1151
+ *
1152
+ * @param maxCount - Optional total cap on returned matches across all routed
1153
+ * backends. When the cap is reached, remaining routes are
1154
+ * short-circuited and the result is flagged `truncated: true`.
1130
1155
  */
1131
- async grep(pattern, path = "/", glob = null) {
1156
+ async grep(pattern, path = "/", glob = null, maxCount = null) {
1132
1157
  const searchPath = path || "/";
1133
1158
  for (const [routePrefix, backend] of this.sortedRoutes) if (this.isPathWithinRoute(searchPath, routePrefix)) {
1134
1159
  const routeSearchPath = searchPath.substring(routePrefix.length - 1);
1135
- const raw = await backend.grep(pattern, routeSearchPath || "/", glob);
1160
+ const raw = await backend.grep(pattern, routeSearchPath || "/", glob, maxCount);
1136
1161
  if (raw.error) return raw;
1137
- return { matches: (raw.matches || []).map((m) => ({
1138
- ...m,
1139
- path: routePrefix.slice(0, -1) + m.path
1140
- })) };
1162
+ return applyGrepMaxCount({
1163
+ result: {
1164
+ matches: (raw.matches || []).map((m) => ({
1165
+ ...m,
1166
+ path: routePrefix.slice(0, -1) + m.path
1167
+ })),
1168
+ truncated: raw.truncated
1169
+ },
1170
+ maxCount
1171
+ });
1141
1172
  }
1142
1173
  const allMatches = [];
1143
- const rawDefault = await this.default.grep(pattern, searchPath, glob);
1174
+ let truncated = false;
1175
+ const rawDefault = await this.default.grep(pattern, searchPath, glob, maxCount);
1144
1176
  if (rawDefault.error) return rawDefault;
1145
- allMatches.push(...rawDefault.matches || []);
1177
+ for (const m of rawDefault.matches || []) allMatches.push(m);
1178
+ truncated = truncated || rawDefault.truncated === true;
1146
1179
  for (const [routePrefix, backend] of Object.entries(this.routes)) {
1147
1180
  if (!this.isRouteUnderPath(routePrefix, searchPath)) continue;
1148
- const raw = await backend.grep(pattern, "/", glob);
1181
+ const remaining = maxCount == null ? null : Math.max(maxCount - allMatches.length, 0);
1182
+ if (remaining === 0) {
1183
+ truncated = true;
1184
+ break;
1185
+ }
1186
+ const raw = await backend.grep(pattern, "/", glob, remaining);
1149
1187
  if (raw.error) return raw;
1150
- const matches = (raw.matches || []).map((m) => ({
1188
+ for (const m of raw.matches || []) allMatches.push({
1151
1189
  ...m,
1152
1190
  path: routePrefix.slice(0, -1) + m.path
1153
- }));
1154
- allMatches.push(...matches);
1191
+ });
1192
+ truncated = truncated || raw.truncated === true;
1155
1193
  }
1156
- return { matches: allMatches };
1194
+ return applyGrepMaxCount({
1195
+ result: {
1196
+ matches: allMatches,
1197
+ truncated
1198
+ },
1199
+ maxCount
1200
+ });
1157
1201
  }
1158
1202
  /**
1159
1203
  * Structured glob matching returning FileInfo objects.
@@ -1164,26 +1208,33 @@ var CompositeBackend = class {
1164
1208
  const searchPath = path.substring(routePrefix.length - 1);
1165
1209
  const result = await backend.glob(pattern, searchPath || "/");
1166
1210
  if (result.error) return result;
1167
- return { files: (result.files || []).map((fi) => ({
1168
- ...fi,
1169
- path: routePrefix.slice(0, -1) + fi.path
1170
- })) };
1211
+ return {
1212
+ files: (result.files || []).map((fi) => ({
1213
+ ...fi,
1214
+ path: routePrefix.slice(0, -1) + fi.path
1215
+ })),
1216
+ truncated: result.truncated
1217
+ };
1171
1218
  }
1172
1219
  const defaultResult = await this.default.glob(pattern, path);
1173
1220
  if (defaultResult.error) return defaultResult;
1174
- results.push(...defaultResult.files || []);
1221
+ for (const fi of defaultResult.files || []) results.push(fi);
1222
+ let truncated = defaultResult.truncated === true;
1175
1223
  for (const [routePrefix, backend] of Object.entries(this.routes)) {
1176
1224
  if (!this.isRouteUnderPath(routePrefix, path)) continue;
1177
1225
  const result = await backend.glob(pattern, "/");
1178
1226
  if (result.error) continue;
1179
- const files = (result.files || []).map((fi) => ({
1227
+ for (const fi of result.files || []) results.push({
1180
1228
  ...fi,
1181
1229
  path: routePrefix.slice(0, -1) + fi.path
1182
- }));
1183
- results.push(...files);
1230
+ });
1231
+ truncated = truncated || result.truncated === true;
1184
1232
  }
1185
1233
  results.sort((a, b) => a.path.localeCompare(b.path));
1186
- return { files: results };
1234
+ return {
1235
+ files: results,
1236
+ truncated
1237
+ };
1187
1238
  }
1188
1239
  /**
1189
1240
  * Write content to a file, routing to appropriate backend.
@@ -1379,6 +1430,15 @@ const READ_FILE_TRUNCATION_MSG = `
1379
1430
 
1380
1431
  [Output was truncated due to size limits. The file content is very large. Consider reformatting the file to make it easier to navigate. For example, if this is JSON, use execute(command='jq . {file_path}') to pretty-print it with line breaks. For other formats, you can use appropriate formatting tools to split long lines.]`;
1381
1432
  /**
1433
+ * Note appended to grep results that were cut short by the match-count cap.
1434
+ */
1435
+ const GREP_TRUNCATION_NOTE = "Note: the search stopped early because it hit the maximum match count. The matches above are valid but incomplete. Narrow the search (a more specific pattern or a narrower path), or raise max_count, to see the rest.";
1436
+ /**
1437
+ * Default cap on the number of matches the grep tool returns.
1438
+ * Set to null to disable the cap.
1439
+ */
1440
+ const DEFAULT_GREP_MAX_COUNT = 1e3;
1441
+ /**
1382
1442
  * Message template for evicted tool results.
1383
1443
  */
1384
1444
  const TOO_LARGE_TOOL_MSG = context`
@@ -1867,13 +1927,14 @@ function createGlobTool(backend, options) {
1867
1927
  * Create grep tool using backend.
1868
1928
  */
1869
1929
  function createGrepTool(backend, options) {
1870
- const { customDescription, permissions, includeExecution } = options;
1930
+ const { customDescription, permissions, includeExecution, grepMaxCount } = options;
1871
1931
  return tool(async (input, runtime) => {
1872
1932
  const permissionError = checkPermission(permissions, "read", input.path ?? "/");
1873
1933
  if (permissionError !== void 0) return toolError(runtime, "grep", permissionError);
1874
1934
  const resolvedBackend = await resolveBackend(backend, runtime);
1875
1935
  const { pattern, path = "/", glob = null } = input;
1876
- const result = await resolvedBackend.grep(pattern, path, glob);
1936
+ const maxCount = input.max_count ?? grepMaxCount;
1937
+ const result = await resolvedBackend.grep(pattern, path, glob, maxCount);
1877
1938
  if (result.error) return result.error;
1878
1939
  const matches = filterByPermissions(result.matches ?? [], permissions, "read", (m) => m.path);
1879
1940
  if (matches.length === 0) return `No matches found for pattern '${pattern}'`;
@@ -1887,15 +1948,17 @@ function createGrepTool(backend, options) {
1887
1948
  lines.push(` ${match.line}: ${match.text}`);
1888
1949
  }
1889
1950
  const truncated = truncateIfTooLong(lines);
1890
- if (Array.isArray(truncated)) return truncated.join("\n");
1891
- return truncated;
1951
+ let content = Array.isArray(truncated) ? truncated.join("\n") : truncated;
1952
+ if (result.truncated) content += `\n\n${GREP_TRUNCATION_NOTE}`;
1953
+ return content;
1892
1954
  }, {
1893
1955
  name: "grep",
1894
1956
  description: customDescription || getGrepToolDescription(includeExecution),
1895
1957
  schema: z.object({
1896
1958
  pattern: z.string().describe("Literal text pattern to search for (not regex)"),
1897
1959
  path: z.string().optional().default("/").describe("Base path to search from (default: /)"),
1898
- glob: z.string().optional().nullable().default(null).describe("Optional glob pattern to filter files (e.g., '*.py')")
1960
+ glob: z.string().optional().nullable().default(null).describe("Optional glob pattern to filter files (e.g., '*.py')"),
1961
+ max_count: z.number().int().positive().optional().nullable().default(null).describe("Optional cap on the total number of matches returned across all files. Leave unset to use the configured default. When the cap is hit, results are truncated and a note says so; narrow the pattern or path to see the rest.")
1899
1962
  })
1900
1963
  });
1901
1964
  }
@@ -1964,7 +2027,7 @@ function allPathsScopedToRoutes(permissions, backend) {
1964
2027
  * ```
1965
2028
  */
1966
2029
  function createFilesystemMiddleware(options = {}) {
1967
- const { backend = (runtime) => new StateBackend(runtime), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4, humanMessageTokenLimitBeforeEvict = 5e4, permissions = [], tools: filesystemTools = null } = options;
2030
+ const { backend = (runtime) => new StateBackend(runtime), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4, humanMessageTokenLimitBeforeEvict = 5e4, permissions = [], tools: filesystemTools = null, grepMaxCount = DEFAULT_GREP_MAX_COUNT } = options;
1968
2031
  const enabledFilesystemTools = normalizeFilesystemTools(filesystemTools);
1969
2032
  const executeToolEnabled = enabledFilesystemTools == null || enabledFilesystemTools.has("execute");
1970
2033
  if (permissions.length > 0) validatePermissionPaths(permissions);
@@ -2000,7 +2063,8 @@ function createFilesystemMiddleware(options = {}) {
2000
2063
  grep: createGrepTool(backend, {
2001
2064
  customDescription: customToolDescriptions?.grep,
2002
2065
  permissions,
2003
- includeExecution: configuredToolNames.has("execute") && typeof backend !== "function" && isSandboxBackend(backend)
2066
+ includeExecution: configuredToolNames.has("execute") && typeof backend !== "function" && isSandboxBackend(backend),
2067
+ grepMaxCount
2004
2068
  }),
2005
2069
  execute: createExecuteTool(backend, {
2006
2070
  customDescription: customToolDescriptions?.execute,
@@ -6357,7 +6421,7 @@ var StoreBackend = class {
6357
6421
  * Search file contents for a literal text pattern.
6358
6422
  * Binary files are skipped.
6359
6423
  */
6360
- async grep(pattern, path = "/", glob = null) {
6424
+ async grep(pattern, path = "/", glob = null, maxCount = null) {
6361
6425
  const store = this.getStore();
6362
6426
  const namespace = this.getNamespace();
6363
6427
  const items = await this.searchStorePaginated(store, namespace);
@@ -6367,7 +6431,10 @@ var StoreBackend = class {
6367
6431
  } catch {
6368
6432
  continue;
6369
6433
  }
6370
- return { matches: grepMatchesFromFiles(files, pattern, path, glob) };
6434
+ return applyGrepMaxCount({
6435
+ result: { matches: grepMatchesFromFiles(files, pattern, path, glob) },
6436
+ maxCount
6437
+ });
6371
6438
  }
6372
6439
  /**
6373
6440
  * Structured glob matching returning FileInfo objects.
@@ -6666,7 +6733,7 @@ var ContextHubBackend = class ContextHubBackend {
6666
6733
  modified_at: now
6667
6734
  } };
6668
6735
  }
6669
- async grep(pattern, path = null, glob = null) {
6736
+ async grep(pattern, path = null, glob = null, maxCount = null) {
6670
6737
  let cache;
6671
6738
  try {
6672
6739
  cache = await this.ensureCache();
@@ -6689,7 +6756,10 @@ var ContextHubBackend = class ContextHubBackend {
6689
6756
  });
6690
6757
  }
6691
6758
  }
6692
- return { matches };
6759
+ return applyGrepMaxCount({
6760
+ result: { matches },
6761
+ maxCount
6762
+ });
6693
6763
  }
6694
6764
  async glob(pattern, _path = "/") {
6695
6765
  let cache;
@@ -7085,7 +7155,7 @@ var BaseSandbox = class {
7085
7155
  * @param glob - Optional glob pattern to filter which files to search.
7086
7156
  * @returns List of GrepMatch dicts containing path, line number, and matched text.
7087
7157
  */
7088
- async grep(pattern, path = "/", glob = null) {
7158
+ async grep(pattern, path = "/", glob = null, maxCount = null) {
7089
7159
  const command = buildGrepCommand(pattern, path, glob);
7090
7160
  const output = (await this.execute(command)).output.trim();
7091
7161
  if (!output) return { matches: [] };
@@ -7103,7 +7173,10 @@ var BaseSandbox = class {
7103
7173
  });
7104
7174
  }
7105
7175
  }
7106
- return { matches };
7176
+ return applyGrepMaxCount({
7177
+ result: { matches },
7178
+ maxCount
7179
+ });
7107
7180
  }
7108
7181
  /**
7109
7182
  * Structured glob matching returning FileInfo objects.
@@ -7458,6 +7531,6 @@ var LangSmithSandbox = class LangSmithSandbox extends BaseSandbox {
7458
7531
  }
7459
7532
  };
7460
7533
  //#endregion
7461
- export { filesValue as A, StateBackend as B, createSummarizationMiddleware as C, MAX_SKILL_NAME_LENGTH as D, MAX_SKILL_FILE_SIZE as E, SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY as F, adaptBackendProtocol as G, isSandboxBackend as H, createSubAgent as I, getMimeType as J, adaptSandboxProtocol as K, createSubAgentMiddleware as L, DEFAULT_GENERAL_PURPOSE_DESCRIPTION as M, DEFAULT_SUBAGENT_PROMPT as N, createSkillsMiddleware as O, GENERAL_PURPOSE_SUBAGENT as P, createFilesystemMiddleware as R, computeSummarizationDefaults as S, MAX_SKILL_DESCRIPTION_LENGTH as T, isSandboxProtocol as U, SandboxError as V, resolveBackend as W, performStringReplacement as X, isTextMimeType as Y, createHarnessProfile as _, ASYNC_TASK_SYSTEM_PROMPT as a, createAsyncSubAgentMiddleware as b, TASK_SYSTEM_PROMPT as c, registerHarnessProfile as d, generalPurposeSubagentConfigSchema as f, EMPTY_HARNESS_PROFILE as g, serializeProfile as h, StoreBackend as i, createPatchToolCallsMiddleware as j, createMemoryMiddleware as k, createDeepAgent as l, parseHarnessProfileConfig as m, BaseSandbox as n, BASE_AGENT_PROMPT as o, harnessProfileConfigSchema as p, checkEmptyContent as q, ContextHubBackend as r, EXECUTION_SYSTEM_PROMPT as s, LangSmithSandbox as t, getHarnessProfile as u, REQUIRED_MIDDLEWARE_NAMES as v, createCompletionCallbackMiddleware as w, isAsyncSubAgent as x, ConfigurationError as y, CompositeBackend as z };
7534
+ export { filesValue as A, StateBackend as B, createSummarizationMiddleware as C, MAX_SKILL_NAME_LENGTH as D, MAX_SKILL_FILE_SIZE as E, SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY as F, resolveBackend as G, applyGrepMaxCount as H, createSubAgent as I, checkEmptyContent as J, adaptBackendProtocol as K, createSubAgentMiddleware as L, DEFAULT_GENERAL_PURPOSE_DESCRIPTION as M, DEFAULT_SUBAGENT_PROMPT as N, createSkillsMiddleware as O, GENERAL_PURPOSE_SUBAGENT as P, createFilesystemMiddleware as R, computeSummarizationDefaults as S, MAX_SKILL_DESCRIPTION_LENGTH as T, isSandboxBackend as U, SandboxError as V, isSandboxProtocol as W, isTextMimeType as X, getMimeType as Y, performStringReplacement as Z, createHarnessProfile as _, ASYNC_TASK_SYSTEM_PROMPT as a, createAsyncSubAgentMiddleware as b, TASK_SYSTEM_PROMPT as c, registerHarnessProfile as d, generalPurposeSubagentConfigSchema as f, EMPTY_HARNESS_PROFILE as g, serializeProfile as h, StoreBackend as i, createPatchToolCallsMiddleware as j, createMemoryMiddleware as k, createDeepAgent as l, parseHarnessProfileConfig as m, BaseSandbox as n, BASE_AGENT_PROMPT as o, harnessProfileConfigSchema as p, adaptSandboxProtocol as q, ContextHubBackend as r, EXECUTION_SYSTEM_PROMPT as s, LangSmithSandbox as t, getHarnessProfile as u, REQUIRED_MIDDLEWARE_NAMES as v, createCompletionCallbackMiddleware as w, isAsyncSubAgent as x, ConfigurationError as y, CompositeBackend as z };
7462
7535
 
7463
- //# sourceMappingURL=langsmith-DgbmWtWj.js.map
7536
+ //# sourceMappingURL=langsmith-b3Dpu8rS.js.map