rucora_core/agent/mod.rs
1//! Agent(智能体)核心抽象模块
2//!
3//! # 概述
4//!
5//! 本模块定义了 Agent 的抽象接口。Agent 是能够思考、决策和行动的自主实体。
6//!
7//! # 核心概念
8//!
9//! ## 决策与执行分离
10//!
11//! - **Agent trait**: 负责思考、决策、规划(大脑)
12//! - **AgentExecutor trait**: 负责执行、调用、编排(身体)
13//!
14//! Agent 通过 `think()` 方法返回决策,`AgentExecutor` 或其他执行器负责执行。
15
16pub mod types;
17
18/// 运行时适配器抽象
19pub mod runtime_adapter;
20
21use async_trait::async_trait;
22use futures_util::stream::BoxStream;
23use serde::{Deserialize, Serialize};
24use serde_json::Value;
25
26use crate::channel::types::ChannelEvent;
27use crate::provider::types::ChatRequest;
28
29/// Agent 决策结果。
30///
31/// Agent 通过 `think()` 方法返回决策,Runtime 或其他执行器负责执行。
32#[derive(Debug, Clone)]
33pub enum AgentDecision {
34 /// 调用 LLM 进行对话。
35 Chat {
36 /// 对话请求。
37 request: Box<ChatRequest>,
38 },
39 /// 并行处理多个对话请求(Map 阶段)。
40 ///
41 /// 所有请求会按 `max_concurrency` 限制并发执行,
42 /// 结果追加到消息历史后继续循环。
43 MapAll {
44 /// 对话请求列表。
45 requests: Vec<ChatRequest>,
46 /// 最大并发数。
47 max_concurrency: usize,
48 },
49 /// 执行归约对话(Reduce 阶段)。
50 ///
51 /// 处理单个 ChatRequest 后返回最终结果。
52 Reduce {
53 /// 对话请求。
54 request: Box<ChatRequest>,
55 },
56 /// 调用工具。
57 ToolCall {
58 /// 工具名称。
59 name: String,
60 /// 工具输入参数。
61 input: Value,
62 },
63 /// 直接返回结果。
64 Return(Value),
65 /// 需要更多思考(继续循环)。
66 ThinkAgain,
67 /// 停止执行。
68 Stop,
69}
70
71/// Agent 上下文。
72///
73/// 包含 Agent 思考所需的所有信息。
74#[derive(Debug, Clone)]
75pub struct AgentContext {
76 /// 用户原始输入。
77 pub input: AgentInput,
78 /// 对话历史。
79 pub messages: Vec<crate::provider::types::ChatMessage>,
80 /// 工具调用结果。
81 pub tool_results: Vec<ToolResult>,
82 /// 当前步骤数。
83 pub step: usize,
84 /// 最大步骤数。
85 pub max_steps: usize,
86}
87
88impl AgentContext {
89 /// 创建新的上下文。
90 pub fn new(input: AgentInput, max_steps: usize) -> Self {
91 Self {
92 input,
93 messages: Vec::new(),
94 tool_results: Vec::new(),
95 step: 0,
96 max_steps,
97 }
98 }
99
100 /// 添加消息到历史。
101 pub fn add_message(&mut self, message: crate::provider::types::ChatMessage) {
102 self.messages.push(message);
103 }
104
105 /// 添加工具调用结果。
106 pub fn add_tool_result(&mut self, tool_name: String, result: Value) {
107 self.tool_results.push(ToolResult { tool_name, result });
108 }
109
110 /// 创建默认的对话请求。
111 ///
112 /// 所有 LLM 参数(temperature 等)默认为 None,使用模型默认值。
113 /// 可通过 `default_chat_request_with()` 传入自定义参数。
114 pub fn default_chat_request(&self) -> crate::provider::types::ChatRequest {
115 crate::provider::types::ChatRequest {
116 messages: self.messages.clone(),
117 model: None,
118 tools: None,
119 temperature: None,
120 max_tokens: None,
121 response_format: None,
122 metadata: None,
123 top_p: None,
124 top_k: None,
125 frequency_penalty: None,
126 presence_penalty: None,
127 stop: None,
128 extra: None,
129 }
130 }
131
132 /// 创建带 LLM 参数的对话请求。
133 pub fn default_chat_request_with(
134 &self,
135 params: &crate::provider::types::LlmParams,
136 ) -> crate::provider::types::ChatRequest {
137 let mut request = self.default_chat_request();
138 params.apply_to(&mut request);
139 request
140 }
141}
142
143/// 工具调用结果。
144#[derive(Debug, Clone)]
145pub struct ToolResult {
146 /// 工具名称。
147 pub tool_name: String,
148 /// 工具返回结果。
149 pub result: Value,
150}
151
152/// Agent 输入。
153///
154/// 用于向 Agent 传递用户请求。
155///
156/// # 使用示例
157///
158/// ```rust
159/// use rucora_core::agent::AgentInput;
160///
161/// // 简单文本输入
162/// let input = AgentInput::new("你好").unwrap();
163///
164/// // 使用 builder 模式
165/// let input = AgentInput::builder("帮我查询天气")
166/// .unwrap()
167/// .with_context("user_location", "北京")
168/// .build();
169/// ```
170#[derive(Debug, Clone)]
171pub struct AgentInput {
172 /// 文本输入。
173 pub text: String,
174 /// 额外上下文数据。
175 pub context: serde_json::Value,
176}
177
178impl AgentInput {
179 /// 从文本创建输入。
180 ///
181 /// # Errors
182 ///
183 /// 当文本为空时返回 `AgentError::Message`。
184 pub fn new(text: impl Into<String>) -> Result<Self, AgentError> {
185 let text = text.into();
186 if text.is_empty() {
187 return Err(AgentError::Message(
188 "AgentInput text must not be empty".to_string(),
189 ));
190 }
191 Ok(Self {
192 text,
193 context: serde_json::Value::Object(serde_json::Map::new()),
194 })
195 }
196
197 /// 从文本和上下文创建输入。
198 ///
199 /// # Errors
200 ///
201 /// 当文本为空时返回 `AgentError::Message`。
202 pub fn with_context(
203 text: impl Into<String>,
204 context: serde_json::Value,
205 ) -> Result<Self, AgentError> {
206 let text = text.into();
207 if text.is_empty() {
208 return Err(AgentError::Message(
209 "AgentInput text must not be empty".to_string(),
210 ));
211 }
212 Ok(Self { text, context })
213 }
214
215 /// 创建 builder。
216 ///
217 /// # Errors
218 ///
219 /// 当文本为空时返回 `AgentError::Message`。
220 pub fn builder(text: impl Into<String>) -> Result<AgentInputBuilder, AgentError> {
221 AgentInputBuilder::new(text)
222 }
223
224 /// 获取文本内容。
225 pub fn text(&self) -> &str {
226 &self.text
227 }
228
229 /// 获取上下文数据。
230 pub fn context(&self) -> &serde_json::Value {
231 &self.context
232 }
233}
234
235/// AgentInput 构建器。
236pub struct AgentInputBuilder {
237 text: String,
238 context: serde_json::Value,
239}
240
241impl AgentInputBuilder {
242 /// 创建新的构建器。
243 ///
244 /// # Errors
245 ///
246 /// 当文本为空时返回 `AgentError::Message`。
247 pub fn new(text: impl Into<String>) -> Result<Self, AgentError> {
248 let text = text.into();
249 if text.is_empty() {
250 return Err(AgentError::Message(
251 "AgentInput text must not be empty".to_string(),
252 ));
253 }
254 Ok(Self {
255 text,
256 context: serde_json::Value::Object(serde_json::Map::new()),
257 })
258 }
259
260 /// 添加上下文键值对。
261 pub fn with_context(
262 mut self,
263 key: impl Into<String>,
264 value: impl Into<serde_json::Value>,
265 ) -> Self {
266 if let serde_json::Value::Object(ref mut map) = self.context {
267 map.insert(key.into(), value.into());
268 }
269 self
270 }
271
272 /// 设置完整上下文。
273 pub fn context(mut self, context: serde_json::Value) -> Self {
274 self.context = context;
275 self
276 }
277
278 /// 构建输入。
279 pub fn build(self) -> AgentInput {
280 AgentInput {
281 text: self.text,
282 context: self.context,
283 }
284 }
285}
286
287impl From<String> for AgentInput {
288 fn from(text: String) -> Self {
289 Self::new(text).expect("AgentInput text must not be empty")
290 }
291}
292
293impl From<&str> for AgentInput {
294 fn from(text: &str) -> Self {
295 Self::new(text).expect("AgentInput text must not be empty")
296 }
297}
298
299/// Agent 输出。
300///
301/// 包含 Agent 执行的结果和相关信息。
302///
303/// # 字段说明
304///
305/// - `value`: 主要输出内容(通常是 JSON 格式)
306/// - `messages`: 对话历史
307/// - `tool_calls`: 工具调用记录
308///
309/// # 使用示例
310///
311/// ```rust
312/// use rucora_core::agent::AgentOutput;
313/// use serde_json::json;
314///
315/// // 创建输出
316/// let output = AgentOutput::new(json!({"content": "Hello"}));
317///
318/// // 提取文本内容
319/// if let Some(content) = output.value.get("content").and_then(|v| v.as_str()) {
320/// assert_eq!(content, "Hello");
321/// }
322///
323/// // 访问对话历史
324/// assert_eq!(output.messages.len(), 0);
325///
326/// // 访问工具调用
327/// assert_eq!(output.tool_calls.len(), 0);
328/// ```
329#[derive(Debug, Clone)]
330pub struct AgentOutput {
331 /// 主要输出内容(通常是 JSON 格式,包含 `content` 字段)。
332 pub value: Value,
333 /// 对话历史。
334 pub messages: Vec<crate::provider::types::ChatMessage>,
335 /// 工具调用记录。
336 pub tool_calls: Vec<ToolCallRecord>,
337 /// Token 使用统计(累计所有 LLM 调用的 usage)。
338 pub usage: Option<crate::provider::types::Usage>,
339}
340
341impl AgentOutput {
342 /// 创建新的输出。
343 pub fn new(value: Value) -> Self {
344 Self {
345 value,
346 messages: Vec::new(),
347 tool_calls: Vec::new(),
348 usage: None,
349 }
350 }
351
352 /// 创建带历史的输出。
353 pub fn with_history(
354 value: Value,
355 messages: Vec<crate::provider::types::ChatMessage>,
356 tool_calls: Vec<ToolCallRecord>,
357 ) -> Self {
358 Self {
359 value,
360 messages,
361 tool_calls,
362 usage: None,
363 }
364 }
365
366 /// 创建带 usage 的输出。
367 pub fn with_usage(
368 value: Value,
369 messages: Vec<crate::provider::types::ChatMessage>,
370 tool_calls: Vec<ToolCallRecord>,
371 usage: Option<crate::provider::types::Usage>,
372 ) -> Self {
373 Self {
374 value,
375 messages,
376 tool_calls,
377 usage,
378 }
379 }
380
381 /// 获取文本内容(如果存在)。
382 pub fn text(&self) -> Option<&str> {
383 self.value.get("content").and_then(|v| v.as_str())
384 }
385
386 /// 获取文本内容,如果不存在则返回空字符串。
387 pub fn text_unwrap(&self) -> &str {
388 self.text().unwrap_or("")
389 }
390
391 /// 获取文本内容,如果不存在则返回默认值。
392 pub fn text_or<'a>(&'a self, default: &'a str) -> &'a str {
393 self.text().unwrap_or(default)
394 }
395
396 /// 消费自身,获取文本内容的所有权。
397 pub fn into_text(self) -> String {
398 self.text().map(String::from).unwrap_or_default()
399 }
400
401 /// 获取对话历史长度。
402 pub fn message_count(&self) -> usize {
403 self.messages.len()
404 }
405
406 /// 获取工具调用次数。
407 pub fn tool_call_count(&self) -> usize {
408 self.tool_calls.len()
409 }
410
411 /// 获取 Token 使用统计。
412 pub fn usage(&self) -> Option<&crate::provider::types::Usage> {
413 self.usage.as_ref()
414 }
415
416 /// 获取总 Token 数。
417 pub fn total_tokens(&self) -> u32 {
418 self.usage.as_ref().map_or(0, |u| u.total_tokens)
419 }
420
421 /// 获取提示词 Token 数。
422 pub fn prompt_tokens(&self) -> u32 {
423 self.usage.as_ref().map_or(0, |u| u.prompt_tokens)
424 }
425
426 /// 获取输出 Token 数。
427 pub fn completion_tokens(&self) -> u32 {
428 self.usage.as_ref().map_or(0, |u| u.completion_tokens)
429 }
430
431 /// 格式化 Token 使用信息。
432 pub fn usage_summary(&self) -> String {
433 match &self.usage {
434 Some(u) => format!(
435 "Tokens: {} total ({} prompt + {} completion)",
436 u.total_tokens, u.prompt_tokens, u.completion_tokens
437 ),
438 None => "Tokens: N/A".to_string(),
439 }
440 }
441}
442
443impl std::fmt::Display for AgentOutput {
444 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
445 match self.text() {
446 Some(text) => write!(f, "{text}"),
447 None => Ok(()),
448 }
449 }
450}
451
452/// 工具调用记录。
453#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct ToolCallRecord {
455 /// 工具名称。
456 pub name: String,
457 /// 工具调用 ID,用于关联调用与结果。
458 pub tool_call_id: String,
459 /// 输入参数。
460 pub input: Value,
461 /// 返回结果。
462 pub result: Value,
463}
464
465/// Agent trait - 智能体的抽象接口。
466///
467/// Agent 负责思考、决策和规划。它可以:
468/// - 独立运行(处理简单任务)
469/// - 使用内置执行能力(处理复杂任务)
470/// - 调用 Tool/MCP/Skill/A2A 等外部能力
471///
472/// # 设计原则
473///
474/// Agent trait 只定义决策接口(`think`),执行能力(`run`/`run_stream`)由具体实现提供。
475///
476/// ## 决策与执行分离
477///
478/// - **决策层** (`think`): 每个 Agent 类型有不同的思考策略
479/// - **执行层** (`run`/`run_stream`): 所有 Agent 共享相同的执行能力
480///
481/// ## 使用方式
482///
483/// ```rust,no_run
484/// use rucora_core::agent::{Agent, AgentContext, AgentDecision, AgentInput, AgentOutput};
485/// use async_trait::async_trait;
486///
487/// struct MyAgent;
488///
489/// #[async_trait]
490/// impl Agent for MyAgent {
491/// async fn think(&self, context: &AgentContext) -> AgentDecision {
492/// // 自定义决策逻辑
493/// AgentDecision::Return(serde_json::json!({"content": "Hello"}))
494/// }
495///
496/// fn name(&self) -> &str { "my_agent" }
497/// }
498/// ```
499///
500/// # 内置执行能力
501///
502/// 如果 Agent 需要工具调用、流式输出等能力,可以组合 `DefaultExecution`:
503///
504/// ```rust,ignore
505/// use rucora::agent::execution::DefaultExecution;
506/// use rucora_core::agent::Agent;
507///
508/// struct MyAgent {
509/// execution: DefaultExecution,
510/// // ... 其他字段
511/// }
512///
513/// impl Agent for MyAgent {
514/// // ... 实现 think 方法
515///
516/// // DefaultExecution 提供默认的 run/run_stream 实现
517/// }
518/// ```
519#[async_trait]
520pub trait Agent: Send + Sync {
521 /// 思考:分析当前情况,决定下一步行动。
522 ///
523 /// 这是 Agent 的核心方法,返回决策结果。
524 async fn think(&self, context: &AgentContext) -> AgentDecision;
525
526 /// 获取 Agent 名称。
527 fn name(&self) -> &str;
528
529 /// 获取 Agent 描述(可选)。
530 ///
531 /// 返回 Agent 的简短描述,用于调试和日志。
532 fn description(&self) -> Option<&str> {
533 None
534 }
535
536 /// 运行 Agent(非流式)。
537 ///
538 /// 默认实现适用于简单场景(直接返回结果)。
539 /// 需要工具调用等复杂能力的 Agent 应该使用 `run_with()` 方法配合 `AgentExecutor`。
540 ///
541 /// # 默认行为
542 ///
543 /// 默认实现会循环调用 `think()` 直到返回 `Return` 或 `Stop`。
544 /// 如果返回 `Chat` 或 `ToolCall`,会返回错误(需要 Runtime 支持)。
545 ///
546 /// # 何时使用默认 `run()` vs `run_with()`
547 ///
548 /// - **纯推理 Agent**(无需工具调用):直接使用 `run()` 即可,例如 ReAct Agent 的思考部分。
549 /// - **需要工具调用的 Agent**:使用 `run_with(executor, input)`,传入一个 `AgentExecutor` 实现(如 `DefaultExecution`)。
550 /// - **需要流式输出的 Agent**:使用 `run_stream()` 或 `run_with().run_stream()`。
551 ///
552 /// # 示例
553 ///
554 /// ## 简单推理 Agent(无需工具)
555 /// ```rust,ignore
556 /// use rucora_core::agent::{Agent, AgentInput};
557 ///
558 /// # async fn example(agent: &dyn Agent) -> Result<(), Box<dyn std::error::Error>> {
559 /// let output = agent.run(AgentInput::new("你好")).await?;
560 /// # Ok(())
561 /// # }
562 /// ```
563 ///
564 /// ## 带工具执行的 Agent
565 /// ```rust,ignore
566 /// use rucora::agent::execution::DefaultExecution;
567 /// use rucora::agent::ToolAgent;
568 /// use rucora_core::agent::{Agent, AgentInput, AgentExecutor};
569 ///
570 /// # async fn example(agent: &impl Agent, executor: &dyn AgentExecutor) -> Result<(), Box<dyn std::error::Error>> {
571 /// let output = agent.run_with(executor, AgentInput::new("你好")).await?;
572 /// # Ok(())
573 /// # }
574 /// ```
575 async fn run(&self, input: AgentInput) -> Result<AgentOutput, AgentError> {
576 // 默认最大步骤数:20
577 // 需要自定义请使用 `run_with(executor, input)` 方法
578 const DEFAULT_MAX_STEPS: usize = 20;
579
580 let mut context = AgentContext::new(input.clone(), DEFAULT_MAX_STEPS);
581
582 loop {
583 let decision = self.think(&context).await;
584
585 match decision {
586 AgentDecision::Return(value) => {
587 return Ok(AgentOutput::with_history(
588 value,
589 context.messages,
590 Vec::new(),
591 ));
592 }
593 AgentDecision::Stop => {
594 return Ok(AgentOutput::with_history(
595 Value::Null,
596 context.messages,
597 Vec::new(),
598 ));
599 }
600 AgentDecision::ThinkAgain => {
601 context.step += 1;
602 if context.step >= context.max_steps {
603 return Err(AgentError::MaxStepsExceeded {
604 max_steps: context.max_steps,
605 });
606 }
607 }
608 AgentDecision::Chat { request: _ } => {
609 // Chat 决策需要 LLM 调用,请使用 `run_with(executor, input)` 方法
610 return Err(AgentError::RequiresRuntime);
611 }
612 AgentDecision::MapAll { .. } | AgentDecision::Reduce { .. } => {
613 // MapAll/Reduce 决策需要执行器支持,请使用 `run_with(executor, input)` 方法
614 return Err(AgentError::RequiresRuntime);
615 }
616 AgentDecision::ToolCall { .. } => {
617 // ToolCall 决策需要工具执行,请使用 `run_with(executor, input)` 方法
618 return Err(AgentError::RequiresRuntime);
619 }
620 }
621 }
622 }
623
624 /// 运行 Agent(带超时控制)。
625 ///
626 /// 此方法允许设置 Agent 级别的整体超时时间。超时后,Agent 会停止执行
627 /// 并返回 `AgentError::Timeout` 错误。
628 ///
629 /// # 参数
630 ///
631 /// - `input`: 用户输入
632 /// - `timeout`: 超时时间
633 ///
634 /// # 示例
635 ///
636 /// ```rust,ignore
637 /// use rucora_core::agent::{Agent, AgentInput};
638 /// use std::time::Duration;
639 ///
640 /// # async fn example(agent: &dyn Agent) -> Result<(), Box<dyn std::error::Error>> {
641 /// let input = AgentInput::new("请在30秒内完成这个任务");
642 /// let output = agent.run_with_timeout(input, Duration::from_secs(30)).await?;
643 /// # Ok(())
644 /// # }
645 /// ```
646 async fn run_with_timeout(
647 &self,
648 input: AgentInput,
649 timeout: std::time::Duration,
650 ) -> Result<AgentOutput, AgentError> {
651 tokio::time::timeout(timeout, self.run(input))
652 .await
653 .map_err(|_| AgentError::Timeout { duration: timeout })?
654 }
655
656 /// 运行 Agent(流式)。
657 ///
658 /// 默认实现返回一个包含错误信息的 stream,表示此 Agent 不支持流式输出。
659 /// 需要流式支持的 Agent 应重写此方法,或使用 `run_with()` 配合流式执行器。
660 ///
661 /// # 何时重写此方法
662 ///
663 /// - Agent 需要流式输出 Token 级增量
664 /// - Agent 需要流式工具调用反馈
665 /// - 构建聊天机器人等需要实时交互的场景
666 ///
667 /// # 示例
668 ///
669 /// ## 使用默认实(不支持流式)
670 /// ```rust,ignore
671 /// use rucora_core::agent::{Agent, AgentInput};
672 /// use futures_util::StreamExt;
673 ///
674 /// # async fn example(agent: &dyn Agent) -> Result<(), Box<dyn std::error::Error>> {
675 /// let mut stream = agent.run_stream(AgentInput::new("你好"));
676 /// while let Some(event) = stream.next().await {
677 /// match event? {
678 /// rucora_core::channel::types::ChannelEvent::TokenDelta(delta) => {
679 /// print!("{}", delta.delta);
680 /// }
681 /// _ => {}
682 /// }
683 /// }
684 /// # Ok(())
685 /// # }
686 /// ```
687 ///
688 /// ## 使用 `DefaultExecution` 提供流式支持
689 /// ```rust,ignore
690 /// use rucora::agent::execution::DefaultExecution;
691 /// use rucora_core::agent::{Agent, AgentInput, AgentExecutor};
692 ///
693 /// # async fn example(agent: &impl Agent, executor: &dyn AgentExecutor) -> Result<(), Box<dyn std::error::Error>> {
694 /// let stream = executor.run_stream(AgentInput::new("你好"));
695 /// # Ok(())
696 /// # }
697 /// ```
698 fn run_stream(
699 &self,
700 _input: AgentInput,
701 ) -> BoxStream<'static, Result<ChannelEvent, AgentError>> {
702 use futures_util::stream;
703 Box::pin(stream::once(async {
704 Err(AgentError::Message("此 Agent 不支持流式输出".to_string()))
705 }))
706 }
707
708 /// 运行 Agent(使用执行器)。
709 ///
710 /// 此方法允许使用外部执行器来运行 Agent。
711 /// 这是实现 dyn 兼容的关键方法。
712 ///
713 /// # 参数
714 ///
715 /// - `executor`: 执行器,负责实际的运行逻辑
716 /// - `input`: 用户输入
717 ///
718 /// # 示例
719 ///
720 /// ```rust,no_run
721 /// use rucora_core::agent::{Agent, AgentInput, AgentExecutor};
722 ///
723 /// # async fn example(agent: &impl Agent, executor: &dyn AgentExecutor) -> Result<(), Box<dyn std::error::Error>> {
724 /// let output = agent.run_with(executor, AgentInput::new("你好")?).await?;
725 /// # Ok(())
726 /// # }
727 /// ```
728 async fn run_with(
729 &self,
730 executor: &dyn AgentExecutor,
731 input: AgentInput,
732 ) -> Result<AgentOutput, AgentError>
733 where
734 Self: Sized,
735 {
736 executor.run(self, input).await
737 }
738}
739
740/// Agent 执行器 trait
741///
742/// 用于执行 Agent 的运行逻辑,支持工具调用、流式输出等。
743/// 这是实现 dyn 兼容的关键。
744#[async_trait]
745pub trait AgentExecutor: Send + Sync {
746 /// 运行 Agent
747 async fn run(&self, agent: &dyn Agent, input: AgentInput) -> Result<AgentOutput, AgentError>;
748
749 /// 流式运行 Agent
750 ///
751 /// 注意:由于生命周期限制,此方法不支持 Agent 决策。
752 /// 它只执行简单的工具调用循环。
753 fn run_stream(&self, input: AgentInput)
754 -> BoxStream<'static, Result<ChannelEvent, AgentError>>;
755}
756
757// 重新导出统一的 AgentError 定义
758pub use crate::error::AgentError;
759
760/// 重新导出运行时适配器相关类型
761pub use runtime_adapter::{
762 LogLevel, NativeRuntimeAdapter, RestrictedRuntimeAdapter, RuntimeAdapter, RuntimeCapabilities,
763 RuntimeError, RuntimePlatform, ShellResult,
764};