deepagents 1.13.5 → 1.14.1

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.
@@ -2683,10 +2683,11 @@ function createFilesystemMiddleware(options = {}) {
2683
2683
  ...runtime,
2684
2684
  state
2685
2685
  });
2686
- const evictPath = `/large_tool_results/${sanitizeToolCallId(fallbackToolCallId || msg.tool_call_id)}.txt`;
2686
+ const sanitizedId = sanitizeToolCallId(fallbackToolCallId || msg.tool_call_id);
2687
+ const evictPath = `/large_tool_results/${new TextEncoder().encode(sanitizedId).length > 128 ? `call-${crypto.randomUUID()}` : sanitizedId}.txt`;
2687
2688
  const writeResult = await resolvedBackend.write(evictPath, textContent);
2688
2689
  const contentSample = createContentPreview(textContent);
2689
- const replacementText = writeResult.error ? `Tool result too large, but the result could not be saved to the filesystem: ${writeResult.error}` : TOO_LARGE_TOOL_MSG.replace("{tool_call_id}", msg.tool_call_id).replace("{file_path}", evictPath).replace("{content_sample}", contentSample);
2690
+ const replacementText = writeResult.error ? `Tool result too large, but the result could not be saved to the filesystem: ${writeResult.error}` : TOO_LARGE_TOOL_MSG.replace("{tool_call_id}", msg.tool_call_id.length > 32 ? `${msg.tool_call_id.slice(0, 32)}...` : msg.tool_call_id).replace("{file_path}", evictPath).replace("{content_sample}", contentSample);
2690
2691
  return {
2691
2692
  message: new langchain.ToolMessage({
2692
2693
  content: replacementText,
@@ -3620,6 +3621,11 @@ const EXCLUDED_STATE_KEYS = [
3620
3621
  * the parent's private channels (skills metadata, memory contents, etc.)
3621
3622
  * to rebuild an equivalent prompt.
3622
3623
  *
3624
+ * A pending invalidation propagates: a fork spawned in the same iteration
3625
+ * that set `skillsMetadata` to `null` inherits the `null`, so its mirrored
3626
+ * skills middleware reloads from its own sources rather than seeing the
3627
+ * parent's last loaded list.
3628
+ *
3623
3629
  * Call counts stay excluded: a fork inherits the parent's middleware, so
3624
3630
  * sharing them collides on the parent's channel.
3625
3631
  */
@@ -4584,30 +4590,37 @@ const SkillMetadataEntrySchema = zod.z.object({
4584
4590
  module: zod.z.string().optional()
4585
4591
  });
4586
4592
  /**
4587
- * Reducer for skillsMetadata that merges arrays from parallel subagents.
4588
- * Skills are deduplicated by name, with later values overriding earlier ones.
4593
+ * State value for a middleware's `skillsMetadata` field.
4594
+ *
4595
+ * A middleware can only read and write the fields declared on its own state
4596
+ * schema. A middleware that needs `skillsMetadata` — to inspect the skills
4597
+ * loaded for the thread, or to set the field to `null` and make the next model
4598
+ * call reload every source — declares it with this value.
4599
+ *
4600
+ * Treat the value as opaque: it is meant to be passed to `StateSchema`, and
4601
+ * its concrete type is an implementation detail that may change. To type an
4602
+ * individual entry, use {@link SkillMetadataEntry}.
4603
+ *
4604
+ * @example
4605
+ * ```typescript
4606
+ * import { createMiddleware } from "langchain";
4607
+ * import { StateSchema } from "@langchain/langgraph";
4608
+ * import { skillsMetadataValue } from "deepagents";
4589
4609
  *
4590
- * @param current - The current skillsMetadata array (from state)
4591
- * @param update - The new skillsMetadata array (from a subagent update)
4592
- * @returns Merged array with duplicates resolved by name (later values win)
4610
+ * const reloadEditedSkills = createMiddleware({
4611
+ * name: "ReloadEditedSkills",
4612
+ * stateSchema: new StateSchema({ skillsMetadata: skillsMetadataValue }),
4613
+ * afterAgent: (state) =>
4614
+ * agentEditedSkills(state) ? { skillsMetadata: null } : undefined,
4615
+ * });
4616
+ * ```
4593
4617
  */
4594
- function skillsMetadataReducer(current, update) {
4595
- if (!update || update.length === 0) return current || [];
4596
- if (!current || current.length === 0) return update;
4597
- const merged = /* @__PURE__ */ new Map();
4598
- for (const skill of current) merged.set(skill.name, skill);
4599
- for (const skill of update) merged.set(skill.name, skill);
4600
- return Array.from(merged.values());
4601
- }
4618
+ const skillsMetadataValue = zod.z.array(SkillMetadataEntrySchema).nullish();
4602
4619
  /**
4603
4620
  * State schema for skills middleware.
4604
- * Uses ReducedValue for skillsMetadata to allow concurrent updates from parallel subagents.
4605
4621
  */
4606
4622
  const SkillsStateSchema = new _langchain_langgraph.StateSchema({
4607
- skillsMetadata: new _langchain_langgraph.ReducedValue(zod.z.array(SkillMetadataEntrySchema).default(() => []), {
4608
- inputSchema: zod.z.array(SkillMetadataEntrySchema).optional(),
4609
- reducer: skillsMetadataReducer
4610
- }),
4623
+ skillsMetadata: skillsMetadataValue,
4611
4624
  files: filesValue
4612
4625
  });
4613
4626
  /**
@@ -4944,6 +4957,21 @@ function validateModulePath(raw) {
4944
4957
  * pattern: skill names and descriptions are shown in the prompt, but the agent
4945
4958
  * reads full SKILL.md content only when needed.
4946
4959
  *
4960
+ * Skills are loaded once per thread and stored in state. To pick up skills
4961
+ * added, edited, or deleted since then, set `skillsMetadata` to `null`; the
4962
+ * next model call reloads every source:
4963
+ *
4964
+ * ```ts
4965
+ * await agent.updateState(config, { skillsMetadata: null });
4966
+ * // or as part of the next run's input
4967
+ * await agent.invoke({ messages, skillsMetadata: null }, config);
4968
+ * ```
4969
+ *
4970
+ * Loading happens in `beforeModel`, so the reload is served by the next model
4971
+ * call rather than the next run. A middleware of your own can therefore
4972
+ * invalidate from any hook — including mid-run, from `afterModel` — and see
4973
+ * the fresh list on the following call. See {@link skillsMetadataValue}.
4974
+ *
4947
4975
  * @param options - Configuration options
4948
4976
  * @returns AgentMiddleware for skills loading and injection
4949
4977
  *
@@ -4960,8 +4988,8 @@ function createSkillsMiddleware(options) {
4960
4988
  return (0, langchain.createMiddleware)({
4961
4989
  name: "SkillsMiddleware",
4962
4990
  stateSchema: SkillsStateSchema,
4963
- async beforeAgent(state) {
4964
- if ("skillsMetadata" in state && Array.isArray(state.skillsMetadata) && state.skillsMetadata.length > 0) return;
4991
+ async beforeModel(state) {
4992
+ if (state.skillsMetadata !== null && state.skillsMetadata !== void 0) return;
4965
4993
  const resolvedBackend = await resolveBackend(backend, { state });
4966
4994
  const allSkills = /* @__PURE__ */ new Map();
4967
4995
  for (const sourcePath of sources) try {
@@ -9193,5 +9221,11 @@ Object.defineProperty(exports, "serializeProfile", {
9193
9221
  return serializeProfile;
9194
9222
  }
9195
9223
  });
9224
+ Object.defineProperty(exports, "skillsMetadataValue", {
9225
+ enumerable: true,
9226
+ get: function() {
9227
+ return skillsMetadataValue;
9228
+ }
9229
+ });
9196
9230
 
9197
- //# sourceMappingURL=langsmith-CG8px69t.cjs.map
9231
+ //# sourceMappingURL=langsmith-Bhg_Q4ZO.cjs.map