fix(desktop): route /btw through prompt.btw so the answer reaches the chat
Desktop sent /btw through the slash worker, which printed the answer after process_command returned, so only the acknowledgement ever showed. Use the TUI's prompt.btw RPC and persist btw.complete on the originating session. Co-authored-by: SsSs <w-kwan@hotmail.com> Co-authored-by: kokhlo <konstantin.khlopkov93@gmail.com> Co-authored-by: xxxigm <tuancanhnguyen706@gmail.com>
This commit is contained in:
committed by
brooklyn!
parent
a2907a8bcd
commit
5994b833b0
@@ -41,6 +41,35 @@ export function handleStatusEvent(ctx: GatewayEventContext): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.type === 'btw.complete') {
|
||||
// prompt.btw answers a side question and emits this on the originating
|
||||
// session. Persistent transcript line, matching the TUI's `[btw "q"]`
|
||||
// — without it Desktop only ever showed the acknowledgement (#99065).
|
||||
const text = coerceGatewayText(payload?.text).trim()
|
||||
|
||||
if (text && sessionId) {
|
||||
const taskId = String(payload?.task_id ?? '').trim()
|
||||
const question = coerceGatewayText(payload?.question).trim()
|
||||
const header = `[btw${question ? ` "${question}"` : ''}${taskId ? ` (${taskId})` : ''}]`
|
||||
|
||||
flushQueuedDeltas(sessionId)
|
||||
updateSessionState(sessionId, state => ({
|
||||
...state,
|
||||
messages: [
|
||||
...state.messages,
|
||||
{
|
||||
id: `btw-complete-${taskId || Date.now()}`,
|
||||
role: 'system',
|
||||
parts: [textPart(`${header}\n${text}`, occurredAt)],
|
||||
timestamp: occurredAt
|
||||
}
|
||||
]
|
||||
}))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.type === 'review.summary') {
|
||||
// Self-improvement background review saved something to memory/skills
|
||||
// and emitted a persistent summary (Python formats it as
|
||||
|
||||
@@ -497,6 +497,52 @@ export function useSlashCommand(deps: SlashCommandDeps) {
|
||||
branch: async () => {
|
||||
await branchCurrentSession()
|
||||
},
|
||||
// /btw uses prompt.btw (the TUI's path). It must NOT go through
|
||||
// runExec: the slash worker prints the answer after process_command
|
||||
// returns, past the stdout capture window (#99065). The RPC replies
|
||||
// with a task id; the answer arrives later as btw.complete.
|
||||
btw: async ctx => {
|
||||
const question = ctx.arg.trim()
|
||||
|
||||
const resolved = await withSlashOutput(ctx)
|
||||
|
||||
if (!resolved) {
|
||||
return
|
||||
}
|
||||
|
||||
const { render: renderSlashOutput, sessionId } = resolved
|
||||
|
||||
if (!question) {
|
||||
renderSlashOutput(
|
||||
'Usage: /btw <question> — answered from a snapshot of this conversation without interrupting it.'
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await requestGateway<{ task_id?: string }>('prompt.btw', {
|
||||
session_id: sessionId,
|
||||
text: question
|
||||
})
|
||||
|
||||
renderSlashOutput(
|
||||
result.task_id
|
||||
? `btw ${result.task_id} — answering from a conversation snapshot`
|
||||
: 'btw — answering from a conversation snapshot'
|
||||
)
|
||||
} catch (err) {
|
||||
// Older gateways without the dedicated RPC still have the
|
||||
// slash-worker route — same compatibility fallback as runRpc.
|
||||
if (isMissingRpcMethod(err)) {
|
||||
await runExec(ctx)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
renderSlashOutput(`error: ${err instanceof Error ? err.message : String(err)}`)
|
||||
}
|
||||
},
|
||||
// /compress (alias /compact) runs the gateway's dedicated
|
||||
// session.compress RPC — the TUI's path
|
||||
// (ui-tui/src/app/slash/commands/session.ts). It must NOT go through
|
||||
|
||||
@@ -94,6 +94,8 @@ export type GatewayEventPayload = {
|
||||
// clarify.request
|
||||
request_id?: string
|
||||
question?: string
|
||||
// btw.complete / background.complete — id of the side/background task
|
||||
task_id?: string
|
||||
choices?: string[] | null
|
||||
multi_select?: boolean
|
||||
// clarify.request batch form: questions replaces question/choices, and
|
||||
|
||||
@@ -55,6 +55,7 @@ export interface DesktopThemeCommandOption {
|
||||
export type DesktopActionId =
|
||||
| 'branch'
|
||||
| 'browser'
|
||||
| 'btw'
|
||||
| 'compress'
|
||||
| 'handoff'
|
||||
| 'hatch'
|
||||
@@ -240,6 +241,15 @@ const DESKTOP_COMMAND_SPECS: readonly DesktopCommandSpec[] = [
|
||||
surface: action('compress'),
|
||||
argumentMode: 'text'
|
||||
},
|
||||
// /btw must be an action (prompt.btw RPC), not exec: the slash worker
|
||||
// prints the answer after process_command returns, so Desktop only ever
|
||||
// saw the acknowledgement (#99065). The answer arrives as btw.complete.
|
||||
{
|
||||
name: '/btw',
|
||||
description: 'Ask a side question about this conversation without interrupting it',
|
||||
surface: action('btw'),
|
||||
argumentMode: 'text'
|
||||
},
|
||||
{
|
||||
name: '/pet',
|
||||
description: 'Toggle or adopt a petdex mascot (/pet, /pet list, /pet boba)',
|
||||
|
||||
Reference in New Issue
Block a user