use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use async_trait::async_trait;
use supercode_harness::server::{run_http, RpcEngine};
use supercode_harness::{
Agent, ApprovalPolicy, ChatMessage, ChatRequest, Config, FunctionCall, Provider, Role,
ToolCall, Usage,
};
struct ApprovalFixtureProvider {
calls: AtomicUsize,
marker: std::path::PathBuf,
}
#[async_trait]
impl Provider for ApprovalFixtureProvider {
async fn complete(
&self,
_request: &ChatRequest,
on_delta: &(dyn for<'a> Fn(&'a str) + Send + Sync),
) -> supercode_harness::Result<(ChatMessage, Usage)> {
if self.calls.fetch_add(1, Ordering::SeqCst) == 0 {
return Ok((
ChatMessage {
role: Role::Assistant,
content: None,
content_parts: None,
tool_calls: Some(vec![ToolCall {
id: "browser-proof-approval".into(),
kind: "function".into(),
function: FunctionCall {
name: "bash".into(),
arguments: serde_json::json!({
"command": format!("printf BROWSER_APPROVED > {}", self.marker.display())
})
.to_string(),
},
}]),
tool_call_id: None,
name: None,
metadata: Default::default(),
},
Usage::default(),
));
}
on_delta("Browser and terminal converged.");
Ok((
ChatMessage::assistant("Browser and terminal converged."),
Usage::default(),
))
}
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let root = std::env::temp_dir().join(format!(
"supercode-browser-observer-proof-{}",
std::process::id()
));
std::fs::create_dir_all(&root)?;
let marker = root.join("approved.marker");
let mut config = Config::builder()
.cwd(root.clone())
.approval(ApprovalPolicy::OnRequest)
.build();
config.permissions_enabled = true;
let agent = Agent::with_provider(
config,
Box::new(ApprovalFixtureProvider {
calls: AtomicUsize::new(0),
marker: marker.clone(),
}),
);
let engine = RpcEngine::new_named_with_frontend_requests(
agent,
"browser-observer-proof",
Default::default(),
None,
);
let token: Arc<str> = "browser-observer-proof-token".into();
let address = run_http(engine.clone(), "127.0.0.1:0", token.clone()).await?;
println!(
"{}",
serde_json::json!({
"baseUrl":format!("http://{address}"),
"observerUrl":format!("http://{address}/observer/"),
"token":token.as_ref(),
"sessionId":"browser-observer-proof",
"marker":marker,
})
);
tokio::signal::ctrl_c().await?;
engine.shutdown().await;
std::fs::remove_dir_all(root).ok();
Ok(())
}