deepagents 1.10.5 → 1.10.7

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.
@@ -424,16 +424,19 @@ function grepMatchesFromFiles(files, pattern, path = null, glob = null) {
424
424
  /**
425
425
  * Determine MIME type from a file path's extension.
426
426
  *
427
- * Returns "application/octet-stream" for unknown extensions so that
428
- * binary files are not accidentally treated as text (grep, read_file,
429
- * etc. rely on {@link isTextMimeType} which would return true for
430
- * "text/plain").
427
+ * Defaults to "text/plain" for unknown extensions. Only the known non-text
428
+ * formats above (images, audio, video, PDF/PPT) are treated as binary by
429
+ * {@link isTextMimeType}; everything else reads as text, including source files
430
+ * with uncommon extensions (.properties, .scss, .tf) and extension-less files
431
+ * (Dockerfile, mvnw). This avoids base64-encoding text into document blocks,
432
+ * which the model can't read and which the Anthropic provider rejects with a
433
+ * 400.
431
434
  *
432
435
  * @param filePath - File path to inspect
433
- * @returns MIME type string (e.g., "image/png", "application/octet-stream")
436
+ * @returns MIME type string (e.g., "image/png", "text/plain")
434
437
  */
435
438
  function getMimeType(filePath) {
436
- return MIME_TYPES[extname(filePath).toLocaleLowerCase()] || "application/octet-stream";
439
+ return MIME_TYPES[extname(filePath).toLocaleLowerCase()] || "text/plain";
437
440
  }
438
441
  /**
439
442
  * Check whether a MIME type represents text content.
@@ -1269,6 +1272,22 @@ var CompositeBackend = class {
1269
1272
  */
1270
1273
  const INT_FORMATTER = new Intl.NumberFormat("en-US");
1271
1274
  /**
1275
+ * Normalizes tool input so that models sending `path` instead of `file_path`
1276
+ * still work. If the input has `path` but not `file_path`, copies `path` into
1277
+ * `file_path`. This makes the filesystem tools resilient to parameter-name
1278
+ * variations across models of different capability levels.
1279
+ */
1280
+ function normalizeFilePathInput(input) {
1281
+ if (typeof input === "object" && input !== null && "path" in input && !("file_path" in input)) {
1282
+ const { path, ...rest } = input;
1283
+ return {
1284
+ ...rest,
1285
+ file_path: path
1286
+ };
1287
+ }
1288
+ return input;
1289
+ }
1290
+ /**
1272
1291
  * Tools that should be excluded from the large result eviction logic.
1273
1292
  *
1274
1293
  * This array contains tools that should NOT have their results evicted to the filesystem
@@ -1545,10 +1564,10 @@ const READ_FILE_TOOL_DESCRIPTION = langchain.context`
1545
1564
  Usage:
1546
1565
  - By default, it reads up to ${100} lines starting from the beginning of the file
1547
1566
  - **IMPORTANT for large files and codebase exploration**: Use pagination with offset and limit parameters to avoid context overflow
1548
- - First scan: read_file(path, limit=${100}) to see file structure
1549
- - Read more sections: read_file(path, offset=${100}, limit=200) for next 200 lines
1567
+ - First scan: read_file(file_path, limit=${100}) to see file structure
1568
+ - Read more sections: read_file(file_path, offset=${100}, limit=200) for next 200 lines
1550
1569
  - Only omit limit (read full file) when necessary for editing
1551
- - Specify offset and limit: read_file(path, offset=0, limit=${100}) reads first ${100} lines
1570
+ - Specify offset and limit: read_file(file_path, offset=0, limit=${100}) reads first ${100} lines
1552
1571
  - Results are returned using cat -n format, with line numbers starting at 1
1553
1572
  - Lines longer than ${INT_FORMATTER.format(MAX_LINE_LENGTH)} characters will be split into multiple lines with continuation markers (e.g., 5.1, 5.2, etc.). When you specify a limit, these continuation lines count towards the limit.
1554
1573
  - You have the capability to call multiple tools in a single response. It is always better to speculatively read multiple files as a batch that are potentially useful.
@@ -1746,11 +1765,11 @@ function createReadFileTool(backend, options) {
1746
1765
  }, {
1747
1766
  name: "read_file",
1748
1767
  description: customDescription || READ_FILE_TOOL_DESCRIPTION,
1749
- schema: zod_v4.z.object({
1768
+ schema: zod_v4.z.preprocess(normalizeFilePathInput, zod_v4.z.object({
1750
1769
  file_path: zod_v4.z.string().describe("Absolute path to the file to read"),
1751
1770
  offset: zod_v4.z.coerce.number().optional().default(0).describe("Line offset to start reading from (0-indexed)"),
1752
1771
  limit: zod_v4.z.coerce.number().optional().default(100).describe("Maximum number of lines to read")
1753
- })
1772
+ }))
1754
1773
  });
1755
1774
  }
1756
1775
  /**
@@ -1778,10 +1797,10 @@ function createWriteFileTool(backend, options) {
1778
1797
  }, {
1779
1798
  name: "write_file",
1780
1799
  description: customDescription || WRITE_FILE_TOOL_DESCRIPTION,
1781
- schema: zod_v4.z.object({
1800
+ schema: zod_v4.z.preprocess(normalizeFilePathInput, zod_v4.z.object({
1782
1801
  file_path: zod_v4.z.string().describe("Absolute path to the file to write"),
1783
1802
  content: zod_v4.z.string().default("").describe("Content to write to the file")
1784
- })
1803
+ }))
1785
1804
  });
1786
1805
  }
1787
1806
  /**
@@ -1809,12 +1828,12 @@ function createEditFileTool(backend, options) {
1809
1828
  }, {
1810
1829
  name: "edit_file",
1811
1830
  description: customDescription || EDIT_FILE_TOOL_DESCRIPTION,
1812
- schema: zod_v4.z.object({
1831
+ schema: zod_v4.z.preprocess(normalizeFilePathInput, zod_v4.z.object({
1813
1832
  file_path: zod_v4.z.string().describe("Absolute path to the file to edit"),
1814
1833
  old_string: zod_v4.z.string().describe("String to be replaced (must match exactly)"),
1815
1834
  new_string: zod_v4.z.string().describe("String to replace with"),
1816
1835
  replace_all: zod_v4.z.boolean().optional().default(false).describe("Whether to replace all occurrences")
1817
- })
1836
+ }))
1818
1837
  });
1819
1838
  }
1820
1839
  /**
@@ -2336,11 +2355,16 @@ function returnCommandWithStateUpdate(result, toolCallId) {
2336
2355
  let content;
2337
2356
  if (result.structuredResponse != null) content = JSON.stringify(result.structuredResponse);
2338
2357
  else {
2339
- const messages = result.messages;
2340
- content = (messages?.[messages.length - 1])?.content || "Task completed";
2341
- if (Array.isArray(content)) {
2342
- content = content.filter((block) => !INVALID_TOOL_MESSAGE_BLOCK_TYPES.includes(block.type));
2343
- if (content.length === 0) content = "Task completed";
2358
+ const messages = result.messages ?? [];
2359
+ content = "Task completed";
2360
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
2361
+ const message = messages[i];
2362
+ if (!message || !_langchain_core_messages.AIMessage.isInstance(message)) continue;
2363
+ const text = typeof message.content === "string" ? message.content.trim() : message.text?.trim() ?? "";
2364
+ if (text) {
2365
+ content = text;
2366
+ break;
2367
+ }
2344
2368
  }
2345
2369
  }
2346
2370
  return new _langchain_langgraph.Command({ update: {
@@ -2702,6 +2726,30 @@ function isAnthropicModel(model) {
2702
2726
  return model.getName() === "ChatAnthropic";
2703
2727
  }
2704
2728
  /**
2729
+ * Detect whether a model is an AWS Bedrock Converse model.
2730
+ *
2731
+ * Accepts the wider `RunnableInterface` shape (the type of `request.model`
2732
+ * inside `wrapModelCall`, aliased as `AgentLanguageModelLike` in langchain)
2733
+ * because the function only depends on `.getName()`, which is part of the
2734
+ * Runnable contract. `BaseLanguageModel` extends `Runnable`, so existing
2735
+ * call sites still type-check.
2736
+ */
2737
+ function isBedrockConverseModel(model) {
2738
+ if (typeof model === "string") {
2739
+ const colonIdx = model.indexOf(":");
2740
+ if (colonIdx !== -1) {
2741
+ const prefix = model.slice(0, colonIdx);
2742
+ if (prefix === "bedrock" || prefix === "aws") return true;
2743
+ }
2744
+ return model.startsWith("amazon.");
2745
+ }
2746
+ if (model.getName() === "ConfigurableModel") {
2747
+ const provider = model._defaultConfig?.modelProvider;
2748
+ return provider === "bedrock" || provider === "aws";
2749
+ }
2750
+ return model.getName() === "ChatBedrockConverse";
2751
+ }
2752
+ /**
2705
2753
  * Extract the provider name from a model instance for profile lookup.
2706
2754
  *
2707
2755
  * Checks `_defaultConfig.modelProvider` (ConfigurableModel) and falls
@@ -3090,7 +3138,7 @@ const SKILLS_SYSTEM_PROMPT = langchain.context`
3090
3138
  User: "Can you research the latest developments in quantum computing?"
3091
3139
 
3092
3140
  1. Check available skills above → See "web-research" skill with its full path
3093
- 2. Read the full skill file: \`read_file(path, limit=${DEFAULT_SKILL_READ_LINE_LIMIT})\`
3141
+ 2. Read the full skill file: \`read_file(file_path, limit=${DEFAULT_SKILL_READ_LINE_LIMIT})\`
3094
3142
  3. Follow the skill's research workflow (search → organize → synthesize)
3095
3143
  4. Use any helper scripts with absolute paths
3096
3144
 
@@ -5782,10 +5830,17 @@ function createDeepAgent(params = {}) {
5782
5830
  const toolOverrides = harnessProfile.toolDescriptionOverrides;
5783
5831
  const effectiveTools = Object.keys(toolOverrides).length > 0 ? tools.map((t) => t.name in toolOverrides ? Object.assign(Object.create(Object.getPrototypeOf(t)), t, { description: toolOverrides[t.name] }) : t) : tools;
5784
5832
  const anthropicModel = isAnthropicModel(model);
5785
- const cacheMiddleware = anthropicModel ? [(0, langchain.anthropicPromptCachingMiddleware)({
5786
- unsupportedModelBehavior: "ignore",
5787
- minMessagesToCache: 1
5788
- }), createCacheBreakpointMiddleware()] : [];
5833
+ const bedrockModel = isBedrockConverseModel(model);
5834
+ let cacheMiddleware = [];
5835
+ if (anthropicModel) cacheMiddleware = [
5836
+ ...cacheMiddleware,
5837
+ (0, langchain.anthropicPromptCachingMiddleware)({
5838
+ unsupportedModelBehavior: "ignore",
5839
+ minMessagesToCache: 1
5840
+ }),
5841
+ createCacheBreakpointMiddleware()
5842
+ ];
5843
+ if (bedrockModel) cacheMiddleware = [...cacheMiddleware, (0, langchain.bedrockPromptCachingMiddleware)({ unsupportedModelBehavior: "ignore" })];
5789
5844
  /**
5790
5845
  * Process subagents to add SkillsMiddleware for those with their own skills.
5791
5846
  *
@@ -7636,4 +7691,4 @@ Object.defineProperty(exports, "serializeProfile", {
7636
7691
  }
7637
7692
  });
7638
7693
 
7639
- //# sourceMappingURL=langsmith-ZfNZ_Pyb.cjs.map
7694
+ //# sourceMappingURL=langsmith-CiAeUke2.cjs.map