Skip to content

feat(exetesion-agent): improve computer backends and task wakeups#916

Merged
dingyi222666 merged 5 commits into
v1-devfrom
feat/agent-new-feature
Jun 14, 2026
Merged

feat(exetesion-agent): improve computer backends and task wakeups#916
dingyi222666 merged 5 commits into
v1-devfrom
feat/agent-new-feature

Conversation

@dingyi222666

@dingyi222666 dingyi222666 commented Jun 12, 2026

Copy link
Copy Markdown
Member

This pr improves the agent computer backend workflow and adds controls for background sub-agent tasks.

New Features

  • Add automatic wakeup for completed background agent tasks in ChatLuna conversations.
  • Add pause/resume/stop/list/chat commands for sub-agent tasks under chatluna.agent.*.
  • Add attach mode so users can chat directly with a running sub-agent task from the parent conversation.
  • Add virtual session restoration so task results can resume the parent chat when the bot is online.
  • Add computer backend temp directory support for local, E2B, and open-terminal sessions.
  • Add a web UI endpoint for resolving the current computer home path.

Bug Fixes

  • Abort background sub-agent tasks when parent conversations stop or clear history.
  • Await task control refreshes after stop, pause, resume, and parent-conversation aborts.
  • Forward completed nested sub-agent task wakeups to the nearest active parent task before waking the conversation.
  • Add core task runtime support for task lookup, stop, pause, resume, parent-conversation aborts, and live chat forwarding.
  • Add an agent pause gate so paused background runs stop progressing until resumed.
  • Only emit chatluna/chat-stopped after a stop request actually succeeds.
  • Keep attach-mode commands from being forwarded before command parsing completes.
  • Surface attach-mode task forwarding failures with logs and a user-visible retry message.
  • Fix the attach-mode exit hint to use chatluna.agent.exit.
  • Keep background task result guidance from encouraging polling.
  • Reuse the core task session implementation from extension-agent instead of duplicated session formatting helpers.
  • Use OS temp directories for local computer execution instead of workspace-scoped temp paths.

Other Changes

  • Simplify local backend permission configuration by removing writableRoots.
  • Update computer backend UI copy and configuration guides.
  • Lower chatluna.agent command authority to allow user-level task controls.

Validation

  • yarn lint-fix (0 errors, existing max-len warnings in packages/extension-agent/src/sub-agent/builtin.ts only)
  • yarn fast-build core && yarn fast-build extension-agent

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c07a79bf-0be4-4c19-b555-a5b80c2f7b28

📥 Commits

Reviewing files that changed from the base of the PR and between be7f07e and b00753f.

📒 Files selected for processing (3)
  • packages/core/src/llm-core/agent/sub-agent.ts
  • packages/extension-agent/src/commands/task.ts
  • packages/extension-agent/src/service/sub_agent.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/extension-agent/src/commands/task.ts
  • packages/extension-agent/src/service/sub_agent.ts
  • packages/core/src/llm-core/agent/sub-agent.ts

Walkthrough

此 PR 实现了两个主要功能流:(1) 后台代理任务完成时自动唤醒父会话的完整管线,通过快照保存、事件派发、虚拟会话恢复与运行时暂停门控联动实现;(2) 计算机后端重构,移除基于 writableRoots 的作用域约束,改用系统临时目录,同时重写沙箱包装策略与文件存取权限模式,并新增 home 目录查询事件与相应的前端导航更新。

Changes

Agent Task Auto-Wakeup Pipeline

Layer / File(s) Summary
Configuration & Runtime Integration
packages/core/src/config.ts, packages/core/src/index.ts, packages/core/src/llm-core/agent/agent.ts, packages/core/src/llm-core/agent/types.ts, packages/core/src/llm-core/agent/legacy-executor.ts
Config 新增 agentTaskAutoWakeup: boolean(默认 true);插件初始化在 auto-purge 之后注册 applyAgentTaskWakeupAgentGenerateOptionsAgentRuntimeConfigurable 新增 pauseGate 异步门控,生成和执行路径透传与等待。
Task Completion & Snapshot Handling
packages/core/src/llm-core/agent/sub-agent.ts
后台任务工具新增 snapshots 映射保存会话快照;runAgentTask 在后台模式下构建并存储 AgentTaskSessionSnapshot;任务成功/失败收尾时调用 notifyFinished,触发队列唤醒或 runtime 回调;新增/导出 AgentTaskSessionSnapshotAgentTaskFinishedPayload 与扩展的 AgentTaskToolRuntime 方法。
Event Flow & Wakeup Dispatch
packages/core/src/services/types.ts, packages/core/src/middlewares/chat/stop_chat.ts, packages/core/src/llm-core/agent/wakeup.ts, packages/core/src/utils/virtual_session.ts
新增 chatluna/chat-stopped 事件类型;停止会话时派发该事件;新增 applyAgentTaskWakeup 监听 chatluna/agent-task-finished 并通过 restoreSession 恢复父会话(在线用快照、离线用虚拟会话),最终下发带 triggerWakeup 的 chat 指令;新增虚拟会话工具支持事件构建。
Message Naming & Extension Services
packages/core/src/middlewares/conversation/request_conversation.ts, packages/extension-agent/src/service/sub_agent.ts
唤醒来源为 agent-task 时,inputMessage.name 显式设为 'task';子代理服务新增对外任务管理方法(获取/停止/暂停/恢复)与历史聚合;新增 onRunFinished 回调在任务完成后派发事件并刷新控制台。
Task Attach Service & CLI Commands
packages/extension-agent/src/sub-agent/task_attach.ts, packages/extension-agent/src/commands/task.ts, packages/extension-agent/src/index.ts, packages/extension-agent/src/commands/agent.ts
新增 ChatLunaAgentTaskAttachService 维护会话级任务绑定缓存,中间件阶段自动转发消息到附加任务;注册 chatluna.agent.list/stop/pause/resume/chat/exit 管理命令,支持 --all 批量操作与会话级筛选;调整 agent 指令权限门槛。
Type & Session Cleanup
packages/extension-agent/src/trigger/session.ts, packages/extension-agent/src/sub-agent/session.ts
buildVirtualSession 从工具模块重导出;BaseMessage 改为类型导入。

Computer Backend Refactoring

Layer / File(s) Summary
API Contracts & Defaults
packages/extension-agent/src/computer/types.ts, packages/extension-agent/src/types/computer.ts, packages/extension-agent/src/config/defaults.ts, packages/extension-agent/src/types.ts
ComputerSessionApi 新增 getTempDir(): Promise<string> 方法;LocalBackendConfig 移除 writableRoots,新增 readOnlyRoots/denyRoots 等配置字段;默认配置同步更新;新增 chatluna-agent/getComputerHome 控制台事件签名。
Backend getTempDir & Execution Flow
packages/extension-agent/src/computer/backends/e2b.ts, packages/extension-agent/src/computer/backends/local/index.ts, packages/extension-agent/src/computer/backends/open_terminal.ts
E2B/OpenTerminal/Local 后端新增 getTempDir() 实现(通过 session 执行或系统调用解析 TMPDIR→TMP→TEMP→/tmp);本地执行改用 os.tmpdir() 作为临时目录,connect()/execute()/prepareBackgroundCommand()/createTerminal() 均同步调整。
Security & Scope Removal
packages/extension-agent/src/computer/backends/local/security.ts
删除 ensureWorkdirInScopeensureCommandPathsInScope 作用域校验函数;保留命令权限与高危确认逻辑。
Sandbox & FileStore Updates
packages/extension-agent/src/computer/backends/local/sandbox.ts, packages/extension-agent/src/computer/backends/local/store.ts
wrapCommandWithSandbox 在 Windows 或 dangerouslySkipPermissions 时跳过 bubblewrap;重写 bubblewrap 参数(始终 --ro-bind / /,按 sandboxMode 决定 /tmp 挂载,显式处理 readOnlyRoots/denyRoots);FileStore 移除 assertInScope 调用,isInScope 在未配置 scopePath 时返回 true。
Service Output & Home Query
packages/extension-agent/src/service/computer.ts, packages/extension-agent/src/service/index.ts, packages/extension-agent/src/webui/index.ts
新增 getHomeForUi() 供 UI 获取会话主目录;truncateTextOutput() 在有 session 时使用 session.getTempDir() 写入完整输出;无 session 时默认使用 os.tmpdir()/chatluna/truncation;新增 chatluna-agent/getComputerHome 控制台事件处理器。
Files Panel Dynamic Root
packages/extension-agent/client/components/computer/files-panel.vue
rootPath 改为可写 ref;改为通过 chatluna-agent/getComputerHome 事件异步获取根目录;更新 canGoUp 判断与 goUp 导航逻辑。
UI Text & Guides
packages/extension-agent/client/components/computer/computer-page.vue, packages/extension-agent/client/components/computer/config-backends/*.vue, packages/extension-agent/client/components/computer/configuration-panel.vue, packages/extension-agent/client/components/computer/status-panel.vue
更新电脑页面、E2B/OpenTerminal/Local 后端配置面板标题/说明文案;重写配置指南内容(含 Docker/裸机示例调整);更新状态与文件面板占位/空状态提示;移除 UI 上 writableRoots 控件与相关说明。
Repository
.gitignore
新增 .chatluna 忽略项;调整 .yarn/install-state.gz 忽略条目位置。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Possibly related PRs

  • ChatLunaLab/chatluna#801: 修改 packages/extension-agent/src/computer/backends/local/sandbox.ts 的 bubblewrap 参数拼装逻辑,与本 PR 的沙箱重写存在代码层面重叠。
  • ChatLunaLab/chatluna#874: 修改 packages/core/src/llm-core/agent/legacy-executor.tsrunAgent 循环,与本 PR 的 pauseGate 门控接入涉及同一执行路径。
  • ChatLunaLab/chatluna#886: 修改 packages/core/src/middlewares/chat/stop_chat.ts 的会话停止流程,与本 PR 的 chat-stopped 事件派发处于相同中间件代码路径。

🐰 我在后台任务完成时醒来,
快照与虚拟会话为你铺路,
不再被可写根束缚,
系统临时目录共宿,
暂停和恢复间,新流转开怀。

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning 标题中出现拼写错误 'exetesion' 应为 'extension',且标题内容与具体改动不够精确。 建议修改标题为 'feat(extension-agent): improve computer backends and background task controls' 或类似更准确的表述。
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed 描述内容详细且与变更集内容高度相关,涵盖新特性、问题修复、其他改动和验证说明。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/agent-new-feature

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an automatic wakeup feature for background agent tasks upon completion, refactors virtual session creation into a shared utility, and refines the computer agent's local, E2B, and open-terminal backend configurations and UI. Feedback on these changes highlights a critical bug where ctx.bots is incorrectly accessed as a dictionary instead of an array, and a UI issue where the files panel watcher needs to be immediate to load the home directory initially. Additionally, defensive checks for chatChain and improved isolation for temporary directories in the local backend are recommended to enhance stability and security.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/core/src/llm-core/agent/wakeup.ts
Comment thread packages/extension-agent/client/components/computer/files-panel.vue
Comment thread packages/core/src/llm-core/agent/wakeup.ts
Comment thread packages/extension-agent/src/computer/backends/local/index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/extension-agent/src/computer/backends/local/index.ts (1)

217-229: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

createTerminal() 现在能直接在受限目录里启动交互 shell。

这里的 cwd 不再经过任何本地路径权限校验,而且这个 PTY 也没有经过 wrapCommandWithSandbox()。调用方只要把 options.cwd 指到 denyRoots 或只读目录,终端就会以该目录启动并直接拿到交互式文件系统访问,这条路径会绕过 denyRoots / readOnlyRoots

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/extension-agent/src/computer/backends/local/index.ts` around lines
217 - 229, createTerminal currently accepts an arbitrary options.cwd and
launches an interactive shell via resolveInteractiveShellCommand +
createLocalTerminal without performing path permission checks or wrapping the
PTY in the sandbox, allowing callers to bypass denyRoots/readOnlyRoots; fix by
validating and normalizing the requested cwd against the existing
denyRoots/readOnlyRoots policy (use the same logic used elsewhere in this
module) and then start the terminal using the sandbox wrapper
(wrapCommandWithSandbox) or an equivalent sandboxed command path before calling
createLocalTerminal; update createTerminal to
resolveInteractiveShellCommand(this._cfg), enforce permission checks on
options.cwd (fall back to this._cwd when denied), and pass the sandboxed
command/env into createLocalTerminal so interactive shells cannot escape
read-only/denied roots.
🧹 Nitpick comments (1)
packages/extension-agent/client/components/computer/files-panel.vue (1)

573-594: ⚡ Quick win

考虑为异步控制台事件调用添加错误处理。

watch 块中的 send('chatluna-agent/getComputerHome', ...) 调用没有错误处理。如果后端服务未就绪或事件失败,组件可能会中断。文件中其他异步操作(如 loadDiropenFilereloadActiveTab)都使用了 try-catch 块。

为保持一致性并提升鲁棒性,建议添加错误处理:

建议的错误处理
 watch(
     () => props.config.defaultProvider,
     async () => {
+        try {
             rootPath.value = clean(
                 await send('chatluna-agent/getComputerHome', {
                     backend: props.config.defaultProvider
                 })
             )
             currentDir.value = rootPath.value
             pathInput.value = rootPath.value
             search.value = ''
             items.value = []
             tabs.value = []
             activeKey.value = ''
             selectedPath.value = ''
             history.value = []
             historyIndex.value = -1
             browserSize.value = 38
             await loadDir(rootPath.value, 'push')
+        } catch {
+            ElMessage.error('获取根目录失败')
+        }
     },
     { immediate: true }
 )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/extension-agent/client/components/computer/files-panel.vue` around
lines 573 - 594, The watch handler that calls
send('chatluna-agent/getComputerHome') lacks error handling and can break the
component if the backend is unavailable; wrap the async body of the watcher in a
try-catch (around the send and subsequent state resets and the await loadDir
call), handle/log the error (e.g., via console.error or an existing logger) and
ensure state remains consistent on failure (avoid clearing critical values or
set safe defaults for rootPath, currentDir, pathInput, items, tabs, activeKey,
selectedPath, history, historyIndex, browserSize) so watch,
send('chatluna-agent/getComputerHome'), loadDir, rootPath and related state
updates are guarded.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/llm-core/agent/sub-agent.ts`:
- Line 873: 该行在调用 escapeXml(...) 的三元表达式被多余的括号和换行打断导致不符合 Prettier 格式,请在
sub-agent.ts 中定位使用 escapeXml 的三元表达式(查找 escapeXml( 出现处),移除不必要的括号并将三元运算符的条件、? 与 :
和结果放置为 Prettier 推荐的紧凑格式(即不要换行在不必要的位置),确保表达式在一行或按 Prettier 默认换行规则分行以通过格式校验。

In `@packages/extension-agent/src/computer/backends/local/sandbox.ts`:
- Around line 152-157: The current sandbox flags build in sandbox.ts return a
'--bind / /' when cfg.sandboxMode === 'writable', which exposes the entire host
FS; instead, always mount host root read-only (use the ro-bind pattern) and
explicitly add writable mounts only for allowed paths (e.g., the workdir and
tmp), and translate denyRoots/readOnlyRoots into additional bwrap mount flags to
enforce restrictions; update the array construction in the function that returns
the bwrap args (the block using quote(bwrap), cfg.sandboxMode, tmp) so it never
uses '--bind / /' — add an explicit writable '--bind' for the workdir and
convert denyRoots/readOnlyRoots into corresponding '--ro-bind'/'--bind' entries
so execute() and prepareBackgroundCommand() cannot write outside permitted
paths.

---

Outside diff comments:
In `@packages/extension-agent/src/computer/backends/local/index.ts`:
- Around line 217-229: createTerminal currently accepts an arbitrary options.cwd
and launches an interactive shell via resolveInteractiveShellCommand +
createLocalTerminal without performing path permission checks or wrapping the
PTY in the sandbox, allowing callers to bypass denyRoots/readOnlyRoots; fix by
validating and normalizing the requested cwd against the existing
denyRoots/readOnlyRoots policy (use the same logic used elsewhere in this
module) and then start the terminal using the sandbox wrapper
(wrapCommandWithSandbox) or an equivalent sandboxed command path before calling
createLocalTerminal; update createTerminal to
resolveInteractiveShellCommand(this._cfg), enforce permission checks on
options.cwd (fall back to this._cwd when denied), and pass the sandboxed
command/env into createLocalTerminal so interactive shells cannot escape
read-only/denied roots.

---

Nitpick comments:
In `@packages/extension-agent/client/components/computer/files-panel.vue`:
- Around line 573-594: The watch handler that calls
send('chatluna-agent/getComputerHome') lacks error handling and can break the
component if the backend is unavailable; wrap the async body of the watcher in a
try-catch (around the send and subsequent state resets and the await loadDir
call), handle/log the error (e.g., via console.error or an existing logger) and
ensure state remains consistent on failure (avoid clearing critical values or
set safe defaults for rootPath, currentDir, pathInput, items, tabs, activeKey,
selectedPath, history, historyIndex, browserSize) so watch,
send('chatluna-agent/getComputerHome'), loadDir, rootPath and related state
updates are guarded.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c1f8f497-f62c-41b2-b0fd-8a5d3f6858b4

📥 Commits

Reviewing files that changed from the base of the PR and between abe32e9 and 70a9f67.

⛔ Files ignored due to path filters (3)
  • packages/core/package.json is excluded by !**/*.json
  • packages/core/src/locales/en-US.schema.yml is excluded by !**/*.yml
  • packages/core/src/locales/zh-CN.schema.yml is excluded by !**/*.yml
📒 Files selected for processing (30)
  • .gitignore
  • packages/core/src/config.ts
  • packages/core/src/index.ts
  • packages/core/src/llm-core/agent/sub-agent.ts
  • packages/core/src/llm-core/agent/wakeup.ts
  • packages/core/src/middlewares/conversation/request_conversation.ts
  • packages/core/src/utils/virtual_session.ts
  • packages/extension-agent/client/components/computer/computer-page.vue
  • packages/extension-agent/client/components/computer/config-backends/backend-e2b.vue
  • packages/extension-agent/client/components/computer/config-backends/backend-local.vue
  • packages/extension-agent/client/components/computer/config-backends/backend-open-terminal.vue
  • packages/extension-agent/client/components/computer/configuration-panel.vue
  • packages/extension-agent/client/components/computer/files-panel.vue
  • packages/extension-agent/client/components/computer/status-panel.vue
  • packages/extension-agent/src/computer/backends/e2b.ts
  • packages/extension-agent/src/computer/backends/local/index.ts
  • packages/extension-agent/src/computer/backends/local/sandbox.ts
  • packages/extension-agent/src/computer/backends/local/security.ts
  • packages/extension-agent/src/computer/backends/local/store.ts
  • packages/extension-agent/src/computer/backends/open_terminal.ts
  • packages/extension-agent/src/computer/types.ts
  • packages/extension-agent/src/config/defaults.ts
  • packages/extension-agent/src/service/computer.ts
  • packages/extension-agent/src/service/index.ts
  • packages/extension-agent/src/service/sub_agent.ts
  • packages/extension-agent/src/sub-agent/session.ts
  • packages/extension-agent/src/trigger/session.ts
  • packages/extension-agent/src/types.ts
  • packages/extension-agent/src/types/computer.ts
  • packages/extension-agent/src/webui/index.ts
💤 Files with no reviewable changes (3)
  • packages/extension-agent/src/types/computer.ts
  • packages/extension-agent/src/config/defaults.ts
  • packages/extension-agent/src/computer/backends/local/security.ts

Comment thread packages/core/src/llm-core/agent/sub-agent.ts
Comment thread packages/extension-agent/src/computer/backends/local/sandbox.ts Outdated
@dingyi222666 dingyi222666 changed the title feat(agent): improve computer backends and task wakeups feat(exetesion-agent): improve computer backends and task wakeups Jun 12, 2026
@dingyi222666 dingyi222666 linked an issue Jun 12, 2026 that may be closed by this pull request

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/middlewares/chat/stop_chat.ts`:
- Around line 64-67: 当前实现无条件在 stop_chat 中调用
ctx.parallel('chatluna/chat-stopped', { conversationId: conversation.id, session
}),导致在判定为“无活动会话”或未实际停止时也派发事件并触发下游 detachConversation;请将该 ctx.parallel
调用移动到仅在确实完成停止逻辑的分支(即在对 conversation.status 或 stop 成功判断后的分支)中触发,确保只有在实际停止成功(例如
status === 'stopped' 或 stop 操作返回成功)时才调用 ctx.parallel,并保留 conversation.id 与
session 作为事件载荷以保持行为一致。

In `@packages/extension-agent/src/commands/task.ts`:
- Line 158: The prompt string using `State: ${state(task, run)}. Send messages
here; use chatluna.agent.task.exit to leave.` references a non-existent command
and should be corrected to match the registered command; update the template to
instruct users to call `chatluna.agent.exit` (or, if you intended the dotted
command, rename the registration to `chatluna.agent.task.exit`) so the displayed
instruction and the registered handler (the code that registers
`chatluna.agent.exit`) match; ensure you update the template where `state(task,
run)` is used and any other helper text to reflect the correct command name.

In `@packages/extension-agent/src/sub-agent/task_attach.ts`:
- Around line 50-59: The call to this.ctx.chatluna_agent.subAgent.chatTask(...)
and the await runConfig(session, conversation) are not guarded, so exceptions
will bubble and break the session chain; wrap the whole await call in a
try/catch around the block that calls subAgent.chatTask and runConfig, log the
caught error using the module logger (e.g., logger.error(e)), and return or emit
a clear failure response to the caller (or set a session-level error result) so
the user/flow receives visible feedback instead of crashing; reference the call
site this.ctx.chatluna_agent.subAgent.chatTask(item.taskId, session.content, {
session, conversationId: item.parentConversationId, source: 'chatluna',
runConfig: await this.runConfig(session, conversation) }) when making the
change.
- Around line 17-29: The prepend middleware currently checks
session.argv?.command too early (constructor uses ctx.middleware(..., true))
which can cause commands to be forwarded as messages; change the middleware
registration to a normal middleware (remove the true prepend flag) or defer
reading session.argv until after command parsing, and remove/replace the if
(session.argv?.command) return next() check so exit commands aren't misrouted;
additionally, wrap awaits to runConfig(...) and subAgent.chatTask(...) in
try/catch inside the task_attach middleware (use the same
error-to-structured-result pattern as sub-agent.runTask) and handle failures by
cleaning up this._items, sending an error notice via session.send, and returning
next() to avoid unhandled rejections.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cc82944a-0593-4cea-bf48-8cdbc1892df2

📥 Commits

Reviewing files that changed from the base of the PR and between 70a9f67 and 13f6dfb.

📒 Files selected for processing (12)
  • packages/core/src/llm-core/agent/agent.ts
  • packages/core/src/llm-core/agent/legacy-executor.ts
  • packages/core/src/llm-core/agent/sub-agent.ts
  • packages/core/src/llm-core/agent/types.ts
  • packages/core/src/middlewares/chat/stop_chat.ts
  • packages/core/src/services/types.ts
  • packages/extension-agent/src/commands/agent.ts
  • packages/extension-agent/src/commands/task.ts
  • packages/extension-agent/src/computer/backends/local/sandbox.ts
  • packages/extension-agent/src/index.ts
  • packages/extension-agent/src/service/sub_agent.ts
  • packages/extension-agent/src/sub-agent/task_attach.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/core/src/services/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/llm-core/agent/sub-agent.ts

Comment thread packages/core/src/middlewares/chat/stop_chat.ts Outdated
Comment thread packages/extension-agent/src/commands/task.ts Outdated
Comment thread packages/extension-agent/src/sub-agent/task_attach.ts
Comment thread packages/extension-agent/src/sub-agent/task_attach.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/core/src/llm-core/agent/sub-agent.ts (2)

695-723: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

不要让 refresh() 改写任务最终状态。

这里的 refresh 是附属的控制台刷新,但它现在被放进了 run 的成功/失败收尾主路径里。只要 options.runtime.refresh?.() 在成功分支抛错,已完成的 run 就会落入 catch 被改写成 failed,随后父会话收到的也是失败通知;而失败分支里的第二次 refresh 若再抛错,还会直接跳过 notifyFinished(...)。建议把完成通知与 UI 刷新解耦,至少保证 refresh 失败不会影响 run.state 和完成事件投递。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/llm-core/agent/sub-agent.ts` around lines 695 - 723, The
problem is that options.runtime.refresh?.() is called inside the main
success/failure teardown so if refresh throws it can flip run.state or prevent
notifyFinished; wrap each call to options.runtime.refresh?.() in its own
try/catch that captures and logs errors without throwing (so it cannot change
run.state or skip notifyFinished), and ensure notifyFinished(options, run,
snapshot) is invoked regardless of refresh outcome (i.e., call notifyFinished
before optional refresh or call refresh inside a non-throwing try/catch after
notifyFinished); update locations around the success path (where
formatTaskResult is returned) and the catch block (after
run.state/run.error/trace/endedAt and cleanup) to use this non-throwing refresh
pattern so refresh failures are decoupled from run completion and notification.

755-773: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

父子代理链路在父 run 已结束时会静默丢掉完成通知。

parentConversationIdsubagent: 开头时,这里只尝试把唤醒消息塞回父任务的 MessageQueue。如果父任务已经结束,active 查找失败后就直接 return;而 wakeup.ts 的消费端又明确跳过 subagent: payload,所以这类后台子任务的结果不会再冒泡回主对话。只要子代理允许继续发起 background task,这条分支就会把“结果自动送达”变成静默丢失。需要在父队列不存在时继续向更上层会话冒泡,或在快照里保留最终要唤醒的会话标识。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/llm-core/agent/sub-agent.ts` around lines 755 - 773, The
branch that handles options.task.parentConversationId.startsWith('subagent:')
silently returns when the parent active run (found via options.tasks and
options.active) is missing, causing background subagent completions to be
dropped; change the logic in sub-agent.ts so that if active is undefined you
either (A) bubble the wakeup up to the next conversation by deriving the parent
id (strip the 'subagent:' prefix or follow the stored parent chain) and
attempting to locate/enqueue the same HumanMessage (constructed via
formatAgentTaskWakeup(..., run)) into that higher-level MessageQueue, or (B)
persist the intended wakeup target in the task snapshot/metadata so the next
time the parent conversation is restored it will deliver the wakeup; ensure you
keep the existing behavior of pushing the HumanMessage into active.queue when
active exists and only fall back to the bubbling/persistence path when active is
missing; reference symbols: options.task.parentConversationId, options.tasks,
options.active, active.queue, HumanMessage, formatAgentTaskWakeup, run (and
ensure wakeup.ts’s consumer will ignore subagent: payloads only when
appropriate).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/llm-core/agent/sub-agent.ts`:
- Around line 60-116: The control methods stopTask, pauseTask, resumeTask, and
abortByParentConversation call options.refresh?.() (which returns an
Awaitable<void>) without awaiting it, causing possible unhandled rejection and
misleading immediate returns; make these APIs async (add async to their
declarations) and await the refresh call (await options.refresh?.()) before
returning, or alternatively consume errors by awaiting and catching rejections
(e.g., try { await options.refresh?.() } catch (e) { /* handle/log */ }); update
each of stopTask, pauseTask, resumeTask, and abortByParentConversation
accordingly so the caller receives the true completion result.

---

Outside diff comments:
In `@packages/core/src/llm-core/agent/sub-agent.ts`:
- Around line 695-723: The problem is that options.runtime.refresh?.() is called
inside the main success/failure teardown so if refresh throws it can flip
run.state or prevent notifyFinished; wrap each call to
options.runtime.refresh?.() in its own try/catch that captures and logs errors
without throwing (so it cannot change run.state or skip notifyFinished), and
ensure notifyFinished(options, run, snapshot) is invoked regardless of refresh
outcome (i.e., call notifyFinished before optional refresh or call refresh
inside a non-throwing try/catch after notifyFinished); update locations around
the success path (where formatTaskResult is returned) and the catch block (after
run.state/run.error/trace/endedAt and cleanup) to use this non-throwing refresh
pattern so refresh failures are decoupled from run completion and notification.
- Around line 755-773: The branch that handles
options.task.parentConversationId.startsWith('subagent:') silently returns when
the parent active run (found via options.tasks and options.active) is missing,
causing background subagent completions to be dropped; change the logic in
sub-agent.ts so that if active is undefined you either (A) bubble the wakeup up
to the next conversation by deriving the parent id (strip the 'subagent:' prefix
or follow the stored parent chain) and attempting to locate/enqueue the same
HumanMessage (constructed via formatAgentTaskWakeup(..., run)) into that
higher-level MessageQueue, or (B) persist the intended wakeup target in the task
snapshot/metadata so the next time the parent conversation is restored it will
deliver the wakeup; ensure you keep the existing behavior of pushing the
HumanMessage into active.queue when active exists and only fall back to the
bubbling/persistence path when active is missing; reference symbols:
options.task.parentConversationId, options.tasks, options.active, active.queue,
HumanMessage, formatAgentTaskWakeup, run (and ensure wakeup.ts’s consumer will
ignore subagent: payloads only when appropriate).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d000c78a-5924-4ddd-927e-7e14934b794d

📥 Commits

Reviewing files that changed from the base of the PR and between 13f6dfb and be7f07e.

📒 Files selected for processing (4)
  • packages/core/src/llm-core/agent/sub-agent.ts
  • packages/core/src/middlewares/chat/stop_chat.ts
  • packages/extension-agent/src/commands/task.ts
  • packages/extension-agent/src/sub-agent/task_attach.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/core/src/middlewares/chat/stop_chat.ts
  • packages/extension-agent/src/commands/task.ts
  • packages/extension-agent/src/sub-agent/task_attach.ts

Comment thread packages/core/src/llm-core/agent/sub-agent.ts Outdated
@dingyi222666 dingyi222666 merged commit 073b6c0 into v1-dev Jun 14, 2026
4 of 5 checks passed
@dingyi222666 dingyi222666 deleted the feat/agent-new-feature branch June 14, 2026 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 可唤醒的 background sub agent

1 participant