重命名 Direct 回合失败载荷并让 typed 失败原样下发
- TurnFailed 更名为 SuperErrorFromStringPlusStage:只有 stage 是 typed,detail 仍是产生层字符串 - TurnFailedUnclassified 更名为 Unclassified:深层字符串兜底,连交付阶段都没有 - 拆掉 direct_runtime 与 thread_manager 两处收口重包,typed 失败原样投影成失败载荷 - 审计写盘保留,只是不再把 direct-codex-failure:v2 收口文案当失败载荷的 detail - 生成绑定重导出(旧 TurnFailed/TurnFailedUnclassified 生成文件删除),前端分支与 directThreadChat 用例同步改名 - 命名债注释补记:这两个载荷臂与 SuperErrorEnumFromStringTyped 属同一笔待清债
This commit is contained in:
@@ -30,6 +30,10 @@
|
||||
//! typed 出口。修法在**上游**:让这些产生层直接产出 typed 变体 / 结构化子错误,判定层改成
|
||||
//! `match`;等上游补完,这张表和 `runtime_error::classify_direct_codex_error` 一起删掉。
|
||||
//! 补齐之前:**不许往表里加词**——新增分类必须先在产生层加 typed 变体。
|
||||
//!
|
||||
//! 同一笔债还挂在两个载荷臂上:[`SuperErrorFromStringPlusStage`](有 stage、没有 typed detail)
|
||||
//! 与 [`Unclassified`](连 stage 都没有)。名字故意起得又长又扎眼,就是在提醒它们不是设计:
|
||||
//! `detail` typed 化之后,这两个名字都该消失。
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
@@ -488,11 +492,15 @@ pub(crate) enum TurnError {
|
||||
/// —— **控制流,不是失败**:与 [`Self::ReviewRequired`] 同一族,只是产生点在收尾阶段。
|
||||
/// 调用方把它写回提示词继续跑:不写终态、不进失败载荷、不上报。
|
||||
RepairRequired { detail: String },
|
||||
/// 已经写成诊断记录的回合失败。
|
||||
TurnFailed(TurnFailed),
|
||||
/// 桥:深层只拿得到字符串的错误。只允许出现在"这一轮已经开始"的层里,
|
||||
/// 且新分类必须先加 typed 变体,别借这个变体蒙混过关。
|
||||
TurnFailedUnclassified(TurnFailedUnclassified),
|
||||
/// 交付阶段失败:`stage` 是 typed 的,`detail` 还是产生层交上来的字符串。
|
||||
///
|
||||
/// 名字故意起得又长又扎眼(`Super…FromStringPlusStage`):这是**待清的债**,
|
||||
/// `detail` typed 化之后这一臂该改名或并入 typed 变体,别把它改漂亮。
|
||||
SuperErrorFromStringPlusStage(SuperErrorFromStringPlusStage),
|
||||
/// 桥:深层只拿得到字符串的错误,**连阶段都没有**。只允许出现在"这一轮已经开始"的层里,
|
||||
/// 且新分类必须先加 typed 变体,别借这个变体蒙混过关。与
|
||||
/// [`Self::SuperErrorFromStringPlusStage`] 是同一笔债的两半。
|
||||
Unclassified(Unclassified),
|
||||
}
|
||||
|
||||
/// 项目目录锚不定的原始原因。
|
||||
@@ -536,20 +544,23 @@ pub(crate) struct TurnInterrupted {
|
||||
pub(crate) detail: String,
|
||||
}
|
||||
|
||||
/// 已写成诊断记录的回合失败:阶段 + 诊断正文。
|
||||
/// 已知交付阶段的失败:`stage` 是 typed enum,`detail` 是产生层原文(字符串债)。
|
||||
///
|
||||
/// 名字故意起得又长又扎眼(`Super…FromStringPlusStage`):与 [`SuperErrorEnumFromStringTyped`]
|
||||
/// 同一笔债——`detail` 一天没 typed 化,它一天不配有个正常名字。
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/view/project-development/chat/generated/"))]
|
||||
pub(crate) struct TurnFailed {
|
||||
pub(crate) struct SuperErrorFromStringPlusStage {
|
||||
pub(crate) stage: FailureStage,
|
||||
pub(crate) detail: String,
|
||||
}
|
||||
|
||||
/// 深层尚未 typed 的字符串错误。
|
||||
/// 深层尚未 typed 的字符串错误:不知道发生在哪一段,只有一条宿主原文。
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = concat!(env!("CARGO_MANIFEST_DIR"), "/../src/view/project-development/chat/generated/"))]
|
||||
pub(crate) struct TurnFailedUnclassified {
|
||||
pub(crate) struct Unclassified {
|
||||
pub(crate) detail: String,
|
||||
}
|
||||
|
||||
@@ -589,15 +600,15 @@ impl TurnError {
|
||||
Self::TurnInterrupted(payload) => Some(TurnFailure::TurnInterrupted(TurnInterrupted {
|
||||
detail: redact(&payload.detail),
|
||||
})),
|
||||
Self::TurnFailed(payload) => Some(TurnFailure::TurnFailed(TurnFailed {
|
||||
stage: payload.stage,
|
||||
Self::SuperErrorFromStringPlusStage(payload) => Some(
|
||||
TurnFailure::SuperErrorFromStringPlusStage(SuperErrorFromStringPlusStage {
|
||||
stage: payload.stage,
|
||||
detail: redact(&payload.detail),
|
||||
}),
|
||||
),
|
||||
Self::Unclassified(payload) => Some(TurnFailure::Unclassified(Unclassified {
|
||||
detail: redact(&payload.detail),
|
||||
})),
|
||||
Self::TurnFailedUnclassified(payload) => Some(TurnFailure::TurnFailedUnclassified(
|
||||
TurnFailedUnclassified {
|
||||
detail: redact(&payload.detail),
|
||||
},
|
||||
)),
|
||||
// 控制流:这一轮还没结束,不是失败。
|
||||
Self::ReviewRequired { .. } | Self::RepairRequired { .. } => None,
|
||||
}
|
||||
@@ -622,15 +633,15 @@ impl TurnError {
|
||||
Self::TimedOut(payload) => payload.deadline.message().to_string(),
|
||||
Self::TurnInterrupted(payload) => payload.detail.clone(),
|
||||
Self::ReviewRequired { detail } | Self::RepairRequired { detail } => detail.clone(),
|
||||
Self::TurnFailed(payload) => payload.detail.clone(),
|
||||
Self::TurnFailedUnclassified(payload) => payload.detail.clone(),
|
||||
Self::SuperErrorFromStringPlusStage(payload) => payload.detail.clone(),
|
||||
Self::Unclassified(payload) => payload.detail.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 已记录失败的诊断阶段;拿不到阶段的错误归到回合主体的代码生成段。
|
||||
pub(crate) fn turn_failure_stage(&self) -> FailureStage {
|
||||
match self {
|
||||
Self::TurnFailed(payload) => payload.stage,
|
||||
Self::SuperErrorFromStringPlusStage(payload) => payload.stage,
|
||||
_ => FailureStage::CodeGeneration,
|
||||
}
|
||||
}
|
||||
@@ -642,10 +653,10 @@ impl TurnError {
|
||||
// 阶段失败 / 桥变体:**认出是哪一类就拦**(产生层还没 typed 出口的深层事实才继续
|
||||
// 反馈)。已归类的都是模型改不动的事实——凭据 / 权限 / 额度 / 历史一致性与契约变化,
|
||||
// 把同一份输入再跑一轮只会拿到同一结论;旧的字面量判据也是这个口径。
|
||||
Self::TurnFailed(payload) => {
|
||||
Self::SuperErrorFromStringPlusStage(payload) => {
|
||||
SuperErrorEnumFromStringTyped::classify(&payload.detail).is_none()
|
||||
}
|
||||
Self::TurnFailedUnclassified(payload) => {
|
||||
Self::Unclassified(payload) => {
|
||||
SuperErrorEnumFromStringTyped::classify(&payload.detail).is_none()
|
||||
}
|
||||
_ => false,
|
||||
@@ -659,12 +670,12 @@ impl TurnError {
|
||||
Self::TransportClosed(_) => false,
|
||||
// 超时/中断后重试是常规动作:宿主已经把这一轮收干净了。
|
||||
Self::TimedOut(_) | Self::TurnInterrupted(_) => true,
|
||||
Self::TurnFailed(payload) => SuperErrorEnumFromStringTyped::classify(&payload.detail)
|
||||
.is_none_or(SuperErrorEnumFromStringTyped::is_retryable),
|
||||
Self::TurnFailedUnclassified(payload) => {
|
||||
Self::SuperErrorFromStringPlusStage(payload) => {
|
||||
SuperErrorEnumFromStringTyped::classify(&payload.detail)
|
||||
.is_none_or(SuperErrorEnumFromStringTyped::is_retryable)
|
||||
}
|
||||
Self::Unclassified(payload) => SuperErrorEnumFromStringTyped::classify(&payload.detail)
|
||||
.is_none_or(SuperErrorEnumFromStringTyped::is_retryable),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -673,12 +684,12 @@ impl TurnError {
|
||||
pub(crate) fn public_summary(&self) -> Option<&'static str> {
|
||||
match self {
|
||||
Self::ModelCallFailed(payload) => payload.kind.public_summary(),
|
||||
Self::TurnFailed(payload) => SuperErrorEnumFromStringTyped::classify(&payload.detail)
|
||||
.and_then(SuperErrorEnumFromStringTyped::public_summary),
|
||||
Self::TurnFailedUnclassified(payload) => {
|
||||
Self::SuperErrorFromStringPlusStage(payload) => {
|
||||
SuperErrorEnumFromStringTyped::classify(&payload.detail)
|
||||
.and_then(SuperErrorEnumFromStringTyped::public_summary)
|
||||
}
|
||||
Self::Unclassified(payload) => SuperErrorEnumFromStringTyped::classify(&payload.detail)
|
||||
.and_then(SuperErrorEnumFromStringTyped::public_summary),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -696,9 +707,11 @@ impl TurnError {
|
||||
Self::TurnInterrupted(_) => {
|
||||
Some("本轮执行被上游中断,请重试;如持续失败请检查项目诊断")
|
||||
}
|
||||
Self::TurnFailed(payload) => stage_recovery_hint(payload.stage, &payload.detail),
|
||||
Self::SuperErrorFromStringPlusStage(payload) => {
|
||||
stage_recovery_hint(payload.stage, &payload.detail)
|
||||
}
|
||||
// 桥变体没有阶段可依,按回合主体的默认段给建议。
|
||||
Self::TurnFailedUnclassified(payload) => {
|
||||
Self::Unclassified(payload) => {
|
||||
stage_recovery_hint(FailureStage::CodeGeneration, &payload.detail)
|
||||
}
|
||||
_ => None,
|
||||
@@ -743,7 +756,7 @@ impl TurnError {
|
||||
|
||||
/// 阶段失败:把深层错误挂到交付的某一段上。深层还没 typed 的口子由这里进桥变体。
|
||||
pub(crate) fn turn_failed(stage: FailureStage, detail: impl Into<String>) -> Self {
|
||||
Self::TurnFailed(TurnFailed {
|
||||
Self::SuperErrorFromStringPlusStage(SuperErrorFromStringPlusStage {
|
||||
stage,
|
||||
detail: detail.into(),
|
||||
})
|
||||
@@ -757,18 +770,18 @@ impl TurnError {
|
||||
}
|
||||
}
|
||||
|
||||
/// 桥:深层尚未 typed 的字符串错误落进 [`TurnError::TurnFailedUnclassified`]。
|
||||
/// 桥:深层尚未 typed 的字符串错误落进 [`TurnError::Unclassified`]。
|
||||
///
|
||||
/// 只给"这一轮已经开始"的层用。调用级(权限、校验、并发)必须显式构造对应变体。
|
||||
impl From<String> for TurnError {
|
||||
fn from(detail: String) -> Self {
|
||||
Self::TurnFailedUnclassified(TurnFailedUnclassified { detail })
|
||||
Self::Unclassified(Unclassified { detail })
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for TurnError {
|
||||
fn from(detail: &str) -> Self {
|
||||
Self::TurnFailedUnclassified(TurnFailedUnclassified {
|
||||
Self::Unclassified(Unclassified {
|
||||
detail: detail.to_string(),
|
||||
})
|
||||
}
|
||||
@@ -1134,14 +1147,14 @@ mod tests {
|
||||
payload
|
||||
);
|
||||
|
||||
let payload = TurnFailure::TurnFailed(TurnFailed {
|
||||
let payload = TurnFailure::SuperErrorFromStringPlusStage(SuperErrorFromStringPlusStage {
|
||||
stage: FailureStage::BrowserValidation,
|
||||
detail: "试玩失败".into(),
|
||||
});
|
||||
assert_eq!(
|
||||
serde_json::to_value(&payload).expect("serialize"),
|
||||
serde_json::json!({
|
||||
"type": "turnFailed",
|
||||
"type": "superErrorFromStringPlusStage",
|
||||
"stage": "browser-validation",
|
||||
"detail": "试玩失败"
|
||||
})
|
||||
|
||||
@@ -1954,6 +1954,8 @@ const DIRECT_CODEX_DEFAULT_RECOVERY_HINT: &str = "请重试;如持续失败请
|
||||
///
|
||||
/// 返回值是 `direct-codex-failure:v2 ...` 这行宿主收口文本:它只进 `.agent/runtime/errors`
|
||||
/// 与应用日志、错误上报池,**不再下发给前端**(前端按 typed 变体自己拼用户可见文案)。
|
||||
/// 调用方现在一律丢弃这个返回值:失败载荷原样透传 typed 变体,收口文案不再当 `detail`,
|
||||
/// 返回值只剩诊断测试在断言。
|
||||
pub(crate) fn record_direct_codex_failure(
|
||||
root: &Path,
|
||||
failure: &TurnError,
|
||||
@@ -2020,8 +2022,10 @@ fn direct_codex_error_code(failure: &TurnError) -> &'static str {
|
||||
| TurnError::RepairRequired { .. } => {
|
||||
classify_direct_codex_error(&failure.diagnostic_detail())
|
||||
}
|
||||
TurnError::TurnFailed(payload) => classify_direct_codex_error(&payload.detail),
|
||||
TurnError::TurnFailedUnclassified(payload) => classify_direct_codex_error(&payload.detail),
|
||||
TurnError::SuperErrorFromStringPlusStage(payload) => {
|
||||
classify_direct_codex_error(&payload.detail)
|
||||
}
|
||||
TurnError::Unclassified(payload) => classify_direct_codex_error(&payload.detail),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4406,8 +4410,10 @@ pub(crate) async fn run_direct_game_creator_turn_at_with_creation_type_and_emitt
|
||||
// 在入队前就查过,能到这条通道的只有放行之后的事(连接、配置、历史注入、`turn/start`
|
||||
// 被拒、模型与交付)。所以不再有"直通调用方"的分支。
|
||||
Err(failure) => {
|
||||
let stage = failure.turn_failure_stage();
|
||||
let error = record_direct_codex_failure(
|
||||
// 审计照写(`.agent/runtime/errors` / 应用日志 / 错误池),但返回值不再当载荷:
|
||||
// typed 失败**原样透传**,前端拿到的是真正的变体(模型调用 / 超时 / 通道断开…),
|
||||
// 而不是被统一重包成 `SuperErrorFromStringPlusStage` 后的 catch-all。
|
||||
let _ = record_direct_codex_failure(
|
||||
root,
|
||||
&failure,
|
||||
turn_emitter.map(|emitter| emitter.turn_id()),
|
||||
@@ -4418,10 +4424,7 @@ pub(crate) async fn run_direct_game_creator_turn_at_with_creation_type_and_emitt
|
||||
if let Some(emitter) = turn_emitter {
|
||||
emitter.emit("failed", Some("none"));
|
||||
}
|
||||
Err(TurnError::TurnFailed(TurnFailed {
|
||||
stage,
|
||||
detail: error,
|
||||
}))
|
||||
Err(failure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,8 +158,8 @@ mod tests {
|
||||
TurnFailure::TransportClosed(payload) => payload.diagnostic.clone(),
|
||||
TurnFailure::TimedOut(payload) => format!("{:?}", payload.deadline),
|
||||
TurnFailure::TurnInterrupted(payload) => payload.detail.clone(),
|
||||
TurnFailure::TurnFailed(payload) => payload.detail.clone(),
|
||||
TurnFailure::TurnFailedUnclassified(payload) => payload.detail.clone(),
|
||||
TurnFailure::SuperErrorFromStringPlusStage(payload) => payload.detail.clone(),
|
||||
TurnFailure::Unclassified(payload) => payload.detail.clone(),
|
||||
TurnFailure::HostDropped => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::agent::{
|
||||
direct_codex_user_item_to_prompt, now_ms, record_direct_codex_failure,
|
||||
redact_agent_runtime_error, run_direct_game_creator_turn_at_with_creation_type_and_emitter,
|
||||
thread_id_for_project, DirectGameCreatorTurnUpdateEmitter, DispatchedTurn, FailureStage,
|
||||
TurnCompletion, TurnError, TurnFailed,
|
||||
TurnCompletion, TurnError,
|
||||
};
|
||||
|
||||
/// 一次放行的占用。持有它就代表这一轮还没收口。
|
||||
@@ -263,9 +263,10 @@ async fn run_dispatched_direct_turn(
|
||||
direct_turn_panic_detail(payload.as_ref())
|
||||
),
|
||||
);
|
||||
let stage = failure.turn_failure_stage();
|
||||
let detail = record_direct_codex_failure(&root, &failure, Some(turn_id.as_str()));
|
||||
Err(TurnError::TurnFailed(TurnFailed { stage, detail }))
|
||||
// 审计照写,载荷原样透传:panic 本身已经是一条 `SuperErrorFromStringPlusStage`,
|
||||
// 不需要再包一层。
|
||||
let _ = record_direct_codex_failure(&root, &failure, Some(turn_id.as_str()));
|
||||
Err(failure)
|
||||
}
|
||||
};
|
||||
match outcome {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use crate::agent::{ThreadEvent, TurnError, TurnFailedUnclassified};
|
||||
use crate::agent::{ThreadEvent, TurnError, Unclassified};
|
||||
|
||||
use super::wire::TurnFailure;
|
||||
|
||||
@@ -85,7 +85,7 @@ pub(crate) fn turn_terminal(
|
||||
// 账本读不出来时(`session_status == "failed"`)没有 typed 原因可用:报告文本就是这一轮
|
||||
// 唯一的收口依据,按未分类失败发出去,不能让界面停在"已结束、没原因"。
|
||||
(None, Ok(report)) if session_status == "failed" => {
|
||||
Some(TurnError::TurnFailedUnclassified(TurnFailedUnclassified {
|
||||
Some(TurnError::Unclassified(Unclassified {
|
||||
detail: report.to_string(),
|
||||
}))
|
||||
}
|
||||
@@ -100,7 +100,7 @@ pub(crate) fn turn_terminal(
|
||||
// 收尾阶段的 `status` 认不出来(当前不可能发生):宁可报一条说不出原因的失败,也不冒充
|
||||
// 正常收场;载荷照样从 typed 错误投影,保持"只在一处拼载荷"。
|
||||
(None, None) => TurnCompletion::Failed(
|
||||
TurnError::TurnFailedUnclassified(TurnFailedUnclassified {
|
||||
TurnError::Unclassified(Unclassified {
|
||||
detail: format!("收尾阶段给出的回合终态无法识别:{session_status}"),
|
||||
})
|
||||
.terminal_failure(history_root)
|
||||
@@ -142,8 +142,7 @@ impl SessionOutcome {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::agent::{
|
||||
ModelCallKind, ThreadEvent, TransportClosed, TurnError, TurnFailedUnclassified,
|
||||
TurnInterrupted,
|
||||
ModelCallKind, ThreadEvent, TransportClosed, TurnError, TurnInterrupted, Unclassified,
|
||||
};
|
||||
use platform_llm::LlmError;
|
||||
|
||||
@@ -180,7 +179,7 @@ mod tests {
|
||||
fn unknown_session_status_fails_closed() {
|
||||
let completion = turn_terminal("something-new", Ok("报告"), None, &history_root());
|
||||
match completion {
|
||||
TurnCompletion::Failed(TurnFailure::TurnFailedUnclassified(payload)) => {
|
||||
TurnCompletion::Failed(TurnFailure::Unclassified(payload)) => {
|
||||
assert!(payload.detail.contains("something-new"));
|
||||
}
|
||||
other => panic!("unknown status must fail closed, got {other:?}"),
|
||||
@@ -208,11 +207,9 @@ mod tests {
|
||||
fn unreadable_session_ledger_still_reports_a_payload() {
|
||||
assert_eq!(
|
||||
turn_terminal("failed", Ok("报告"), None, &history_root()),
|
||||
TurnCompletion::Failed(TurnFailure::TurnFailedUnclassified(
|
||||
TurnFailedUnclassified {
|
||||
detail: "报告".into()
|
||||
}
|
||||
))
|
||||
TurnCompletion::Failed(TurnFailure::Unclassified(Unclassified {
|
||||
detail: "报告".into()
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::agent::{
|
||||
EnvironmentNotReady, HostStateUnavailable, ModelCallFailed, ProjectRootUnanchored, TimedOut,
|
||||
TransportClosed, TurnFailed, TurnFailedUnclassified, TurnInterrupted,
|
||||
EnvironmentNotReady, HostStateUnavailable, ModelCallFailed, ProjectRootUnanchored,
|
||||
SuperErrorFromStringPlusStage, TimedOut, TransportClosed, TurnInterrupted, Unclassified,
|
||||
};
|
||||
|
||||
/// 失败终态的可下发载荷(`turn.completed.status == "failed"` 时必有,其余终态没有)。
|
||||
@@ -41,8 +41,8 @@ pub(crate) enum TurnFailure {
|
||||
TransportClosed(TransportClosed),
|
||||
TimedOut(TimedOut),
|
||||
TurnInterrupted(TurnInterrupted),
|
||||
TurnFailed(TurnFailed),
|
||||
TurnFailedUnclassified(TurnFailedUnclassified),
|
||||
SuperErrorFromStringPlusStage(SuperErrorFromStringPlusStage),
|
||||
Unclassified(Unclassified),
|
||||
/// 宿主任务提前结束(panic / 被取消):说不出原因的那一种兜底。
|
||||
HostDropped,
|
||||
}
|
||||
|
||||
@@ -1248,7 +1248,7 @@ export function projectRuntimeVisibleError(
|
||||
normalized.includes('落盘失败') ||
|
||||
normalized.includes('持久化失败') ||
|
||||
normalized.includes('写入失败') ||
|
||||
// 宿主"历史落盘"的事实句不带"失败"两个字:`TurnFailed` 的原因就是
|
||||
// 宿主"历史落盘"的事实句不带"失败"两个字:`SuperErrorFromStringPlusStage` 的原因就是
|
||||
// "DirectProject 收尾历史失败:未确认历史完整落盘"这一类。
|
||||
normalized.includes('收尾历史失败') ||
|
||||
normalized.includes('未确认历史完整落盘') ||
|
||||
|
||||
+2
-2
@@ -172,9 +172,9 @@ export function directTurnFailureNoticeText(failure: TurnFailure): string {
|
||||
return `${DIRECT_TURN_SUBJECT} ${directTurnDeadlineText(failure.deadline)}`;
|
||||
case 'turnInterrupted':
|
||||
return `${DIRECT_TURN_SUBJECT} 本轮执行被中断,请重试`;
|
||||
case 'turnFailed':
|
||||
case 'superErrorFromStringPlusStage':
|
||||
return `${DIRECT_TURN_SUBJECT}:${DIRECT_FAILURE_STAGE_LABELS[failure.stage]},请检查项目诊断后重试`;
|
||||
case 'turnFailedUnclassified':
|
||||
case 'unclassified':
|
||||
return `${DIRECT_TURN_SUBJECT} 执行失败,请稍后重试`;
|
||||
case 'hostDropped':
|
||||
return '陶泥儿回合的宿主任务提前结束(崩溃或任务被取消),本轮已按失败收口,请重试。';
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { FailureStage } from './FailureStage';
|
||||
|
||||
/**
|
||||
* 已知交付阶段的失败:`stage` 是 typed enum,`detail` 是产生层原文(字符串债)。
|
||||
*
|
||||
* 名字故意起得又长又扎眼(`Super…FromStringPlusStage`):与 [`SuperErrorEnumFromStringTyped`]
|
||||
* 同一笔债——`detail` 一天没 typed 化,它一天不配有个正常名字。
|
||||
*/
|
||||
export type SuperErrorFromStringPlusStage = {
|
||||
stage: FailureStage;
|
||||
detail: string;
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { FailureStage } from './FailureStage';
|
||||
|
||||
/**
|
||||
* 已写成诊断记录的回合失败:阶段 + 诊断正文。
|
||||
*/
|
||||
export type TurnFailed = { stage: FailureStage; detail: string };
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* 深层尚未 typed 的字符串错误。
|
||||
*/
|
||||
export type TurnFailedUnclassified = { detail: string };
|
||||
+4
-4
@@ -3,11 +3,11 @@ import type { EnvironmentNotReady } from './EnvironmentNotReady';
|
||||
import type { HostStateUnavailable } from './HostStateUnavailable';
|
||||
import type { ModelCallFailed } from './ModelCallFailed';
|
||||
import type { ProjectRootUnanchored } from './ProjectRootUnanchored';
|
||||
import type { SuperErrorFromStringPlusStage } from './SuperErrorFromStringPlusStage';
|
||||
import type { TimedOut } from './TimedOut';
|
||||
import type { TransportClosed } from './TransportClosed';
|
||||
import type { TurnFailed } from './TurnFailed';
|
||||
import type { TurnFailedUnclassified } from './TurnFailedUnclassified';
|
||||
import type { TurnInterrupted } from './TurnInterrupted';
|
||||
import type { Unclassified } from './Unclassified';
|
||||
|
||||
/**
|
||||
* 失败终态的可下发载荷(`turn.completed.status == "failed"` 时必有,其余终态没有)。
|
||||
@@ -27,6 +27,6 @@ export type TurnFailure =
|
||||
| ({ type: 'transportClosed' } & TransportClosed)
|
||||
| ({ type: 'timedOut' } & TimedOut)
|
||||
| ({ type: 'turnInterrupted' } & TurnInterrupted)
|
||||
| ({ type: 'turnFailed' } & TurnFailed)
|
||||
| ({ type: 'turnFailedUnclassified' } & TurnFailedUnclassified)
|
||||
| ({ type: 'superErrorFromStringPlusStage' } & SuperErrorFromStringPlusStage)
|
||||
| ({ type: 'unclassified' } & Unclassified)
|
||||
| { type: 'hostDropped' };
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* 深层尚未 typed 的字符串错误:不知道发生在哪一段,只有一条宿主原文。
|
||||
*/
|
||||
export type Unclassified = { detail: string };
|
||||
@@ -506,7 +506,7 @@ describe('DirectProject 聊天 reducer', () => {
|
||||
type: 'turn.completed',
|
||||
status: 'failed',
|
||||
failure: {
|
||||
type: 'turnFailedUnclassified',
|
||||
type: 'unclassified',
|
||||
detail: '模型服务暂不可用',
|
||||
},
|
||||
at: 1_000_900,
|
||||
@@ -521,7 +521,7 @@ describe('DirectProject 聊天 reducer', () => {
|
||||
type: 'turn.completed',
|
||||
status: 'failed',
|
||||
failure: {
|
||||
type: 'turnFailedUnclassified',
|
||||
type: 'unclassified',
|
||||
detail: '模型服务暂不可用',
|
||||
},
|
||||
at: 9_900_000,
|
||||
@@ -547,7 +547,7 @@ describe('DirectProject 聊天 reducer', () => {
|
||||
event({
|
||||
type: 'turn.completed',
|
||||
status: 'failed',
|
||||
failure: { type: 'turnFailedUnclassified', detail: '上一轮的失败' },
|
||||
failure: { type: 'unclassified', detail: '上一轮的失败' },
|
||||
at: 2_000_900,
|
||||
userItemId: 'direct-codex:turn-1:user',
|
||||
}),
|
||||
@@ -627,7 +627,7 @@ describe('DirectProject 聊天 reducer', () => {
|
||||
event({
|
||||
type: 'turn.completed',
|
||||
status: 'failed',
|
||||
failure: { type: 'turnFailedUnclassified', detail: '第一轮失败' },
|
||||
failure: { type: 'unclassified', detail: '第一轮失败' },
|
||||
at: 2_000,
|
||||
}),
|
||||
]);
|
||||
@@ -687,7 +687,7 @@ describe('DirectProject 聊天 reducer', () => {
|
||||
event({
|
||||
type: 'turn.completed',
|
||||
status: 'failed',
|
||||
failure: { type: 'turnFailedUnclassified', detail: '第一轮失败' },
|
||||
failure: { type: 'unclassified', detail: '第一轮失败' },
|
||||
at: 2_000,
|
||||
}),
|
||||
]);
|
||||
@@ -696,7 +696,7 @@ describe('DirectProject 聊天 reducer', () => {
|
||||
event({
|
||||
type: 'turn.completed',
|
||||
status: 'failed',
|
||||
failure: { type: 'turnFailedUnclassified', detail: '第二轮失败' },
|
||||
failure: { type: 'unclassified', detail: '第二轮失败' },
|
||||
at: 4_000,
|
||||
}),
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user