-
Notifications
You must be signed in to change notification settings - Fork 0
feat(async-agents): fire-and-forget subagent tasks #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: rekram1-node <[email protected]>
Co-authored-by: shuv <[email protected]>
Co-authored-by: Aiden Cline <[email protected]> Co-authored-by: Aiden Cline <[email protected]>
…ple directories per project
Co-authored-by: Brendan Allan <[email protected]>
Co-authored-by: Brendan Allan <[email protected]>
Summary of ChangesHello @IgorWarzocha, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the agent interaction model by introducing asynchronous subagent tasks, allowing for parallel execution of complex operations. It integrates these capabilities deeply into the TUI for improved user experience and introduces new git worktree management features. The changes also include updates to core configuration, LSP integration, and permission systems, alongside a major cleanup of repository-specific configuration files. Highlights
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
…k tool Adds async agent capability with live tool call updates in parent session: - Add async parameter to task tool for fire-and-forget parallel execution - Implement SubtaskPart type for live status updates in parent messages - Add running children tracking via Session.runningChildren (internal only) - Auto-notify parent via subtask parts when child completes - Add UX improvements (sidebar status, toasts, agent preservation) - Remove manual /wipe, /wipeout, /finished commands (task tool handles lifecycle) - Add new spec document: specs/async-agents.md Breaking: Subagent sessions now auto-notify parent on completion instead of requiring /finished command
a790fc8 to
70574fe
Compare
There was a problem hiding this comment.
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 significant enhancements to asynchronous task management and worktree support, alongside various UI/UX improvements and bug fixes. Key changes include updating the task tool to support asynchronous execution with concurrency limits and detailed notifications for completion or failure, including a new SubtaskPart message type. It also adds Git worktree creation and listing capabilities, allowing users to create new sessions within dedicated worktrees. The UI has been refined with a new worktree selection for new sessions, improved session header navigation, and a dedicated sidebar section for background tasks. Dependency updates for @opentui/core and @opentui/solid were included. Review comments highlighted a fallthrough bug in the permission onSelect handler that could incorrectly treat rejections as one-time allowances, an incorrect logic for identifying the Git worktree root, the removal of manual Content-Type headers for proxied static assets which might cause web UI issues, a bug preventing live tool call updates for async tasks due to an inverted pending status check, and a potential performance regression from removing equals: same from createMemo calls. Additionally, a design concern was raised regarding the use of role: "assistant" for system-level subtask notifications, suggesting role: "system" as more appropriate.
I am having trouble creating individual review comments. Click here to see my feedback.
packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx (234-253)
There's a fallthrough bug in the onSelect handler. When option is 'reject' and it's not a sub-agent session, the code correctly calls sdk.client.permission.reply with reply: 'reject'. However, it then continues execution and immediately calls sdk.client.permission.reply again with reply: 'once', effectively overriding the rejection. This will cause rejected permissions to be incorrectly treated as allowed for one-time use.
You should restructure this logic using if/else if/else or add a return statement after handling the 'reject' case to prevent this double-reply.
onSelect={(option) => {
if (option === "always") {
setStore("stage", "always");
return;
}
if (option === "reject") {
if (session()?.parentID) {
setStore("stage", "reject");
} else {
sdk.client.permission.reply({
reply: "reject",
requestID: props.request.id,
});
}
return;
}
sdk.client.permission.reply({
reply: "once",
requestID: props.request.id,
});
}}
packages/opencode/src/project/project.ts (81-90)
The logic for finding the worktree root has been changed from git rev-parse --show-toplevel to path.dirname($(git rev-parse --git-common-dir)). This is incorrect for worktrees. git rev-parse --git-common-dir returns the path to the main repository's .git directory, so taking its dirname will always resolve to the main worktree's root, not the root of the current worktree where the command is executed.
This will cause issues when operating inside a git worktree, as it will fail to identify the correct project root. You should revert to using git rev-parse --show-toplevel, which correctly returns the root of the current working tree.
worktree = await $`git rev-parse --show-toplevel`
.quiet()
.nothrow()
.cwd(worktree)
.text()
.then((x) => x.trim())packages/opencode/src/server/server.ts (2802-2809)
The logic for manually setting Content-Type headers for proxied static assets has been removed. The comment indicated this was a workaround for an issue with Cloudflare not returning the correct mime types. If this issue still exists, removing this block could break the web UI, as browsers may fail to interpret CSS, JavaScript, and other assets without the correct Content-Type header.
Please verify if this workaround is no longer needed. If the underlying issue with the proxy source persists, this change could be a critical regression.
packages/opencode/src/tool/task.ts (224)
The condition if (state.status === "pending") return prevents the parent tool part from being updated as long as it's in a pending state. This is the opposite of what's needed for live updates of an async task. The parent part is created as pending and should be updated with new metadata as the child task progresses.
This bug will prevent the UI from showing any live tool call updates for async tasks. The check should likely be inverted to if (state.status !== "pending") return to prevent updates to an already completed or failed part, as the comment above suggests.
if (state.status !== "pending") returnpackages/app/src/pages/session.tsx (221-234)
The equals: same option has been removed from these createMemo calls. This may lead to unnecessary re-renders of components that depend on userMessages and visibleUserMessages, as new array instances will be created on each run. While SolidJS's default shallow comparison might handle this, re-introducing a custom equals function (like the likely-removed same) could be a valuable performance optimization, especially in sessions with many messages.
packages/opencode/src/session/message-v2.ts (584-595)
Injecting subtask notifications using role: "assistant" is problematic. This misrepresents the conversation history by making it appear as if the assistant generated these instructions, which can confuse the language model and lead to unpredictable behavior. The correct role for such instructional content is system.
If the internal UIMessage type supports it, please change this to role: "system". If not, this points to a design limitation that should be addressed, as misusing the assistant role for system-level instructions is not a robust solution.
if (subtaskNotifications.length > 0) {
// Using 'system' role is more appropriate for instructions to the model.
// This assumes the message processing pipeline can handle a system message here.
result.unshift({
id: Identifier.ascending("message"),
role: "system",
parts: [
{
type: "text",
text: subtaskNotifications.join("\n\n---\n\n"),
},
],
});
}
|
Closing to refresh base after dev sync. |
Summary