@warble/claude-agent-sdk 0.16.0 → 0.18.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/README.md CHANGED
@@ -111,7 +111,11 @@ owned by the current user, with no group or other permission bits (`chmod 600`).
111
111
  `[a-z0-9_]{1,32}`, `tools` is a non-empty list of `[a-z0-9_]{1,64}`, `instruction` is one line of at
112
112
  most 300 characters, and unknown keys are rejected. The server is passed to `query()` as a stdio
113
113
  `mcpServers` entry; the read-only guardrail then allows exactly `mcp__<name>__<tool>` for the listed
114
- tools and still refuses every other `mcp__*` tool, and the `wren`-only Bash rule is unchanged. Keep
114
+ tools and still refuses every other `mcp__*` tool, and the `wren`-only Bash rule is unchanged. In a
115
+ per-step-tier split the steps run as subagents with an exhaustive tool list, so every subagent that
116
+ has `Bash` (the data-access ones) also gets the listed host tools and the instruction line. That
117
+ includes the subagents of a setup or mutating component with data access: the guardrail allows the
118
+ listed host tools by exact name in every component, as it already did for the driver. Keep
115
119
  secrets out of this file — pass a token file path in `args` instead; the CLI never prints the file,
116
120
  its `args`, or the environment. Hybrid-staged plans refuse the flag. Without it, `chat` behaves
117
121
  exactly as before.
@@ -138,7 +138,7 @@ function makeReadOnlyGuard(cfg: {
138
138
  const denials: Denial[] = [];
139
139
  const hooks: never[] = [];
140
140
  const canUseTool = async (toolName: string, input: Record<string, unknown>) => {
141
- if (toolName === "Read" || toolName === "Task" || toolName === "TodoWrite") {
141
+ if (toolName === "Read" || toolName === "Task" || toolName === "Agent" || toolName === "TodoWrite") {
142
142
  return { behavior: "allow" as const, updatedInput: input };
143
143
  }
144
144
  if (toolName === "Bash") {
@@ -514,7 +514,7 @@ var COMPONENT_TYPES = [
514
514
  ];
515
515
  var TRIGGER_KINDS = ["one_shot", "scheduled", "event"];
516
516
  var OUTCOME_KINDS = ["none", "assertion", "mutation", "dispatch"];
517
- var SUPPORTED_IR_VERSIONS = ["0.8"];
517
+ var SUPPORTED_IR_VERSIONS = ["0.9"];
518
518
  function assertSupportedIrVersion(version) {
519
519
  if (!SUPPORTED_IR_VERSIONS.includes(version)) {
520
520
  throw new DispatchError(
@@ -843,6 +843,9 @@ function parseIr(json2) {
843
843
  const obj = requireObject(root, "<root>");
844
844
  const version = requireString(obj, "warble_ir_version", "<root>");
845
845
  assertSupportedIrVersion(version);
846
+ if (obj["context_binding"] === null) {
847
+ fail("context-free IR is not supported by claude-agent-sdk:local");
848
+ }
846
849
  const configRaw = obj["config"];
847
850
  const config = {};
848
851
  if (configRaw !== void 0) {
@@ -2118,12 +2121,17 @@ import { resolve as resolvePath, sep as pathSep } from "path";
2118
2121
  function withinScope(abs, scopeAbs) {
2119
2122
  return abs === scopeAbs || abs.startsWith(scopeAbs.endsWith(pathSep) ? scopeAbs : scopeAbs + pathSep);
2120
2123
  }
2124
+ var OUT_OF_BAND_DENIAL = {
2125
+ behavior: "deny",
2126
+ message: "the embedding host answered this permission request out-of-band, which the guardrail cannot compose with"
2127
+ };
2121
2128
  function composeCanUseTool(embedder, floor) {
2122
2129
  if (embedder === void 0) return floor;
2123
2130
  return async (toolName, input, options) => {
2124
2131
  const fromEmbedder = await embedder(toolName, input, options);
2132
+ if (fromEmbedder === null) return OUT_OF_BAND_DENIAL;
2125
2133
  if (fromEmbedder.behavior !== "allow") return fromEmbedder;
2126
- return floor(toolName, fromEmbedder.updatedInput, options);
2134
+ return floor(toolName, fromEmbedder.updatedInput ?? input, options);
2127
2135
  };
2128
2136
  }
2129
2137
  function composeHooks(embedder, guardHooks) {
@@ -2188,7 +2196,7 @@ function makeReadOnlyGuard(cfg) {
2188
2196
  }
2189
2197
  return allow(input);
2190
2198
  }
2191
- if (toolName === "Task" || toolName === "TodoWrite") {
2199
+ if (toolName === "Task" || toolName === "Agent" || toolName === "TodoWrite") {
2192
2200
  return allow(input);
2193
2201
  }
2194
2202
  if (toolName === "Bash") {
@@ -2624,7 +2632,7 @@ var ChatEventMapper = class {
2624
2632
  return [{ t: "step_start", id: this.stepId, name: this.stepId, parent: null, depth: 0 }];
2625
2633
  }
2626
2634
  onAssistant(message) {
2627
- const content = message.message?.content;
2635
+ const content = isRecord(message.message) ? message.message["content"] : void 0;
2628
2636
  if (!Array.isArray(content)) return [];
2629
2637
  const parent = message.parent_tool_use_id ?? null;
2630
2638
  const depth = parent ? 1 : 0;
@@ -2645,7 +2653,7 @@ var ChatEventMapper = class {
2645
2653
  return events;
2646
2654
  }
2647
2655
  onUser(message) {
2648
- const content = message.message?.content;
2656
+ const content = isRecord(message.message) ? message.message["content"] : void 0;
2649
2657
  if (!Array.isArray(content)) return [];
2650
2658
  const events = [];
2651
2659
  for (const block of content) {
@@ -2717,6 +2725,20 @@ function applyHostMcp(options, hostMcp) {
2717
2725
  next.systemPrompt = `${options.systemPrompt}
2718
2726
  ${hostMcp.instruction}`;
2719
2727
  }
2728
+ if (options.agents !== void 0) {
2729
+ const hostTools = hostMcpToolNames(hostMcp);
2730
+ next.agents = Object.fromEntries(
2731
+ Object.entries(options.agents).map(([name, agent]) => {
2732
+ if (!agent.tools?.includes("Bash")) return [name, agent];
2733
+ return [name, {
2734
+ ...agent,
2735
+ tools: [...agent.tools, ...hostTools],
2736
+ ...hostMcp.instruction !== void 0 ? { prompt: `${agent.prompt}
2737
+ ${hostMcp.instruction}` } : {}
2738
+ }];
2739
+ })
2740
+ );
2741
+ }
2720
2742
  return next;
2721
2743
  }
2722
2744
  var DispatchSessionError = class extends DispatchError {
@@ -3713,7 +3735,7 @@ function componentStepSystemPrompt(run) {
3713
3735
  function componentTools(component) {
3714
3736
  const configured = component.plan.options.tools;
3715
3737
  if (!Array.isArray(configured)) return ["Read"];
3716
- return configured.filter((name) => name !== "Task" && name !== "Write" && name !== "Edit");
3738
+ return configured.filter((name) => name !== "Task" && name !== "Agent" && name !== "Write" && name !== "Edit");
3717
3739
  }
3718
3740
  function createSdkComponentStepRunner(cfg = {}) {
3719
3741
  const denials = [];
@@ -3761,7 +3783,8 @@ function createSdkComponentStepRunner(cfg = {}) {
3761
3783
  if (!toolNames.has(name)) return originalCanUseTool(name, input, options2);
3762
3784
  if (!cfg.hostCanUseTool) return { behavior: "allow", updatedInput: input };
3763
3785
  const permission = await cfg.hostCanUseTool(name, input, options2);
3764
- if (permission.behavior === "allow") rememberApproval(name, permission.updatedInput);
3786
+ if (permission === null) return OUT_OF_BAND_DENIAL;
3787
+ if (permission.behavior === "allow") rememberApproval(name, permission.updatedInput ?? input);
3765
3788
  return permission;
3766
3789
  };
3767
3790
  const componentCalls = run.aliases.map((alias) => tool2(
@@ -3772,14 +3795,16 @@ function createSdkComponentStepRunner(cfg = {}) {
3772
3795
  const name = `mcp__${MCP_SERVER_NAME2}__${alias}`;
3773
3796
  let input = { request: args.request, input: args.input ?? {} };
3774
3797
  if (cfg.hostCanUseTool && !consumeApproval(name, input)) {
3798
+ const toolUseID = `${run.rootRunId}:${run.callId ?? "root"}:${run.step.name}:${alias}`;
3775
3799
  const permission = await cfg.hostCanUseTool(name, input, {
3776
3800
  signal: run.signal,
3777
- toolUseID: `${run.rootRunId}:${run.callId ?? "root"}:${run.step.name}:${alias}`
3801
+ toolUseID,
3802
+ requestId: toolUseID
3778
3803
  });
3779
- if (permission.behavior !== "allow") {
3804
+ if (permission === null || permission.behavior !== "allow") {
3780
3805
  throw new DispatchError("component invocation was denied by the embedding host");
3781
3806
  }
3782
- input = permission.updatedInput;
3807
+ input = permission.updatedInput ?? input;
3783
3808
  }
3784
3809
  const result2 = await run.invoke(alias, input);
3785
3810
  return {
@@ -4163,8 +4188,8 @@ async function dispatch(input, runCfg) {
4163
4188
 
4164
4189
  // src/manifest.ts
4165
4190
  var MANIFEST_VERSION = "0.3";
4166
- var MIN_SUPPORTED_IR_VERSION = "0.8";
4167
- var MAX_SUPPORTED_IR_VERSION = "0.8";
4191
+ var MIN_SUPPORTED_IR_VERSION = "0.9";
4192
+ var MAX_SUPPORTED_IR_VERSION = "0.9";
4168
4193
  var DEFAULT_MAX_ATTEMPTS = 1;
4169
4194
  function classifyStep(node, stepIndex) {
4170
4195
  const when = node.llm_calls[stepIndex].when;
@@ -4659,4 +4684,4 @@ export {
4659
4684
  ChatSession,
4660
4685
  createChatSession
4661
4686
  };
4662
- //# sourceMappingURL=chunk-6GZGHFX7.js.map
4687
+ //# sourceMappingURL=chunk-MIW7NT66.js.map