deepagents 1.9.1 → 1.10.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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AIMessage, HumanMessage, SystemMessage, ToolMessage, anthropicPromptCachingMiddleware, context, countTokensApproximately, createAgent, createMiddleware, humanInTheLoopMiddleware, todoListMiddleware, tool } from "langchain";
2
- import { Command, REMOVE_ALL_MESSAGES, ReducedValue, StateSchema, getConfig, getCurrentTaskInput, getStore, isCommand } from "@langchain/langgraph";
2
+ import { ChatModelStreamImpl, Command, REMOVE_ALL_MESSAGES, ReducedValue, StateSchema, StreamChannel, getConfig, getCurrentTaskInput, getStore, isCommand } from "@langchain/langgraph";
3
3
  import { z } from "zod/v4";
4
4
  import micromatch from "micromatch";
5
5
  import path, { basename } from "path";
@@ -2438,6 +2438,13 @@ function createPatchToolCallsMiddleware() {
2438
2438
  if (!needsPatch) return;
2439
2439
  return { messages: [new RemoveMessage({ id: REMOVE_ALL_MESSAGES }), ...patchedMessages] };
2440
2440
  },
2441
+ /**
2442
+ * Also patch in wrapModelCall as a safety net.
2443
+ * This handles edge cases where:
2444
+ * - HITL rejects a tool call during graph resume
2445
+ * - The state update from beforeAgent might not be applied in time
2446
+ * - The model would otherwise receive dangling tool_call_ids
2447
+ */
2441
2448
  wrapModelCall: async (request, handler) => {
2442
2449
  const messages = request.messages;
2443
2450
  if (!messages || messages.length === 0) return handler(request);
@@ -2539,6 +2546,10 @@ const filesValue = new ReducedValue(z$1.record(z$1.string(), FileDataSchema).def
2539
2546
  * State schema for memory middleware.
2540
2547
  */
2541
2548
  const MemoryStateSchema = new StateSchema({
2549
+ /**
2550
+ * Dict mapping source paths to their loaded content.
2551
+ * Marked as private so it's not included in the final agent state.
2552
+ */
2542
2553
  memoryContents: z$1.record(z$1.string(), z$1.string()).optional(),
2543
2554
  files: filesValue
2544
2555
  });
@@ -3247,7 +3258,9 @@ const CALLBACK_THREAD_ID_KEY = "callbackThreadId";
3247
3258
  * and read by `CompletionCallbackMiddleware` when sending callback
3248
3259
  * notifications.
3249
3260
  */
3250
- const CompletionCallbackStateSchema = z$2.object({ [CALLBACK_THREAD_ID_KEY]: z$2.string().optional() });
3261
+ const CompletionCallbackStateSchema = z$2.object({
3262
+ /** The callback thread ID. Used to address the notification. */
3263
+ [CALLBACK_THREAD_ID_KEY]: z$2.string().optional() });
3251
3264
  /**
3252
3265
  * Build headers for the callback LangGraph server.
3253
3266
  *
@@ -3365,12 +3378,25 @@ function createCompletionCallbackMiddleware(options) {
3365
3378
  return createMiddleware({
3366
3379
  name: "CompletionCallbackMiddleware",
3367
3380
  stateSchema: CompletionCallbackStateSchema,
3381
+ /**
3382
+ * After-agent hook: fires when the subagent completes successfully.
3383
+ *
3384
+ * Extracts the last message as a summary and sends it to the callback
3385
+ * thread.
3386
+ */
3368
3387
  async afterAgent(state, runtime) {
3369
3388
  const callbackThreadId = state[CALLBACK_THREAD_ID_KEY];
3370
3389
  if (callbackThreadId == null) throw new Error(`Missing required state key '${CALLBACK_THREAD_ID_KEY}'`);
3371
3390
  const taskId = getTaskId(runtime);
3372
3391
  await sendNotification(callbackThreadId, formatNotification(`Completed. Result: ${extractLastMessage(state, typeof taskId === "string" ? taskId : void 0)}`, runtime));
3373
3392
  },
3393
+ /**
3394
+ * Wrap model calls to catch errors and notify the callback thread.
3395
+ *
3396
+ * If a model call raises an exception, a generic error message is
3397
+ * reported to the callback thread before re-raising. The actual error
3398
+ * details are not leaked to the callback agent.
3399
+ */
3374
3400
  async wrapModelCall(request, handler) {
3375
3401
  try {
3376
3402
  return await handler(request);
@@ -3504,15 +3530,22 @@ Summary:`;
3504
3530
  * list on subsequent calls.
3505
3531
  */
3506
3532
  const SummarizationEventSchema = z$1.object({
3533
+ /**
3534
+ * The index in the state messages list where summarization occurred.
3535
+ * Messages before this index have been summarized. */
3507
3536
  cutoffIndex: z$1.number(),
3537
+ /** The HumanMessage containing the summary. */
3508
3538
  summaryMessage: z$1.instanceof(HumanMessage),
3539
+ /** Path where the conversation history was offloaded, or null if offload failed. */
3509
3540
  filePath: z$1.string().nullable()
3510
3541
  });
3511
3542
  /**
3512
3543
  * State schema for summarization middleware.
3513
3544
  */
3514
3545
  const SummarizationStateSchema = z$1.object({
3546
+ /** Session ID for history file naming */
3515
3547
  _summarizationSessionId: z$1.string().optional(),
3548
+ /** Most recent summarization event (private state, not visible to agent) */
3516
3549
  _summarizationEvent: SummarizationEventSchema.optional()
3517
3550
  });
3518
3551
  /**
@@ -6622,6 +6655,271 @@ function createCacheBreakpointMiddleware() {
6622
6655
  });
6623
6656
  }
6624
6657
  //#endregion
6658
+ //#region src/stream.ts
6659
+ /**
6660
+ * Deep Agent streaming support (experimental).
6661
+ *
6662
+ * Provides:
6663
+ * - `DeepAgentRunStream` — type overlay that adds `.subagents` to the
6664
+ * `AgentRunStream` shape
6665
+ * - `createSubagentTransformer` — a `__native` transformer whose
6666
+ * projection (`subagents`) lands directly on the `GraphRunStream`
6667
+ * instance via langgraph-core's native transformer support
6668
+ *
6669
+ * See protocol proposal §15 (In-Process Streaming Interface) and §16
6670
+ * (Native Stream Transformers).
6671
+ */
6672
+ function hasPrefix(ns, prefix) {
6673
+ if (prefix.length > ns.length) return false;
6674
+ for (let i = 0; i < prefix.length; i += 1) if (ns[i] !== prefix[i]) return false;
6675
+ return true;
6676
+ }
6677
+ /**
6678
+ * Native transformer that correlates `task` tool calls into
6679
+ * {@link SubagentRunStream} objects and routes child-namespace
6680
+ * `tools` and `messages` events into per-subagent channels.
6681
+ *
6682
+ * Marked `__native: true` — the `subagents` projection key lands
6683
+ * directly on the `GraphRunStream` instance as `run.subagents`.
6684
+ */
6685
+ function createSubagentTransformer(path) {
6686
+ return () => {
6687
+ const subagentsLog = StreamChannel.local();
6688
+ const pendingByCallId = /* @__PURE__ */ new Map();
6689
+ const pendingByNamespaceSegment = /* @__PURE__ */ new Map();
6690
+ const latestValuesByNamespaceSegment = /* @__PURE__ */ new Map();
6691
+ const subagentsByName = /* @__PURE__ */ new Map();
6692
+ /** Maps tools-node namespace segment to subagent name. */
6693
+ const toolsNodeToName = /* @__PURE__ */ new Map();
6694
+ const childToolCalls = /* @__PURE__ */ new Map();
6695
+ /** Active ChatModelStreamImpl per subagent (keyed by subagent name). */
6696
+ const activeMessages = /* @__PURE__ */ new Map();
6697
+ function deletePendingSubagent(pending) {
6698
+ pendingByCallId.delete(pending.callId);
6699
+ for (const [segment, entry] of pendingByNamespaceSegment) if (entry === pending) {
6700
+ pendingByNamespaceSegment.delete(segment);
6701
+ latestValuesByNamespaceSegment.delete(segment);
6702
+ }
6703
+ }
6704
+ function subagentSegment(ns) {
6705
+ return ns.length === path.length + 1 ? ns[path.length] : void 0;
6706
+ }
6707
+ function getOrCreateSubagentLogs(name) {
6708
+ let logs = subagentsByName.get(name);
6709
+ if (!logs) {
6710
+ logs = {
6711
+ messagesLog: StreamChannel.local(),
6712
+ toolCallsLog: StreamChannel.local(),
6713
+ nestedSubagentsLog: StreamChannel.local()
6714
+ };
6715
+ subagentsByName.set(name, logs);
6716
+ }
6717
+ return logs;
6718
+ }
6719
+ return {
6720
+ __native: true,
6721
+ init: () => ({ subagents: subagentsLog }),
6722
+ process(event) {
6723
+ if (!hasPrefix(event.params.namespace, path)) return true;
6724
+ const ns = event.params.namespace;
6725
+ const depth = ns.length - path.length;
6726
+ if (depth <= 1 && event.method === "tools") {
6727
+ const data = event.params.data;
6728
+ const toolCallId = data.tool_call_id;
6729
+ const toolName = data.tool_name;
6730
+ if (toolName === "task" && data.event === "tool-started") {
6731
+ const rawInput = data.input;
6732
+ const input = typeof rawInput === "string" ? JSON.parse(rawInput) : rawInput ?? {};
6733
+ const subagentName = input.subagent_type ?? "unknown";
6734
+ const taskDescription = input.description ?? "";
6735
+ let resolveTaskInput;
6736
+ let resolveOutput;
6737
+ let rejectOutput;
6738
+ const taskInput = new Promise((res) => {
6739
+ resolveTaskInput = res;
6740
+ });
6741
+ const output = new Promise((res, rej) => {
6742
+ resolveOutput = res;
6743
+ rejectOutput = rej;
6744
+ });
6745
+ const pending = {
6746
+ name: subagentName,
6747
+ callId: toolCallId,
6748
+ resolveTaskInput,
6749
+ resolveOutput,
6750
+ rejectOutput
6751
+ };
6752
+ if (toolCallId) pendingByCallId.set(toolCallId, pending);
6753
+ resolveTaskInput(taskDescription);
6754
+ if (depth === 1) {
6755
+ toolsNodeToName.set(ns[path.length], subagentName);
6756
+ pendingByNamespaceSegment.set(ns[path.length], pending);
6757
+ }
6758
+ if (toolCallId) {
6759
+ const taskSegment = `tools:${toolCallId}`;
6760
+ toolsNodeToName.set(taskSegment, subagentName);
6761
+ pendingByNamespaceSegment.set(taskSegment, pending);
6762
+ }
6763
+ const logs = getOrCreateSubagentLogs(subagentName);
6764
+ subagentsLog.push({
6765
+ name: subagentName,
6766
+ taskInput,
6767
+ output,
6768
+ messages: logs.messagesLog,
6769
+ toolCalls: logs.toolCallsLog,
6770
+ subagents: logs.nestedSubagentsLog
6771
+ });
6772
+ }
6773
+ if (toolName === "task" && toolCallId) {
6774
+ const pending = pendingByCallId.get(toolCallId);
6775
+ if (pending) {
6776
+ if (data.event === "tool-finished") {
6777
+ pending.resolveOutput(data.output);
6778
+ deletePendingSubagent(pending);
6779
+ } else if (data.event === "tool-error") {
6780
+ const message = data.message ?? "unknown error";
6781
+ pending.rejectOutput(new Error(message));
6782
+ deletePendingSubagent(pending);
6783
+ }
6784
+ }
6785
+ }
6786
+ }
6787
+ const segment = subagentSegment(ns);
6788
+ const pending = segment ? pendingByNamespaceSegment.get(segment) : void 0;
6789
+ if (pending) {
6790
+ if (event.method === "values") latestValuesByNamespaceSegment.set(segment, event.params.data);
6791
+ else if (event.method === "lifecycle") {
6792
+ const data = event.params.data;
6793
+ if (data.event === "completed" || data.event === "interrupted") {
6794
+ pending.resolveOutput(latestValuesByNamespaceSegment.get(segment));
6795
+ deletePendingSubagent(pending);
6796
+ } else if (data.event === "failed") {
6797
+ pending.rejectOutput(/* @__PURE__ */ new Error(`Subagent ${pending.name} failed`));
6798
+ deletePendingSubagent(pending);
6799
+ }
6800
+ }
6801
+ }
6802
+ if (depth >= 2) {
6803
+ const parentSegment = ns[path.length];
6804
+ const subagentName = toolsNodeToName.get(parentSegment);
6805
+ const logs = subagentName ? subagentsByName.get(subagentName) : void 0;
6806
+ if (logs && subagentName) {
6807
+ if (event.method === "tools") {
6808
+ const data = event.params.data;
6809
+ const toolCallId = data.tool_call_id;
6810
+ const toolName = data.tool_name;
6811
+ if (data.event === "tool-started") {
6812
+ let resolveOutput;
6813
+ let rejectOutput;
6814
+ let resolveStatus;
6815
+ let resolveError;
6816
+ const output = new Promise((res, rej) => {
6817
+ resolveOutput = res;
6818
+ rejectOutput = rej;
6819
+ });
6820
+ const status = new Promise((res) => {
6821
+ resolveStatus = res;
6822
+ });
6823
+ const error = new Promise((res) => {
6824
+ resolveError = res;
6825
+ });
6826
+ childToolCalls.set(toolCallId, {
6827
+ resolveOutput,
6828
+ rejectOutput,
6829
+ resolveStatus,
6830
+ resolveError
6831
+ });
6832
+ const rawInput = data.input;
6833
+ const parsedInput = typeof rawInput === "string" ? JSON.parse(rawInput) : rawInput;
6834
+ logs.toolCallsLog.push({
6835
+ name: toolName ?? "unknown",
6836
+ callId: toolCallId,
6837
+ input: parsedInput,
6838
+ output,
6839
+ status,
6840
+ error
6841
+ });
6842
+ }
6843
+ const pending = toolCallId ? childToolCalls.get(toolCallId) : void 0;
6844
+ if (pending) {
6845
+ if (data.event === "tool-finished") {
6846
+ pending.resolveOutput(data.output);
6847
+ pending.resolveStatus("finished");
6848
+ pending.resolveError(void 0);
6849
+ childToolCalls.delete(toolCallId);
6850
+ } else if (data.event === "tool-error") {
6851
+ const message = data.message ?? "unknown error";
6852
+ pending.rejectOutput(new Error(message));
6853
+ pending.resolveStatus("error");
6854
+ pending.resolveError(message);
6855
+ childToolCalls.delete(toolCallId);
6856
+ }
6857
+ }
6858
+ }
6859
+ if (event.method === "messages") {
6860
+ const data = event.params.data;
6861
+ if (data.event === "message-start") {
6862
+ const eventsLog = StreamChannel.local();
6863
+ const stream = new ChatModelStreamImpl(eventsLog);
6864
+ eventsLog.push(data);
6865
+ activeMessages.set(subagentName, {
6866
+ stream,
6867
+ eventsLog
6868
+ });
6869
+ logs.messagesLog.push(stream);
6870
+ } else if (data.event === "message-finish") {
6871
+ const active = activeMessages.get(subagentName);
6872
+ if (active) {
6873
+ active.eventsLog.push(data);
6874
+ active.eventsLog.close();
6875
+ activeMessages.delete(subagentName);
6876
+ }
6877
+ } else activeMessages.get(subagentName)?.eventsLog.push(data);
6878
+ }
6879
+ }
6880
+ }
6881
+ return true;
6882
+ },
6883
+ finalize() {
6884
+ for (const pending of pendingByCallId.values()) pending.resolveOutput(void 0);
6885
+ pendingByCallId.clear();
6886
+ for (const pending of childToolCalls.values()) {
6887
+ pending.resolveOutput(void 0);
6888
+ pending.resolveStatus("finished");
6889
+ pending.resolveError(void 0);
6890
+ }
6891
+ childToolCalls.clear();
6892
+ for (const active of activeMessages.values()) active.eventsLog.fail(/* @__PURE__ */ new Error("run finalized before message completed"));
6893
+ activeMessages.clear();
6894
+ subagentsLog.close();
6895
+ for (const logs of subagentsByName.values()) {
6896
+ logs.toolCallsLog.close();
6897
+ logs.messagesLog.close();
6898
+ logs.nestedSubagentsLog.close();
6899
+ }
6900
+ },
6901
+ fail(err) {
6902
+ for (const pending of pendingByCallId.values()) pending.rejectOutput(err);
6903
+ pendingByCallId.clear();
6904
+ for (const pending of childToolCalls.values()) {
6905
+ pending.rejectOutput(err);
6906
+ pending.resolveStatus("error");
6907
+ pending.resolveError(err instanceof Error ? err.message : String(err));
6908
+ }
6909
+ childToolCalls.clear();
6910
+ for (const active of activeMessages.values()) active.eventsLog.fail(err);
6911
+ activeMessages.clear();
6912
+ subagentsLog.fail(err);
6913
+ for (const logs of subagentsByName.values()) {
6914
+ logs.toolCallsLog.fail(err);
6915
+ logs.messagesLog.fail(err);
6916
+ logs.nestedSubagentsLog.fail(err);
6917
+ }
6918
+ }
6919
+ };
6920
+ };
6921
+ }
6922
+ //#endregion
6625
6923
  //#region src/agent.ts
6626
6924
  const BASE_AGENT_PROMPT = context`
6627
6925
  You are a Deep Agent, an AI assistant that helps users accomplish tasks using tools. You respond with text and tool calls. The user can see your responses and tool outputs in real time.
@@ -6707,7 +7005,7 @@ function isAnthropicModel(model) {
6707
7005
  * ```
6708
7006
  */
6709
7007
  function createDeepAgent(params = {}) {
6710
- const { model = "anthropic:claude-sonnet-4-6", tools = [], systemPrompt, middleware: customMiddleware = [], subagents = [], responseFormat, contextSchema, checkpointer, store, backend = (config) => new StateBackend(config), interruptOn, name, memory, skills, permissions = [] } = params;
7008
+ const { model = "anthropic:claude-sonnet-4-6", tools = [], systemPrompt, middleware: customMiddleware = [], subagents = [], responseFormat, contextSchema, checkpointer, store, backend = (config) => new StateBackend(config), interruptOn, name, memory, skills, permissions = [], streamTransformers = [] } = params;
6711
7009
  const collidingTools = tools.map((t) => t.name).filter((n) => typeof n === "string" && BUILTIN_TOOL_NAMES.has(n));
6712
7010
  if (collidingTools.length > 0) throw new ConfigurationError(`Tool name(s) [${collidingTools.join(", ")}] conflict with built-in tools. Rename your custom tools to avoid this.`, "TOOL_NAME_COLLISION");
6713
7011
  const anthropicModel = isAnthropicModel(model);
@@ -6802,6 +7100,7 @@ function createDeepAgent(params = {}) {
6802
7100
  * - Middleware: AllMiddleware (built-in + custom + subagent middleware for state inference)
6803
7101
  * - Tools: TTools
6804
7102
  * - Subagents: TSubagents (for type-safe streaming)
7103
+ * - StreamTransformers: TStreamTransformers
6805
7104
  */
6806
7105
  return createAgent({
6807
7106
  model,
@@ -6824,7 +7123,8 @@ function createDeepAgent(params = {}) {
6824
7123
  contextSchema,
6825
7124
  checkpointer,
6826
7125
  store,
6827
- name
7126
+ name,
7127
+ streamTransformers: [createSubagentTransformer([]), ...streamTransformers]
6828
7128
  }).withConfig({
6829
7129
  recursionLimit: 1e4,
6830
7130
  metadata: {
@@ -6964,7 +7264,9 @@ function createSettings(options = {}) {
6964
7264
  * State schema for agent memory middleware.
6965
7265
  */
6966
7266
  const AgentMemoryStateSchema = z$1.object({
7267
+ /** Personal preferences from ~/.deepagents/{agent}/ (applies everywhere) */
6967
7268
  userMemory: z$1.string().optional(),
7269
+ /** Project-specific context (loaded from project root) */
6968
7270
  projectMemory: z$1.string().optional()
6969
7271
  });
6970
7272
  /**
@@ -7344,6 +7646,6 @@ function listSkills(options) {
7344
7646
  return Array.from(allSkills.values());
7345
7647
  }
7346
7648
  //#endregion
7347
- export { BaseSandbox, CompositeBackend, ConfigurationError, DEFAULT_GENERAL_PURPOSE_DESCRIPTION, DEFAULT_SUBAGENT_PROMPT, FilesystemBackend, GENERAL_PURPOSE_SUBAGENT, LangSmithSandbox, LocalShellBackend, MAX_SKILL_DESCRIPTION_LENGTH, MAX_SKILL_FILE_SIZE, MAX_SKILL_NAME_LENGTH, SandboxError, StateBackend, StoreBackend, TASK_SYSTEM_PROMPT, adaptBackendProtocol, adaptSandboxProtocol, computeSummarizationDefaults, createAgentMemoryMiddleware, createAsyncSubAgentMiddleware, createCompletionCallbackMiddleware, createDeepAgent, createFilesystemMiddleware, createMemoryMiddleware, createPatchToolCallsMiddleware, createSettings, createSkillsMiddleware, createSubAgentMiddleware, createSummarizationMiddleware, filesValue, findProjectRoot, isAsyncSubAgent, isSandboxBackend, isSandboxProtocol, listSkills, parseSkillMetadata, resolveBackend };
7649
+ export { BaseSandbox, CompositeBackend, ConfigurationError, DEFAULT_GENERAL_PURPOSE_DESCRIPTION, DEFAULT_SUBAGENT_PROMPT, FilesystemBackend, GENERAL_PURPOSE_SUBAGENT, LangSmithSandbox, LocalShellBackend, MAX_SKILL_DESCRIPTION_LENGTH, MAX_SKILL_FILE_SIZE, MAX_SKILL_NAME_LENGTH, SandboxError, StateBackend, StoreBackend, TASK_SYSTEM_PROMPT, adaptBackendProtocol, adaptSandboxProtocol, computeSummarizationDefaults, createAgentMemoryMiddleware, createAsyncSubAgentMiddleware, createCompletionCallbackMiddleware, createDeepAgent, createFilesystemMiddleware, createMemoryMiddleware, createPatchToolCallsMiddleware, createSettings, createSkillsMiddleware, createSubAgentMiddleware, createSubagentTransformer, createSummarizationMiddleware, filesValue, findProjectRoot, isAsyncSubAgent, isSandboxBackend, isSandboxProtocol, listSkills, parseSkillMetadata, resolveBackend };
7348
7650
 
7349
7651
  //# sourceMappingURL=index.js.map