perf: agent loop#7055
Conversation
Coverage Report
File CoverageNo changed files found. |
There was a problem hiding this comment.
💡 Codex Review
When a streamed model emits visible text before a runtime tool call, answer_delta has already appended that text into assistantResponses; this unconditional llm_request_end path then inserts the same event.answerText again before the tool card. In tool-call turns with preamble text (e.g. “I’ll check that” + tool_calls), the saved chat history and refreshed UI will show duplicated assistant text, so this needs to skip insertion when the current streamed text already represents the same assistant turn.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| //==================== Beta features ==================== | ||
| AGENT_ENGINE: z.enum(['default', 'pi']).default('default').meta({ | ||
| description: 'Agent 引擎选择:default(unified agent loop)| pi(pi-agent-core 引擎)' | ||
| AGENT_ENGINE: z.enum(['fastAgent', 'piAgent']).default('fastAgent').meta({ |
There was a problem hiding this comment.
Preserve legacy AGENT_ENGINE values
Existing self-hosted deployments that already set AGENT_ENGINE=default or AGENT_ENGINE=pi will now fail environment validation during startup because the schema no longer accepts the previously documented values. Unless every upgrade path rewrites those env vars first, this turns a provider rename into a boot blocker; accept/map the old values during migration or fail later with an explicit compatibility message.
Useful? React with 👍 / 👎.
|
✅ Docs Preview Deployed! 🔗 👀 Click here to visit preview 🕒 Time: 2026-06-05 10:15:49 (UTC+8) |
There was a problem hiding this comment.
Pull request overview
This PR refactors the agent-loop stack to a provider-based architecture (defaulting to fastAgent), moves plan/ask/sandbox/read-file into “system tools” (with system_* naming), and updates ToolCall/Agent workflow adapters plus extensive tests/docs to match the new event and tool lifecycle.
Changes:
- Introduces agent-loop provider registry (
fastAgent/piAgent) with new typed contracts (input/runtime/result/event), and rewires callers torunAgentLoop(...). - Converts internal tools to system tools (
system_update_plan,system_ask,system_read_file,system_sandbox_*) and updates event mapping (tool_run_end,assistant_push, etc.). - Updates sandbox client handling (pass
SandboxClientdown; sandbox tool executor requires a provided client) and adds fallback nodeResponse builders for sandbox/read-file.
Reviewed changes
Copilot reviewed 109 out of 111 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/service/test/core/workflow/dispatch/ai/toolcall/index.test.ts | Adds ToolCall sandbox initialization + file injection test coverage. |
| packages/service/test/core/workflow/dispatch/ai/toolcall/hooks/useToolRunner.test.ts | Updates tool runner tests for sandbox client + sandbox tool info. |
| packages/service/test/core/workflow/dispatch/ai/toolcall/hooks/useToolCatalog.test.ts | Updates catalog tests for system read-file and sandbox prompt behavior. |
| packages/service/test/core/workflow/dispatch/ai/agent/utils.test.ts | Updates agent subapp tool collection expectations (system tools excluded). |
| packages/service/test/core/workflow/dispatch/ai/agent/piAgent/toolAdapter.test.ts | Removes pi-agent adapter tests (legacy path). |
| packages/service/test/core/workflow/dispatch/ai/agent/piAgent/adapter/runtime.test.ts | Removes pi-agent runtime tests (legacy path). |
| packages/service/test/core/workflow/dispatch/ai/agent/adapter/useToolNodeResponse.test.ts | Renames tool events to tool_run_end and system tool names. |
| packages/service/test/core/workflow/dispatch/ai/agent/adapter/toolCatalog.test.ts | Validates system ask/plan tool names + no mutation of completion tools. |
| packages/service/test/core/workflow/dispatch/ai/agent/adapter/memory.test.ts | Updates memory shape to store providerState. |
| packages/service/test/core/workflow/dispatch/ai/agent/adapter/eventMapper.test.ts | Updates event mapper expectations for new event types and system tool names. |
| packages/service/test/core/chat/saveChat.test.ts | Updates stop-gate payload expectations (removes assistant/reasoning drafts). |
| packages/service/test/core/ai/sandbox/toolCall/index.test.ts | Updates sandbox toolCall executor tests to require provided client. |
| packages/service/test/core/ai/sandbox/toolCall/getFileUrl.tool.test.ts | Updates file export tool test to read context from sandbox client. |
| packages/service/test/core/ai/sandbox/service/runtime.test.ts | Adds assertions for SandboxClient.getContext(). |
| packages/service/test/core/ai/llm/agentLoop/tools.test.ts | Updates tools helper tests for fastAgent provider and sandbox tools. |
| packages/service/test/core/ai/llm/agentLoop/systemSandboxTools.test.ts | Adds tests for system-prefixed sandbox tool name mapping. |
| packages/service/test/core/ai/llm/agentLoop/systemAskTool.test.ts | Updates system ask tool parsing + schema creation tests. |
| packages/service/test/core/ai/llm/agentLoop/stopGate.test.ts | Updates stop-gate copy to reference system_update_plan. |
| packages/service/test/core/ai/llm/agentLoop/providerRegistry.test.ts | Adds tests for provider registry defaulting + unknown provider errors. |
| packages/service/test/core/ai/llm/agentLoop/planState.test.ts | Adds tests for append/delete plan-step actions. |
| packages/service/test/core/ai/llm/agentLoop/planReviser.test.ts | Updates import path for plan reviser utilities. |
| packages/service/test/core/ai/llm/agentLoop/piAgentModelBridge.test.ts | Moves piAgent model bridge tests to new provider location + maxTokens cap. |
| packages/service/test/core/ai/llm/agentLoop/fastAgentProvider.test.ts | Adds provider-level tests for system tool injection and readFile interception. |
| packages/service/test/core/ai/llm/agentLoop/eventUsage.test.ts | Adds tests for usage normalization helper. |
| packages/service/test/core/ai/llm/agentLoop/baseLoop.test.ts | Updates loop tests for new callback names (onLLMRequestEnd, onToolRunEnd). |
| packages/service/env.ts | Renames AGENT_ENGINE values to fastAgent / piAgent. |
| packages/service/core/workflow/dispatch/ai/toolcall/type.ts | Adds optional sandboxClient to ToolCall dispatch props. |
| packages/service/core/workflow/dispatch/ai/toolcall/tools/file.ts | Refactors read-file tool display + adds getToolCallFileUrl. |
| packages/service/core/workflow/dispatch/ai/toolcall/toolCall.ts | Rewires ToolCall to provider-based runAgentLoop and system read-file tool. |
| packages/service/core/workflow/dispatch/ai/toolcall/index.ts | Initializes sandbox client + injects input files before ToolCall execution. |
| packages/service/core/workflow/dispatch/ai/toolcall/hooks/useToolRunner.ts | Updates sandbox execution to require provided client + system read-file params. |
| packages/service/core/workflow/dispatch/ai/toolcall/hooks/useToolNodeResponse.ts | Updates comments/terminology from onAfterToolCall to onToolRunEnd. |
| packages/service/core/workflow/dispatch/ai/toolcall/hooks/useToolEventEmitter.ts | Adds new event-to-stream/nodeResponse mapping layer for ToolCall. |
| packages/service/core/workflow/dispatch/ai/toolcall/hooks/useToolCatalog.ts | Stops injecting sandbox tools/read_files schema; maps system read-file tool info. |
| packages/service/core/workflow/dispatch/ai/toolcall/constants.ts | Removes legacy sandbox tool workflow response builder. |
| packages/service/core/workflow/dispatch/ai/nodeResponse/utils.ts | Adds shared helpers for nodeResponse formatting (points/tool input/response). |
| packages/service/core/workflow/dispatch/ai/nodeResponse/sandbox.ts | Adds fallback nodeResponse builder for sandbox system tools. |
| packages/service/core/workflow/dispatch/ai/nodeResponse/readFile.ts | Adds fallback nodeResponse builder for system read-file. |
| packages/service/core/workflow/dispatch/ai/nodeResponse/index.ts | Re-exports nodeResponse builders. |
| packages/service/core/workflow/dispatch/ai/agent/sub/utils.ts | New subapp tool collection + executeTool dispatcher excluding system tools. |
| packages/service/core/workflow/dispatch/ai/agent/sub/sandbox/index.ts | Removes legacy workflow-level sandbox subtool dispatcher. |
| packages/service/core/workflow/dispatch/ai/agent/sub/file/utils.ts | Removes legacy workflow-level read_files tool schema. |
| packages/service/core/workflow/dispatch/ai/agent/piAgent/index.ts | Removes legacy workflow piAgent dispatch entry. |
| packages/service/core/workflow/dispatch/ai/agent/adapter/useToolNodeResponse.ts | Extends adapter to handle more event types + sandbox/read-file nodeResponses. |
| packages/service/core/workflow/dispatch/ai/agent/adapter/userContext.ts | Updates prompts to reference system_read_file. |
| packages/service/core/workflow/dispatch/ai/agent/adapter/toolCatalog.ts | Switches workflow adapter internal tool schemas to system tool variants. |
| packages/service/core/workflow/dispatch/ai/agent/adapter/memory.ts | Stores generic providerState instead of pendingMainContext. |
| packages/service/core/workflow/dispatch/ai/agent/adapter/eventMapper.ts | Improves assistant delta accumulation + updates stop-gate mapping to assistant_push. |
| packages/service/core/ai/sandbox/toolCall/type.ts | Removes app/user/chat from tool execute context (use sandbox client context instead). |
| packages/service/core/ai/sandbox/toolCall/index.ts | Makes sandbox tool executor require a provided sandbox client. |
| packages/service/core/ai/sandbox/toolCall/getFileUrl.tool.ts | Reads export context from sandboxInstance.getContext() and guards missing context. |
| packages/service/core/ai/sandbox/service/runtime.ts | Adds SandboxClient.getContext(). |
| packages/service/core/ai/llm/toolCall/type.ts | Renames/extends lifecycle hooks to onToolRunStart / onToolRunEnd w/ rawResponse. |
| packages/service/core/ai/llm/agentLoop/type/tool.ts | Adds new agent-loop tool/system-tool contract types. |
| packages/service/core/ai/llm/agentLoop/type/runtime.ts | Adds provider-agnostic runtime contract for agent loop. |
| packages/service/core/ai/llm/agentLoop/type/result.ts | Adds provider-agnostic result contract (providerState, usage, etc.). |
| packages/service/core/ai/llm/agentLoop/type/provider.ts | Defines provider name union type. |
| packages/service/core/ai/llm/agentLoop/type/interactive.ts | Adds generic interactive params/types for agent loop. |
| packages/service/core/ai/llm/agentLoop/type/input.ts | Adds provider-agnostic input contract (messages/plan/providerState/etc.). |
| packages/service/core/ai/llm/agentLoop/type/index.ts | Re-exports new type modules. |
| packages/service/core/ai/llm/agentLoop/type/event.ts | Defines new unified agent-loop event set + usage normalization helper. |
| packages/service/core/ai/llm/agentLoop/systemTools/sandbox/index.ts | Adds system sandbox tool wrappers + name mapping helpers. |
| packages/service/core/ai/llm/agentLoop/systemTools/readFile/index.ts | Adds system read-file tool schema + zod params schema. |
| packages/service/core/ai/llm/agentLoop/systemTools/plan/updateTool.ts | Extends plan update tool schema with append/delete step actions. |
| packages/service/core/ai/llm/agentLoop/systemTools/plan/state.ts | Implements append/delete plan step operations and safeguards. |
| packages/service/core/ai/llm/agentLoop/systemTools/plan/reviser.ts | Adds plan reviser merge logic preserving completed evidence and resetting new steps. |
| packages/service/core/ai/llm/agentLoop/systemTools/plan/requirePlan.ts | Updates explicit-plan detection for system-prefixed update_plan names. |
| packages/service/core/ai/llm/agentLoop/systemTools/plan/index.ts | Adds system update-plan tool factory and re-exports. |
| packages/service/core/ai/llm/agentLoop/systemTools/index.ts | Aggregates system tools exports. |
| packages/service/core/ai/llm/agentLoop/systemTools/ask/tool.ts | Renames ask payload schema/type and relaxes option minItems. |
| packages/service/core/ai/llm/agentLoop/systemTools/ask/parser.ts | Moves/renames parser to system tools module and updates imports. |
| packages/service/core/ai/llm/agentLoop/systemTools/ask/index.ts | Adds system ask tool factory and re-exports. |
| packages/service/core/ai/llm/agentLoop/run.ts | Adds provider-dispatching runAgentLoop top-level entry. |
| packages/service/core/ai/llm/agentLoop/providers/type.ts | Defines provider interface contract. |
| packages/service/core/ai/llm/agentLoop/providers/registry.ts | Adds provider registry + default provider resolution. |
| packages/service/core/ai/llm/agentLoop/providers/piAgent/modelBridge.ts | Updates imports and maxTokens computation for piAgent provider. |
| packages/service/core/ai/llm/agentLoop/providers/index.ts | Exports provider registry/types/providers. |
| packages/service/core/ai/llm/agentLoop/providers/fastAgent/tools/index.ts | Updates tool catalog normalization and tool assembly for fastAgent system tools. |
| packages/service/core/ai/llm/agentLoop/providers/fastAgent/stop/index.ts | Updates stop-gate feedback text to system_update_plan. |
| packages/service/core/ai/llm/agentLoop/providers/fastAgent/prompt/mainPrompt.ts | Updates prompt rules to use system tool names. |
| packages/service/core/ai/llm/agentLoop/providers/fastAgent/loop/type.ts | Adds internal fastAgent loop runtime types (provider adapter layer). |
| packages/service/core/ai/llm/agentLoop/providers/fastAgent/loop/message.ts | Adds helper to filter empty assistant messages. |
| packages/service/core/ai/llm/agentLoop/providers/fastAgent/loop/base.ts | Updates tool lifecycle hooks and usage callbacks wiring. |
| packages/service/core/ai/llm/agentLoop/providers/fastAgent/index.ts | Implements provider adapter that injects system tools based on runtime.systemTools flags. |
| packages/service/core/ai/llm/agentLoop/loop/type.ts | Removes legacy unified loop type definitions. |
| packages/service/core/ai/llm/agentLoop/index.ts | Re-exports new types and run entry (removes legacy exports). |
| packages/service/core/ai/llm/agentLoop/constants.ts | Removes piMaster display entry; adds readFile display config. |
| packages/global/test/core/chat/adapt.test.ts | Updates stop-gate related message conversion expectations. |
| packages/global/core/chat/adapt.ts | Removes stop-gate draft assistant/reasoning injection behavior. |
| packages/global/core/ai/agent/type.ts | Simplifies stop-gate schema to keep only hidden feedback. |
| document/content/self-host/config/env.mdx | Updates AGENT_ENGINE docs to fastAgent/piAgent. |
| document/content/self-host/config/env.en.mdx | Updates AGENT_ENGINE docs to fastAgent/piAgent. |
| .agents/design/core/ai/compress/history-context-checkpoint-compression.md | Updates design doc references after path moves. |
| .agents/design/core/ai/agentCall-declarative-tools.md | Updates design doc lifecycle hook naming. |
| .agents/design/core/ai/agent-loop/technical-design.md | Removes legacy technical design doc. |
| .agents/design/core/ai/agent-loop/requirements.md | Removes legacy requirements doc. |
Comments suppressed due to low confidence (3)
packages/service/core/ai/llm/agentLoop/systemTools/ask/tool.ts:9
parseAgentAskToolCallusesAgentAskPayloadSchema, butoptionsis currently required in the schema and in the exported tool JSON schema (required: ['reason','blockerType','question','options']). This contradicts the updated tests expectingoptionsto be optional ("parses ... without suggested options") and will make that test fail at runtime.
packages/service/core/ai/llm/agentLoop/providers/fastAgent/prompt/mainPrompt.ts:68- The
system_askprompt rules still say the model "must provide" 3–5options, but the updated tests and schema intent suggestoptionsare optional (free-form input is supported). Leaving this as-is increases the likelihood the model will overfit to producing options and conflicts with the tool contract.
packages/service/core/ai/llm/agentLoop/systemTools/ask/tool.ts:49 createAskAgentToolstill marksoptionsas required (required: ['reason','blockerType','question','options']). Ifoptionsare intended to be optional (as implied by the updated tests and the prompt wording about free-form input), the JSON schema should also not requireoptions, otherwise the model/tooling will keep treating it as mandatory.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return { | ||
| requestIds, | ||
| error, | ||
| error: typeof error === 'string' ? error : undefined, | ||
| toolDispatchFlowResponses: toolRunResponses, |
| // 初始化沙盒 | ||
| const sandboxClient = await (async () => { | ||
| if (useSandbox) { | ||
| const sandboxClient = await getSandboxClient({ | ||
| appId: props.runningAppInfo.id, | ||
| userId: props.uid, | ||
| chatId: props.chatId | ||
| }); | ||
| if (currentInputFiles.length > 0) { | ||
| await injectSandboxFiles({ | ||
| appId: props.runningAppInfo.id, | ||
| userId: props.uid, | ||
| chatId: props.chatId, | ||
| files: currentInputFiles.map((file) => ({ | ||
| path: file.sandboxPath!, | ||
| url: file.url | ||
| })) | ||
| }); | ||
| } |
| if (event.type === 'tool_run_end') { | ||
| streamToolResponse({ | ||
| toolCallId: event.call.id, | ||
| response: event.response | ||
| }); |
|
✅ Admin Preview Image Ready! 🕒 Time: 2026-06-05 10:20:18 (UTC+8) |
|
✅ Build Successful - Preview fastgpt Image for this PR: 🕒 Time: 2026-06-05 10:20:50 (UTC+8) |
No description provided.