已合并
feat(core): concurrent tool batch, verified finish, plan on control path #193
RomanAndr创建于 6月14日
feat(core): concurrent tool batch, verified finish, plan on control path #193
已合并
Pull Request已成功合入, 合并人@openeuler-ci-bot
(感谢 RomanAndr 的贡献)6月14日 将lyhu,huzhengce,liumiao27,fromhsc,gogoxiaoxiao,wqianli,leon-wang2021,kaitiandu设为审查人
6月14日 将lyhu,huzhengce,liumiao27,fromhsc,gogoxiaoxiao,wqianli,leon-wang2021,kaitiandu设为审查人
6月14日 添加了label:sig/sig-intelligence
openeuler-ci-bot
6月14日 评论:
6月14日 评论:
Welcome To openEuler Community
Hey @Roman-Andr , thanks for your contribution to the community.
Bot Usage Manual
I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands.
Contact Guide
If you have any questions, please contact the SIG: sig-intelligence ,
and any of the maintainers: @fromhsc, @gogoxiaoxiao, @huzhengce, @kaitiandu, @leon-wang2021, @liumiao27, @lyhu, @wqianli ,
and any of the committers: @extinctfire, @hypothesiser, @xiangyou_xie .


6月14日 添加了label:openeuler-cla/yes
此处折叠了42条消息 查看更多
openeuler-ci-bot
6月15日 评论:
6月15日 评论:
6月15日 添加了label:approved
openeuler-ci-bot
6月15日 评论:
6月15日 评论:
6月15日 合入了pull request,合并节点 SHA:39a6a24791d6a57f919b0b72900ad6ffe6cf494f
6月15日 修改了pull request 的描述
Was This PR authored or co-authored using generative AI tooling?
[ ] - No
[x] - Yes
__1. AI Agent : Claude Code
__2. AI Model : Claude Opus 4.8 xhigh
What this PR does / why we need it
The agent loop has four structural weaknesses that no prompt change can fix.
tool_execruns every tool call in a turn sequentially, so a turn that emits several independent reads/greps awaits them back-to-back and wastes turn budget on calls with no ordering dependency.decideaccepts the model's first stop as terminal, so a run ends the instant the model claims it is done — a confidently-wrong, unverified answer finishes the run.todo_writeplan state is write-only: the loop never reads back open items, so the model can stop with its own plan half-done. And stale tool-result bodies accumulate in the message history forever, paying input tokens for output already consumed. These are properties of the control path, not the prompt.This PR reworks the loop core.
tool_execnow builds all calls, then executes the valid ones throughfutures_util::future::join_alland stitches the outcomes back into call order — only the awaits overlap; history, suspend, and stop-after-result semantics are byte-for-byte the prior order. A suspendingjoin_subagentis sorted last in the batch, and a batch that writes and reads the samefile_pathfalls back to sequential execution, so concurrency never strands a committed mutation across a suspend or races two writers on one file.decideno longer completes on the first stop: it first consults open plan items (tool::open_todo_lines, re-injected each turn) and then runs a one-shot completion checklist that re-anchors on the original task — only a second stop completes, and the checklist is gated to runs that expose tools so a conversational turn is never nudged.LoopRunResult::Suspendednow carries aVec<SuspendedToolCall>so a turn with severaljoin_subagentcalls suspends and resolves all of them;session_supervisor.rsresolves each in turn anddrop_unanswered_tool_usesdefensively clears any tool_use stranded by an earlier stop short-circuit.is_transientnow classifiesStreamError/IoErroras recoverable;repair_tool_namesnormalizes malformed tool names before rejection; the final turn withholds tools so the model commits an answer rather than a cut-off tool call;prune_stale_tool_outputcollapses tool-result bodies beyond a recent window to a marker; and a repeated identical failing or successful tool call injects a one-shot strategy-change nudge. The stop verdict, the resume contract, and per-call tool execution semantics are otherwise unchanged.Defensive properties:
join_subagentis ordered last so every side-effecting sibling has its tool_result recorded before the first suspend; all suspends are collected and each is resolved on resume, anddrop_unanswered_tool_usesguarantees the resumed history carries no dangling tool_use.plan_nudged/completion_nudged/streak counters fire each at most once per condition and force a single extra turn, so verification and plan reminders cannot loop; both gate onturn_number < max_turnsand the completion checklist gates on tools being visible.KEEP_RECENT_TOOL_BYTESand aboveMIN_PRUNABLE_BYTEScollapse to a marker; recent output and small results are untouched, and the marker itself is skipped on re-entry.No new unit tests are added; one existing loop test updates its expected
turn_count(2 → 3) to account for the one verification turn the completion nudge now inserts when tools are visible.This PR adds
futures-utilas a direct dependency ofcrates/core(futures-util.workspace = true) to drive the concurrent tool batch;Cargo.lockis committed alongside.Which issue this PR fixes
Closes #31
Special notes for your reviewer:
xiaoo-core,tool, andxiaoo-app. Core:agent_loop.rs(loop-core slice — concurrency, verified finish, plan-on-control-path, error classification, tool withholding, pruning),loop_state.rs(live-only nudge/streak fields),suspend.rs(Suspendednow holds aVec),Cargo.toml(futures-util). App:session_supervisor.rs(resolves several suspends per turn +drop_unanswered_tool_uses). Tool:todo_write/{executor.rs,mod.rs},impl/{mod.rs,builtin/mod.rs},lib.rs(theopen_todo_linesreader plumbed out for the loop).LoopRunResultshape change isSuspended(SuspendedToolCall)→Suspended(Vec<SuspendedToolCall>), and its sole consumer (session_supervisor.rs) is updated in this PR. NewLoopStatefields are live-only and reset on resume, so the snapshot schema is untouched. The cached-tokens accounting from the original bundle lives in a sibling PR and is not part of this slice.feat(core): concurrent tool batch, verified finish, plan on control path— the loop-core slice in full (single commit on this branch).chore/test-fixture-drift: this branch is stacked on the test-repair PR that makes dev's suite compile and pass; merge that PR first. Until it lands, this PR's diff also lists those 4 test files.cargo test --workspaceon this branch (chore base + this feature) — green (560 passed, 0 failed).