mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 02:02:42 +00:00
Let Claude sessions pass structured launch arguments (#5206)
Expose Claude Agent SDK's documented extraArgs map through providerOptions so Claude-specific flags such as --chrome reach the CLI. Document boolean and valued flags, link the upstream contract, and validate through schema tests, the public session interface, and a real Claude launch.
This commit is contained in:
+14
-5
@@ -8,7 +8,8 @@ This guide walks through adding a new agent provider end-to-end. There are two i
|
||||
names and nesting are the provider's native contract; options are not portable between providers.
|
||||
Paseo validates the object with the selected provider's strict schema before constructing a session.
|
||||
Unknown keys fail with their `providerOptions.*` path. Paseo-owned controls such as cwd, model,
|
||||
prompt, environment, session identity, MCP transport, callbacks, and hooks cannot be passed here.
|
||||
prompt, environment, session identity, MCP transport, callbacks, and hooks are not accepted as
|
||||
top-level provider options.
|
||||
|
||||
This Paseo version accepts these keys:
|
||||
|
||||
@@ -19,10 +20,18 @@ This Paseo version accepts these keys:
|
||||
`allow_local_binding`, `allow_upstream_proxy`, `dangerously_allow_all_unix_sockets`,
|
||||
`dangerously_allow_non_loopback_proxy`, `domains`, and `unix_sockets`. See the
|
||||
[Codex configuration reference](https://developers.openai.com/codex/config-reference).
|
||||
- **Claude:** `allowedTools`, `disallowedTools`, `additionalDirectories`, `sandbox`, and `settings`.
|
||||
The accepted sandbox fields cover enablement, fail-if-unavailable behavior, excluded and
|
||||
unsandboxed commands, filesystem read/write rules, network domain/socket/local-binding rules,
|
||||
weaker nested sandboxing, ignored violations, and the ripgrep command. `settings` accepts native
|
||||
- **Claude:** `allowedTools`, `disallowedTools`, `additionalDirectories`, `extraArgs`, `sandbox`, and
|
||||
`settings`. `providerOptions.extraArgs` passes the SDK's documented
|
||||
[`Options.extraArgs`](https://platform.claude.com/docs/en/agent-sdk/typescript#options) map
|
||||
unchanged: keys omit the leading `--`, string values supply an argument value, and `null`
|
||||
supplies a boolean flag. For example, `providerOptions: { extraArgs: { chrome: null } }`
|
||||
passes `--chrome`, and `providerOptions: { extraArgs: { model: "x" } }` passes `--model x`.
|
||||
Set it in session configuration or a plugin's `server.before("agent.create", ...)` hook; see
|
||||
[plugin configuration hooks](../public-docs/plugins/reference.md#change-configuration-and-inject-an-mcp-server). Values are literal;
|
||||
shell expressions such as `$(command)` are not evaluated. The accepted sandbox
|
||||
fields cover enablement, fail-if-unavailable behavior, excluded and unsandboxed commands,
|
||||
filesystem read/write rules, network domain/socket/local-binding rules, weaker nested
|
||||
sandboxing, ignored violations, and the ripgrep command. `settings` accepts native
|
||||
`permissions.{allow,ask,deny}` and sandbox settings. See the
|
||||
[Claude Agent SDK TypeScript reference](https://platform.claude.com/docs/en/agent-sdk/typescript)
|
||||
and [Claude settings reference](https://code.claude.com/docs/en/settings).
|
||||
|
||||
@@ -51,6 +51,7 @@ describe("provider-owned option schemas", () => {
|
||||
ClaudeProviderOptionsSchema.parse({
|
||||
allowedTools: ["Read"],
|
||||
disallowedTools: ["Bash(rm *)"],
|
||||
extraArgs: { chrome: null, model: "x" },
|
||||
sandbox: {
|
||||
enabled: true,
|
||||
failIfUnavailable: true,
|
||||
@@ -63,7 +64,26 @@ describe("provider-owned option schemas", () => {
|
||||
},
|
||||
settings: { permissions: { ask: ["Bash(*)"], deny: ["Edit(.env)"] } },
|
||||
}),
|
||||
).toMatchObject({ sandbox: { enabled: true, failIfUnavailable: true } });
|
||||
).toMatchObject({
|
||||
extraArgs: { chrome: null, model: "x" },
|
||||
sandbox: { enabled: true, failIfUnavailable: true },
|
||||
});
|
||||
});
|
||||
|
||||
test.each([true, 42, ["x"]])("rejects invalid Claude extra argument values: %j", (value) => {
|
||||
expect(() =>
|
||||
validateProviderOptions("claude", ClaudeProviderOptionsSchema, {
|
||||
extraArgs: { chrome: value },
|
||||
}),
|
||||
).toThrow("providerOptions.extraArgs.chrome");
|
||||
});
|
||||
|
||||
test("rejects a raw argument list for the SDK argument map", () => {
|
||||
expect(() =>
|
||||
validateProviderOptions("claude", ClaudeProviderOptionsSchema, {
|
||||
extraArgs: ["--chrome"],
|
||||
}),
|
||||
).toThrow("providerOptions.extraArgs");
|
||||
});
|
||||
|
||||
test("reports the exact invalid Claude option path", () => {
|
||||
|
||||
@@ -785,6 +785,29 @@ describe("ClaudeAgentSession features", () => {
|
||||
await session.close();
|
||||
});
|
||||
|
||||
test("passes extra Claude Code CLI arguments to the SDK", async () => {
|
||||
const { queryFactory, launches } = createQueryMock();
|
||||
const client = new ClaudeAgentClient({
|
||||
logger,
|
||||
queryFactory,
|
||||
resolveBinary: async () => "/test/claude/bin",
|
||||
});
|
||||
const session = await client.createSession({
|
||||
provider: "claude",
|
||||
cwd: process.cwd(),
|
||||
providerOptions: {
|
||||
extraArgs: { chrome: null, model: "x" },
|
||||
},
|
||||
});
|
||||
|
||||
await expect(session.startTurn("hello")).resolves.toEqual({
|
||||
turnId: expect.stringMatching(/^foreground-turn-/),
|
||||
});
|
||||
|
||||
expect(launches[0]?.options.extraArgs).toEqual({ chrome: null, model: "x" });
|
||||
await session.close();
|
||||
});
|
||||
|
||||
test("lists fast mode only for supported Opus models", async () => {
|
||||
const client = new ClaudeAgentClient({ logger, resolveBinary: async () => "/test/claude/bin" });
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ export const ClaudeProviderOptionsSchema = z
|
||||
allowedTools: z.array(z.string()).optional(),
|
||||
disallowedTools: z.array(z.string()).optional(),
|
||||
additionalDirectories: z.array(z.string()).optional(),
|
||||
extraArgs: z.record(z.string(), z.string().nullable()).optional(),
|
||||
sandbox: z
|
||||
.object({
|
||||
enabled: z.boolean().optional(),
|
||||
|
||||
Reference in New Issue
Block a user