RunRequest: add effort (low|medium|high|xhigh|max)

Mirrors the system_mode wiring: optional field on the wire,
maps to 'claude -p --effort <level>'. None lets the CLI default
decide. Right for prose-craft tasks (skald) where the author
persona benefits from extra thinking budget.
This commit is contained in:
Kayos 2026-05-13 14:19:05 -07:00
parent d4c3a9d2de
commit 65ea96bb1f
4 changed files with 40 additions and 1 deletions

View file

@ -34,6 +34,7 @@ class Runner:
model: str | None = None,
system: str | None = None,
system_mode: str | None = "append",
effort: str | None = None,
files: list[str] | None = None,
timeout_secs: int | None = None,
) -> RunResult:
@ -60,6 +61,8 @@ class Runner:
cmd += ["--system-prompt", system]
else:
cmd += ["--append-system-prompt", system]
if effort:
cmd += ["--effort", effort]
if files:
for f in files:
cmd += ["--files", f]

View file

@ -122,6 +122,12 @@ class RunRequest(BaseModel):
# Default is "append" for back-compat — every caller before this
# field landed used append semantics implicitly.
system_mode: Literal["append", "replace"] | None = "append"
# claude -p --effort <level>. Controls extended-thinking budget on the
# reasoning models. None = let claude default decide (today: medium).
# Right for prose-craft tasks where the model benefits from extra
# thinking; e.g. skald passes "max" on gen + cleanup so author personas
# get the budget they deserve.
effort: Literal["low", "medium", "high", "xhigh", "max"] | None = None
files: list[str] | None = None
timeout_secs: int | None = Field(default=None, ge=5, le=600)
@ -203,6 +209,7 @@ def run(
model=body.model,
system=body.system,
system_mode=body.system_mode,
effort=body.effort,
files=file_paths or None,
timeout_secs=body.timeout_secs,
)

View file

@ -53,6 +53,6 @@ pub use client::{Client, ClientBuilder};
pub use error::Error;
pub use session::{Session, SessionList, SessionOptions, SessionState, TurnEvent, TurnResult};
pub use types::{
AppToken, AppTokenInfo, FileToken, Healthz, RunFailure, RunRequest, RunResult,
AppToken, AppTokenInfo, Effort, FileToken, Healthz, RunFailure, RunRequest, RunResult,
SystemMode, TokenCreateRequest, TokenList,
};

View file

@ -26,6 +26,30 @@ impl Default for SystemMode {
}
}
/// Maps to `claude -p --effort <level>`. Controls the extended-thinking
/// budget on the reasoning models. `None` on [`RunRequest::effort`] means
/// "let the CLI default decide" (today: medium).
///
/// Use [`Effort::Max`] for prose-craft tasks (fiction generation,
/// long-form rewrite) where the author persona benefits from extra
/// thinking. Leave default for tool-use / structured-JSON tasks.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Effort {
/// `--effort low` — minimum thinking budget.
Low,
/// `--effort medium` — claude's default if no flag is passed.
Medium,
/// `--effort high`.
High,
/// `--effort xhigh`.
Xhigh,
/// `--effort max` — maximum thinking budget. Right for long-form
/// prose generation where the author persona benefits from extra
/// thinking before each paragraph.
Max,
}
/// `GET /healthz` response body.
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Healthz {
@ -80,6 +104,11 @@ pub struct RunRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub system_mode: Option<SystemMode>,
/// Maps to `claude -p --effort <level>`. `None` lets the CLI default
/// decide. Use [`Effort::Max`] on prose-craft / long-form generation.
#[serde(skip_serializing_if = "Option::is_none")]
pub effort: Option<Effort>,
/// File tokens previously returned from [`Client::upload_file`].
///
/// [`Client::upload_file`]: crate::Client::upload_file