fix: include idle-only input in runtime API contract

This commit is contained in:
2026-10-02 03:33:30 +09:00
parent d5f49cbf00
commit d0ea9f598d
3 changed files with 49 additions and 8 deletions
+2
View File
@@ -402,6 +402,8 @@ pub struct WorkingDirectoryStatus {
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum WorkerInputKind { pub enum WorkerInputKind {
User, User,
/// Agent input accepted only while Idle; never enters the human Submit queue.
UserIfIdle,
Notify, Notify,
Compact, Compact,
ListRewindTargets, ListRewindTargets,
+22 -5
View File
@@ -3490,14 +3490,31 @@ mod tests {
conflicting_request.create_fingerprint = "different-fingerprint".to_string(); conflicting_request.create_fingerprint = "different-fingerprint".to_string();
let generated = client.create_worker(generated_request).await.unwrap(); let generated = client.create_worker(generated_request).await.unwrap();
assert_eq!(generated.worker.worker_id.to_string(), generated_worker_id); assert_eq!(generated.worker.worker_id.to_string(), generated_worker_id);
let generated_input: runtime_api::WorkerInput = serde_json::from_value( for kind in [
serde_json::to_value(WorkerInput::user("generated client input")).unwrap(), crate::interaction::WorkerInputKind::User,
) crate::interaction::WorkerInputKind::UserIfIdle,
.unwrap(); ] {
client let mut input = WorkerInput::user("generated client input");
input.kind = kind.clone();
input.submission_request_id = Some(format!("generated-{kind:?}"));
// The remote adapter performs this same conversion before sending.
// Both the generated API contract and the HTTP receiver must retain
// Idle-only admission rather than silently downgrading it to User.
let generated_input: runtime_api::WorkerInput =
serde_json::from_value(serde_json::to_value(&input).unwrap()).unwrap();
assert_eq!(
serde_json::to_value(&generated_input).unwrap(),
serde_json::to_value(&input).unwrap()
);
let response = client
.send_worker_input(generated_worker_id.clone(), generated_input) .send_worker_input(generated_worker_id.clone(), generated_input)
.await .await
.unwrap(); .unwrap();
assert_eq!(
Some(response.ack.submission.unwrap().submission_request_id),
input.submission_request_id
);
}
client client
.stop_worker( .stop_worker(
generated_worker_id.clone(), generated_worker_id.clone(),
+22
View File
@@ -6341,6 +6341,28 @@ mod tests {
assert_eq!(delivered.content, archive.content); assert_eq!(delivered.content, archive.content);
} }
#[test]
fn runtime_input_contract_preserves_every_input_kind() {
for kind in [
EmbeddedWorkerInputKind::User,
EmbeddedWorkerInputKind::UserIfIdle,
EmbeddedWorkerInputKind::Notify,
EmbeddedWorkerInputKind::Compact,
EmbeddedWorkerInputKind::ListRewindTargets,
EmbeddedWorkerInputKind::RegisterPeer,
] {
let input = EmbeddedWorkerInput {
kind,
content: "contract test".to_string(),
submission_request_id: Some("contract-request".to_string()),
segments: Some(vec![protocol::Segment::text("contract test")]),
};
let wire: runtime_api::WorkerInput = runtime_contract_convert(input.clone()).unwrap();
let decoded: EmbeddedWorkerInput = runtime_contract_convert(wire).unwrap();
assert_eq!(decoded, input);
}
}
#[test] #[test]
fn remote_profile_source_uses_workspace_config_archive_reference() { fn remote_profile_source_uses_workspace_config_archive_reference() {
let request = embedded_spawn_request(); let request = embedded_spawn_request();