Skip to content

Commit a2b1d6b

Browse files
committed
feat: align Orchestrator monitoring APIs to Python and Node.js SDKs
Python SDK: - Add PySubAgentInfo class with metadata and current_activity - Add PySubAgentActivity class (idle, calling_tool, requesting_llm, waiting_for_control) - Add orchestrator.list_subagents() - get all SubAgent info - Add orchestrator.get_subagent_info(id) - get specific SubAgent details - Add orchestrator.get_active_activities() - get all active activities - Add orchestrator.get_all_states() - get all SubAgent states - Add orchestrator.pause_subagent(id) / resume_subagent(id) / cancel_subagent(id) - Add orchestrator.wait_all() - wait for all SubAgents to complete Node.js SDK: - Add SubAgentInfo interface with metadata and currentActivity - Add SubAgentActivity interface (activityType, data) - Add SubAgentActivityEntry and SubAgentStateEntry for tuple returns - Add orchestrator.listSubagents() - get all SubAgent info - Add orchestrator.getSubagentInfo(id) - get specific SubAgent details - Add orchestrator.getActiveActivities() - get all active activities - Add orchestrator.getAllStates() - get all SubAgent states - Add orchestrator.pauseSubagent(id) / resumeSubagent(id) / cancelSubagent(id) - Add orchestrator.waitAll() - wait for all SubAgents to complete - Update TypeScript definitions with complete API documentation and examples All Rust core APIs now fully aligned across Python and Node.js SDKs.
1 parent 8f85e3f commit a2b1d6b

3 files changed

Lines changed: 489 additions & 9 deletions

File tree

sdk/node/index.d.ts

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,54 @@ export interface SubAgentConfig {
593593
parentId?: string;
594594
}
595595

596+
/**
597+
* SubAgent activity type.
598+
*/
599+
export interface SubAgentActivity {
600+
/** Activity type: idle, calling_tool, requesting_llm, waiting_for_control */
601+
activityType: string;
602+
/** Activity data (JSON string) */
603+
data?: string;
604+
}
605+
606+
/**
607+
* SubAgent information with metadata and current activity.
608+
*/
609+
export interface SubAgentInfo {
610+
/** SubAgent ID */
611+
id: string;
612+
/** Agent type */
613+
agentType: string;
614+
/** Task description */
615+
description: string;
616+
/** Current state */
617+
state: string;
618+
/** Parent SubAgent ID */
619+
parentId?: string;
620+
/** Creation timestamp (milliseconds) */
621+
createdAt: number;
622+
/** Last update timestamp (milliseconds) */
623+
updatedAt: number;
624+
/** Current activity */
625+
currentActivity?: SubAgentActivity;
626+
}
627+
628+
/**
629+
* SubAgent activity entry (id + activity).
630+
*/
631+
export interface SubAgentActivityEntry {
632+
id: string;
633+
activity: SubAgentActivity;
634+
}
635+
636+
/**
637+
* SubAgent state entry (id + state).
638+
*/
639+
export interface SubAgentStateEntry {
640+
id: string;
641+
state: string;
642+
}
643+
596644
/**
597645
* SubAgent handle for control and monitoring.
598646
*/
@@ -632,13 +680,21 @@ export declare class SubAgentHandle {
632680
* const handle = orch.spawnSubagent(config);
633681
* console.log('SubAgent ID:', handle.id);
634682
*
683+
* // Real-time monitoring
684+
* const subagents = orch.listSubagents();
685+
* for (const info of subagents) {
686+
* console.log(`${info.id}: ${info.state}`);
687+
* if (info.currentActivity) {
688+
* console.log(` Activity: ${info.currentActivity.activityType}`);
689+
* }
690+
* }
691+
*
635692
* // Control operations
636-
* handle.pause();
637-
* handle.resume();
693+
* orch.pauseSubagent(handle.id);
694+
* orch.resumeSubagent(handle.id);
638695
*
639-
* // Wait for result
640-
* const result = handle.wait();
641-
* console.log('Result:', result);
696+
* // Wait for all to complete
697+
* orch.waitAll();
642698
* ```
643699
*/
644700
export declare class Orchestrator {
@@ -648,6 +704,22 @@ export declare class Orchestrator {
648704
spawnSubagent(config: SubAgentConfig): SubAgentHandle;
649705
/** Get active SubAgent count */
650706
activeCount(): number;
707+
/** Get all SubAgent information list */
708+
listSubagents(): SubAgentInfo[];
709+
/** Get specific SubAgent information */
710+
getSubagentInfo(id: string): SubAgentInfo | null;
711+
/** Get all active SubAgent activities */
712+
getActiveActivities(): SubAgentActivityEntry[];
713+
/** Get all SubAgent states */
714+
getAllStates(): SubAgentStateEntry[];
715+
/** Pause a SubAgent */
716+
pauseSubagent(id: string): void;
717+
/** Resume a SubAgent */
718+
resumeSubagent(id: string): void;
719+
/** Cancel a SubAgent */
720+
cancelSubagent(id: string): void;
721+
/** Wait for all SubAgents to complete */
722+
waitAll(): void;
651723
}
652724

653725
// ============================================================================

sdk/node/src/lib.rs

Lines changed: 176 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ use a3s_code_core::agent_teams::{
2525
};
2626
use a3s_code_core::orchestrator::{
2727
AgentOrchestrator as RustOrchestrator, ControlSignal as RustControlSignal,
28-
OrchestratorEvent as RustOrchestratorEvent, SubAgentConfig as RustSubAgentConfig,
29-
SubAgentHandle as RustSubAgentHandle, SubAgentState as RustSubAgentState,
28+
OrchestratorEvent as RustOrchestratorEvent, SubAgentActivity as RustSubAgentActivity,
29+
SubAgentConfig as RustSubAgentConfig, SubAgentHandle as RustSubAgentHandle,
30+
SubAgentInfo as RustSubAgentInfo, SubAgentState as RustSubAgentState,
3031
};
3132
use a3s_code_core::config::{
3233
SearchConfig as RustSearchConfig, SearchEngineConfig as RustSearchEngineConfig,
@@ -2361,6 +2362,96 @@ impl SubAgentHandle {
23612362
}
23622363
}
23632364

2365+
/// SubAgent activity type
2366+
#[napi(object)]
2367+
pub struct SubAgentActivity {
2368+
/// Activity type: idle, calling_tool, requesting_llm, waiting_for_control
2369+
pub activity_type: String,
2370+
/// Activity data (JSON string)
2371+
pub data: Option<String>,
2372+
}
2373+
2374+
impl From<RustSubAgentActivity> for SubAgentActivity {
2375+
fn from(activity: RustSubAgentActivity) -> Self {
2376+
match activity {
2377+
RustSubAgentActivity::Idle => Self {
2378+
activity_type: "idle".to_string(),
2379+
data: None,
2380+
},
2381+
RustSubAgentActivity::CallingTool { tool_name, args } => Self {
2382+
activity_type: "calling_tool".to_string(),
2383+
data: Some(
2384+
serde_json::json!({
2385+
"tool_name": tool_name,
2386+
"args": args
2387+
})
2388+
.to_string(),
2389+
),
2390+
},
2391+
RustSubAgentActivity::RequestingLlm { message_count } => Self {
2392+
activity_type: "requesting_llm".to_string(),
2393+
data: Some(
2394+
serde_json::json!({
2395+
"message_count": message_count
2396+
})
2397+
.to_string(),
2398+
),
2399+
},
2400+
RustSubAgentActivity::WaitingForControl { reason } => Self {
2401+
activity_type: "waiting_for_control".to_string(),
2402+
data: Some(
2403+
serde_json::json!({
2404+
"reason": reason
2405+
})
2406+
.to_string(),
2407+
),
2408+
},
2409+
}
2410+
}
2411+
}
2412+
2413+
/// SubAgent information with metadata and current activity
2414+
#[napi(object)]
2415+
pub struct SubAgentInfo {
2416+
pub id: String,
2417+
pub agent_type: String,
2418+
pub description: String,
2419+
pub state: String,
2420+
pub parent_id: Option<String>,
2421+
pub created_at: i64,
2422+
pub updated_at: i64,
2423+
pub current_activity: Option<SubAgentActivity>,
2424+
}
2425+
2426+
impl From<RustSubAgentInfo> for SubAgentInfo {
2427+
fn from(info: RustSubAgentInfo) -> Self {
2428+
Self {
2429+
id: info.id,
2430+
agent_type: info.agent_type,
2431+
description: info.description,
2432+
state: info.state,
2433+
parent_id: info.parent_id,
2434+
created_at: info.created_at as i64,
2435+
updated_at: info.updated_at as i64,
2436+
current_activity: info.current_activity.map(|a| a.into()),
2437+
}
2438+
}
2439+
}
2440+
2441+
/// SubAgent activity entry (id + activity)
2442+
#[napi(object)]
2443+
pub struct SubAgentActivityEntry {
2444+
pub id: String,
2445+
pub activity: SubAgentActivity,
2446+
}
2447+
2448+
/// SubAgent state entry (id + state)
2449+
#[napi(object)]
2450+
pub struct SubAgentStateEntry {
2451+
pub id: String,
2452+
pub state: String,
2453+
}
2454+
23642455
/// Agent Orchestrator for main-sub agent coordination.
23652456
#[napi]
23662457
pub struct Orchestrator {
@@ -2396,4 +2487,87 @@ impl Orchestrator {
23962487
let orch = self.inner.clone();
23972488
Ok(get_runtime().block_on(async move { orch.lock().await.active_count().await }) as u32)
23982489
}
2490+
2491+
/// Get all SubAgent information list
2492+
#[napi]
2493+
pub fn list_subagents(&self) -> napi::Result<Vec<SubAgentInfo>> {
2494+
let orch = self.inner.clone();
2495+
let infos = get_runtime().block_on(async move { orch.lock().await.list_subagents().await });
2496+
Ok(infos.into_iter().map(|i| i.into()).collect())
2497+
}
2498+
2499+
/// Get specific SubAgent information
2500+
#[napi]
2501+
pub fn get_subagent_info(&self, id: String) -> napi::Result<Option<SubAgentInfo>> {
2502+
let orch = self.inner.clone();
2503+
let info =
2504+
get_runtime().block_on(async move { orch.lock().await.get_subagent_info(&id).await });
2505+
Ok(info.map(|i| i.into()))
2506+
}
2507+
2508+
/// Get all active SubAgent activities
2509+
#[napi]
2510+
pub fn get_active_activities(&self) -> napi::Result<Vec<SubAgentActivityEntry>> {
2511+
let orch = self.inner.clone();
2512+
let activities =
2513+
get_runtime().block_on(async move { orch.lock().await.get_active_activities().await });
2514+
Ok(activities
2515+
.into_iter()
2516+
.map(|(id, activity)| SubAgentActivityEntry {
2517+
id,
2518+
activity: activity.into(),
2519+
})
2520+
.collect())
2521+
}
2522+
2523+
/// Get all SubAgent states
2524+
#[napi]
2525+
pub fn get_all_states(&self) -> napi::Result<Vec<SubAgentStateEntry>> {
2526+
let orch = self.inner.clone();
2527+
let states =
2528+
get_runtime().block_on(async move { orch.lock().await.get_all_states().await });
2529+
Ok(states
2530+
.into_iter()
2531+
.map(|(id, state)| SubAgentStateEntry {
2532+
id,
2533+
state: format!("{:?}", state),
2534+
})
2535+
.collect())
2536+
}
2537+
2538+
/// Pause a SubAgent
2539+
#[napi]
2540+
pub fn pause_subagent(&self, id: String) -> napi::Result<()> {
2541+
let orch = self.inner.clone();
2542+
get_runtime()
2543+
.block_on(async move { orch.lock().await.pause_subagent(&id).await })
2544+
.map_err(|e| napi::Error::from_reason(format!("Pause failed: {}", e)))
2545+
}
2546+
2547+
/// Resume a SubAgent
2548+
#[napi]
2549+
pub fn resume_subagent(&self, id: String) -> napi::Result<()> {
2550+
let orch = self.inner.clone();
2551+
get_runtime()
2552+
.block_on(async move { orch.lock().await.resume_subagent(&id).await })
2553+
.map_err(|e| napi::Error::from_reason(format!("Resume failed: {}", e)))
2554+
}
2555+
2556+
/// Cancel a SubAgent
2557+
#[napi]
2558+
pub fn cancel_subagent(&self, id: String) -> napi::Result<()> {
2559+
let orch = self.inner.clone();
2560+
get_runtime()
2561+
.block_on(async move { orch.lock().await.cancel_subagent(&id).await })
2562+
.map_err(|e| napi::Error::from_reason(format!("Cancel failed: {}", e)))
2563+
}
2564+
2565+
/// Wait for all SubAgents to complete
2566+
#[napi]
2567+
pub fn wait_all(&self) -> napi::Result<()> {
2568+
let orch = self.inner.clone();
2569+
get_runtime()
2570+
.block_on(async move { orch.lock().await.wait_all().await })
2571+
.map_err(|e| napi::Error::from_reason(format!("Wait failed: {}", e)))
2572+
}
23992573
}

0 commit comments

Comments
 (0)