Skip to content

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

Merged
A-x6 merged 5 commits into
devfrom
btw-command
Jul 31, 2026
Merged

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

Conversation

@A-x6

@A-x6A-x6 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.constfork=awaitsdk.client.session.fork({sessionID: route.sessionID})// ...constresult=awaitsdk.client.session.prompt({sessionID: fork.data.id,parts: [{type: "text",text: `The user has a side question about the work above. ...`}],})voidDialogAlert.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

vercelBot 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

coderabbitaiBot 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 nameStatusExplanation
Title check✅ PassedThe title clearly summarizes the main change: adding /btw side questions without interrupting the active task.
Description check✅ PassedThe description includes the required issue, change type, implementation details, verification, screenshots note, and completed checklist.
Linked Issues check✅ PassedThe changes implement /btw by forking the session, prompting concurrently, displaying the response, and preserving the original run [#71].
Out of Scope Changes check✅ PassedThe changes are limited to the TUI session route and directly support the linked issue objectives.
Docstring Coverage✅ PassedNo 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-ioBot 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

AnalyzerStatusUpdated (UTC)Details
JavaScriptJul 31, 2026 6:26a.m.Review ↗
ShellJul 31, 2026 6:26a.m.Review ↗
SecretsJul 31, 2026 6:26a.m.Review ↗
DockerJul 31, 2026 6:26a.m.Review ↗
PythonJul 31, 2026 6:26a.m.Review ↗
CSSJul 31, 2026 6:26a.m.Review ↗
RustJul 31, 2026 6:26a.m.Review ↗
RubyJul 31, 2026 6:26a.m.Review ↗
SwiftJul 31, 2026 6:26a.m.Review ↗
PHPJul 31, 2026 6:26a.m.Review ↗
LuaJul 31, 2026 6:26a.m.Review ↗
JavaJul 31, 2026 6:26a.m.Review ↗
GoJul 31, 2026 6:26a.m.Review ↗
C & C++Jul 31, 2026 6:26a.m.Review ↗
AnsibleJul 31, 2026 6:26a.m.Review ↗
ApexJul 31, 2026 6:26a.m.Review ↗
ElixirJul 31, 2026 6:26a.m.Review ↗
GroovyJul 31, 2026 6:26a.m.Review ↗
Objective-CJul 31, 2026 6:26a.m.Review ↗
PowerShellJul 31, 2026 6:26a.m.Review ↗
TerraformJul 31, 2026 6:26a.m.Review ↗
VB.NETJul 31, 2026 6:26a.m.Review ↗
SQLJul 31, 2026 6:26a.m.Review ↗
ScalaJul 31, 2026 6:26a.m.Review ↗
PerlJul 31, 2026 6:26a.m.Review ↗
KotlinJul 31, 2026 6:26a.m.Review ↗
HelmJul 31, 2026 6:26a.m.Review ↗
ErlangJul 31, 2026 6:26a.m.Review ↗
DartJul 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>

@coderabbitaicoderabbitaiBot 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 threadpackages/tui/src/routes/session/index.tsx Outdated
Comment threadpackages/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.

@A-x6
A-x6 merged commit 5ac241e into devJul 31, 2026
9 of 11 checks passed
Sign up for freeto 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

@A-x6