Skip to content

feat(tui): /btw side questions without interrupting the task - #73

Merged
DevFlex-AI merged 5 commits into
devfrom
btw-command
Jul 31, 2026
Merged

feat(tui): /btw side questions without interrupting the task#73
DevFlex-AI merged 5 commits into
devfrom
btw-command

Conversation

@DevFlex-AI

@DevFlex-AI DevFlex-AI commented Jul 31, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #71

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds /btw (alias /aside) to the TUI: while the agent is mid-task, ask a question and get an answer without steering or interrupting the run. The command captures the question in a prompt dialog, forks the current session so the side question sees the conversation so far, and prompts the fork; run loops are keyed per session, so the fork answers concurrently while the original session keeps streaming untouched. The answer pops in an alert dialog when it arrives:

// Fork the session so the side question sees the conversation so far;
// the fork runs on its own per-session runner, so the original run
// keeps streaming untouched.
const fork = await sdk.client.session.fork({ sessionID: route.sessionID })
// ...
const result = await sdk.client.session.prompt({
  sessionID: fork.data.id,
  parts: [{ type: "text", text: `The user has a side question about the work above. ...` }],
})
void DialogAlert.show(dialog, `btw: ${label}`, answer)

Details a reviewer can't infer from the diff:

  • session.fork has no busy assertion server-side; mid-run it snapshots whatever messages are committed, which is exactly the context a side question wants.
  • The fork inherits the model from the copied last user message (server model resolution), so no model wiring is needed; the question text also instructs the model to answer directly and not touch files, since the original session owns the task.
  • The fork is retitled btw: <question>, so if the answer dialog is dismissed (or the toast is missed) the full markdown-rendered answer is one /sessions away.
  • Failure modes degrade to toasts (fork failed, no answer came back); a dismissed or empty prompt dialog is a no-op.

How did you verify your code works?

  • bunx tsgo --noEmit in packages/tui: clean
  • bun test in packages/tui: 198 pass

Screenshots / recordings

N/A (uses the existing DialogPrompt / DialogAlert components)

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

View with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is enabled.

Summary by CodeRabbit

  • New Features

    • Added /btw and /aside commands for asking side questions during a session.
    • Side questions are handled separately without modifying files or interrupting the original task.
    • Added progress and completion feedback while side questions are processed.
  • Bug Fixes

    • Added clear error notifications when side-question sessions fail or produce no response.

@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/adevloper152s-projects?upgradeToPro=build-rate-limit

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

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 Plus

Run ID: 180fd67a-b69e-4f69-a5b5-11f0c972bcfe

📥 Commits

Reviewing files that changed from the base of the PR and between 6d1df88 and 2d8d076.

📒 Files selected for processing (1)
  • packages/tui/src/routes/session/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/tui/src/routes/session/index.tsx

📝 Walkthrough

Walkthrough

The session route adds /btw and /aside commands. The command collects a side question, forks the current session, submits isolated instructions, reports failures with error toasts, and displays successful answers in an alert dialog.

Changes

Side-question session flow

Layer / File(s) Summary
Side-question command and forked response flow
packages/tui/src/routes/session/index.tsx
The route imports DialogPrompt and adds session.btw with /btw and /aside aliases. The command validates input, forks the session, submits side-question instructions, handles failures with error toasts, and displays the response in an alert dialog.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DialogPrompt
  participant CurrentSession
  participant ForkedSession
  participant AlertDialog

  DialogPrompt->>CurrentSession: Submit side question
  CurrentSession->>ForkedSession: Fork current session
  ForkedSession->>ForkedSession: Answer without modifying files
  ForkedSession-->>AlertDialog: Display answer
Loading

Possibly related PRs

  • bolt-builder/bolt-cli#72: Both changes add session slash commands in packages/tui/src/routes/session/index.tsx, but they implement different commands.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding /btw side questions without interrupting the active task.
Description check ✅ Passed The description includes the required issue, change type, implementation details, verification, screenshots note, and completed checklist.
Linked Issues check ✅ Passed The changes implement /btw by forking the session, prompting concurrently, displaying the response, and preserving the original run [#71].
Out of Scope Changes check ✅ Passed The changes are limited to the TUI session route and directly support the linked issue objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch btw-command

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


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

@github-actions

Copy link
Copy Markdown

The following comment was made by an LLM, it may be inaccurate:

@deepsource-io

deepsource-io Bot commented Jul 31, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in ba2adba...2d8d076 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade  

Focus Area: Hygiene
Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Jul 31, 2026 6:26a.m. Review ↗
Shell Jul 31, 2026 6:26a.m. Review ↗
Secrets Jul 31, 2026 6:26a.m. Review ↗
Docker Jul 31, 2026 6:26a.m. Review ↗
Python Jul 31, 2026 6:26a.m. Review ↗
CSS Jul 31, 2026 6:26a.m. Review ↗
Rust Jul 31, 2026 6:26a.m. Review ↗
Ruby Jul 31, 2026 6:26a.m. Review ↗
Swift Jul 31, 2026 6:26a.m. Review ↗
PHP Jul 31, 2026 6:26a.m. Review ↗
Lua Jul 31, 2026 6:26a.m. Review ↗
Java Jul 31, 2026 6:26a.m. Review ↗
Go Jul 31, 2026 6:26a.m. Review ↗
C & C++ Jul 31, 2026 6:26a.m. Review ↗
Ansible Jul 31, 2026 6:26a.m. Review ↗
Apex Jul 31, 2026 6:26a.m. Review ↗
Elixir Jul 31, 2026 6:26a.m. Review ↗
Groovy Jul 31, 2026 6:26a.m. Review ↗
Objective-C Jul 31, 2026 6:26a.m. Review ↗
PowerShell Jul 31, 2026 6:26a.m. Review ↗
Terraform Jul 31, 2026 6:26a.m. Review ↗
VB.NET Jul 31, 2026 6:26a.m. Review ↗
SQL Jul 31, 2026 6:26a.m. Review ↗
Scala Jul 31, 2026 6:26a.m. Review ↗
Perl Jul 31, 2026 6:26a.m. Review ↗
Kotlin Jul 31, 2026 6:26a.m. Review ↗
Helm Jul 31, 2026 6:26a.m. Review ↗
Erlang Jul 31, 2026 6:26a.m. Review ↗
Dart Jul 31, 2026 6:26a.m. Review ↗
C# Jul 31, 2026 6:26a.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

name: "btw",
aliases: ["aside"],
},
run: async () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Function has a cyclomatic complexity of 6 with "medium" risk


A function with high cyclomatic complexity can be hard to understand and
maintain. Cyclomatic complexity is a software metric that measures the number of
independent paths through a function. A higher cyclomatic complexity indicates
that the function has more decision points and is more complex.

})
if (!question?.trim()) return
dialog.clear()
const label = question.length > 40 ? question.slice(0, 40) + "..." : question

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unexpected string concatenation


In ES2015 (ES6), we can use template literals instead of string concatenation.

toast.show({ variant: "error", message: "btw: failed to fork the session", duration: 5000 })
return
}
void sdk.client.session.update({ sessionID: id, title: `btw: ${label}` })

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Expected 'undefined' and instead saw 'void'


The void operator takes an operand and returns undefined. It can be used to ignore the value produced by an expression. However, this can lead to code that is difficult to understand and maintain. Historically, the void operator was used to get a "pure" undefined value, as the undefined variable was mutable prior to ES5.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

void for fire-and-forget promises is the established convention in this file (11 existing usages, e.g. lines 365, 621, 709); changing it would deviate from local style.

toast.show({ variant: "error", message: "btw: no answer came back", duration: 5000 })
return
}
void DialogAlert.show(dialog, `btw: ${label}`, answer)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Expected 'undefined' and instead saw 'void'


The void operator takes an operand and returns undefined. It can be used to ignore the value produced by an expression. However, this can lead to code that is difficult to understand and maintain. Historically, the void operator was used to get a "pure" undefined value, as the undefined variable was mutable prior to ES5.

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/tui/src/routes/session/index.tsx`:
- Line 573: Update the session fork and prompt error handling around
sdk.client.session.fork and sdk.client.session.prompt to retain the caught error
instead of replacing it with undefined, then include its message in the
corresponding failure toasts while preserving the existing generic context and
empty-response handling.
- Line 579: Add a rejection handler to the fire-and-forget
sdk.client.session.update call in the title rename flow, preserving the existing
title update behavior while ensuring rejected promises are contained.
🪄 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 Plus

Run ID: 444ba354-3039-4f9b-aa2c-63beff65e171

📥 Commits

Reviewing files that changed from the base of the PR and between ba2adba and 6d1df88.

📒 Files selected for processing (1)
  • packages/tui/src/routes/session/index.tsx

Comment thread packages/tui/src/routes/session/index.tsx Outdated
Comment thread packages/tui/src/routes/session/index.tsx Outdated
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
name: "btw",
aliases: ["aside"],
},
run: async () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Function has a cyclomatic complexity of 8 with "medium" risk


A function with high cyclomatic complexity can be hard to understand and
maintain. Cyclomatic complexity is a software metric that measures the number of
independent paths through a function. A higher cyclomatic complexity indicates
that the function has more decision points and is more complex.

if (fork) toast.show({ variant: "error", message: "btw: failed to fork the session", duration: 5000 })
return
}
void sdk.client.session.update({ sessionID: id, title: `btw: ${label}` }).catch(() => {})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Expected 'undefined' and instead saw 'void'


The void operator takes an operand and returns undefined. It can be used to ignore the value produced by an expression. However, this can lead to code that is difficult to understand and maintain. Historically, the void operator was used to get a "pure" undefined value, as the undefined variable was mutable prior to ES5.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

void for fire-and-forget promises is the established convention in this file (11 existing usages, e.g. lines 365, 432, 2355); changing it would deviate from local style.

if (fork) toast.show({ variant: "error", message: "btw: failed to fork the session", duration: 5000 })
return
}
void sdk.client.session.update({ sessionID: id, title: `btw: ${label}` }).catch(() => {})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unexpected empty arrow function


Having empty functions hurts readability, and is considered a code-smell. There's almost always a way to avoid using them. If you must use one, consider adding a comment to inform the reader of its purpose.

Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
return
}
// Best-effort rename; a failed title update should not block the side question.
void sdk.client.session.update({ sessionID: id, title: `btw: ${label}` }).catch(() => undefined)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Expected 'undefined' and instead saw 'void'


The void operator takes an operand and returns undefined. It can be used to ignore the value produced by an expression. However, this can lead to code that is difficult to understand and maintain. Historically, the void operator was used to get a "pure" undefined value, as the undefined variable was mutable prior to ES5.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

void for fire-and-forget promises is the established convention in this file (11 existing usages, e.g. lines 365, 432, 2355); changing this one line would deviate from local style.

@DevFlex-AI
DevFlex-AI merged commit 5ac241e into dev Jul 31, 2026
9 of 11 checks passed
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.

feat: /btw command for side questions without interrupting the task

1 participant