Show a session's subagents as subcards, each with a read-only transcript
A subagent is a second transcript owned by a session, in the same event model, with no process and no controls. The claude translator routes lines carrying parent_tool_use_id to a per-subagent translator and transcript under <session>/subagents/<tool_use_id>; three routes expose the list, a transcript page and the SSE stream. Echo grows /subagent [n] as the rig. On the phone a card with subagents ends in a chevron expander, collapsed by default, opening to outlined subcards styled like dev-updater's components; a subcard opens SessionScreen in read-only form, addressed through TranscriptAddress so paging, cache and stream are shared. Design in SUBAGENTS.md; choices awaiting review in DECISIONS.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
eff5c8b0c0
commit
9fa09b0af1
21 files changed
+1953
-332
No files matched your search
@@ -59,6 +59,7 @@ use tokio::sync::mpsc;
|
||||
|
||||
use super::driver::{AttachmentRef, Driver, Event, EventSink, SessionStatus, Unqueued};
|
||||
use super::process;
|
||||
use super::subagent::Subagents;
|
||||
use super::transport::{Launch, Streams, Transport};
|
||||
use crate::config::{ProviderConfig, SessionConfig};
|
||||
use translate::{AnswerOutcome, Setting, Translator, starts_a_model_call};
|
||||
@@ -213,8 +214,12 @@ impl ClaudeDriver {
|
||||
transport: &Transport,
|
||||
session_dir: &Path,
|
||||
sink: EventSink,
|
||||
subagents: Arc<Subagents>,
|
||||
) -> Result<Self> {
|
||||
let state = Arc::new(Mutex::new(Translator::new(session_dir.to_path_buf())));
|
||||
let state = Arc::new(Mutex::new(Translator::new(
|
||||
session_dir.to_path_buf(),
|
||||
subagents,
|
||||
)));
|
||||
let queue = Arc::new(Mutex::new(Queue::default()));
|
||||
let reading = Arc::new(AtomicBool::new(true));
|
||||
|
||||
@@ -1169,7 +1174,10 @@ mod tests {
|
||||
/// this" and "the transcript records that".
|
||||
fn events_from_lines(lines: &[&str]) -> Vec<Event> {
|
||||
let dir = tempfile::tempdir().expect("temp dir");
|
||||
let state = Arc::new(Mutex::new(Translator::new(dir.path().to_path_buf())));
|
||||
let state = Arc::new(Mutex::new(Translator::new(
|
||||
dir.path().to_path_buf(),
|
||||
Arc::new(Subagents::new(dir.path().to_path_buf())),
|
||||
)));
|
||||
let queue = Arc::new(Mutex::new(Queue::default()));
|
||||
let (sink, mut out) = mpsc::unbounded_channel::<Event>();
|
||||
for line in lines {
|
||||
@@ -1193,7 +1201,10 @@ mod tests {
|
||||
interject: impl FnOnce(&Arc<Mutex<Queue>>),
|
||||
) -> Vec<Event> {
|
||||
let dir = tempfile::tempdir().expect("temp dir");
|
||||
let state = Arc::new(Mutex::new(Translator::new(dir.path().to_path_buf())));
|
||||
let state = Arc::new(Mutex::new(Translator::new(
|
||||
dir.path().to_path_buf(),
|
||||
Arc::new(Subagents::new(dir.path().to_path_buf())),
|
||||
)));
|
||||
let queue = Arc::new(Mutex::new(Queue::default()));
|
||||
let (sink, mut out) = mpsc::unbounded_channel::<Event>();
|
||||
let mut interject = Some(interject);
|
||||
@@ -1487,7 +1498,10 @@ mod tests {
|
||||
// doing.
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let (sink, mut received) = mpsc::unbounded_channel();
|
||||
let state = Arc::new(Mutex::new(Translator::new(dir.path().to_path_buf())));
|
||||
let state = Arc::new(Mutex::new(Translator::new(
|
||||
dir.path().to_path_buf(),
|
||||
Arc::new(Subagents::new(dir.path().to_path_buf())),
|
||||
)));
|
||||
let queue = Arc::new(Mutex::new(Queue::default()));
|
||||
|
||||
let text = r#"{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"working"}},"parent_tool_use_id":null}"#;
|
||||
@@ -1532,7 +1546,10 @@ mod tests {
|
||||
// session back to work.
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let (sink, mut received) = mpsc::unbounded_channel();
|
||||
let state = Arc::new(Mutex::new(Translator::new(dir.path().to_path_buf())));
|
||||
let state = Arc::new(Mutex::new(Translator::new(
|
||||
dir.path().to_path_buf(),
|
||||
Arc::new(Subagents::new(dir.path().to_path_buf())),
|
||||
)));
|
||||
let queue = Arc::new(Mutex::new(Queue::default()));
|
||||
queue.lock().unwrap().close(&sink, "the session ended");
|
||||
|
||||
|
||||
Reference in new issue
Block a user