use anyhow::Result;
use serde_json::{Value, json};
use super::super::helpers::{normalize_thread_summary, thread_status_info, thread_token_usage};
use crate::bridge_protocol::ThreadStatusInfo;
use crate::state::BridgeState;
use crate::state::helpers::{normalize_name, optional_string, required_string};
pub(super) async fn handle_thread_started(
state: &BridgeState,
runtime_id: &str,
params: Value,
) -> Result<()> {
let thread_summary = params
.get("thread")
.and_then(|thread| normalize_thread_summary(runtime_id, thread, false));
if let Some(thread) = thread_summary.as_ref() {
state.storage.upsert_thread_index(thread)?;
let _ = state
.storage
.record_directory_usage(std::path::Path::new(&thread.cwd));
let _ = state.emit_directory_state();
}
state.emit_event(
"thread/started",
Some(runtime_id),
params
.get("thread")
.and_then(|thread| thread.get("id"))
.and_then(Value::as_str),
json!({
"runtimeId": runtime_id,
"thread": params.get("thread"),
"threadSummary": thread_summary,
}),
)?;
Ok(())
}
pub(super) async fn handle_thread_status_changed(
state: &BridgeState,
runtime_id: &str,
params: Value,
) -> Result<()> {
let thread_id = required_string(¶ms, "threadId")?;
let status_value = params.get("status").cloned().unwrap_or(Value::Null);
let status_info = thread_status_info(&status_value);
if let Some(mut thread) = state.storage.get_thread_index(thread_id)? {
thread.is_loaded = status_info.kind != "notLoaded";
thread.is_active = status_info.kind == "active";
thread.status = status_info.kind.clone();
thread.status_info = status_info.clone();
state.storage.upsert_thread_index(&thread)?;
}
state.emit_event(
"thread/status/changed",
Some(runtime_id),
Some(thread_id),
json!({
"runtimeId": runtime_id,
"threadId": thread_id,
"status": status_value,
"statusInfo": status_info,
}),
)?;
Ok(())
}
pub(super) async fn handle_thread_name_updated(
state: &BridgeState,
runtime_id: &str,
params: Value,
) -> Result<()> {
let thread_id = required_string(¶ms, "threadId")?;
let thread_name = normalize_name(optional_string(¶ms, "threadName"));
if let Some(mut thread) = state.storage.get_thread_index(thread_id)? {
thread.name = thread_name.clone();
state.storage.upsert_thread_index(&thread)?;
}
state.emit_event(
"thread/name/updated",
Some(runtime_id),
Some(thread_id),
json!({
"runtimeId": runtime_id,
"threadId": thread_id,
"threadName": thread_name,
}),
)?;
Ok(())
}
pub(super) async fn handle_thread_archived(
state: &BridgeState,
runtime_id: &str,
params: Value,
) -> Result<()> {
let thread_id = required_string(¶ms, "threadId")?;
state.storage.set_thread_archived(thread_id, true)?;
state.emit_event(
"thread/archived",
Some(runtime_id),
Some(thread_id),
json!({
"runtimeId": runtime_id,
"threadId": thread_id,
}),
)?;
Ok(())
}
pub(super) async fn handle_thread_unarchived(
state: &BridgeState,
runtime_id: &str,
params: Value,
) -> Result<()> {
let thread_id = required_string(¶ms, "threadId")?;
state.storage.set_thread_archived(thread_id, false)?;
state.emit_event(
"thread/unarchived",
Some(runtime_id),
Some(thread_id),
json!({
"runtimeId": runtime_id,
"threadId": thread_id,
}),
)?;
Ok(())
}
pub(super) async fn handle_thread_closed(
state: &BridgeState,
runtime_id: &str,
params: Value,
) -> Result<()> {
let thread_id = required_string(¶ms, "threadId")?;
if let Some(mut thread) = state.storage.get_thread_index(thread_id)? {
thread.is_loaded = false;
thread.is_active = false;
thread.status = "closed".to_string();
thread.status_info = ThreadStatusInfo {
kind: "closed".to_string(),
reason: optional_string(¶ms, "reason"),
raw: params
.get("status")
.cloned()
.unwrap_or_else(|| json!({ "type": "closed" })),
};
state.storage.upsert_thread_index(&thread)?;
}
state.emit_event(
"thread/closed",
Some(runtime_id),
Some(thread_id),
json!({
"runtimeId": runtime_id,
"threadId": thread_id,
"reason": params.get("reason"),
}),
)?;
Ok(())
}
pub(super) async fn handle_thread_token_usage_updated(
state: &BridgeState,
runtime_id: &str,
params: Value,
) -> Result<()> {
let thread_id = required_string(¶ms, "threadId")?;
let token_usage = thread_token_usage(
params
.get("tokenUsage")
.or_else(|| params.get("usage"))
.unwrap_or(&Value::Null),
);
if let Some(mut thread) = state.storage.get_thread_index(thread_id)? {
thread.token_usage = Some(token_usage.clone());
state.storage.upsert_thread_index(&thread)?;
}
state.emit_event(
"thread/tokenUsage/updated",
Some(runtime_id),
Some(thread_id),
json!({
"runtimeId": runtime_id,
"threadId": thread_id,
"tokenUsage": token_usage,
}),
)?;
Ok(())
}