Default thinking level for new sessions, and move the rigs out of AGENTS.md
`Config::default_effort` is what a session starts at when nothing chose one, applied in `spawn_session` rather than filled in by the spawn screen so it holds for an import and a bare API call too. It is set by the spawn screen's own picker, whose label says so: one control, where new sessions are made, rather than a settings page for a single value. Not on a provider, because providers are discovered and the next rediscovery would erase it; not on the phone, because a second device would then spawn at a level nobody there chose. `GET`/`POST /defaults` carry it as a struct, so the permission mode -- still hardcoded to `auto` on the spawn screen -- can move there later without a second route. Only drivers that read a level are given one: an echo session was storing a `--effort` it never passes to anything, which is a config file answering a question about itself wrongly. Separately, `AGENTS.md` is 35 KB sent with every request in this repo, and 12 KB of it was rigs and reference measurements that only matter once you are running one. Those are the `ai-app-rigs` skill now -- the same text, still the only copy, read when the work touches it. 35,198 -> 20,813 chars. Verified on the emulator against the sandbox: the spawn screen pre-fills from the server, picking `low` spawned a session at `low` and left `/defaults` set to it, and an echo session spawned afterwards took no level at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1ff662c7c3
commit
4821a02bd3
8 files changed
+468
-235
No files matched your search
+102
-1
@@ -1038,7 +1038,19 @@ impl SessionManager {
|
||||
model: spec.model,
|
||||
cwd: spec.cwd,
|
||||
permission_mode: spec.permission_mode,
|
||||
effort: spec.effort,
|
||||
// Applied here rather than on the spawn screen, so it holds
|
||||
// however a session was made -- the phone, an import, or a bare
|
||||
// API call -- instead of only where somebody remembered to fill it
|
||||
// in. And only where the driver reads one: a llama session storing
|
||||
// a level it never passes to anything is a config file that
|
||||
// answers a question about itself wrongly.
|
||||
effort: spec.effort.or_else(|| {
|
||||
provider
|
||||
.kind
|
||||
.takes_effort()
|
||||
.then(|| inner.config.default_effort.clone())
|
||||
.flatten()
|
||||
}),
|
||||
params: spec.params,
|
||||
// On by default. Not offered at spawn: a session's first turn
|
||||
// is exactly the one somebody is waiting for.
|
||||
@@ -1283,6 +1295,27 @@ impl SessionManager {
|
||||
///
|
||||
/// `None` clears it, which is a level in its own right -- the CLI's own
|
||||
/// default -- and the reason this takes an option rather than a string.
|
||||
/// What a new session's thinking level is when nothing chose one, and the
|
||||
/// setting of it. See `Config::default_effort`; `None` is the CLI's own.
|
||||
///
|
||||
/// Only the default: a session already spawned keeps the level it was
|
||||
/// given, because changing what running conversations do from a screen
|
||||
/// about *new* ones is not something anybody asked for by setting a
|
||||
/// default.
|
||||
pub fn default_effort(&self) -> Option<String> {
|
||||
self.inner.read().unwrap().config.default_effort.clone()
|
||||
}
|
||||
|
||||
pub fn set_default_effort(&self, effort: Option<&str>) -> Result<()> {
|
||||
let effort = effort.map(str::trim).filter(|level| !level.is_empty());
|
||||
let mut inner = self.inner.write().unwrap();
|
||||
let mut candidate = inner.config.clone();
|
||||
candidate.default_effort = effort.map(str::to_string);
|
||||
candidate.save(&self.config_path)?;
|
||||
inner.config = candidate;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_session_effort(&self, id: &str, effort: Option<&str>) -> Result<()> {
|
||||
let effort = effort.map(str::trim).filter(|level| !level.is_empty());
|
||||
{
|
||||
@@ -3480,6 +3513,74 @@ mod tests {
|
||||
std::fs::write(path, rewritten).expect("write transcript");
|
||||
}
|
||||
|
||||
/// A new session takes the stored default, and an explicit choice still
|
||||
/// wins over it.
|
||||
///
|
||||
/// Applied where the session is made rather than on the spawn screen, so
|
||||
/// it holds for an import and a bare API call too -- a default that only
|
||||
/// worked from one screen would be a default somebody had already set and
|
||||
/// would reasonably believe was in force.
|
||||
#[tokio::test]
|
||||
async fn a_new_session_starts_at_the_stored_default_thinking_level() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let config_path = dir.path().join("config.ron");
|
||||
let data_dir = dir.path().join("sessions");
|
||||
// Seeded with both kinds, because half of what this asks is that a
|
||||
// driver which does not read a level is not given one.
|
||||
let cli = seed_stand_in_cli(&config_path, dir.path());
|
||||
let manager = SessionManager::new(
|
||||
config_path.clone(),
|
||||
data_dir.clone(),
|
||||
data_dir.join("models"),
|
||||
)
|
||||
.expect("manager");
|
||||
assert_eq!(
|
||||
manager.default_effort(),
|
||||
None,
|
||||
"nothing is set to begin with"
|
||||
);
|
||||
|
||||
manager
|
||||
.set_default_effort(Some("low"))
|
||||
.expect("store the default");
|
||||
let took = manager.spawn_session(stand_in_spec(&cli)).expect("spawn");
|
||||
assert_eq!(
|
||||
took.effort.as_deref(),
|
||||
Some("low"),
|
||||
"a new session takes it"
|
||||
);
|
||||
|
||||
let chosen = manager
|
||||
.spawn_session(SpawnSpec {
|
||||
effort: Some("max".to_string()),
|
||||
..stand_in_spec(&cli)
|
||||
})
|
||||
.expect("spawn");
|
||||
assert_eq!(
|
||||
chosen.effort.as_deref(),
|
||||
Some("max"),
|
||||
"an explicit choice is not overwritten by the default"
|
||||
);
|
||||
|
||||
// The case this change had no reason to touch: echo does not read a
|
||||
// level, so storing one on it would be a config file describing a
|
||||
// session in terms of something that never reaches it.
|
||||
let echo = manager.spawn_session(echo_spec()).expect("spawn echo");
|
||||
assert_eq!(
|
||||
echo.effort, None,
|
||||
"a driver that does not take a level is not given the default"
|
||||
);
|
||||
|
||||
// Clearing it is reachable, so the CLI's own default can be restored.
|
||||
manager.set_default_effort(None).expect("clear the default");
|
||||
let cleared = manager.spawn_session(stand_in_spec(&cli)).expect("spawn");
|
||||
assert_eq!(cleared.effort, None, "and then new sessions choose nothing");
|
||||
|
||||
for id in [took.id, chosen.id, echo.id, cleared.id] {
|
||||
manager.delete_session(&id).expect("delete");
|
||||
}
|
||||
}
|
||||
|
||||
/// A thinking level is stored and the process **ended**, because `--effort`
|
||||
/// is read when the CLI launches and has no control request behind it. A
|
||||
/// session left running would go on thinking at the old level underneath a
|
||||
|
||||
Reference in new issue
Block a user