summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-20 23:20:32 +0000
committerGitHub <noreply@github.com>2026-01-20 23:20:32 +0000
commit7155e6cd7ddf25a5a4d4f6d6abecd49f0cf519dc (patch)
tree2475a951c4bcba685b010909bf4abd5351cb3623 /makima/src/server/handlers
parent055e2c4a72e3b2331a18fdc9f8132ef990af7e38 (diff)
downloadsoryu-7155e6cd7ddf25a5a4d4f6d6abecd49f0cf519dc.tar.gz
soryu-7155e6cd7ddf25a5a4d4f6d6abecd49f0cf519dc.zip
Add non-blocking persistent contract completion questions (#14)
* [WIP] Heartbeat checkpoint - 2026-01-20 22:40:37 UTC * Task completion checkpoint
Diffstat (limited to 'makima/src/server/handlers')
-rw-r--r--makima/src/server/handlers/mesh_supervisor.rs28
1 files changed, 28 insertions, 0 deletions
diff --git a/makima/src/server/handlers/mesh_supervisor.rs b/makima/src/server/handlers/mesh_supervisor.rs
index df8f77c..e5d33c7 100644
--- a/makima/src/server/handlers/mesh_supervisor.rs
+++ b/makima/src/server/handlers/mesh_supervisor.rs
@@ -76,6 +76,16 @@ pub struct AskQuestionRequest {
/// When true, allow selecting multiple choices (response will be comma-separated)
#[serde(default)]
pub multi_select: bool,
+ /// When true, return immediately without waiting for response
+ #[serde(default)]
+ pub non_blocking: bool,
+ /// Question type: general, phase_confirmation, or contract_complete
+ #[serde(default = "default_question_type")]
+ pub question_type: String,
+}
+
+fn default_question_type() -> String {
+ "general".to_string()
}
fn default_question_timeout() -> i32 {
@@ -124,6 +134,9 @@ pub struct PendingQuestionSummary {
/// Whether multiple choices can be selected
#[serde(default)]
pub multi_select: bool,
+ /// Question type: general, phase_confirmation, or contract_complete
+ #[serde(default)]
+ pub question_type: String,
}
/// Request to create a checkpoint.
@@ -1532,6 +1545,7 @@ pub async fn ask_question(
request.choices.clone(),
request.context.clone(),
request.multi_select,
+ request.question_type.clone(),
);
// Broadcast question as task output entry for the task's chat
@@ -1540,6 +1554,7 @@ pub async fn ask_question(
"choices": request.choices,
"context": request.context,
"multi_select": request.multi_select,
+ "question_type": request.question_type,
});
state.broadcast_task_output(TaskOutputNotification {
task_id: supervisor_id,
@@ -1572,6 +1587,18 @@ pub async fn ask_question(
).await;
}
+ // If non_blocking mode is enabled, return immediately with the question_id
+ if request.non_blocking {
+ return (
+ StatusCode::OK,
+ Json(AskQuestionResponse {
+ question_id,
+ response: None,
+ timed_out: false,
+ }),
+ ).into_response();
+ }
+
// Poll for response with timeout
let timeout_duration = std::time::Duration::from_secs(request.timeout_seconds.max(1) as u64);
let start = std::time::Instant::now();
@@ -1644,6 +1671,7 @@ pub async fn list_pending_questions(
context: q.context,
created_at: q.created_at,
multi_select: q.multi_select,
+ question_type: q.question_type,
})
.collect();