Tell the model when a message was a steer
A message typed during a turn reaches the model at the next model call if the turn has one left, and otherwise as the opening line of the next turn -- Claude's read out of the fifo after the turn ended, Codex's requeued when turn/steer is refused. Read there it is indistinguishable from a reply, so the model treats the answer it just gave as seen. Both drivers now compose the text the CLI receives through driver::message_body, which prefixes a note saying the message was written without having seen the rest of that turn. The transcript still holds the words that were typed; only the CLI's copy carries the note. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
59ebd75b46
commit
3af2502982
4 files changed
+107
-18
No files matched your search
@@ -44,6 +44,14 @@ struct Waiting {
|
||||
/// The id Codex echoes on its user-message item.
|
||||
#[serde(default)]
|
||||
client_id: String,
|
||||
/// Typed while a turn was already running, so the CLI is told as much --
|
||||
/// see `super::driver::message_body`. Recorded at the moment it was typed
|
||||
/// rather than read off the turn state when it is dispatched, because a
|
||||
/// steer Codex refuses as `activeTurnNotSteerable` is requeued and sent as
|
||||
/// the start of the next turn, which is precisely the case the note exists
|
||||
/// for.
|
||||
#[serde(default)]
|
||||
steering: bool,
|
||||
text: String,
|
||||
#[serde(default)]
|
||||
attachments: Vec<AttachmentRef>,
|
||||
@@ -202,10 +210,12 @@ impl Driver for CodexDriver {
|
||||
return;
|
||||
}
|
||||
let id = state.running.then(super::random_hex).unwrap_or_default();
|
||||
let steering = state.running;
|
||||
state.running = true;
|
||||
state.waiting.push_back(Waiting {
|
||||
id: id.clone(),
|
||||
client_id: format!("ai-app-{}", super::random_hex()),
|
||||
steering,
|
||||
text: text.clone(),
|
||||
attachments: attachments.clone(),
|
||||
});
|
||||
@@ -463,7 +473,7 @@ fn sandbox_policy(mode: &str) -> Value {
|
||||
}
|
||||
|
||||
fn input_for(inner: &Inner, message: &Waiting) -> Result<Vec<Value>> {
|
||||
let mut text = message.text.clone();
|
||||
let mut files = Vec::new();
|
||||
let mut input = Vec::new();
|
||||
for attachment in &message.attachments {
|
||||
let path = attachment_path(&inner.session_dir, attachment)?;
|
||||
@@ -477,12 +487,10 @@ fn input_for(inner: &Inner, message: &Waiting) -> Result<Vec<Value>> {
|
||||
input.push(inline_image(&path, media_type)?);
|
||||
}
|
||||
} else {
|
||||
if !text.is_empty() {
|
||||
text.push_str("\n\n");
|
||||
}
|
||||
text.push_str(&format!("Attached file: {}", path.display()));
|
||||
files.push(path);
|
||||
}
|
||||
}
|
||||
let text = super::driver::message_body(&message.text, &files, message.steering);
|
||||
if !text.is_empty() {
|
||||
input.insert(0, json!({"type": "text", "text": text}));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user