@warlock.js/ai 4.14.0 → 4.16.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.
Files changed (104) hide show
  1. package/CHANGELOG.md +182 -141
  2. package/cjs/index.cjs +640 -139
  3. package/cjs/index.cjs.map +1 -1
  4. package/esm/contracts/index.d.mts +3 -3
  5. package/esm/contracts/memory/index.d.mts +1 -1
  6. package/esm/contracts/memory/memory-config.type.d.mts +29 -3
  7. package/esm/contracts/memory/memory-config.type.d.mts.map +1 -1
  8. package/esm/contracts/memory/memory-item.type.d.mts +15 -1
  9. package/esm/contracts/memory/memory-item.type.d.mts.map +1 -1
  10. package/esm/contracts/memory/memory.contract.d.mts +15 -2
  11. package/esm/contracts/memory/memory.contract.d.mts.map +1 -1
  12. package/esm/contracts/memory/recall-options.type.d.mts +12 -0
  13. package/esm/contracts/memory/recall-options.type.d.mts.map +1 -1
  14. package/esm/contracts/orchestrator/index.d.mts +1 -1
  15. package/esm/contracts/orchestrator/orchestrator-config.type.d.mts +38 -1
  16. package/esm/contracts/orchestrator/orchestrator-config.type.d.mts.map +1 -1
  17. package/esm/contracts/orchestrator/orchestrator.contract.d.mts +67 -3
  18. package/esm/contracts/orchestrator/orchestrator.contract.d.mts.map +1 -1
  19. package/esm/contracts/supervisor/supervisor-config.type.d.mts +23 -0
  20. package/esm/contracts/supervisor/supervisor-config.type.d.mts.map +1 -1
  21. package/esm/contracts/team/team-config.type.d.mts +9 -6
  22. package/esm/contracts/team/team-config.type.d.mts.map +1 -1
  23. package/esm/contracts/tool.contract.d.mts +35 -3
  24. package/esm/contracts/tool.contract.d.mts.map +1 -1
  25. package/esm/index.d.mts +8 -7
  26. package/esm/index.mjs +3 -2
  27. package/esm/memory/episodic-memory.mjs +14 -6
  28. package/esm/memory/episodic-memory.mjs.map +1 -1
  29. package/esm/memory/index.d.mts +1 -1
  30. package/esm/memory/memory.d.mts +13 -1
  31. package/esm/memory/memory.d.mts.map +1 -1
  32. package/esm/memory/memory.mjs +41 -7
  33. package/esm/memory/memory.mjs.map +1 -1
  34. package/esm/memory/procedural-memory.mjs +20 -7
  35. package/esm/memory/procedural-memory.mjs.map +1 -1
  36. package/esm/memory/semantic-memory.mjs +27 -10
  37. package/esm/memory/semantic-memory.mjs.map +1 -1
  38. package/esm/memory/working-memory.mjs +70 -13
  39. package/esm/memory/working-memory.mjs.map +1 -1
  40. package/esm/middleware/builtins/semantic-cache.d.mts +46 -1
  41. package/esm/middleware/builtins/semantic-cache.d.mts.map +1 -1
  42. package/esm/middleware/builtins/semantic-cache.mjs +60 -15
  43. package/esm/middleware/builtins/semantic-cache.mjs.map +1 -1
  44. package/esm/middleware/index.d.mts +1 -1
  45. package/esm/mock/index.d.mts +1 -1
  46. package/esm/mock/mock-config.type.d.mts +33 -4
  47. package/esm/mock/mock-config.type.d.mts.map +1 -1
  48. package/esm/mock/mock-model.d.mts +2 -1
  49. package/esm/mock/mock-model.d.mts.map +1 -1
  50. package/esm/mock/mock-model.mjs +5 -4
  51. package/esm/mock/mock-model.mjs.map +1 -1
  52. package/esm/mock/mock-sdk.d.mts +11 -3
  53. package/esm/mock/mock-sdk.d.mts.map +1 -1
  54. package/esm/mock/mock-sdk.mjs.map +1 -1
  55. package/esm/orchestrator/as-tool.d.mts +35 -9
  56. package/esm/orchestrator/as-tool.d.mts.map +1 -1
  57. package/esm/orchestrator/as-tool.mjs +67 -19
  58. package/esm/orchestrator/as-tool.mjs.map +1 -1
  59. package/esm/orchestrator/execution.d.mts.map +1 -1
  60. package/esm/orchestrator/execution.mjs +2 -2
  61. package/esm/orchestrator/execution.mjs.map +1 -1
  62. package/esm/orchestrator/index.d.mts +1 -1
  63. package/esm/orchestrator/index.mjs +1 -1
  64. package/esm/orchestrator/memory.d.mts +41 -5
  65. package/esm/orchestrator/memory.d.mts.map +1 -1
  66. package/esm/orchestrator/memory.mjs +53 -5
  67. package/esm/orchestrator/memory.mjs.map +1 -1
  68. package/esm/planner/plan-schema.d.mts +15 -4
  69. package/esm/planner/plan-schema.d.mts.map +1 -1
  70. package/esm/planner/plan-schema.mjs +27 -16
  71. package/esm/planner/plan-schema.mjs.map +1 -1
  72. package/esm/security/index.mjs +1 -0
  73. package/esm/security/outbound-policy.d.mts +9 -0
  74. package/esm/security/outbound-policy.d.mts.map +1 -1
  75. package/esm/security/outbound-policy.mjs +79 -5
  76. package/esm/security/outbound-policy.mjs.map +1 -1
  77. package/esm/security/outbound-policy.type.d.mts +8 -0
  78. package/esm/security/outbound-policy.type.d.mts.map +1 -1
  79. package/esm/security/safe-merge.d.mts +52 -0
  80. package/esm/security/safe-merge.d.mts.map +1 -0
  81. package/esm/security/safe-merge.mjs +68 -0
  82. package/esm/security/safe-merge.mjs.map +1 -0
  83. package/esm/supervisor/decide.mjs +52 -5
  84. package/esm/supervisor/decide.mjs.map +1 -1
  85. package/esm/supervisor/execution.d.mts +22 -12
  86. package/esm/supervisor/execution.d.mts.map +1 -1
  87. package/esm/supervisor/execution.mjs +47 -24
  88. package/esm/supervisor/execution.mjs.map +1 -1
  89. package/esm/supervisor/supervisor.mjs +4 -0
  90. package/esm/supervisor/supervisor.mjs.map +1 -1
  91. package/llms-full.txt +185 -14
  92. package/llms.txt +5 -4
  93. package/package.json +24 -4
  94. package/skills/README.md +6 -2
  95. package/skills/attach-ai-middleware/SKILL.md +17 -1
  96. package/skills/generate-images/SKILL.md +11 -4
  97. package/skills/rag-loaders-and-stores/SKILL.md +3 -0
  98. package/skills/run-ai-agent/SKILL.md +3 -0
  99. package/skills/run-orchestrator/SKILL.md +6 -1
  100. package/skills/run-planner/SKILL.md +7 -3
  101. package/skills/run-supervisor/SKILL.md +11 -1
  102. package/skills/secure-outbound-requests/SKILL.md +85 -0
  103. package/skills/use-ai-memory/SKILL.md +36 -3
  104. package/skills/use-runtime-skills/SKILL.md +2 -1
@@ -11,8 +11,9 @@ import "../utils/index.mjs";
11
11
  import { runPipeline } from "../middleware/pipeline.mjs";
12
12
  import { END } from "../contracts/end.type.mjs";
13
13
  import { isAgentResult, isWorkflowResult } from "./entries.mjs";
14
+ import { assignSafeKey, isUnsafeMergeKey, mergeSafely } from "../security/safe-merge.mjs";
14
15
  import { createCancelledError } from "./cancellation.mjs";
15
- import { decide } from "./decide.mjs";
16
+ import { capFanOut, decide, resolveMaxFanOut } from "./decide.mjs";
16
17
  import { persistSupervisorSnapshot } from "./snapshot.mjs";
17
18
  import { log } from "@warlock.js/logger";
18
19
 
@@ -432,9 +433,17 @@ var SupervisorExecution = class {
432
433
  * branch errors don't abort siblings — they're recorded on the
433
434
  * branch snapshot and let evaluate (or default termination logic)
434
435
  * decide the response.
436
+ *
437
+ * `capFanOut` runs here as well as in `decide.ts` — this is the one
438
+ * chokepoint every dispatch source funnels through (router/route
439
+ * decisions, `evaluate.reassignTo`, classifier picks, per-intent
440
+ * `next` unions), so the width bound holds even for the paths that
441
+ * build a `DispatchDecision` without going through `normalize()`.
442
+ * Idempotent for already-normalized decisions.
435
443
  */
436
444
  async dispatchBranches(decision) {
437
- return await Promise.all(decision.intents.map((intent) => this.dispatchOne(intent)));
445
+ const intents = capFanOut(decision.intents, this.entries, resolveMaxFanOut(this.config));
446
+ return await Promise.all(intents.map((intent) => this.dispatchOne(intent)));
438
447
  }
439
448
  /**
440
449
  * Execute a single branch — resolve the input, invoke the
@@ -819,24 +828,10 @@ var SupervisorExecution = class {
819
828
  * through unchanged so structured inputs work.
820
829
  */
821
830
  coerceInlineInput(executable, input) {
822
- if (!("signature" in executable) && typeof executable.execute === "function" && !this.isSupervisor(executable) && typeof input !== "string") return safeStringify(input);
831
+ if ("isAnonymous" in executable && typeof input !== "string") return safeStringify(input);
823
832
  return input;
824
833
  }
825
834
  /**
826
- * Heuristic detection of `SupervisorContract` — the contract carries
827
- * a `signature` getter same as workflows, but supervisors expose
828
- * `resume()` while workflows expose `resume(runId, options)` too.
829
- * Cleanest distinguisher in the public surface: supervisors carry
830
- * the `asTool` method name `as` … unfortunately so do workflows.
831
- * Use the `streamableType` brand if we add one in v2; for now lean
832
- * on a duck-typed check that's good enough for the ctx.run path
833
- * (incorrect routing for workflows would still produce a runnable
834
- * call — workflow.execute accepts the same args either way).
835
- */
836
- isSupervisor(executable) {
837
- return typeof executable.resume === "function" && typeof executable.signature === "string" && typeof executable.stream === "function";
838
- }
839
- /**
840
835
  * Invoke the underlying dispatchable unit. Agents and workflows
841
836
  * both satisfy `ExecutableContract<string, …>` so the call shape
842
837
  * is uniform; the `type` discriminator picks which options get
@@ -1134,7 +1129,31 @@ var SupervisorExecution = class {
1134
1129
  if (ackOutcome.error || !ackOutcome.output) return;
1135
1130
  if (typeof ackOutcome.output !== "object" || ackOutcome.output === null) return;
1136
1131
  const slice = ackOutcome.output;
1137
- for (const [key, value] of Object.entries(slice)) this.state[key] = value;
1132
+ this.mergeIntoState(slice, "ack");
1133
+ }
1134
+ /**
1135
+ * Single funnel for "shallow-merge a model-influenced slice into
1136
+ * `this.state`". Wraps the shared {@link mergeSafely} guard so no
1137
+ * merge site can assign `__proto__` / `constructor` / `prototype`
1138
+ * onto the run's state object, and logs when something tried.
1139
+ *
1140
+ * Every slice reaching state is model- or tool-influenced (agent
1141
+ * outputs validated against a DEVELOPER-supplied schema, which may
1142
+ * legitimately be permissive: `z.record()`, `.passthrough()`,
1143
+ * `z.any()`), so the key names are untrusted input even when the
1144
+ * values are shaped.
1145
+ */
1146
+ mergeIntoState(slice, origin) {
1147
+ const skipped = mergeSafely(this.state, slice);
1148
+ this.warnOnUnsafeKeys(skipped, origin);
1149
+ }
1150
+ /** Shared logging for refused prototype-tampering keys. */
1151
+ warnOnUnsafeKeys(skipped, origin) {
1152
+ if (skipped.length === 0) return;
1153
+ this.logger.warn(this.logModule, "state.merge.unsafe-key", `dropped prototype-tampering key(s) from "${origin}" merge: ${skipped.join(", ")}`, {
1154
+ origin,
1155
+ keys: skipped
1156
+ });
1138
1157
  }
1139
1158
  /**
1140
1159
  * Run the iter-0 classifier prelude (Phase 7 / decisions §37).
@@ -1258,9 +1277,9 @@ var SupervisorExecution = class {
1258
1277
  refined = interpretation.refined;
1259
1278
  halted = interpretation.halted;
1260
1279
  final = interpretation.final ?? raw;
1261
- if (interpretation.sliceToMerge) for (const [key, value] of Object.entries(interpretation.sliceToMerge)) this.state[key] = value;
1280
+ if (interpretation.sliceToMerge) this.mergeIntoState(interpretation.sliceToMerge, "classifier.refine");
1262
1281
  }
1263
- for (const [key, value] of Object.entries(final)) this.state[key] = value;
1282
+ this.mergeIntoState(final, "classifier");
1264
1283
  this.classifierSnapshot = {
1265
1284
  intent: halted ? void 0 : final.intent,
1266
1285
  reasoning: final.reasoning,
@@ -1457,7 +1476,7 @@ var SupervisorExecution = class {
1457
1476
  const slice = {};
1458
1477
  for (const [key, value] of Object.entries(record)) {
1459
1478
  if (key === "intent") continue;
1460
- slice[key] = value;
1479
+ assignSafeKey(slice, key, value);
1461
1480
  }
1462
1481
  const final = {
1463
1482
  ...raw,
@@ -1533,6 +1552,10 @@ var SupervisorExecution = class {
1533
1552
  continue;
1534
1553
  }
1535
1554
  for (const [key, value] of Object.entries(slice)) {
1555
+ if (isUnsafeMergeKey(key)) {
1556
+ this.warnOnUnsafeKeys([key], `intent "${intent}"`);
1557
+ continue;
1558
+ }
1536
1559
  const previousOwner = mergedKeys.get(key);
1537
1560
  if (previousOwner !== void 0 && previousOwner !== intent) this.logger.warn(this.logModule, "state.merge.conflict", `state key "${key}" written by both "${previousOwner}" and "${intent}" — last-in-decision-array wins (Q15)`, {
1538
1561
  key,
@@ -1584,9 +1607,9 @@ var SupervisorExecution = class {
1584
1607
  const finalize = this.config.finalizeArtifacts;
1585
1608
  if (finalize) {
1586
1609
  const merged = finalize(this.state, artifacts);
1587
- for (const key of Object.keys(this.state)) if (!(key in merged)) delete this.state[key];
1588
- for (const [key, value] of Object.entries(merged)) this.state[key] = value;
1589
- } else for (const [key, value] of Object.entries(artifacts)) this.state[key] = value;
1610
+ for (const key of Object.keys(this.state)) if (!Object.hasOwn(merged, key)) delete this.state[key];
1611
+ this.mergeIntoState(merged, "finalizeArtifacts");
1612
+ } else this.mergeIntoState(artifacts, "artifacts");
1590
1613
  this.currentArtifacts = {};
1591
1614
  }
1592
1615
  /**