@warble/claude-agent-sdk 0.17.0 → 0.19.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 +5 -1
- package/dist/{chunk-74JAAZB7.js → chunk-J53WGCGG.js} +50 -21
- package/dist/chunk-J53WGCGG.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-74JAAZB7.js.map +0 -1
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.
|
|
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.
|
|
@@ -5,6 +5,12 @@ var DispatchError = class extends Error {
|
|
|
5
5
|
this.name = "DispatchError";
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
|
+
function boundedMessage(message) {
|
|
9
|
+
const collapsed = message.replace(/[\r\n\t]+/g, " ").replace(/\s+/g, " ").trim();
|
|
10
|
+
const withoutPaths = collapsed.replace(/(?:^|\s)\/(?:[^\s/]+\/)*[^\s]*/g, " [redacted path]");
|
|
11
|
+
const safe = /\b(select|insert|update|delete|merge|alter|drop|create)\b/i.test(withoutPaths) ? "The callee did not complete the request." : withoutPaths;
|
|
12
|
+
return (safe || "The child run did not complete.").slice(0, 240);
|
|
13
|
+
}
|
|
8
14
|
|
|
9
15
|
// src/codegen.ts
|
|
10
16
|
function ident(verb) {
|
|
@@ -138,7 +144,7 @@ function makeReadOnlyGuard(cfg: {
|
|
|
138
144
|
const denials: Denial[] = [];
|
|
139
145
|
const hooks: never[] = [];
|
|
140
146
|
const canUseTool = async (toolName: string, input: Record<string, unknown>) => {
|
|
141
|
-
if (toolName === "Read" || toolName === "Task" || toolName === "TodoWrite") {
|
|
147
|
+
if (toolName === "Read" || toolName === "Task" || toolName === "Agent" || toolName === "TodoWrite") {
|
|
142
148
|
return { behavior: "allow" as const, updatedInput: input };
|
|
143
149
|
}
|
|
144
150
|
if (toolName === "Bash") {
|
|
@@ -2121,12 +2127,17 @@ import { resolve as resolvePath, sep as pathSep } from "path";
|
|
|
2121
2127
|
function withinScope(abs, scopeAbs) {
|
|
2122
2128
|
return abs === scopeAbs || abs.startsWith(scopeAbs.endsWith(pathSep) ? scopeAbs : scopeAbs + pathSep);
|
|
2123
2129
|
}
|
|
2130
|
+
var OUT_OF_BAND_DENIAL = {
|
|
2131
|
+
behavior: "deny",
|
|
2132
|
+
message: "the embedding host answered this permission request out-of-band, which the guardrail cannot compose with"
|
|
2133
|
+
};
|
|
2124
2134
|
function composeCanUseTool(embedder, floor) {
|
|
2125
2135
|
if (embedder === void 0) return floor;
|
|
2126
2136
|
return async (toolName, input, options) => {
|
|
2127
2137
|
const fromEmbedder = await embedder(toolName, input, options);
|
|
2138
|
+
if (fromEmbedder === null) return OUT_OF_BAND_DENIAL;
|
|
2128
2139
|
if (fromEmbedder.behavior !== "allow") return fromEmbedder;
|
|
2129
|
-
return floor(toolName, fromEmbedder.updatedInput, options);
|
|
2140
|
+
return floor(toolName, fromEmbedder.updatedInput ?? input, options);
|
|
2130
2141
|
};
|
|
2131
2142
|
}
|
|
2132
2143
|
function composeHooks(embedder, guardHooks) {
|
|
@@ -2191,7 +2202,7 @@ function makeReadOnlyGuard(cfg) {
|
|
|
2191
2202
|
}
|
|
2192
2203
|
return allow(input);
|
|
2193
2204
|
}
|
|
2194
|
-
if (toolName === "Task" || toolName === "TodoWrite") {
|
|
2205
|
+
if (toolName === "Task" || toolName === "Agent" || toolName === "TodoWrite") {
|
|
2195
2206
|
return allow(input);
|
|
2196
2207
|
}
|
|
2197
2208
|
if (toolName === "Bash") {
|
|
@@ -2627,7 +2638,7 @@ var ChatEventMapper = class {
|
|
|
2627
2638
|
return [{ t: "step_start", id: this.stepId, name: this.stepId, parent: null, depth: 0 }];
|
|
2628
2639
|
}
|
|
2629
2640
|
onAssistant(message) {
|
|
2630
|
-
const content = message.message
|
|
2641
|
+
const content = isRecord(message.message) ? message.message["content"] : void 0;
|
|
2631
2642
|
if (!Array.isArray(content)) return [];
|
|
2632
2643
|
const parent = message.parent_tool_use_id ?? null;
|
|
2633
2644
|
const depth = parent ? 1 : 0;
|
|
@@ -2648,7 +2659,7 @@ var ChatEventMapper = class {
|
|
|
2648
2659
|
return events;
|
|
2649
2660
|
}
|
|
2650
2661
|
onUser(message) {
|
|
2651
|
-
const content = message.message
|
|
2662
|
+
const content = isRecord(message.message) ? message.message["content"] : void 0;
|
|
2652
2663
|
if (!Array.isArray(content)) return [];
|
|
2653
2664
|
const events = [];
|
|
2654
2665
|
for (const block of content) {
|
|
@@ -2720,6 +2731,20 @@ function applyHostMcp(options, hostMcp) {
|
|
|
2720
2731
|
next.systemPrompt = `${options.systemPrompt}
|
|
2721
2732
|
${hostMcp.instruction}`;
|
|
2722
2733
|
}
|
|
2734
|
+
if (options.agents !== void 0) {
|
|
2735
|
+
const hostTools = hostMcpToolNames(hostMcp);
|
|
2736
|
+
next.agents = Object.fromEntries(
|
|
2737
|
+
Object.entries(options.agents).map(([name, agent]) => {
|
|
2738
|
+
if (!agent.tools?.includes("Bash")) return [name, agent];
|
|
2739
|
+
return [name, {
|
|
2740
|
+
...agent,
|
|
2741
|
+
tools: [...agent.tools, ...hostTools],
|
|
2742
|
+
...hostMcp.instruction !== void 0 ? { prompt: `${agent.prompt}
|
|
2743
|
+
${hostMcp.instruction}` } : {}
|
|
2744
|
+
}];
|
|
2745
|
+
})
|
|
2746
|
+
);
|
|
2747
|
+
}
|
|
2723
2748
|
return next;
|
|
2724
2749
|
}
|
|
2725
2750
|
var DispatchSessionError = class extends DispatchError {
|
|
@@ -2948,18 +2973,19 @@ async function runHybridStaged(plan, cfg) {
|
|
|
2948
2973
|
continue;
|
|
2949
2974
|
}
|
|
2950
2975
|
if (decision.kind === "repair") {
|
|
2951
|
-
|
|
2976
|
+
const originalFailureText = boundedMessage(artifacts[decision.target.produces ?? decision.target.name] ?? "");
|
|
2977
|
+
let lastFailureText = originalFailureText;
|
|
2952
2978
|
const { recovered, attempts } = await runRepairLoop(DEFAULT_MAX_REPAIR_ATTEMPTS, async () => {
|
|
2953
2979
|
const attempt = await executeStep(step, artifacts, execCtx, true);
|
|
2954
2980
|
outcomes[step.name] = attempt.outcome;
|
|
2955
2981
|
artifacts[artifactKey(step)] = attempt.text;
|
|
2956
2982
|
if (attempt.outcome === "success") finalText = attempt.text;
|
|
2957
|
-
else lastFailureText = attempt.text;
|
|
2983
|
+
else lastFailureText = boundedMessage(attempt.text);
|
|
2958
2984
|
return { failed: attempt.outcome === "failure" };
|
|
2959
2985
|
});
|
|
2960
2986
|
if (!recovered) {
|
|
2961
2987
|
throw new DispatchError(
|
|
2962
|
-
`repair step '${step.name}' did not recover '${decision.target.name}' after ${attempts} attempt(s); last failure: ${lastFailureText}`
|
|
2988
|
+
`repair step '${step.name}' did not recover '${decision.target.name}' after ${attempts} attempt(s); ${decision.target.name} failed: ${originalFailureText}; last failure: ${lastFailureText}`
|
|
2963
2989
|
);
|
|
2964
2990
|
}
|
|
2965
2991
|
process.stderr.write(
|
|
@@ -3071,12 +3097,6 @@ function assertSupportedComponentInvocationLimits(input) {
|
|
|
3071
3097
|
function byteLength(value) {
|
|
3072
3098
|
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
3073
3099
|
}
|
|
3074
|
-
function boundedMessage(message) {
|
|
3075
|
-
const collapsed = message.replace(/[\r\n\t]+/g, " ").replace(/\s+/g, " ").trim();
|
|
3076
|
-
const withoutPaths = collapsed.replace(/(?:^|\s)\/(?:[^\s/]+\/)*[^\s]*/g, " [redacted path]");
|
|
3077
|
-
const safe = /\b(select|insert|update|delete|merge|alter|drop|create)\b/i.test(withoutPaths) ? "The callee did not complete the request." : withoutPaths;
|
|
3078
|
-
return (safe || "The child run did not complete.").slice(0, 240);
|
|
3079
|
-
}
|
|
3080
3100
|
function isJsonValue(value, seen = /* @__PURE__ */ new Set()) {
|
|
3081
3101
|
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
3082
3102
|
if (typeof value === "number") return Number.isFinite(value);
|
|
@@ -3517,7 +3537,13 @@ var ComponentInvocationRuntime = class {
|
|
|
3517
3537
|
if (result2.outcome === "success") finalText = result2.text;
|
|
3518
3538
|
return { failed: result2.outcome === "failure" };
|
|
3519
3539
|
});
|
|
3520
|
-
if (!repair.recovered)
|
|
3540
|
+
if (!repair.recovered) {
|
|
3541
|
+
const target = decision.target;
|
|
3542
|
+
const original = boundedMessage(artifacts[target.produces ?? target.name] ?? "");
|
|
3543
|
+
throw new DispatchError(
|
|
3544
|
+
`callee_failed: repair step '${call.name}' did not recover; ${target.name} failed: ${original}`
|
|
3545
|
+
);
|
|
3546
|
+
}
|
|
3521
3547
|
continue;
|
|
3522
3548
|
}
|
|
3523
3549
|
}
|
|
@@ -3716,7 +3742,7 @@ function componentStepSystemPrompt(run) {
|
|
|
3716
3742
|
function componentTools(component) {
|
|
3717
3743
|
const configured = component.plan.options.tools;
|
|
3718
3744
|
if (!Array.isArray(configured)) return ["Read"];
|
|
3719
|
-
return configured.filter((name) => name !== "Task" && name !== "Write" && name !== "Edit");
|
|
3745
|
+
return configured.filter((name) => name !== "Task" && name !== "Agent" && name !== "Write" && name !== "Edit");
|
|
3720
3746
|
}
|
|
3721
3747
|
function createSdkComponentStepRunner(cfg = {}) {
|
|
3722
3748
|
const denials = [];
|
|
@@ -3764,7 +3790,8 @@ function createSdkComponentStepRunner(cfg = {}) {
|
|
|
3764
3790
|
if (!toolNames.has(name)) return originalCanUseTool(name, input, options2);
|
|
3765
3791
|
if (!cfg.hostCanUseTool) return { behavior: "allow", updatedInput: input };
|
|
3766
3792
|
const permission = await cfg.hostCanUseTool(name, input, options2);
|
|
3767
|
-
if (permission
|
|
3793
|
+
if (permission === null) return OUT_OF_BAND_DENIAL;
|
|
3794
|
+
if (permission.behavior === "allow") rememberApproval(name, permission.updatedInput ?? input);
|
|
3768
3795
|
return permission;
|
|
3769
3796
|
};
|
|
3770
3797
|
const componentCalls = run.aliases.map((alias) => tool2(
|
|
@@ -3775,14 +3802,16 @@ function createSdkComponentStepRunner(cfg = {}) {
|
|
|
3775
3802
|
const name = `mcp__${MCP_SERVER_NAME2}__${alias}`;
|
|
3776
3803
|
let input = { request: args.request, input: args.input ?? {} };
|
|
3777
3804
|
if (cfg.hostCanUseTool && !consumeApproval(name, input)) {
|
|
3805
|
+
const toolUseID = `${run.rootRunId}:${run.callId ?? "root"}:${run.step.name}:${alias}`;
|
|
3778
3806
|
const permission = await cfg.hostCanUseTool(name, input, {
|
|
3779
3807
|
signal: run.signal,
|
|
3780
|
-
toolUseID
|
|
3808
|
+
toolUseID,
|
|
3809
|
+
requestId: toolUseID
|
|
3781
3810
|
});
|
|
3782
|
-
if (permission.behavior !== "allow") {
|
|
3811
|
+
if (permission === null || permission.behavior !== "allow") {
|
|
3783
3812
|
throw new DispatchError("component invocation was denied by the embedding host");
|
|
3784
3813
|
}
|
|
3785
|
-
input = permission.updatedInput;
|
|
3814
|
+
input = permission.updatedInput ?? input;
|
|
3786
3815
|
}
|
|
3787
3816
|
const result2 = await run.invoke(alias, input);
|
|
3788
3817
|
return {
|
|
@@ -4662,4 +4691,4 @@ export {
|
|
|
4662
4691
|
ChatSession,
|
|
4663
4692
|
createChatSession
|
|
4664
4693
|
};
|
|
4665
|
-
//# sourceMappingURL=chunk-
|
|
4694
|
+
//# sourceMappingURL=chunk-J53WGCGG.js.map
|