OpenTUI 0.6.3
A coding agent such as opencode can wait for minutes at a permission prompt in a background tab. Before this release, the terminal could not tell the user about it. In 0.6.3, the agent can report its state to the terminal:
renderer.setProgramStatus({ state: "blocked", kind: "permission", app: "opencode", message: "Allow bash?" })
This call writes one report in the
Program Status Protocol,
OSC 7501. The terminal decides how to show the report. It can use a tab
indicator, an inbox entry, or a desktop notification. A terminal that does not
implement the protocol ignores the sequence, so setProgramStatus() does not
wait for capability detection. capabilities.program_status only tells you that
a reply arrived. A false value can also mean that the reply has not arrived
yet.
Each report replaces one record, and a field that a report omits is gone from
the record. Send app and title with every report that needs them. A program
that runs several tasks can give each task its own record with an id. It can
then remove that record with clear:
renderer.setProgramStatus({ state: "working", id: "subagent-1", title: "Explore", progress: 40 })
renderer.setProgramStatus({ state: "clear", id: "subagent-1" })
Records belong to the terminal, not to the renderer. OpenTUI does not clear them
when the renderer is destroyed or suspended. When the process exits, the
terminal drops working and blocked records. It keeps done and error
records for the user to find. If the user should see the result, report done or
error before the program exits. OpenTUI also does not wrap reports in tmux or
GNU Screen passthrough. The outer terminal cannot tell panes apart or see the
program exit, so a working record from a pane would never clear.
C hosts send the same report with ot_session_control() and
OT_CONTROL_PROGRAM_STATUS. The payload is an ot_session_program_status struct,
followed by the id, app, title, and message bytes. Native code checks every
report on both paths before it writes anything. A report that a terminal would
discard or only partly read fails at the call.
Added
- core:
renderer.setProgramStatus(status)andNativeSession.setProgramStatus(status)send one OSC 7501 program status report. They returnfalsewhen OpenTUI does not queue the report, and they throw for an invalid report. See Program status. (#1657) - core:
TerminalCapabilities.program_statusistruewhen the terminal replies to theOSC 7501 ; ?query. The renderer sends this query at startup with the other capability queries, but not to foot. See Terminal capabilities. (#1657) - native:
ot_session_control()withOT_CONTROL_PROGRAM_STATUSand anot_session_program_statuspayload sends a program status report.OT_CAP_PROGRAM_STATUSis set when the terminal replies to the query. See Program status. (#1657)
Changed
- native:
ot_session_control()now checks the payload before the terminal phase. While the terminal is not active, an invalid payload returnsOT_INVALID_ARGUMENTinstead ofOT_INVALID_PHASE. A title with control characters is one example. See Frames and output. (#1657)
API changes#
@opentui/core#
Added
method CliRenderer.setProgramStatus(status: ProgramStatus): booleanmethod NativeSession.setProgramStatus(status: ProgramStatus): booleanproperty TerminalCapabilities.program_status: booleantype ProgramStatus = (ProgramStatusRecord & { state: "idle" | "done" | "error"; }) | (ProgramStatusRecord & { state: "working"; progress?: number; }) | (ProgramStatusRecord & { state: "blocked"; kind?: ProgramStatusKind; progress?: number; }) | { state: "clear"; id?: string; }type ProgramStatusKind = "permission" | "question" | "auth"
Changed
type NativeSessionControl = { kind: "capability-response"; bytes: Uint8Array; } | { kind: "palette-query"; bytes: Uint8Array; } | { kind: "title"; title: string; } | { kind: "mouse"; mode: "disabled" | "drag" | "motion"; } | { kind: "kitty-keyboard-flags"; flags: number; } | { kind: "restore-modes" | "query-pixel-resolution" | "query-theme-colors" | "reset-background"; }type NativeSessionControl = { kind: "capability-response"; bytes: Uint8Array; } | { kind: "palette-query"; bytes: Uint8Array; } | { kind: "title"; title: string; } | { kind: "mouse"; mode: "disabled" | "drag" | "motion"; } | { kind: "kitty-keyboard-flags"; flags: number; } | { kind: "program-status"; status: ProgramStatus; } | { kind: "restore-modes" | "query-pixel-resolution" | "query-theme-colors" | "reset-background"; }
opentui.h#
Added
const OT_CAP_PROGRAM_STATUS = 131072const OT_CONTROL_PROGRAM_STATUS = 11const OT_PROGRAM_KIND_AUTH = 3const OT_PROGRAM_KIND_PERMISSION = 1const OT_PROGRAM_KIND_QUESTION = 2const OT_PROGRAM_STATE_BLOCKED = 4const OT_PROGRAM_STATE_CLEAR = 6const OT_PROGRAM_STATE_DONE = 3const OT_PROGRAM_STATE_ERROR = 5const OT_PROGRAM_STATE_IDLE = 1const OT_PROGRAM_STATE_WORKING = 2const OT_PROGRAM_STATUS_PROGRESS = 1struct ot_session_program_status