deepagents 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as langchain0 from "langchain";
2
2
  import { AgentMiddleware, AgentMiddleware as AgentMiddleware$1, InterruptOnConfig, ReactAgent, StructuredTool } from "langchain";
3
3
  import { AnnotationRoot } from "@langchain/langgraph";
4
4
  import { StructuredTool as StructuredTool$1 } from "@langchain/core/tools";
5
- import { LanguageModelLike } from "@langchain/core/language_models/base";
5
+ import { BaseLanguageModel, LanguageModelLike } from "@langchain/core/language_models/base";
6
6
  import { BaseCheckpointSaver, BaseStore } from "@langchain/langgraph-checkpoint";
7
7
  import { InteropZodObject } from "@langchain/core/utils/types";
8
8
 
@@ -117,6 +117,13 @@ interface BackendProtocol {
117
117
  * @returns Formatted file content with line numbers, or error message
118
118
  */
119
119
  read(filePath: string, offset?: number, limit?: number): string | Promise<string>;
120
+ /**
121
+ * Read file content as raw FileData.
122
+ *
123
+ * @param filePath - Absolute file path
124
+ * @returns Raw file content as FileData
125
+ */
126
+ readRaw(filePath: string): FileData | Promise<FileData>;
120
127
  /**
121
128
  * Structured search results or error string for invalid input.
122
129
  *
@@ -191,6 +198,15 @@ interface StateAndStore {
191
198
  type BackendFactory = (stateAndStore: StateAndStore) => BackendProtocol;
192
199
  //#endregion
193
200
  //#region src/middleware/fs.d.ts
201
+ type FilesystemEventResponse = {
202
+ kind: "raw-contents";
203
+ } | {
204
+ kind: "metadata";
205
+ data: Record<string, unknown>;
206
+ };
207
+ interface FilesystemEvents {
208
+ onWrite?: (path: string, backend: BackendProtocol) => void | FilesystemEventResponse | Promise<void | FilesystemEventResponse>;
209
+ }
194
210
  /**
195
211
  * Options for creating filesystem middleware.
196
212
  */
@@ -203,6 +219,8 @@ interface FilesystemMiddlewareOptions {
203
219
  customToolDescriptions?: Record<string, string> | null;
204
220
  /** Optional token limit before evicting a tool result to the filesystem (default: 20000 tokens, ~80KB) */
205
221
  toolTokenLimitBeforeEvict?: number | null;
222
+ /** Filesystem events callbacks */
223
+ events?: FilesystemEvents;
206
224
  }
207
225
  /**
208
226
  * Create filesystem middleware with all tools and features.
@@ -314,6 +332,13 @@ declare class StateBackend implements BackendProtocol {
314
332
  * @returns Formatted file content with line numbers, or error message
315
333
  */
316
334
  read(filePath: string, offset?: number, limit?: number): string;
335
+ /**
336
+ * Read file content as raw FileData.
337
+ *
338
+ * @param filePath - Absolute file path
339
+ * @returns Raw file content as FileData
340
+ */
341
+ readRaw(filePath: string): FileData;
317
342
  /**
318
343
  * Create a new file with content.
319
344
  * Returns WriteResult with filesUpdate to update LangGraph state.
@@ -360,7 +385,7 @@ declare class StoreBackend implements BackendProtocol {
360
385
  * [assistant_id, "filesystem"] to provide per-assistant isolation.
361
386
  * Otherwise return ["filesystem"].
362
387
  */
363
- private getNamespace;
388
+ protected getNamespace(): string[];
364
389
  /**
365
390
  * Convert a store Item to FileData format.
366
391
  *
@@ -402,6 +427,13 @@ declare class StoreBackend implements BackendProtocol {
402
427
  * @returns Formatted file content with line numbers, or error message
403
428
  */
404
429
  read(filePath: string, offset?: number, limit?: number): Promise<string>;
430
+ /**
431
+ * Read file content as raw FileData.
432
+ *
433
+ * @param filePath - Absolute file path
434
+ * @returns Raw file content as FileData
435
+ */
436
+ readRaw(filePath: string): Promise<FileData>;
405
437
  /**
406
438
  * Create a new file with content.
407
439
  * Returns WriteResult. External storage sets filesUpdate=null.
@@ -469,6 +501,13 @@ declare class FilesystemBackend implements BackendProtocol {
469
501
  * @returns Formatted file content with line numbers, or error message
470
502
  */
471
503
  read(filePath: string, offset?: number, limit?: number): Promise<string>;
504
+ /**
505
+ * Read file content as raw FileData.
506
+ *
507
+ * @param filePath - Absolute file path
508
+ * @returns Raw file content as FileData
509
+ */
510
+ readRaw(filePath: string): Promise<FileData>;
472
511
  /**
473
512
  * Create a new file with content.
474
513
  * Returns WriteResult. External storage sets filesUpdate=null.
@@ -538,6 +577,13 @@ declare class CompositeBackend implements BackendProtocol {
538
577
  * @returns Formatted file content with line numbers, or error message
539
578
  */
540
579
  read(filePath: string, offset?: number, limit?: number): Promise<string>;
580
+ /**
581
+ * Read file content as raw FileData.
582
+ *
583
+ * @param filePath - Absolute file path
584
+ * @returns Raw file content as FileData
585
+ */
586
+ readRaw(filePath: string): Promise<FileData>;
541
587
  /**
542
588
  * Structured search results or error string for invalid input.
543
589
  */
@@ -573,7 +619,7 @@ declare class CompositeBackend implements BackendProtocol {
573
619
  */
574
620
  interface CreateDeepAgentParams<ContextSchema extends AnnotationRoot<any> | InteropZodObject = AnnotationRoot<any>> {
575
621
  /** The model to use (model name string or LanguageModelLike instance). Defaults to claude-sonnet-4-5-20250929 */
576
- model?: LanguageModelLike | string;
622
+ model?: BaseLanguageModel | string;
577
623
  /** Tools the agent should have access to */
578
624
  tools?: StructuredTool$1[];
579
625
  /** Custom system prompt for the agent. This will be combined with the base agent prompt */
package/dist/index.js CHANGED
@@ -312,6 +312,17 @@ var StateBackend = class {
312
312
  return formatReadResponse(fileData, offset, limit);
313
313
  }
314
314
  /**
315
+ * Read file content as raw FileData.
316
+ *
317
+ * @param filePath - Absolute file path
318
+ * @returns Raw file content as FileData
319
+ */
320
+ readRaw(filePath) {
321
+ const fileData = this.getFiles()[filePath];
322
+ if (!fileData) throw new Error(`File '${filePath}' not found`);
323
+ return fileData;
324
+ }
325
+ /**
315
326
  * Create a new file with content.
316
327
  * Returns WriteResult with filesUpdate to update LangGraph state.
317
328
  */
@@ -426,7 +437,8 @@ const GREP_TOOL_DESCRIPTION = "Search for a regex pattern in files. Returns matc
426
437
  /**
427
438
  * Create ls tool using backend.
428
439
  */
429
- function createLsTool(backend, customDescription) {
440
+ function createLsTool(backend, options) {
441
+ const { customDescription } = options;
430
442
  return tool(async (input, config) => {
431
443
  const resolvedBackend = getBackend(backend, {
432
444
  state: getCurrentTaskInput(config),
@@ -451,7 +463,8 @@ function createLsTool(backend, customDescription) {
451
463
  /**
452
464
  * Create read_file tool using backend.
453
465
  */
454
- function createReadFileTool(backend, customDescription) {
466
+ function createReadFileTool(backend, options) {
467
+ const { customDescription } = options;
455
468
  return tool(async (input, config) => {
456
469
  const resolvedBackend = getBackend(backend, {
457
470
  state: getCurrentTaskInput(config),
@@ -472,24 +485,32 @@ function createReadFileTool(backend, customDescription) {
472
485
  /**
473
486
  * Create write_file tool using backend.
474
487
  */
475
- function createWriteFileTool(backend, customDescription) {
488
+ function createWriteFileTool(backend, options) {
489
+ const { customDescription, events } = options;
476
490
  return tool(async (input, config) => {
477
491
  const resolvedBackend = getBackend(backend, {
478
492
  state: getCurrentTaskInput(config),
479
493
  store: config.store
480
494
  });
481
495
  const { file_path, content } = input;
482
- const result = await awaitIfPromise(resolvedBackend.write(file_path, content));
496
+ const result = await resolvedBackend.write(file_path, content);
483
497
  if (result.error) return result.error;
498
+ const resolved = await events?.onWrite?.(file_path, resolvedBackend) ?? void 0;
499
+ const metadata = await (async () => {
500
+ if (resolved?.kind === "metadata") return resolved.data;
501
+ if (resolved?.kind === "raw-contents") return { ...await resolvedBackend.readRaw(file_path) };
502
+ })();
503
+ const message = new ToolMessage({
504
+ content: `Successfully wrote to '${file_path}'`,
505
+ tool_call_id: config.toolCall?.id,
506
+ name: "write_file",
507
+ metadata
508
+ });
484
509
  if (result.filesUpdate) return new Command({ update: {
485
510
  files: result.filesUpdate,
486
- messages: [new ToolMessage({
487
- content: `Successfully wrote to '${file_path}'`,
488
- tool_call_id: config.toolCall?.id,
489
- name: "write_file"
490
- })]
511
+ messages: [message]
491
512
  } });
492
- return `Successfully wrote to '${file_path}'`;
513
+ return message;
493
514
  }, {
494
515
  name: "write_file",
495
516
  description: customDescription || WRITE_FILE_TOOL_DESCRIPTION,
@@ -502,7 +523,8 @@ function createWriteFileTool(backend, customDescription) {
502
523
  /**
503
524
  * Create edit_file tool using backend.
504
525
  */
505
- function createEditFileTool(backend, customDescription) {
526
+ function createEditFileTool(backend, options) {
527
+ const { customDescription, events } = options;
506
528
  return tool(async (input, config) => {
507
529
  const resolvedBackend = getBackend(backend, {
508
530
  state: getCurrentTaskInput(config),
@@ -511,14 +533,20 @@ function createEditFileTool(backend, customDescription) {
511
533
  const { file_path, old_string, new_string, replace_all = false } = input;
512
534
  const result = await awaitIfPromise(resolvedBackend.edit(file_path, old_string, new_string, replace_all));
513
535
  if (result.error) return result.error;
514
- const message = `Successfully replaced ${result.occurrences} occurrence(s) in '${file_path}'`;
536
+ const resolved = await events?.onWrite?.(file_path, resolvedBackend) ?? void 0;
537
+ const metadata = await (async () => {
538
+ if (resolved?.kind === "metadata") return resolved.data;
539
+ if (resolved?.kind === "raw-contents") return { ...await resolvedBackend.readRaw(file_path) };
540
+ })();
541
+ const message = new ToolMessage({
542
+ content: `Successfully replaced ${result.occurrences} occurrence(s) in '${file_path}'`,
543
+ tool_call_id: config.toolCall?.id,
544
+ name: "edit_file",
545
+ metadata
546
+ });
515
547
  if (result.filesUpdate) return new Command({ update: {
516
548
  files: result.filesUpdate,
517
- messages: [new ToolMessage({
518
- content: message,
519
- tool_call_id: config.toolCall?.id,
520
- name: "edit_file"
521
- })]
549
+ messages: [message]
522
550
  } });
523
551
  return message;
524
552
  }, {
@@ -535,7 +563,8 @@ function createEditFileTool(backend, customDescription) {
535
563
  /**
536
564
  * Create glob tool using backend.
537
565
  */
538
- function createGlobTool(backend, customDescription) {
566
+ function createGlobTool(backend, options) {
567
+ const { customDescription } = options;
539
568
  return tool(async (input, config) => {
540
569
  const resolvedBackend = getBackend(backend, {
541
570
  state: getCurrentTaskInput(config),
@@ -557,7 +586,8 @@ function createGlobTool(backend, customDescription) {
557
586
  /**
558
587
  * Create grep tool using backend.
559
588
  */
560
- function createGrepTool(backend, customDescription) {
589
+ function createGrepTool(backend, options) {
590
+ const { customDescription } = options;
561
591
  return tool(async (input, config) => {
562
592
  const resolvedBackend = getBackend(backend, {
563
593
  state: getCurrentTaskInput(config),
@@ -591,15 +621,33 @@ function createGrepTool(backend, customDescription) {
591
621
  * Create filesystem middleware with all tools and features.
592
622
  */
593
623
  function createFilesystemMiddleware(options = {}) {
594
- const { backend = (stateAndStore) => new StateBackend(stateAndStore), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4 } = options;
624
+ const { backend = (stateAndStore) => new StateBackend(stateAndStore), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4, events = void 0 } = options;
595
625
  const systemPrompt = customSystemPrompt || FILESYSTEM_SYSTEM_PROMPT;
596
626
  const tools = [
597
- createLsTool(backend, customToolDescriptions?.ls ?? null),
598
- createReadFileTool(backend, customToolDescriptions?.read_file ?? null),
599
- createWriteFileTool(backend, customToolDescriptions?.write_file ?? null),
600
- createEditFileTool(backend, customToolDescriptions?.edit_file ?? null),
601
- createGlobTool(backend, customToolDescriptions?.glob ?? null),
602
- createGrepTool(backend, customToolDescriptions?.grep ?? null)
627
+ createLsTool(backend, {
628
+ customDescription: customToolDescriptions?.ls ?? null,
629
+ events
630
+ }),
631
+ createReadFileTool(backend, {
632
+ customDescription: customToolDescriptions?.read_file ?? null,
633
+ events
634
+ }),
635
+ createWriteFileTool(backend, {
636
+ customDescription: customToolDescriptions?.write_file ?? null,
637
+ events
638
+ }),
639
+ createEditFileTool(backend, {
640
+ customDescription: customToolDescriptions?.edit_file ?? null,
641
+ events
642
+ }),
643
+ createGlobTool(backend, {
644
+ customDescription: customToolDescriptions?.glob ?? null,
645
+ events
646
+ }),
647
+ createGrepTool(backend, {
648
+ customDescription: customToolDescriptions?.grep ?? null,
649
+ events
650
+ })
603
651
  ];
604
652
  return createMiddleware({
605
653
  name: "FilesystemMiddleware",
@@ -908,7 +956,7 @@ function createTaskTool(options) {
908
956
  const subagent = subagentGraphs[subagent_type];
909
957
  const subagentState = filterStateForSubagent(getCurrentTaskInput());
910
958
  subagentState.messages = [new HumanMessage({ content: description })];
911
- const result = await subagent.invoke(subagentState);
959
+ const result = await subagent.invoke(subagentState, config);
912
960
  if (!config.toolCall?.id) throw new Error("Tool call ID is required for subagent invocation");
913
961
  return returnCommandWithStateUpdate(result, config.toolCall.id);
914
962
  }, {
@@ -1146,17 +1194,26 @@ var StoreBackend = class {
1146
1194
  * @returns Formatted file content with line numbers, or error message
1147
1195
  */
1148
1196
  async read(filePath, offset = 0, limit = 2e3) {
1149
- const store = this.getStore();
1150
- const namespace = this.getNamespace();
1151
- const item = await store.get(namespace, filePath);
1152
- if (!item) return `Error: File '${filePath}' not found`;
1153
1197
  try {
1154
- return formatReadResponse(this.convertStoreItemToFileData(item), offset, limit);
1198
+ return formatReadResponse(await this.readRaw(filePath), offset, limit);
1155
1199
  } catch (e) {
1156
1200
  return `Error: ${e.message}`;
1157
1201
  }
1158
1202
  }
1159
1203
  /**
1204
+ * Read file content as raw FileData.
1205
+ *
1206
+ * @param filePath - Absolute file path
1207
+ * @returns Raw file content as FileData
1208
+ */
1209
+ async readRaw(filePath) {
1210
+ const store = this.getStore();
1211
+ const namespace = this.getNamespace();
1212
+ const item = await store.get(namespace, filePath);
1213
+ if (!item) throw new Error(`File '${filePath}' not found`);
1214
+ return this.convertStoreItemToFileData(item);
1215
+ }
1216
+ /**
1160
1217
  * Create a new file with content.
1161
1218
  * Returns WriteResult. External storage sets filesUpdate=null.
1162
1219
  */
@@ -1389,6 +1446,37 @@ var FilesystemBackend = class {
1389
1446
  }
1390
1447
  }
1391
1448
  /**
1449
+ * Read file content as raw FileData.
1450
+ *
1451
+ * @param filePath - Absolute file path
1452
+ * @returns Raw file content as FileData
1453
+ */
1454
+ async readRaw(filePath) {
1455
+ const resolvedPath = this.resolvePath(filePath);
1456
+ let content;
1457
+ let stat;
1458
+ if (SUPPORTS_NOFOLLOW) {
1459
+ stat = await fs.stat(resolvedPath);
1460
+ if (!stat.isFile()) throw new Error(`File '${filePath}' not found`);
1461
+ const fd = await fs.open(resolvedPath, fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW);
1462
+ try {
1463
+ content = await fd.readFile({ encoding: "utf-8" });
1464
+ } finally {
1465
+ await fd.close();
1466
+ }
1467
+ } else {
1468
+ stat = await fs.lstat(resolvedPath);
1469
+ if (stat.isSymbolicLink()) throw new Error(`Symlinks are not allowed: ${filePath}`);
1470
+ if (!stat.isFile()) throw new Error(`File '${filePath}' not found`);
1471
+ content = await fs.readFile(resolvedPath, "utf-8");
1472
+ }
1473
+ return {
1474
+ content: content.split("\n"),
1475
+ created_at: stat.ctime.toISOString(),
1476
+ modified_at: stat.mtime.toISOString()
1477
+ };
1478
+ }
1479
+ /**
1392
1480
  * Create a new file with content.
1393
1481
  * Returns WriteResult. External storage sets filesUpdate=null.
1394
1482
  */
@@ -1720,6 +1808,16 @@ var CompositeBackend = class {
1720
1808
  return await backend.read(strippedKey, offset, limit);
1721
1809
  }
1722
1810
  /**
1811
+ * Read file content as raw FileData.
1812
+ *
1813
+ * @param filePath - Absolute file path
1814
+ * @returns Raw file content as FileData
1815
+ */
1816
+ async readRaw(filePath) {
1817
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
1818
+ return await backend.readRaw(strippedKey);
1819
+ }
1820
+ /**
1723
1821
  * Structured search results or error string for invalid input.
1724
1822
  */
1725
1823
  async grepRaw(pattern, path$1 = "/", glob = null) {
@@ -1829,8 +1927,8 @@ function createDeepAgent(params = {}) {
1829
1927
  createFilesystemMiddleware({ backend: filesystemBackend }),
1830
1928
  summarizationMiddleware({
1831
1929
  model,
1832
- maxTokensBeforeSummary: 17e4,
1833
- messagesToKeep: 6
1930
+ trigger: { tokens: 17e4 },
1931
+ keep: { messages: 6 }
1834
1932
  }),
1835
1933
  anthropicPromptCachingMiddleware({ unsupportedModelBehavior: "ignore" }),
1836
1934
  createPatchToolCallsMiddleware()
@@ -1841,8 +1939,8 @@ function createDeepAgent(params = {}) {
1841
1939
  }),
1842
1940
  summarizationMiddleware({
1843
1941
  model,
1844
- maxTokensBeforeSummary: 17e4,
1845
- messagesToKeep: 6
1942
+ trigger: { tokens: 17e4 },
1943
+ keep: { messages: 6 }
1846
1944
  }),
1847
1945
  anthropicPromptCachingMiddleware({ unsupportedModelBehavior: "ignore" }),
1848
1946
  createPatchToolCallsMiddleware()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepagents",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Deep Agents - a library for building controllable AI agents with LangGraph",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "@langchain/core": "^1.0.0",
29
29
  "@langchain/langgraph": "^1.0.0",
30
30
  "fast-glob": "^3.3.3",
31
- "langchain": "^1.0.0",
31
+ "langchain": "^1.0.4",
32
32
  "micromatch": "^4.0.8",
33
33
  "zod": "^4.1.11"
34
34
  },
@@ -36,9 +36,9 @@
36
36
  "@changesets/cli": "^2.29.7",
37
37
  "@eslint/eslintrc": "^3.1.0",
38
38
  "@eslint/js": "^9.19.0",
39
- "@langchain/langgraph-checkpoint": "^0.0.13",
39
+ "@langchain/langgraph-checkpoint": "^1.0.0",
40
40
  "@langchain/openai": "^1.0.0",
41
- "@langchain/tavily": "^0.1.4",
41
+ "@langchain/tavily": "^1.0.0",
42
42
  "@tsconfig/recommended": "^1.0.10",
43
43
  "@types/micromatch": "^4.0.10",
44
44
  "@types/node": "^22.13.5",