2026-04-15 14:14:01 -05:00
|
|
|
import type { SessionInfo, SlashCategory, Usage } from './types.js'
|
|
|
|
|
|
|
|
|
|
export interface GatewaySkin {
|
|
|
|
|
banner_hero?: string
|
|
|
|
|
banner_logo?: string
|
|
|
|
|
branding?: Record<string, string>
|
|
|
|
|
colors?: Record<string, string>
|
feat(tui): put the kawaii face+verb ticker in the status bar, not the thinking panel
The status bar was showing stale lifecycle text ("running…") while the
face+verb stream flickered through the thinking panel as Python pushed
thinking.delta events. That's backwards — the face ticker is the
primary "I'm alive" signal, it belongs in the status bar; the thinking
panel is for substantive reasoning and tool activity.
Status bar now reads `ui.busy`: when true, renders a local `<FaceTicker>`
cycling FACES × VERBS on a 2.5s interval, unaffected by server events.
When false, the bar shows the actual status string (ready, starting
agent…, interrupted, etc.).
Side effect: `scheduleThinkingStatus` still patches `ui.status` with
Python's face text, but while busy the bar ignores that string and uses
the ticker instead. No server-side changes needed — Python keeps
emitting thinking.delta as a liveness heartbeat, the TUI just doesn't
let it fight the status bar.
2026-04-16 20:14:25 -05:00
|
|
|
help_header?: string
|
|
|
|
|
tool_prefix?: string
|
2026-04-15 14:14:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface GatewayCompletionItem {
|
|
|
|
|
display: string
|
|
|
|
|
meta?: string
|
|
|
|
|
text: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface GatewayTranscriptMessage {
|
|
|
|
|
context?: string
|
|
|
|
|
name?: string
|
|
|
|
|
role: 'assistant' | 'system' | 'tool' | 'user'
|
|
|
|
|
text?: string
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
// ── Commands / completion ────────────────────────────────────────────
|
|
|
|
|
|
2026-04-15 14:14:01 -05:00
|
|
|
export interface CommandsCatalogResponse {
|
|
|
|
|
canon?: Record<string, string>
|
|
|
|
|
categories?: SlashCategory[]
|
|
|
|
|
pairs?: [string, string][]
|
|
|
|
|
skill_count?: number
|
|
|
|
|
sub?: Record<string, string[]>
|
|
|
|
|
warning?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface CompletionResponse {
|
|
|
|
|
items?: GatewayCompletionItem[]
|
|
|
|
|
replace_from?: number
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
export interface SlashExecResponse {
|
|
|
|
|
output?: string
|
|
|
|
|
warning?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type CommandDispatchResponse =
|
|
|
|
|
| { output?: string; type: 'exec' | 'plugin' }
|
|
|
|
|
| { target: string; type: 'alias' }
|
|
|
|
|
| { message?: string; name: string; type: 'skill' }
|
fix(tui): slash.exec _pending_input commands, tool ANSI, terminal title
Additional TUI fixes discovered in the same audit:
1. /plan slash command was silently lost — process_command() queues the
plan skill invocation onto _pending_input which nobody reads in the
slash worker subprocess. Now intercepted in slash.exec and routed
through command.dispatch with a new 'send' dispatch type.
Same interception added for /retry, /queue, /steer as safety nets
(these already have correct TUI-local handlers in core.ts, but the
server-side guard prevents regressions if the local handler is
bypassed).
2. Tool results were stripping ANSI escape codes — the messageLine
component used stripAnsi() + plain <Text> for tool role messages,
losing all color/styling from terminal, search_files, etc. Now
uses <Ansi> component (already imported) when ANSI is detected.
3. Terminal tab title now shows model + busy status via useTerminalTitle
hook from @hermes/ink (was never used). Users can identify Hermes
tabs and see at a glance whether the agent is busy or ready.
4. Added 'send' variant to CommandDispatchResponse type + asCommandDispatch
parser + createSlashHandler handler for commands that need to inject
a message into the conversation (plan, queue fallback, steer fallback).
2026-04-18 17:52:19 +05:30
|
|
|
| { message: string; type: 'send' }
|
2026-04-16 12:18:56 -05:00
|
|
|
|
|
|
|
|
// ── Config ───────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-04-15 14:14:01 -05:00
|
|
|
export interface ConfigDisplayConfig {
|
|
|
|
|
bell_on_complete?: boolean
|
|
|
|
|
details_mode?: string
|
2026-04-18 09:23:29 -05:00
|
|
|
inline_diffs?: boolean
|
|
|
|
|
show_cost?: boolean
|
|
|
|
|
show_reasoning?: boolean
|
|
|
|
|
streaming?: boolean
|
2026-04-15 14:14:01 -05:00
|
|
|
thinking_mode?: string
|
|
|
|
|
tui_compact?: boolean
|
|
|
|
|
tui_statusbar?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ConfigFullResponse {
|
2026-04-16 12:18:56 -05:00
|
|
|
config?: { display?: ConfigDisplayConfig }
|
2026-04-15 14:14:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ConfigMtimeResponse {
|
|
|
|
|
mtime?: number
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
export interface ConfigGetValueResponse {
|
|
|
|
|
display?: string
|
|
|
|
|
home?: string
|
|
|
|
|
value?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ConfigSetResponse {
|
|
|
|
|
credential_warning?: string
|
|
|
|
|
history_reset?: boolean
|
|
|
|
|
info?: SessionInfo
|
|
|
|
|
value?: string
|
|
|
|
|
warning?: string
|
2026-04-15 14:14:01 -05:00
|
|
|
}
|
|
|
|
|
|
2026-04-17 10:58:01 -05:00
|
|
|
export interface SetupStatusResponse {
|
|
|
|
|
provider_configured?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
// ── Session lifecycle ────────────────────────────────────────────────
|
|
|
|
|
|
2026-04-15 14:14:01 -05:00
|
|
|
export interface SessionCreateResponse {
|
|
|
|
|
info?: SessionInfo & { credential_warning?: string }
|
|
|
|
|
session_id: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SessionResumeResponse {
|
|
|
|
|
info?: SessionInfo
|
|
|
|
|
message_count?: number
|
|
|
|
|
messages: GatewayTranscriptMessage[]
|
|
|
|
|
resumed?: string
|
|
|
|
|
session_id: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SessionListItem {
|
|
|
|
|
id: string
|
|
|
|
|
message_count: number
|
|
|
|
|
preview: string
|
|
|
|
|
source?: string
|
|
|
|
|
started_at: number
|
|
|
|
|
title: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SessionListResponse {
|
|
|
|
|
sessions?: SessionListItem[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SessionUndoResponse {
|
|
|
|
|
removed?: number
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 14:48:29 -05:00
|
|
|
export interface SessionUsageResponse {
|
|
|
|
|
cache_read?: number
|
|
|
|
|
cache_write?: number
|
|
|
|
|
calls?: number
|
|
|
|
|
compressions?: number
|
|
|
|
|
context_max?: number
|
|
|
|
|
context_percent?: number
|
|
|
|
|
context_used?: number
|
|
|
|
|
cost_status?: 'estimated' | 'exact'
|
|
|
|
|
cost_usd?: number
|
|
|
|
|
input?: number
|
|
|
|
|
model?: string
|
|
|
|
|
output?: number
|
|
|
|
|
total?: number
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
export interface SessionCompressResponse {
|
|
|
|
|
info?: SessionInfo
|
|
|
|
|
messages?: GatewayTranscriptMessage[]
|
|
|
|
|
removed?: number
|
|
|
|
|
usage?: Usage
|
2026-04-15 14:14:01 -05:00
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
export interface SessionBranchResponse {
|
|
|
|
|
session_id?: string
|
|
|
|
|
title?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SessionCloseResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SessionInterruptResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
feat(steer): /steer <prompt> injects a mid-run note after the next tool call (#12116)
* feat(steer): /steer <prompt> injects a mid-run note after the next tool call
Adds a new slash command that sits between /queue (turn boundary) and
interrupt. /steer <text> stashes the message on the running agent and
the agent loop appends it to the LAST tool result's content once the
current tool batch finishes. The model sees it as part of the tool
output on its next iteration.
No interrupt is fired, no new user turn is inserted, and no prompt
cache invalidation happens beyond the normal per-turn tool-result
churn. Message-role alternation is preserved — we only modify an
existing role:"tool" message's content.
Wiring
------
- hermes_cli/commands.py: register /steer + add to ACTIVE_SESSION_BYPASS_COMMANDS.
- run_agent.py: add _pending_steer state, AIAgent.steer(), _drain_pending_steer(),
_apply_pending_steer_to_tool_results(); drain at end of both parallel and
sequential tool executors; clear on interrupt; return leftover as
result['pending_steer'] if the agent exits before another tool batch.
- cli.py: /steer handler — route to agent.steer() when running, fall back to
the regular queue otherwise; deliver result['pending_steer'] as next turn.
- gateway/run.py: running-agent intercept calls running_agent.steer(); idle-agent
path strips the prefix and forwards as a regular user message.
- tui_gateway/server.py: new session.steer JSON-RPC method.
- ui-tui: SessionSteerResponse type + local /steer slash command that calls
session.steer when ui.busy, otherwise enqueues for the next turn.
Fallbacks
---------
- Agent exits mid-steer → surfaces in run_conversation result as pending_steer
so CLI/gateway deliver it as the next user turn instead of silently dropping it.
- All tools skipped after interrupt → re-stashes pending_steer for the caller.
- No active agent → /steer reduces to sending the text as a normal message.
Tests
-----
- tests/run_agent/test_steer.py — accept/reject, concatenation, drain,
last-tool-result injection, multimodal list content, thread safety,
cleared-on-interrupt, registry membership, bypass-set membership.
- tests/gateway/test_steer_command.py — running agent, pending sentinel,
missing steer() method, rejected payload, empty payload.
- tests/gateway/test_command_bypass_active_session.py — /steer bypasses
the Level-1 base adapter guard.
- tests/test_tui_gateway_server.py — session.steer RPC paths.
72/72 targeted tests pass under scripts/run_tests.sh.
* feat(steer): register /steer in Discord's native slash tree
Discord's app_commands tree is a curated subset of slash commands (not
derived from COMMAND_REGISTRY like Telegram/Slack). /steer already
works there as plain text (routes through handle_message → base
adapter bypass → runner), but registering it here adds Discord's
native autocomplete + argument hint UI so users can discover and
type it like any other first-class command.
2026-04-18 04:17:18 -07:00
|
|
|
export interface SessionSteerResponse {
|
|
|
|
|
status?: 'queued' | 'rejected'
|
|
|
|
|
text?: string
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
// ── Prompt / submission ──────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
export interface PromptSubmitResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface BackgroundStartResponse {
|
|
|
|
|
task_id?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface BtwStartResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ClarifyRespondResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ApprovalRespondResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SudoRespondResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SecretRespondResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Shell / clipboard / input ────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
export interface ShellExecResponse {
|
|
|
|
|
code: number
|
|
|
|
|
stderr?: string
|
|
|
|
|
stdout?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ClipboardPasteResponse {
|
|
|
|
|
attached?: boolean
|
|
|
|
|
count?: number
|
|
|
|
|
height?: number
|
|
|
|
|
message?: string
|
|
|
|
|
token_estimate?: number
|
|
|
|
|
width?: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface InputDetectDropResponse {
|
|
|
|
|
height?: number
|
|
|
|
|
is_image?: boolean
|
|
|
|
|
matched?: boolean
|
|
|
|
|
name?: string
|
|
|
|
|
text?: string
|
|
|
|
|
token_estimate?: number
|
|
|
|
|
width?: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface TerminalResizeResponse {
|
|
|
|
|
ok?: boolean
|
2026-04-15 14:14:01 -05:00
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
// ── Image attach ─────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
export interface ImageAttachResponse {
|
|
|
|
|
height?: number
|
|
|
|
|
name?: string
|
|
|
|
|
remainder?: string
|
|
|
|
|
token_estimate?: number
|
|
|
|
|
width?: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Voice ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
export interface VoiceToggleResponse {
|
|
|
|
|
enabled?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface VoiceRecordResponse {
|
|
|
|
|
text?: string
|
|
|
|
|
}
|
|
|
|
|
|
refactor(tui): stop shadowing python — slash fallback inherits worker output
Python's slash worker already prints every echo/panel command through Rich.
TS was reformatting the same data client-side for 23 commands. Delete those
shadows; let the `slash.exec` fallback in `createSlashHandler` route the
worker's text (via `<Ansi>`) and page-wrap long output.
TS registry now contains 23 commands (down from 45) — only those that:
- mutate React-local state (composer, transcript, overlays, uiStore)
- touch the terminal (OSC52 copy, `$EDITOR`, clipboard)
- open pickers (`/model`, `/resume`)
- trigger history surgery (`/undo`, `/retry`, `/compress`, `/personality`)
- need TS-only composition (`/help` merges HOTKEYS + catalog)
Deleted shadows:
session: yolo, skin, verbose, reasoning, provider, stop, reload-mcp,
save, title, insights, debug, fast, platforms, snapshot,
usage, history, profile
ops: plugins, rollback, agents, tasks, cron, config, toolsets,
browser, skills (list/browse only; `/tools configure` kept
for its history-reset side effect)
Side effects:
- Drops `slash/shared.ts` + `SlashShared` + `shared`/`SLASH_OUTPUT_PAGE` —
generic slash.exec fallback handles titled paging via `createSlashHandler`.
- Prunes 17 now-unreferenced `*Response` interfaces from gatewayTypes.ts.
- `createSlashHandler` fallback now pages long output (len>180 || lines>2)
and uses the command name as title.
session.ts: 670 -> 199 (-70%)
ops.ts: 460 -> 52 (-88%)
gatewayTypes.ts: 450 -> 302 (-33%)
2026-04-16 14:26:15 -05:00
|
|
|
// ── Tools (TS keeps configure since it resets local history) ─────────
|
2026-04-15 14:14:01 -05:00
|
|
|
|
|
|
|
|
export interface ToolsConfigureResponse {
|
|
|
|
|
changed?: string[]
|
|
|
|
|
enabled_toolsets?: string[]
|
|
|
|
|
info?: SessionInfo
|
|
|
|
|
missing_servers?: string[]
|
|
|
|
|
reset?: boolean
|
|
|
|
|
unknown?: string[]
|
|
|
|
|
}
|
|
|
|
|
|
refactor(tui): stop shadowing python — slash fallback inherits worker output
Python's slash worker already prints every echo/panel command through Rich.
TS was reformatting the same data client-side for 23 commands. Delete those
shadows; let the `slash.exec` fallback in `createSlashHandler` route the
worker's text (via `<Ansi>`) and page-wrap long output.
TS registry now contains 23 commands (down from 45) — only those that:
- mutate React-local state (composer, transcript, overlays, uiStore)
- touch the terminal (OSC52 copy, `$EDITOR`, clipboard)
- open pickers (`/model`, `/resume`)
- trigger history surgery (`/undo`, `/retry`, `/compress`, `/personality`)
- need TS-only composition (`/help` merges HOTKEYS + catalog)
Deleted shadows:
session: yolo, skin, verbose, reasoning, provider, stop, reload-mcp,
save, title, insights, debug, fast, platforms, snapshot,
usage, history, profile
ops: plugins, rollback, agents, tasks, cron, config, toolsets,
browser, skills (list/browse only; `/tools configure` kept
for its history-reset side effect)
Side effects:
- Drops `slash/shared.ts` + `SlashShared` + `shared`/`SLASH_OUTPUT_PAGE` —
generic slash.exec fallback handles titled paging via `createSlashHandler`.
- Prunes 17 now-unreferenced `*Response` interfaces from gatewayTypes.ts.
- `createSlashHandler` fallback now pages long output (len>180 || lines>2)
and uses the command name as title.
session.ts: 670 -> 199 (-70%)
ops.ts: 460 -> 52 (-88%)
gatewayTypes.ts: 450 -> 302 (-33%)
2026-04-16 14:26:15 -05:00
|
|
|
// ── Model picker ─────────────────────────────────────────────────────
|
2026-04-16 12:18:56 -05:00
|
|
|
|
|
|
|
|
export interface ModelOptionProvider {
|
|
|
|
|
is_current?: boolean
|
|
|
|
|
models?: string[]
|
|
|
|
|
name: string
|
|
|
|
|
slug: string
|
|
|
|
|
total_models?: number
|
2026-04-15 14:14:01 -05:00
|
|
|
warning?: string
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
export interface ModelOptionsResponse {
|
|
|
|
|
model?: string
|
|
|
|
|
provider?: string
|
|
|
|
|
providers?: ModelOptionProvider[]
|
|
|
|
|
}
|
|
|
|
|
|
refactor(tui): stop shadowing python — slash fallback inherits worker output
Python's slash worker already prints every echo/panel command through Rich.
TS was reformatting the same data client-side for 23 commands. Delete those
shadows; let the `slash.exec` fallback in `createSlashHandler` route the
worker's text (via `<Ansi>`) and page-wrap long output.
TS registry now contains 23 commands (down from 45) — only those that:
- mutate React-local state (composer, transcript, overlays, uiStore)
- touch the terminal (OSC52 copy, `$EDITOR`, clipboard)
- open pickers (`/model`, `/resume`)
- trigger history surgery (`/undo`, `/retry`, `/compress`, `/personality`)
- need TS-only composition (`/help` merges HOTKEYS + catalog)
Deleted shadows:
session: yolo, skin, verbose, reasoning, provider, stop, reload-mcp,
save, title, insights, debug, fast, platforms, snapshot,
usage, history, profile
ops: plugins, rollback, agents, tasks, cron, config, toolsets,
browser, skills (list/browse only; `/tools configure` kept
for its history-reset side effect)
Side effects:
- Drops `slash/shared.ts` + `SlashShared` + `shared`/`SLASH_OUTPUT_PAGE` —
generic slash.exec fallback handles titled paging via `createSlashHandler`.
- Prunes 17 now-unreferenced `*Response` interfaces from gatewayTypes.ts.
- `createSlashHandler` fallback now pages long output (len>180 || lines>2)
and uses the command name as title.
session.ts: 670 -> 199 (-70%)
ops.ts: 460 -> 52 (-88%)
gatewayTypes.ts: 450 -> 302 (-33%)
2026-04-16 14:26:15 -05:00
|
|
|
// ── MCP ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
export interface ReloadMcpResponse {
|
|
|
|
|
ok?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:18:56 -05:00
|
|
|
// ── Subagent events ──────────────────────────────────────────────────
|
2026-04-16 01:04:35 -05:00
|
|
|
|
2026-04-15 14:14:01 -05:00
|
|
|
export interface SubagentEventPayload {
|
|
|
|
|
duration_seconds?: number
|
|
|
|
|
goal: string
|
|
|
|
|
status?: 'completed' | 'failed' | 'interrupted' | 'running'
|
|
|
|
|
summary?: string
|
|
|
|
|
task_count?: number
|
|
|
|
|
task_index: number
|
|
|
|
|
text?: string
|
|
|
|
|
tool_name?: string
|
|
|
|
|
tool_preview?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type GatewayEvent =
|
|
|
|
|
| { payload?: { skin?: GatewaySkin }; session_id?: string; type: 'gateway.ready' }
|
|
|
|
|
| { payload?: GatewaySkin; session_id?: string; type: 'skin.changed' }
|
|
|
|
|
| { payload: SessionInfo; session_id?: string; type: 'session.info' }
|
|
|
|
|
| { payload?: { text?: string }; session_id?: string; type: 'thinking.delta' }
|
|
|
|
|
| { payload?: undefined; session_id?: string; type: 'message.start' }
|
|
|
|
|
| { payload?: { kind?: string; text?: string }; session_id?: string; type: 'status.update' }
|
|
|
|
|
| { payload: { line: string }; session_id?: string; type: 'gateway.stderr' }
|
|
|
|
|
| { payload?: { cwd?: string; python?: string }; session_id?: string; type: 'gateway.start_timeout' }
|
|
|
|
|
| { payload?: { preview?: string }; session_id?: string; type: 'gateway.protocol_error' }
|
|
|
|
|
| { payload?: { text?: string }; session_id?: string; type: 'reasoning.delta' | 'reasoning.available' }
|
|
|
|
|
| { payload: { name?: string; preview?: string }; session_id?: string; type: 'tool.progress' }
|
|
|
|
|
| { payload: { name?: string }; session_id?: string; type: 'tool.generating' }
|
|
|
|
|
| { payload: { context?: string; name?: string; tool_id: string }; session_id?: string; type: 'tool.start' }
|
|
|
|
|
| {
|
|
|
|
|
payload: { error?: string; inline_diff?: string; name?: string; summary?: string; tool_id: string }
|
|
|
|
|
session_id?: string
|
|
|
|
|
type: 'tool.complete'
|
|
|
|
|
}
|
|
|
|
|
| {
|
|
|
|
|
payload: { choices: string[] | null; question: string; request_id: string }
|
|
|
|
|
session_id?: string
|
|
|
|
|
type: 'clarify.request'
|
|
|
|
|
}
|
|
|
|
|
| { payload: { command: string; description: string }; session_id?: string; type: 'approval.request' }
|
|
|
|
|
| { payload: { request_id: string }; session_id?: string; type: 'sudo.request' }
|
|
|
|
|
| { payload: { env_var: string; prompt: string; request_id: string }; session_id?: string; type: 'secret.request' }
|
|
|
|
|
| { payload: { task_id: string; text: string }; session_id?: string; type: 'background.complete' }
|
|
|
|
|
| { payload: { text: string }; session_id?: string; type: 'btw.complete' }
|
|
|
|
|
| { payload: SubagentEventPayload; session_id?: string; type: 'subagent.start' }
|
|
|
|
|
| { payload: SubagentEventPayload; session_id?: string; type: 'subagent.thinking' }
|
|
|
|
|
| { payload: SubagentEventPayload; session_id?: string; type: 'subagent.tool' }
|
|
|
|
|
| { payload: SubagentEventPayload; session_id?: string; type: 'subagent.progress' }
|
|
|
|
|
| { payload: SubagentEventPayload; session_id?: string; type: 'subagent.complete' }
|
|
|
|
|
| { payload: { rendered?: string; text?: string }; session_id?: string; type: 'message.delta' }
|
2026-04-16 08:27:41 -05:00
|
|
|
| {
|
|
|
|
|
payload?: { reasoning?: string; rendered?: string; text?: string; usage?: Usage }
|
|
|
|
|
session_id?: string
|
|
|
|
|
type: 'message.complete'
|
|
|
|
|
}
|
2026-04-15 14:14:01 -05:00
|
|
|
| { payload?: { message?: string }; session_id?: string; type: 'error' }
|