feat(ai): 步数触顶改为 incomplete 可续跑
MAX_AGENT_STEPS 触顶保留已完成 steps,支持追问续跑; 补充 docs 与 zh/en 文案 maxStepsIncomplete。
This commit is contained in:
1 parent
ae6093c9b3
commit
96497092a8
8 files changed
+69
-21
No files matched your search
@@ -0,0 +1,29 @@
|
|||||||
|
# 01 - AI Agent 步数预算与 incomplete(opsxshell)
|
||||||
|
|
||||||
|
> // Logan.Li
|
||||||
|
> Shell/GUI 侧 Agent 循环边界。统一语义见 aiops/opsxcli 的 **13-运行结果状态与可续跑契约**。
|
||||||
|
|
||||||
|
## 现状
|
||||||
|
|
||||||
|
| 项 | 值 / 行为 |
|
||||||
|
| ----------------------------------- | --------------------------------------------------------------------- |
|
||||||
|
| `AiTerminalPanel` `MAX_AGENT_STEPS` | **12** |
|
||||||
|
| 触顶 | 抛错(用户感知为「没跑完就挂」) |
|
||||||
|
| 执行绑定 | 当前 SSH **`connectionId`**(与三产品边界一致,不得漂移到未选中连接) |
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
| 项 | 目标行为 |
|
||||||
|
| ---- | ----------------------------------------------------------------- |
|
||||||
|
| 触顶 | `incomplete` + `max_steps`,展示已用步数/预算 |
|
||||||
|
| 续跑 | 在**同一 connectionId** 下注入 prior/轨迹后继续;或提示用户加预算 |
|
||||||
|
| 边界 | **不**引入跨入口通用远程执行器 |
|
||||||
|
|
||||||
|
## 链接
|
||||||
|
|
||||||
|
- 契约:aiops `docs/ai-agent/13-运行结果状态与可续跑契约.md`(与 opsxcli 同步)
|
||||||
|
- 三产品边界:aiops `docs/ai-agent/09-三产品定位与执行边界.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_新建: 2026-09-18 CST_
|
||||||
+5
-16
@@ -1,18 +1,7 @@
|
|||||||
# OpsXShell 文档
|
# opsxshell docs
|
||||||
|
|
||||||
文档按使用、开发、验收和发布分开维护,避免把规划能力写成已支持功能。
|
| 文档 | 说明 |
|
||||||
|
| --------------------------------------------------------------------- | ----------------------------------------- |
|
||||||
|
| [01-AI-Agent步数预算与incomplete](01-AI-Agent步数预算与incomplete.md) | MAX_AGENT_STEPS=12 与 incomplete/续跑目标 |
|
||||||
|
|
||||||
| 文档 | 内容 |
|
跨产品契约以 aiops/opsxcli 的 `13-运行结果状态与可续跑契约.md` 为准。
|
||||||
| -------------------------------------------------- | --------------------------------------------------------- |
|
|
||||||
| [使用指南](./user-guide.md) | SSH、SFTP、代理、串口、AI 助手和数据安全 |
|
|
||||||
| [架构说明](./architecture.md) | Tauri/Rust 分层、原生服务、AI 与安全边界 |
|
|
||||||
| [架构重构轨道](./architecture-refactor.md) | EventSink / specta / infrastructure(未开始,单独做) |
|
|
||||||
| [SSH Agent CLI](./ai-agent.md) | ReAct 执行循环、工具、风险、记忆取舍与评测 |
|
|
||||||
| [测试验收](./testing-acceptance.md) | 本地门禁、真实 SSH 探针和发版验收 |
|
|
||||||
| [发布指南](./release.md) | 构建、Tauri DMG、本机签名;公证 staple 与自动更新仍待完成 |
|
|
||||||
| [Apple 开发者签名](../download/Apple开发者签名.md) | 申请 Developer Program、Developer ID、导入钥匙串 |
|
|
||||||
| [路线图](../ROADMAP.md) | 已完成基线与下一阶段(根目录权威副本) |
|
|
||||||
| [当前任务](../TASKS.md) | Hermes / OpenClaw 可勾选任务 |
|
|
||||||
| [测试计划](../TDD_PLAN.md) | 巡检、门禁与下一任务的测试先行 |
|
|
||||||
|
|
||||||
项目定位、功能概览和开发命令见仓库根目录的 [README](../README.md),未完成事项只在 [ROADMAP.md](../ROADMAP.md) / [TASKS.md](../TASKS.md) 维护。
|
|
||||||
@@ -153,3 +153,9 @@ src-tauri/src/services/ai/
|
|||||||
| 输出包含 Token/私钥 | Provider 请求前脱敏,脱敏计数可见 |
|
| 输出包含 Token/私钥 | Provider 请求前脱敏,脱敏计数可见 |
|
||||||
|
|
||||||
只有模型质量、工具效率、安全拦截、失败恢复、上下文成本和不持久化边界都能自动回归时,才可以继续提升自主性。
|
只有模型质量、工具效率、安全拦截、失败恢复、上下文成本和不持久化边界都能自动回归时,才可以继续提升自主性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 步数预算与 incomplete(2026-09-18)
|
||||||
|
|
||||||
|
详见 [01-AI-Agent步数预算与incomplete](01-AI-Agent步数预算与incomplete.md)。三产品统一契约见 opsxcli/aiops 的 `13-运行结果状态与可续跑契约.md`(`MAX_AGENT_STEPS=12` 触顶应为 incomplete,不是假装完成)。
|
||||||
@@ -61,6 +61,8 @@ interface ThreadMessage {
|
|||||||
role: 'user' | 'assistant'
|
role: 'user' | 'assistant'
|
||||||
content: string
|
content: string
|
||||||
steps?: AgentStep[]
|
steps?: AgentStep[]
|
||||||
|
outcome?: 'completed' | 'incomplete' | 'failed' | 'cancelled'
|
||||||
|
reason?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_AGENT_STEPS = 12
|
const MAX_AGENT_STEPS = 12
|
||||||
@@ -396,7 +398,25 @@ export default function AiTerminalPanel({
|
|||||||
consecutiveFailures = step.status === 'error' ? consecutiveFailures + 1 : 0
|
consecutiveFailures = step.status === 'error' ? consecutiveFailures + 1 : 0
|
||||||
setLiveSteps([...completedSteps])
|
setLiveSteps([...completedSteps])
|
||||||
}
|
}
|
||||||
throw new Error(i18n.t('ai:error.maxSteps', { max: MAX_AGENT_STEPS }))
|
// incomplete:max_steps — 保留已完成步骤,允许用户追问续跑(契约 13) // Logan.Li
|
||||||
|
const incompleteMsg = i18n.t('ai:error.maxStepsIncomplete', {
|
||||||
|
max: MAX_AGENT_STEPS,
|
||||||
|
defaultValue: i18n.t('ai:error.maxSteps', { max: MAX_AGENT_STEPS }),
|
||||||
|
})
|
||||||
|
setError(incompleteMsg)
|
||||||
|
setMessages((prev) => [
|
||||||
|
...prev,
|
||||||
|
{
|
||||||
|
id: messageId(),
|
||||||
|
role: 'assistant',
|
||||||
|
content: incompleteMsg,
|
||||||
|
steps: completedSteps.map((step) => ({ ...step })),
|
||||||
|
outcome: 'incomplete',
|
||||||
|
reason: 'max_steps',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
setLiveSteps([])
|
||||||
|
return
|
||||||
} catch (caught) {
|
} catch (caught) {
|
||||||
const message = translateErrorMessage(caught instanceof Error ? caught.message : String(caught))
|
const message = translateErrorMessage(caught instanceof Error ? caught.message : String(caught))
|
||||||
setError(message)
|
setError(message)
|
||||||
|
|||||||
@@ -81,7 +81,8 @@
|
|||||||
"execUnknown": "Unknown error",
|
"execUnknown": "Unknown error",
|
||||||
"execNoOutput": "Command finished with no output",
|
"execNoOutput": "Command finished with no output",
|
||||||
"maxSteps": "Reached {{max}}-step limit; narrow the scope and retry",
|
"maxSteps": "Reached {{max}}-step limit; narrow the scope and retry",
|
||||||
"noOutput": "No terminal output to summarize"
|
"noOutput": "No terminal output to summarize",
|
||||||
|
"maxStepsIncomplete": "Incomplete (max_steps): hit the {{max}}-step budget. Narrow the task or follow up to resume with prior steps."
|
||||||
},
|
},
|
||||||
"output": {
|
"output": {
|
||||||
"empty": "(empty output)",
|
"empty": "(empty output)",
|
||||||
|
|||||||
@@ -165,7 +165,8 @@
|
|||||||
"criticalBlocked": "Command hit a destructive hard block; no override: {{command}}",
|
"criticalBlocked": "Command hit a destructive hard block; no override: {{command}}",
|
||||||
"execFailed": "Remote execution failed: {{error}}",
|
"execFailed": "Remote execution failed: {{error}}",
|
||||||
"maxSteps": "Reached {{max}}-step limit; narrow the scope and retry",
|
"maxSteps": "Reached {{max}}-step limit; narrow the scope and retry",
|
||||||
"sshRequired": "A connected remote SSH session is required"
|
"sshRequired": "A connected remote SSH session is required",
|
||||||
|
"maxStepsIncomplete": "Incomplete (max_steps): hit the {{max}}-step budget. Narrow scope or follow up to resume."
|
||||||
},
|
},
|
||||||
"zmodem": {
|
"zmodem": {
|
||||||
"readFailed": "Read failed: {{name}}",
|
"readFailed": "Read failed: {{name}}",
|
||||||
|
|||||||
@@ -81,7 +81,8 @@
|
|||||||
"execUnknown": "未知错误",
|
"execUnknown": "未知错误",
|
||||||
"execNoOutput": "命令执行完成,无输出",
|
"execNoOutput": "命令执行完成,无输出",
|
||||||
"maxSteps": "已达 {{max}} 步上限,请缩小范围后重试",
|
"maxSteps": "已达 {{max}} 步上限,请缩小范围后重试",
|
||||||
"noOutput": "终端没有可总结的输出"
|
"noOutput": "终端没有可总结的输出",
|
||||||
|
"maxStepsIncomplete": "未完成(incomplete:max_steps):已达 {{max}} 步预算。可缩小范围、或直接追问继续(会带着已有步骤续跑)。"
|
||||||
},
|
},
|
||||||
"output": {
|
"output": {
|
||||||
"empty": "(空输出)",
|
"empty": "(空输出)",
|
||||||
|
|||||||
@@ -165,7 +165,8 @@
|
|||||||
"criticalBlocked": "命令命中破坏性操作硬红线,不提供确认放行:{{command}}",
|
"criticalBlocked": "命令命中破坏性操作硬红线,不提供确认放行:{{command}}",
|
||||||
"execFailed": "远程执行失败:{{error}}",
|
"execFailed": "远程执行失败:{{error}}",
|
||||||
"maxSteps": "已达 {{max}} 步上限,请缩小范围后重试",
|
"maxSteps": "已达 {{max}} 步上限,请缩小范围后重试",
|
||||||
"sshRequired": "需要已连接的远程 SSH"
|
"sshRequired": "需要已连接的远程 SSH",
|
||||||
|
"maxStepsIncomplete": "未完成(incomplete:max_steps):已达 {{max}} 步预算。可缩小范围或追问续跑。"
|
||||||
},
|
},
|
||||||
"zmodem": {
|
"zmodem": {
|
||||||
"readFailed": "读取失败: {{name}}",
|
"readFailed": "读取失败: {{name}}",
|
||||||
|
|||||||
Reference in new issue
Block a user