use std::fs;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use async_trait::async_trait;
use serde_json::{json, Value};
use supercode_harness::server::{run_http, RpcEngine};
use supercode_harness::{
register_live_runtime, Agent, ChatMessage, ChatRequest, Config, FrontendRuntime,
HarnessSessionService, LiveRuntimeSource, Provider, Usage,
};
use tokio::sync::Semaphore;
struct GatedProvider {
gate: Arc<Semaphore>,
}
#[async_trait]
impl Provider for GatedProvider {
async fn complete(
&self,
_request: &ChatRequest,
_on_delta: &(dyn for<'a> Fn(&'a str) + Send + Sync),
) -> supercode_harness::Result<(ChatMessage, Usage)> {
let permit = self.gate.acquire().await.expect("gate stays open");
permit.forget();
Ok((ChatMessage::assistant("gated reply"), Usage::default()))
}
}
fn subscribe(service: &mut HarnessSessionService, id: i64, locator: &Value) -> String {
let opened = service.handle(json!({
"jsonrpc": "2.0",
"id": id,
"method": "harness.v1.sessions.follow",
"params": {"locator": locator},
}));
assert!(opened.get("error").is_none(), "{opened}");
opened["result"]["subscription"]
.as_str()
.expect("follow returns a subscription")
.to_string()
}
async fn poll_states(service: &mut HarnessSessionService) -> Vec<(String, String)> {
service
.poll_session_runtime_states()
.await
.into_iter()
.map(|notification| {
assert_eq!(
notification["method"], "harness.v1.sessions.event",
"lifecycle rides the session subscription, not a second channel"
);
let event = ¬ification["params"]["event"];
assert_eq!(event["type"], "runtime_state");
assert!(
event.get("sequence").is_none(),
"an unsequenced lifecycle event must not disturb transcript sequencing"
);
(
notification["params"]["subscription"]
.as_str()
.unwrap()
.to_string(),
event["state"].as_str().unwrap().to_string(),
)
})
.collect()
}
async fn wait_for_state(
service: &mut HarnessSessionService,
subscription: &str,
expected: &str,
) -> Vec<(String, String)> {
let mut seen = Vec::new();
tokio::time::timeout(Duration::from_secs(5), async {
loop {
let states = poll_states(service).await;
let hit = states
.iter()
.any(|(sub, state)| sub == subscription && state == expected);
seen.extend(states);
if hit {
return;
}
tokio::time::sleep(Duration::from_millis(20)).await;
}
})
.await
.unwrap_or_else(|_| panic!("subscription never reported `{expected}`; saw {seen:?}"));
seen
}
#[tokio::test]
async fn a_followed_session_reports_its_live_runtime_working_and_idle_again() {
let nonce = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
let root = std::env::temp_dir().join(format!(
"supercode-session-runtime-state-{}-{nonce}",
std::process::id()
));
let workspace = root.join("project");
let codex_home = root.join("codex-sessions");
fs::create_dir_all(&workspace).unwrap();
fs::create_dir_all(&codex_home).unwrap();
std::env::set_var("SUPERCODE_HOME", root.join("supercode-home"));
for id in ["hosted-source", "terminal-only"] {
fs::write(
codex_home.join(format!("{id}.jsonl")),
json!({
"timestamp": "2026-01-01T00:00:00Z",
"type": "session_meta",
"payload": {"id": id, "cwd": workspace, "model": "test"}
})
.to_string()
+ "\n",
)
.unwrap();
}
let gate = Arc::new(Semaphore::new(0));
let engine = RpcEngine::new_named(
Agent::with_provider(
Config::builder().cwd(workspace.clone()).build(),
Box::new(GatedProvider { gate: gate.clone() }),
),
"hosted-runtime",
None,
);
let token: Arc<str> = "private-live-token".into();
let address = run_http(engine.clone(), "127.0.0.1:0", token.clone())
.await
.unwrap();
let registration = register_live_runtime(
engine.session_id(),
LiveRuntimeSource {
harness: "codex".into(),
session_id: "hosted-source".into(),
workspace: workspace.clone(),
},
format!("http://{address}"),
token.to_string(),
)
.unwrap();
let mut service = HarnessSessionService::new();
let discovered = service.handle(json!({
"jsonrpc": "2.0",
"id": 1,
"method": "harness.v1.sessions.discover",
"params": {
"workspace": workspace,
"harnesses": ["codex"],
"homes": {"codex": codex_home}
}
}));
let sessions = discovered["result"]["sessions"].as_array().unwrap();
let locator_of = |id: &str| {
sessions
.iter()
.find(|session| session["locator"]["session_id"] == id)
.unwrap_or_else(|| panic!("discovery should list `{id}`"))["locator"]
.clone()
};
let hosted = locator_of("hosted-source");
let terminal = locator_of("terminal-only");
let hosted_sub = subscribe(&mut service, 2, &hosted);
let terminal_sub = subscribe(&mut service, 3, &terminal);
let baseline = poll_states(&mut service).await;
assert!(
baseline.contains(&(hosted_sub.clone(), "idle".into())),
"{baseline:?}"
);
assert!(
baseline.contains(&(terminal_sub.clone(), "persisted".into())),
"{baseline:?}"
);
assert!(
poll_states(&mut service).await.is_empty(),
"an unchanged state must not re-notify"
);
FrontendRuntime::send_input(engine.clone(), "start working".into())
.await
.unwrap();
let working = wait_for_state(&mut service, &hosted_sub, "busy").await;
assert!(
!working.iter().any(|(sub, _)| sub == &terminal_sub),
"an unregistered session must not change state because a neighbour got busy: {working:?}"
);
gate.add_permits(1);
wait_for_state(&mut service, &hosted_sub, "idle").await;
let unfollowed = service.handle(json!({
"jsonrpc": "2.0",
"id": 4,
"method": "harness.v1.sessions.unfollow",
"params": {"subscription": hosted_sub},
}));
assert_eq!(unfollowed["result"]["removed"], true);
assert!(poll_states(&mut service).await.is_empty());
engine.shutdown().await;
drop(registration);
std::env::remove_var("SUPERCODE_HOME");
fs::remove_dir_all(root).ok();
}