c0re: schedule_prompt approval kind + worker + manager surface (#444 step 2)
This commit is contained in:
parent
c803bb714e
commit
aa7d8d9c9a
9 changed files with 612 additions and 4 deletions
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use anyhow::{Context as _, Result, bail};
|
||||
use hive_sh4re::{ApprovalKind, ApprovalStatus, HelperEvent, MANAGER_AGENT};
|
||||
|
||||
use crate::coordinator::{Coordinator, TransientKind};
|
||||
|
|
@ -90,6 +90,15 @@ pub async fn approve(coord: Arc<Coordinator>, id: i64) -> Result<()> {
|
|||
coord.emit_rebuild_queue_snapshot();
|
||||
Ok(())
|
||||
}
|
||||
ApprovalKind::SchedulePrompt => {
|
||||
// No queue card for SchedulePrompt — the work is a single
|
||||
// sqlite insert, the actual "running" lifetime lives on
|
||||
// the scheduled-prompts surface itself (worker fires it
|
||||
// at the scheduled time). Run inline + fire
|
||||
// `ApprovalResolved` so the approval row leaves Pending
|
||||
// immediately.
|
||||
run_approval_schedule_prompt(&coord, approval).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +136,39 @@ pub async fn run_approval_apply_commit(
|
|||
finish_approval(coord, &approval, result, terminal_tag, is_first_spawn)
|
||||
}
|
||||
|
||||
/// Inline (non-queued) handler for `ApprovalKind::SchedulePrompt`.
|
||||
/// On approve, decode the `SchedulePromptPayload` JSON from the
|
||||
/// approval's `commit_ref`, insert a row into `scheduled_prompts`
|
||||
/// (with `source = Approval { id }`), and fire `ApprovalResolved`.
|
||||
/// The worker takes over from here — fan-out at fire time.
|
||||
async fn run_approval_schedule_prompt(
|
||||
coord: &Coordinator,
|
||||
approval: hive_sh4re::Approval,
|
||||
) -> Result<()> {
|
||||
let result: Result<()> = async {
|
||||
let payload: hive_sh4re::SchedulePromptPayload =
|
||||
serde_json::from_str(&approval.commit_ref)
|
||||
.context("decode SchedulePromptPayload from approval.commit_ref")?;
|
||||
coord
|
||||
.scheduled_prompts
|
||||
.submit(crate::scheduled_prompts::NewSchedule {
|
||||
owner: approval.agent.clone(),
|
||||
targets: payload.targets,
|
||||
body: payload.body,
|
||||
first_fire_at_unix: payload.first_fire_at_unix,
|
||||
interval_seconds: payload.interval_seconds,
|
||||
description: payload.description,
|
||||
source: crate::scheduled_prompts::ScheduleSource::Approval {
|
||||
id: approval.id,
|
||||
},
|
||||
})
|
||||
.map(|_| ())
|
||||
.context("insert scheduled prompt")
|
||||
}
|
||||
.await;
|
||||
finish_approval(coord, &approval, result, None, false)
|
||||
}
|
||||
|
||||
/// Worker entry point for `ApprovalKind::UpdateMetaInputs` queue
|
||||
/// entries. Inputs come from the approval row's `commit_ref` field
|
||||
/// (JSON-encoded by the manager submit path), not the queue entry's
|
||||
|
|
@ -301,6 +343,7 @@ fn finish_approval(
|
|||
ApprovalKind::ApplyCommit => "apply_commit",
|
||||
ApprovalKind::InitConfig => "init_config",
|
||||
ApprovalKind::UpdateMetaInputs => "update_meta_inputs",
|
||||
ApprovalKind::SchedulePrompt => "schedule_prompt",
|
||||
};
|
||||
let sha_short = approval
|
||||
.fetched_sha
|
||||
|
|
@ -350,9 +393,9 @@ fn finish_approval(
|
|||
sha: approval.fetched_sha.clone(),
|
||||
tag: terminal_tag,
|
||||
}),
|
||||
// UpdateMetaInputs: ApprovalResolved already carries the result.
|
||||
// No separate lifecycle event needed.
|
||||
ApprovalKind::UpdateMetaInputs => {}
|
||||
// UpdateMetaInputs / SchedulePrompt: ApprovalResolved already
|
||||
// carries the result. No separate lifecycle event needed.
|
||||
ApprovalKind::UpdateMetaInputs | ApprovalKind::SchedulePrompt => {}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
|
@ -684,6 +727,7 @@ pub async fn deny(coord: &Coordinator, id: i64, note: Option<&str>) -> Result<()
|
|||
ApprovalKind::ApplyCommit => "apply_commit",
|
||||
ApprovalKind::InitConfig => "init_config",
|
||||
ApprovalKind::UpdateMetaInputs => "update_meta_inputs",
|
||||
ApprovalKind::SchedulePrompt => "schedule_prompt",
|
||||
};
|
||||
let sha_short = sha.as_deref().map(|s| s[..s.len().min(12)].to_owned());
|
||||
let description = a.description.clone();
|
||||
|
|
|
|||
Loading…
Reference in a new issue