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