d4075c3423
新增纯 Rust agent-runtime-core,提供运行时契约、能力注册、Agent 目录、Profile、完成策略与零重放恢复 抽取中立 LLM Provider 协议与可扩展 Registry,并适配 OpenAI Responses、OpenAI Chat 和 Anthropic 将 AGC interaction、Provider 控制、Runner 生命周期、steering 与 tool-plan handoff 接入统一运行时边界 补充非游戏消费者、Provider 网络闭环、Runtime 恢复及 GUI Runner owner 测试 同步 Cargo/npm 门禁、Runtime 技术方案和项目共享记忆
89 lines
2.3 KiB
Rust
89 lines
2.3 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
#[serde(rename_all = "kebab-case")]
|
|
pub enum RecoverableTaskState {
|
|
Pending,
|
|
Running,
|
|
WaitingForConfirmation,
|
|
WaitingForUserInput,
|
|
Other,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum RecoveryStep {
|
|
ResumeRunning { index: usize },
|
|
WaitForExternalInput,
|
|
StartPending { index: usize },
|
|
Idle,
|
|
}
|
|
|
|
pub fn next_recovery_step(tasks: &[RecoverableTaskState]) -> RecoveryStep {
|
|
if let Some(index) = tasks
|
|
.iter()
|
|
.position(|state| *state == RecoverableTaskState::Running)
|
|
{
|
|
return RecoveryStep::ResumeRunning { index };
|
|
}
|
|
if tasks.iter().any(|state| {
|
|
matches!(
|
|
state,
|
|
RecoverableTaskState::WaitingForConfirmation
|
|
| RecoverableTaskState::WaitingForUserInput
|
|
)
|
|
}) {
|
|
return RecoveryStep::WaitForExternalInput;
|
|
}
|
|
tasks
|
|
.iter()
|
|
.position(|state| *state == RecoverableTaskState::Pending)
|
|
.map_or(RecoveryStep::Idle, |index| RecoveryStep::StartPending {
|
|
index,
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn recovery_prefers_first_running_task() {
|
|
assert_eq!(
|
|
next_recovery_step(&[
|
|
RecoverableTaskState::Pending,
|
|
RecoverableTaskState::Running,
|
|
RecoverableTaskState::Running,
|
|
RecoverableTaskState::WaitingForConfirmation,
|
|
]),
|
|
RecoveryStep::ResumeRunning { index: 1 }
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn external_input_blocks_pending_recovery() {
|
|
assert_eq!(
|
|
next_recovery_step(&[
|
|
RecoverableTaskState::Pending,
|
|
RecoverableTaskState::WaitingForUserInput,
|
|
]),
|
|
RecoveryStep::WaitForExternalInput
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn recovery_starts_first_pending_or_remains_idle() {
|
|
assert_eq!(
|
|
next_recovery_step(&[
|
|
RecoverableTaskState::Other,
|
|
RecoverableTaskState::Pending,
|
|
RecoverableTaskState::Pending,
|
|
]),
|
|
RecoveryStep::StartPending { index: 1 }
|
|
);
|
|
assert_eq!(
|
|
next_recovery_step(&[RecoverableTaskState::Other]),
|
|
RecoveryStep::Idle
|
|
);
|
|
}
|
|
}
|