da84e98f Andy McCall 2 days ago ↶
1
2
3
4
5
mod common ;
6
7
use common:: { add_agent, hermetic, run, setup, text, Serving} ;
8
use serde_json:: { json, Value} ;
9
use spectra_mcp:: client:: Client;
10
use std:: io:: { BufRead, BufReader} ;
11
use std:: process:: Stdio;
12
use std:: time:: Duration;
13
14
fn json_of ( d : & std:: path:: Path, args : & [& str ]) -> Value {
15
let o = run ( d, args) ;
16
assert! ( o.status.success ( ) , " {args:?}: {}" , text ( & o) ) ;
17
serde_json:: from_slice( & o.stdout)
18
.unwrap_or_else ( | e | panic! ( " {args:?} printed more than one JSON document ({e}): {}" , String :: from_utf8_lossy( & o.stdout) ) )
19
}
20
21
# [ test ]
22
fn every_json_output_parses_without_the_daemon ( ) {
23
let dir = setup ( ) ;
24
let d = dir.path ( ) ;
25
add_agent ( d, " claude-oxygen" , & [ ] ) ;
26
assert_eq! ( json_of ( d, & [ " version" , " --json" ] ) [ " ledger_format" ] , 1 ) ;
27
assert_eq! ( json_of ( d, & [ " identity" , " show" , " --json" ] ) [ " owner" ] [ " name" ] , " Andy McCall" ) ;
28
assert_eq! ( json_of ( d, & [ " agent" , " list" , " --json" ] ) [ 0 ] [ " name" ] , " claude-oxygen" ) ;
29
assert_eq! ( json_of ( d, & [ " project" , " list" , " --json" ] ) [ 0 ] [ " name" ] , " oxygen" ) ;
30
let posted = json_of ( d, & [ " say" , " --json" , " -c" , " general" , " the release is tomorrow @claude-oxygen" ] ) ;
31
assert_eq! ( posted[ " channel" ] , " #general" ) ;
32
assert! ( json_of ( d, & [ " inbox" , " --json" ] ) .as_array ( ) .unwrap ( ) .is_empty ( ) ) ;
33
assert_eq! ( json_of ( d, & [ " search" , " --json" , " release" ] ) .as_array ( ) .unwrap ( ) .len ( ) , 1 ) ;
34
let v = json_of ( d, & [ " admin" , " verify" , " --json" ] ) ;
35
assert! ( v[ " findings" ] .as_array ( ) .unwrap ( ) .is_empty ( ) , " a CLI post verifies: {v}" ) ;
36
}
37
38
# [ tokio ::test ]
39
async fn a_terminal_chat_with_the_agents ( ) {
40
let dir = setup ( ) ;
41
let d = dir.path ( ) ;
42
let claude = add_agent ( d, " claude-oxygen" , & [ ] ) ;
43
let srv = Serving:: start( d) ;
44
let a = Client:: new( & srv.socket, Some ( claude) ) ;
45
46
47
assert_eq! ( json_of ( d, & [ " say" , " --json" , " hello from the terminal" ] ) [ " channel" ] , " #general" ) ;
48
let api: Value = serde_json:: from_slice( & run ( d, & [ " api" , " GET" , " /api/v1/brief" ] ) .stdout) .unwrap ( ) ;
49
assert_eq! ( api[ " actor" ] , " human" ) ;
50
51
let mut follow = hermetic ( d) .args ( [ " inbox" , " --follow" , " --json" ] ) .stdout ( Stdio:: piped( ) ) .stderr ( Stdio:: null( ) ) .spawn ( ) .unwrap ( ) ;
52
let mut lines = BufReader:: new( follow.stdout.take ( ) .unwrap ( ) ) .lines ( ) ;
53
tokio:: time:: sleep( Duration:: from_millis( 500 ) ) .await;
54
let say = json! ( { " jsonrpc" : " 2.0" , " id" : 1 , " method" : " tools/call" , " params" : { " name" : " say" , " arguments" : { " body" : " @andy the build is green" , " channel" : " general" } } } ) ;
55
assert_eq! ( a.mcp ( " 2025-11-25" , & say) .await.unwrap ( ) .status, 200 ) ;
56
let got = tokio:: task:: spawn_blocking( move | | lines.next ( ) ) .await.unwrap ( ) .expect ( " a line" ) .unwrap ( ) ;
57
let item: Value = serde_json:: from_str( & got) .unwrap ( ) ;
58
assert_eq! ( item[ " from" ] , " agent:claude-oxygen" ) ;
59
assert! ( item[ " summary" ] .as_str ( ) .unwrap ( ) .contains ( " the build is green" ) ) ;
60
follow.kill ( ) .ok ( ) ;
61
follow.wait ( ) .ok ( ) ;
62
srv.stop ( ) ;
63
}