use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::canonical::{AttemptRecord, NextMove};
use crate::view::PlanningView;
#[async_trait]
pub trait PlanProducer: Send + Sync {
async fn decide_next(
&self,
goal: &str,
history: &[AttemptRecord],
shared_memory: &serde_json::Value,
view: &PlanningView,
screenshot_png: Option<&[u8]>,
) -> Result<NextMove, String>;
async fn verify_done(
&self,
_goal: &str,
_summary: &str,
_shared_memory: &serde_json::Value,
_view: &PlanningView,
_screenshot_png: Option<&[u8]>,
) -> Result<DoneVerdict, String> {
Ok(DoneVerdict {
verified: true,
reason: String::new(),
next_action_hint: None,
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DoneVerdict {
pub verified: bool,
pub reason: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_action_hint: Option<NextActionHint>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum NextActionHint {
RetryLastAction,
DifferentAction,
DifferentTarget,
GiveUp,
}