deepagents 1.1.1 → 1.3.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
@@ -4,10 +4,11 @@ import { AnnotationRoot } from "@langchain/langgraph";
4
4
  import { StructuredTool as StructuredTool$1 } from "@langchain/core/tools";
5
5
  import { BaseLanguageModel, LanguageModelLike } from "@langchain/core/language_models/base";
6
6
  import { BaseCheckpointSaver, BaseStore } from "@langchain/langgraph-checkpoint";
7
+ import { Runnable } from "@langchain/core/runnables";
7
8
  import { InteropZodObject } from "@langchain/core/utils/types";
8
9
 
9
10
  //#region src/backends/protocol.d.ts
10
-
11
+ type MaybePromise<T> = T | Promise<T>;
11
12
  /**
12
13
  * Structured file listing info.
13
14
  *
@@ -65,6 +66,8 @@ interface WriteResult {
65
66
  * External backends set null (already persisted to disk/S3/database/etc).
66
67
  */
67
68
  filesUpdate?: Record<string, FileData> | null;
69
+ /** Metadata for the write operation, attached to the ToolMessage */
70
+ metadata?: Record<string, unknown>;
68
71
  }
69
72
  /**
70
73
  * Result from backend edit operations.
@@ -85,6 +88,8 @@ interface EditResult {
85
88
  filesUpdate?: Record<string, FileData> | null;
86
89
  /** Number of replacements made, undefined on failure */
87
90
  occurrences?: number;
91
+ /** Metadata for the edit operation, attached to the ToolMessage */
92
+ metadata?: Record<string, unknown>;
88
93
  }
89
94
  /**
90
95
  * Protocol for pluggable memory backends (single, unified).
@@ -107,7 +112,7 @@ interface BackendProtocol {
107
112
  * @param path - Absolute path to directory
108
113
  * @returns List of FileInfo objects for files and directories directly in the directory
109
114
  */
110
- lsInfo(path: string): FileInfo[] | Promise<FileInfo[]>;
115
+ lsInfo(path: string): MaybePromise<FileInfo[]>;
111
116
  /**
112
117
  * Read file content with line numbers or an error string.
113
118
  *
@@ -116,7 +121,14 @@ interface BackendProtocol {
116
121
  * @param limit - Maximum number of lines to read, default 2000
117
122
  * @returns Formatted file content with line numbers, or error message
118
123
  */
119
- read(filePath: string, offset?: number, limit?: number): string | Promise<string>;
124
+ read(filePath: string, offset?: number, limit?: number): MaybePromise<string>;
125
+ /**
126
+ * Read file content as raw FileData.
127
+ *
128
+ * @param filePath - Absolute file path
129
+ * @returns Raw file content as FileData
130
+ */
131
+ readRaw(filePath: string): MaybePromise<FileData>;
120
132
  /**
121
133
  * Structured search results or error string for invalid input.
122
134
  *
@@ -127,7 +139,7 @@ interface BackendProtocol {
127
139
  * @param glob - Optional glob pattern to filter files (e.g., "*.py")
128
140
  * @returns List of GrepMatch objects or error string for invalid regex
129
141
  */
130
- grepRaw(pattern: string, path?: string | null, glob?: string | null): GrepMatch[] | string | Promise<GrepMatch[] | string>;
142
+ grepRaw(pattern: string, path?: string | null, glob?: string | null): MaybePromise<GrepMatch[] | string>;
131
143
  /**
132
144
  * Structured glob matching returning FileInfo objects.
133
145
  *
@@ -135,7 +147,7 @@ interface BackendProtocol {
135
147
  * @param path - Base path to search from (default: "/")
136
148
  * @returns List of FileInfo objects matching the pattern
137
149
  */
138
- globInfo(pattern: string, path?: string): FileInfo[] | Promise<FileInfo[]>;
150
+ globInfo(pattern: string, path?: string): MaybePromise<FileInfo[]>;
139
151
  /**
140
152
  * Create a new file.
141
153
  *
@@ -143,7 +155,7 @@ interface BackendProtocol {
143
155
  * @param content - File content as string
144
156
  * @returns WriteResult with error populated on failure
145
157
  */
146
- write(filePath: string, content: string): WriteResult | Promise<WriteResult>;
158
+ write(filePath: string, content: string): MaybePromise<WriteResult>;
147
159
  /**
148
160
  * Edit a file by replacing string occurrences.
149
161
  *
@@ -153,7 +165,7 @@ interface BackendProtocol {
153
165
  * @param replaceAll - If true, replace all occurrences (default: false)
154
166
  * @returns EditResult with error, path, filesUpdate, and occurrences
155
167
  */
156
- edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): EditResult | Promise<EditResult>;
168
+ edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): MaybePromise<EditResult>;
157
169
  }
158
170
  /**
159
171
  * State and store container for backend initialization.
@@ -210,6 +222,17 @@ interface FilesystemMiddlewareOptions {
210
222
  declare function createFilesystemMiddleware(options?: FilesystemMiddlewareOptions): langchain0.AgentMiddleware<any, undefined, any>;
211
223
  //#endregion
212
224
  //#region src/middleware/subagents.d.ts
225
+ /**
226
+ * Type definitions for pre-compiled agents.
227
+ */
228
+ interface CompiledSubAgent {
229
+ /** The name of the agent */
230
+ name: string;
231
+ /** The description of the agent */
232
+ description: string;
233
+ /** The agent instance */
234
+ runnable: ReactAgent<any, any, any, any> | Runnable;
235
+ }
213
236
  /**
214
237
  * Type definitions for subagents
215
238
  */
@@ -242,7 +265,7 @@ interface SubAgentMiddlewareOptions {
242
265
  /** The tool configs for the default general-purpose subagent */
243
266
  defaultInterruptOn?: Record<string, boolean | InterruptOnConfig> | null;
244
267
  /** A list of additional subagents to provide to the agent */
245
- subagents?: Array<SubAgent>;
268
+ subagents?: (SubAgent | CompiledSubAgent)[];
246
269
  /** Full system prompt override */
247
270
  systemPrompt?: string | null;
248
271
  /** Whether to include the general-purpose agent */
@@ -314,6 +337,13 @@ declare class StateBackend implements BackendProtocol {
314
337
  * @returns Formatted file content with line numbers, or error message
315
338
  */
316
339
  read(filePath: string, offset?: number, limit?: number): string;
340
+ /**
341
+ * Read file content as raw FileData.
342
+ *
343
+ * @param filePath - Absolute file path
344
+ * @returns Raw file content as FileData
345
+ */
346
+ readRaw(filePath: string): FileData;
317
347
  /**
318
348
  * Create a new file with content.
319
349
  * Returns WriteResult with filesUpdate to update LangGraph state.
@@ -360,7 +390,7 @@ declare class StoreBackend implements BackendProtocol {
360
390
  * [assistant_id, "filesystem"] to provide per-assistant isolation.
361
391
  * Otherwise return ["filesystem"].
362
392
  */
363
- private getNamespace;
393
+ protected getNamespace(): string[];
364
394
  /**
365
395
  * Convert a store Item to FileData format.
366
396
  *
@@ -402,6 +432,13 @@ declare class StoreBackend implements BackendProtocol {
402
432
  * @returns Formatted file content with line numbers, or error message
403
433
  */
404
434
  read(filePath: string, offset?: number, limit?: number): Promise<string>;
435
+ /**
436
+ * Read file content as raw FileData.
437
+ *
438
+ * @param filePath - Absolute file path
439
+ * @returns Raw file content as FileData
440
+ */
441
+ readRaw(filePath: string): Promise<FileData>;
405
442
  /**
406
443
  * Create a new file with content.
407
444
  * Returns WriteResult. External storage sets filesUpdate=null.
@@ -469,6 +506,13 @@ declare class FilesystemBackend implements BackendProtocol {
469
506
  * @returns Formatted file content with line numbers, or error message
470
507
  */
471
508
  read(filePath: string, offset?: number, limit?: number): Promise<string>;
509
+ /**
510
+ * Read file content as raw FileData.
511
+ *
512
+ * @param filePath - Absolute file path
513
+ * @returns Raw file content as FileData
514
+ */
515
+ readRaw(filePath: string): Promise<FileData>;
472
516
  /**
473
517
  * Create a new file with content.
474
518
  * Returns WriteResult. External storage sets filesUpdate=null.
@@ -538,6 +582,13 @@ declare class CompositeBackend implements BackendProtocol {
538
582
  * @returns Formatted file content with line numbers, or error message
539
583
  */
540
584
  read(filePath: string, offset?: number, limit?: number): Promise<string>;
585
+ /**
586
+ * Read file content as raw FileData.
587
+ *
588
+ * @param filePath - Absolute file path
589
+ * @returns Raw file content as FileData
590
+ */
591
+ readRaw(filePath: string): Promise<FileData>;
541
592
  /**
542
593
  * Structured search results or error string for invalid input.
543
594
  */
@@ -581,7 +632,7 @@ interface CreateDeepAgentParams<ContextSchema extends AnnotationRoot<any> | Inte
581
632
  /** Custom middleware to apply after standard middleware */
582
633
  middleware?: AgentMiddleware[];
583
634
  /** List of subagent specifications for task delegation */
584
- subagents?: SubAgent[];
635
+ subagents?: (SubAgent | CompiledSubAgent)[];
585
636
  /** Structured output response format for the agent */
586
637
  responseFormat?: any;
587
638
  /** Optional schema for context (not persisted between invocations) */
@@ -621,4 +672,4 @@ interface CreateDeepAgentParams<ContextSchema extends AnnotationRoot<any> | Inte
621
672
  */
622
673
  declare function createDeepAgent<ContextSchema extends AnnotationRoot<any> | InteropZodObject = AnnotationRoot<any>>(params?: CreateDeepAgentParams<ContextSchema>): ReactAgent<any, any, ContextSchema, any>;
623
674
  //#endregion
624
- export { type BackendFactory, type BackendProtocol, CompositeBackend, type CreateDeepAgentParams, type EditResult, type FileData, type FileInfo, FilesystemBackend, type FilesystemMiddlewareOptions, type GrepMatch, StateBackend, StoreBackend, type SubAgent, type SubAgentMiddlewareOptions, type WriteResult, createDeepAgent, createFilesystemMiddleware, createPatchToolCallsMiddleware, createSubAgentMiddleware };
675
+ export { type BackendFactory, type BackendProtocol, type CompiledSubAgent, CompositeBackend, type CreateDeepAgentParams, type EditResult, type FileData, type FileInfo, FilesystemBackend, type FilesystemMiddlewareOptions, type GrepMatch, StateBackend, StoreBackend, type SubAgent, type SubAgentMiddlewareOptions, type WriteResult, createDeepAgent, createFilesystemMiddleware, createPatchToolCallsMiddleware, createSubAgentMiddleware };
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
  */
@@ -403,12 +414,6 @@ function getBackend(backend, stateAndStore) {
403
414
  if (typeof backend === "function") return backend(stateAndStore);
404
415
  return backend;
405
416
  }
406
- /**
407
- * Helper to await if Promise, otherwise return value directly.
408
- */
409
- async function awaitIfPromise(value) {
410
- return value;
411
- }
412
417
  const FILESYSTEM_SYSTEM_PROMPT = `You have access to a virtual filesystem. All file paths must start with a /.
413
418
 
414
419
  - ls: list files in a directory (requires absolute path)
@@ -426,14 +431,15 @@ const GREP_TOOL_DESCRIPTION = "Search for a regex pattern in files. Returns matc
426
431
  /**
427
432
  * Create ls tool using backend.
428
433
  */
429
- function createLsTool(backend, customDescription) {
434
+ function createLsTool(backend, options) {
435
+ const { customDescription } = options;
430
436
  return tool(async (input, config) => {
431
437
  const resolvedBackend = getBackend(backend, {
432
438
  state: getCurrentTaskInput(config),
433
439
  store: config.store
434
440
  });
435
441
  const path$1 = input.path || "/";
436
- const infos = await awaitIfPromise(resolvedBackend.lsInfo(path$1));
442
+ const infos = await resolvedBackend.lsInfo(path$1);
437
443
  if (infos.length === 0) return `No files found in ${path$1}`;
438
444
  const lines = [];
439
445
  for (const info of infos) if (info.is_dir) lines.push(`${info.path} (directory)`);
@@ -451,14 +457,15 @@ function createLsTool(backend, customDescription) {
451
457
  /**
452
458
  * Create read_file tool using backend.
453
459
  */
454
- function createReadFileTool(backend, customDescription) {
460
+ function createReadFileTool(backend, options) {
461
+ const { customDescription } = options;
455
462
  return tool(async (input, config) => {
456
463
  const resolvedBackend = getBackend(backend, {
457
464
  state: getCurrentTaskInput(config),
458
465
  store: config.store
459
466
  });
460
467
  const { file_path, offset = 0, limit = 2e3 } = input;
461
- return await awaitIfPromise(resolvedBackend.read(file_path, offset, limit));
468
+ return await resolvedBackend.read(file_path, offset, limit);
462
469
  }, {
463
470
  name: "read_file",
464
471
  description: customDescription || READ_FILE_TOOL_DESCRIPTION,
@@ -472,24 +479,27 @@ function createReadFileTool(backend, customDescription) {
472
479
  /**
473
480
  * Create write_file tool using backend.
474
481
  */
475
- function createWriteFileTool(backend, customDescription) {
482
+ function createWriteFileTool(backend, options) {
483
+ const { customDescription } = options;
476
484
  return tool(async (input, config) => {
477
485
  const resolvedBackend = getBackend(backend, {
478
486
  state: getCurrentTaskInput(config),
479
487
  store: config.store
480
488
  });
481
489
  const { file_path, content } = input;
482
- const result = await awaitIfPromise(resolvedBackend.write(file_path, content));
490
+ const result = await resolvedBackend.write(file_path, content);
483
491
  if (result.error) return result.error;
492
+ const message = new ToolMessage({
493
+ content: `Successfully wrote to '${file_path}'`,
494
+ tool_call_id: config.toolCall?.id,
495
+ name: "write_file",
496
+ metadata: result.metadata
497
+ });
484
498
  if (result.filesUpdate) return new Command({ update: {
485
499
  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
- })]
500
+ messages: [message]
491
501
  } });
492
- return `Successfully wrote to '${file_path}'`;
502
+ return message;
493
503
  }, {
494
504
  name: "write_file",
495
505
  description: customDescription || WRITE_FILE_TOOL_DESCRIPTION,
@@ -502,23 +512,25 @@ function createWriteFileTool(backend, customDescription) {
502
512
  /**
503
513
  * Create edit_file tool using backend.
504
514
  */
505
- function createEditFileTool(backend, customDescription) {
515
+ function createEditFileTool(backend, options) {
516
+ const { customDescription } = options;
506
517
  return tool(async (input, config) => {
507
518
  const resolvedBackend = getBackend(backend, {
508
519
  state: getCurrentTaskInput(config),
509
520
  store: config.store
510
521
  });
511
522
  const { file_path, old_string, new_string, replace_all = false } = input;
512
- const result = await awaitIfPromise(resolvedBackend.edit(file_path, old_string, new_string, replace_all));
523
+ const result = await resolvedBackend.edit(file_path, old_string, new_string, replace_all);
513
524
  if (result.error) return result.error;
514
- const message = `Successfully replaced ${result.occurrences} occurrence(s) in '${file_path}'`;
525
+ const message = new ToolMessage({
526
+ content: `Successfully replaced ${result.occurrences} occurrence(s) in '${file_path}'`,
527
+ tool_call_id: config.toolCall?.id,
528
+ name: "edit_file",
529
+ metadata: result.metadata
530
+ });
515
531
  if (result.filesUpdate) return new Command({ update: {
516
532
  files: result.filesUpdate,
517
- messages: [new ToolMessage({
518
- content: message,
519
- tool_call_id: config.toolCall?.id,
520
- name: "edit_file"
521
- })]
533
+ messages: [message]
522
534
  } });
523
535
  return message;
524
536
  }, {
@@ -535,14 +547,15 @@ function createEditFileTool(backend, customDescription) {
535
547
  /**
536
548
  * Create glob tool using backend.
537
549
  */
538
- function createGlobTool(backend, customDescription) {
550
+ function createGlobTool(backend, options) {
551
+ const { customDescription } = options;
539
552
  return tool(async (input, config) => {
540
553
  const resolvedBackend = getBackend(backend, {
541
554
  state: getCurrentTaskInput(config),
542
555
  store: config.store
543
556
  });
544
557
  const { pattern, path: path$1 = "/" } = input;
545
- const infos = await awaitIfPromise(resolvedBackend.globInfo(pattern, path$1));
558
+ const infos = await resolvedBackend.globInfo(pattern, path$1);
546
559
  if (infos.length === 0) return `No files found matching pattern '${pattern}'`;
547
560
  return infos.map((info) => info.path).join("\n");
548
561
  }, {
@@ -557,14 +570,15 @@ function createGlobTool(backend, customDescription) {
557
570
  /**
558
571
  * Create grep tool using backend.
559
572
  */
560
- function createGrepTool(backend, customDescription) {
573
+ function createGrepTool(backend, options) {
574
+ const { customDescription } = options;
561
575
  return tool(async (input, config) => {
562
576
  const resolvedBackend = getBackend(backend, {
563
577
  state: getCurrentTaskInput(config),
564
578
  store: config.store
565
579
  });
566
580
  const { pattern, path: path$1 = "/", glob = null } = input;
567
- const result = await awaitIfPromise(resolvedBackend.grepRaw(pattern, path$1, glob));
581
+ const result = await resolvedBackend.grepRaw(pattern, path$1, glob);
568
582
  if (typeof result === "string") return result;
569
583
  if (result.length === 0) return `No matches found for pattern '${pattern}'`;
570
584
  const lines = [];
@@ -594,12 +608,12 @@ function createFilesystemMiddleware(options = {}) {
594
608
  const { backend = (stateAndStore) => new StateBackend(stateAndStore), systemPrompt: customSystemPrompt = null, customToolDescriptions = null, toolTokenLimitBeforeEvict = 2e4 } = options;
595
609
  const systemPrompt = customSystemPrompt || FILESYSTEM_SYSTEM_PROMPT;
596
610
  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)
611
+ createLsTool(backend, { customDescription: customToolDescriptions?.ls }),
612
+ createReadFileTool(backend, { customDescription: customToolDescriptions?.read_file }),
613
+ createWriteFileTool(backend, { customDescription: customToolDescriptions?.write_file }),
614
+ createEditFileTool(backend, { customDescription: customToolDescriptions?.edit_file }),
615
+ createGlobTool(backend, { customDescription: customToolDescriptions?.glob }),
616
+ createGrepTool(backend, { customDescription: customToolDescriptions?.grep })
603
617
  ];
604
618
  return createMiddleware({
605
619
  name: "FilesystemMiddleware",
@@ -625,7 +639,7 @@ function createFilesystemMiddleware(options = {}) {
625
639
  store: request.config?.store
626
640
  });
627
641
  const evictPath = `/large_tool_results/${sanitizeToolCallId(request.toolCall?.id || msg.tool_call_id)}`;
628
- const writeResult = await awaitIfPromise(resolvedBackend.write(evictPath, msg.content));
642
+ const writeResult = await resolvedBackend.write(evictPath, msg.content);
629
643
  if (writeResult.error) return {
630
644
  message: msg,
631
645
  filesUpdate: null
@@ -871,15 +885,18 @@ function getSubagents(options) {
871
885
  }
872
886
  for (const agentParams of subagents) {
873
887
  subagentDescriptions.push(`- ${agentParams.name}: ${agentParams.description}`);
874
- const middleware = agentParams.middleware ? [...defaultSubagentMiddleware, ...agentParams.middleware] : [...defaultSubagentMiddleware];
875
- const interruptOn = agentParams.interruptOn || defaultInterruptOn;
876
- if (interruptOn) middleware.push(humanInTheLoopMiddleware({ interruptOn }));
877
- agents[agentParams.name] = createAgent({
878
- model: agentParams.model ?? defaultModel,
879
- systemPrompt: agentParams.systemPrompt,
880
- tools: agentParams.tools ?? defaultTools,
881
- middleware
882
- });
888
+ if ("runnable" in agentParams) agents[agentParams.name] = agentParams.runnable;
889
+ else {
890
+ const middleware = agentParams.middleware ? [...defaultSubagentMiddleware, ...agentParams.middleware] : [...defaultSubagentMiddleware];
891
+ const interruptOn = agentParams.interruptOn || defaultInterruptOn;
892
+ if (interruptOn) middleware.push(humanInTheLoopMiddleware({ interruptOn }));
893
+ agents[agentParams.name] = createAgent({
894
+ model: agentParams.model ?? defaultModel,
895
+ systemPrompt: agentParams.systemPrompt,
896
+ tools: agentParams.tools ?? defaultTools,
897
+ middleware
898
+ });
899
+ }
883
900
  }
884
901
  return {
885
902
  agents,
@@ -1146,17 +1163,26 @@ var StoreBackend = class {
1146
1163
  * @returns Formatted file content with line numbers, or error message
1147
1164
  */
1148
1165
  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
1166
  try {
1154
- return formatReadResponse(this.convertStoreItemToFileData(item), offset, limit);
1167
+ return formatReadResponse(await this.readRaw(filePath), offset, limit);
1155
1168
  } catch (e) {
1156
1169
  return `Error: ${e.message}`;
1157
1170
  }
1158
1171
  }
1159
1172
  /**
1173
+ * Read file content as raw FileData.
1174
+ *
1175
+ * @param filePath - Absolute file path
1176
+ * @returns Raw file content as FileData
1177
+ */
1178
+ async readRaw(filePath) {
1179
+ const store = this.getStore();
1180
+ const namespace = this.getNamespace();
1181
+ const item = await store.get(namespace, filePath);
1182
+ if (!item) throw new Error(`File '${filePath}' not found`);
1183
+ return this.convertStoreItemToFileData(item);
1184
+ }
1185
+ /**
1160
1186
  * Create a new file with content.
1161
1187
  * Returns WriteResult. External storage sets filesUpdate=null.
1162
1188
  */
@@ -1389,6 +1415,37 @@ var FilesystemBackend = class {
1389
1415
  }
1390
1416
  }
1391
1417
  /**
1418
+ * Read file content as raw FileData.
1419
+ *
1420
+ * @param filePath - Absolute file path
1421
+ * @returns Raw file content as FileData
1422
+ */
1423
+ async readRaw(filePath) {
1424
+ const resolvedPath = this.resolvePath(filePath);
1425
+ let content;
1426
+ let stat;
1427
+ if (SUPPORTS_NOFOLLOW) {
1428
+ stat = await fs.stat(resolvedPath);
1429
+ if (!stat.isFile()) throw new Error(`File '${filePath}' not found`);
1430
+ const fd = await fs.open(resolvedPath, fsSync.constants.O_RDONLY | fsSync.constants.O_NOFOLLOW);
1431
+ try {
1432
+ content = await fd.readFile({ encoding: "utf-8" });
1433
+ } finally {
1434
+ await fd.close();
1435
+ }
1436
+ } else {
1437
+ stat = await fs.lstat(resolvedPath);
1438
+ if (stat.isSymbolicLink()) throw new Error(`Symlinks are not allowed: ${filePath}`);
1439
+ if (!stat.isFile()) throw new Error(`File '${filePath}' not found`);
1440
+ content = await fs.readFile(resolvedPath, "utf-8");
1441
+ }
1442
+ return {
1443
+ content: content.split("\n"),
1444
+ created_at: stat.ctime.toISOString(),
1445
+ modified_at: stat.mtime.toISOString()
1446
+ };
1447
+ }
1448
+ /**
1392
1449
  * Create a new file with content.
1393
1450
  * Returns WriteResult. External storage sets filesUpdate=null.
1394
1451
  */
@@ -1720,6 +1777,16 @@ var CompositeBackend = class {
1720
1777
  return await backend.read(strippedKey, offset, limit);
1721
1778
  }
1722
1779
  /**
1780
+ * Read file content as raw FileData.
1781
+ *
1782
+ * @param filePath - Absolute file path
1783
+ * @returns Raw file content as FileData
1784
+ */
1785
+ async readRaw(filePath) {
1786
+ const [backend, strippedKey] = this.getBackendAndKey(filePath);
1787
+ return await backend.readRaw(strippedKey);
1788
+ }
1789
+ /**
1723
1790
  * Structured search results or error string for invalid input.
1724
1791
  */
1725
1792
  async grepRaw(pattern, path$1 = "/", glob = null) {
@@ -1829,8 +1896,8 @@ function createDeepAgent(params = {}) {
1829
1896
  createFilesystemMiddleware({ backend: filesystemBackend }),
1830
1897
  summarizationMiddleware({
1831
1898
  model,
1832
- maxTokensBeforeSummary: 17e4,
1833
- messagesToKeep: 6
1899
+ trigger: { tokens: 17e4 },
1900
+ keep: { messages: 6 }
1834
1901
  }),
1835
1902
  anthropicPromptCachingMiddleware({ unsupportedModelBehavior: "ignore" }),
1836
1903
  createPatchToolCallsMiddleware()
@@ -1841,8 +1908,8 @@ function createDeepAgent(params = {}) {
1841
1908
  }),
1842
1909
  summarizationMiddleware({
1843
1910
  model,
1844
- maxTokensBeforeSummary: 17e4,
1845
- messagesToKeep: 6
1911
+ trigger: { tokens: 17e4 },
1912
+ keep: { messages: 6 }
1846
1913
  }),
1847
1914
  anthropicPromptCachingMiddleware({ unsupportedModelBehavior: "ignore" }),
1848
1915
  createPatchToolCallsMiddleware()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepagents",
3
- "version": "1.1.1",
3
+ "version": "1.3.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",
@@ -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",