Files
Genarrative/server-rs/crates/agent-runtime-core/src/lifecycle.rs
T
AIGameCreator App d4075c3423
Project CI / Frontend tests (push) Failing after 3m43s
Project CI / Native shell tests (push) Failing after 3m36s
Project CI / Repository checks (push) Failing after 4m36s
Project CI / Backend tests (push) Successful in 8m36s
抽取通用多智能体运行时与可扩展Provider
新增纯 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 技术方案和项目共享记忆
2026-07-30 16:15:51 +08:00

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
);
}
}