Every named declaration in the file, 570 of them, verbatim and in the order Claude Code wrote them, 50 to a page. This is the page to land on from a signature: a verb that returns ToolCallResult links here, at whichever page it is on, and what you get is the declaration itself rather than a description of it.
The source is 13,820 lines of TypeScript mined from build 2.1.283. Anything longer than 12 lines is folded; click the line count to open it. To find a name on another page, search every symbol.
Names on this page, 301 to 350 of 570
RenderComponent type
#
line 8025
In the first published surface (2.1.259) · changed in 2.1.265, 2.1.271, 2.1.277
Everything ui.render can draw: one name per component that has a render site; a matcher narrows on it.
The permission dialog is drawn by the engine alone, since its answer authorises an action; a plugin adds context with $.ui.notice. Pane is the one component whose instances a plugin opens ($.ui.open).
export type RenderComponent = 'AskUserQuestion' | 'UserMessage' | 'AssistantMessage' | 'ToolUse' | 'ToolResult' | 'ToolGroup' | 'ToolProgress' | 'CommandOutput' | 'Spinner' | 'TurnDuration' | 'InfoNotice' | 'SessionMode' | 'PromptHint' | 'AbovePrompt' | 'Pane';
RenderElement type
#
line 8035
In the first published surface (2.1.259) · changed in 2.1.260, 2.1.265, 2.1.267, 2.1.271, 2.1.274, 2.1.275, 2.1.277, 2.1.282, 2.1.283
What a render hook returns, and what next(e) resolves to: a plain-data tree of elements (a Box or Text is a StyledElement), strings as children.
Props are an allowlisted subset of Ink's Box/Text props (the ones ElementProps declares); a tree with any other prop fails validation as a whole and the engine's own component is drawn with the original props.
321 lines
export type RenderElement = StyledElement<'Box', BoxHoverProps> | StyledElement<'Text', TextHoverProps> | {
/**
* A button, on every surface: `[ label ]` on the terminal, a native
* button on a desktop; a press raises `ui.press` (`e.element` the key).
*
* Built by `<Button>` or the table's `t.Button`. The `onPress` closure
* stays in the plugin's own environment under `press.handle`; the host
* holds the handle for the lifetime of the drawing. A leaf: no children.
*/
type: 'Button';
props: {
/**
* The element's address: what `e.element` carries and what a matcher
* names (`{ element: "explain" }`).
*/
key: string;
/**
* The text drawn on the button.
*/
label: string;
/**
* One digit (`"1"`) or one lowercase letter (`"w"`) that presses it
* while the plugin's site holds the focus; anything else is refused.
*
* The band after ctrl+x tab or a click, a focused `Pane`: on keydown,
* lowercased; never from the composer, save a bare digit in an empty
* one pressing a band Button. Two on one hotkey: the later wins.
*/
hotkey?: string;
/**
* An engine keybinding action (`"app:cycleDiffBase"`) whose chord
* presses the Button from the prompt; an unknown name is refused.
*
* Chords, or a modified key Global or an active context binds, on
* the terminal while mounted, no dialog up, no engine handler of it
* mounted; a pane's over the band's over another's, the last drawn.
*/
action?: string;
/**
* Drawn without chrome: the hotkey in the accent color, a colon,
* then the label (`1: Yes`); without a `hotkey`, the label alone.
*
* The focus still inverts it. In JSX the label may be the one string
* child (`<Button hotkey="1" plain onPress={...}>Yes</Button>`); the
* key defaults to the label.
*/
plain?: true;
/**
* The label dim at rest, as `Text`'s `dimColor`, and at full strength
* under the pointer or the focus; absent draws as false.
*/
dimColor?: TextProps['dimColor'];
/**
* `"primary"` marks the main action of several, drawn as the surface
* marks the one to press; `"secondary"`, and absent, draw as before.
*
* The terminal draws a primary in the accent color; `plain` wins over
* it. Carried to every surface as written, never filled in.
*
* @example { key: 'save', label: 'Save', variant: 'primary' }
*/
variant?: ButtonProps['variant'];
/**
* `"dismiss"` marks the Button that closes its site, a drawing hint
* only: the terminal draws it as without, a desktop its close control.
*
* Carried to every surface as written, never filled in.
*
* @example { key: 'dismiss', label: 'Dismiss', role: 'dismiss' }
*/
role?: ButtonProps['role'];
/**
* The site's ring starts on this element when the site takes the
* keyboard; the first drawn of several. Absent draws as before.
*/
autoFocus?: true;
};
/**
* Where the handler lives: the plugin whose hook drew the element, and
* the handle its environment keeps the `onPress` closure under.
*
* The runtime stamps the plugin as the tree leaves that hook.
*/
press: {
plugin: string;
handle: number;
};
/**
* Label style overrides (the Text set) the surface applies while the
* nearest keyed Box, or the group `scope` names, is hovered; plain data.
*/
hover?: TextHoverProps;
} | {
/**
* A one-line text field on every surface; a change and Enter raise
* `ui.input` (`e.element` the key, `e.kind` which, `e.value` the text).
*
* Built by `<Input>` or the table's `t.Input`. The `onInput` and
* `onSubmit` closures stay in the plugin's own environment under
* `press.handle`, held as a Button's is. A leaf: no children.
*/
type: 'Input';
props: {
/**
* The element's address: what `e.element` carries and what a matcher
* names (`{ element: "reply" }`).
*/
key: string;
/**
* Text drawn before the field.
*/
label?: string;
/**
* Text drawn dim in an empty field.
*/
placeholder?: string;
/**
* The text the field holds when drawn.
*/
value?: string;
/**
* What Enter does, drawn beside the field while it has focus.
*/
submitLabel?: string;
/**
* The site's ring starts on this element when the site takes the
* keyboard; the first drawn of several. Absent draws as before.
*/
autoFocus?: true;
};
/**
* Where the handlers live: the plugin whose hook drew the element, and
* the handle its environment keeps the closures under.
*
* The runtime stamps the plugin as the tree leaves that hook.
*/
press: {
plugin: string;
handle: number;
};
children?: undefined;
} | {
/**
* A one-of-several picker on every surface; a pick raises `ui.select`
* (`e.element` the key, `e.value` the option's value).
*
* Built by `<Select>` or the table's `t.Select`. The `onSelect` closure
* stays in the plugin's own environment under `press.handle`, held as
* a Button's is. A leaf: no children.
*/
type: 'Select';
props: {
/**
* The element's address: what `e.element` carries and what a matcher
* names (`{ element: "peer" }`).
*/
key: string;
/**
* Text drawn before the current value.
*/
label?: string;
/**
* What can be picked, in the order drawn: each a value and the text
* drawn for it.
*/
options: readonly SelectOption[];
/**
* Which option is selected when drawn.
*/
value?: string;
/**
* The site's ring starts on this element when the site takes the
* keyboard; the first drawn of several. Absent draws as before.
*/
autoFocus?: true;
};
/**
* Where the handler lives: the plugin whose hook drew the element, and
* the handle its environment keeps the closure under.
*
* The runtime stamps the plugin as the tree leaves that hook.
*/
press: {
plugin: string;
handle: number;
};
children?: undefined;
} | {
/**
* A hyperlink every surface draws: an OSC 8 span on the terminal (its
* text then the URL in dim where unsupported), an anchor on desktop.
*
* Inline: its children are the text, strings and inline elements;
* absent children the label, absent both the URL. `href` is `https:`
* (or `http://localhost`) and bounded, or the tree is refused.
*/
type: 'Link';
props: LinkProps;
children?: RenderNode[];
} | {
/**
* Source code every surface draws with the engine's highlighter, tokens
* coloured by language; under `format: 'diff'`, unified-diff hunks.
*
* A leaf: a dim gutter numbers the lines from `startLine`; a diff has
* both gutters, markers, add and remove backgrounds. `source` is
* bounded as a Text's string is, or the tree is refused.
*/
type: 'Code';
props: CodeProps;
children?: undefined;
} | {
/**
* A block of markdown every surface draws as it draws an assistant
* reply's text: its own renderer, theme, hyperlinks and highlighting.
*
* Built by `<Markdown>` or the table's `t.Markdown`. A leaf: `text` is
* bounded as a Text's string is, or the tree is refused. Without a
* `press` its links are the surface's own, opened as it opens links.
*/
type: 'Markdown';
props: MarkdownLeafProps;
children?: undefined;
} | {
/**
* A `Markdown` whose plugin answers the links it drew (`onLinkPress`):
* a press on one raises `ui.press` with `e.link`, the surface opens none.
*/
type: 'Markdown';
props: MarkdownLeafProps;
/**
* Where the `onLinkPress` handler lives: the plugin whose hook drew
* the element, and the handle its environment keeps the closure under.
*
* The runtime stamps the plugin as the tree leaves that hook.
*/
press: {
plugin: string;
handle: number;
};
children?: undefined;
} | {
/**
* A region one of the plugin's SURFACE MODULES, named by path, draws and
* handles input for on the drawing thread, without `$` (ClientModule).
*
* `Client` from the table. One instance per plugin, drawing and `key`
* lives while the node stays in the tree, and talks to the plugin's
* hooks through `ui.message`. The desktop carries it as data.
*/
type: 'Client';
props: ClientProps;
/**
* Whose surface module `props.module` names: the plugin whose hook
* drew the element, stamped by the runtime as the tree leaves it.
*/
client: {
plugin: string;
};
children?: undefined;
} | {
/**
* A vector drawing, the remote surfaces' alone: the SVG markup is the
* element's data, drawn in an isolated box, off the page.
*
* A leaf: hooks above wrap or replace it whole, nothing reaches inside;
* a press other plugins should see goes on an enclosing Button. On a
* surface whose table lacks it the tree is refused.
*/
type: 'Svg';
props: SvgProps;
children?: undefined;
} | {
/**
* A grid of terminal cells, the terminal surface's alone: each cell a
* glyph, a foreground and a background, packed in `props.cells`.
*
* A leaf, one node however many cells; hooks above wrap or replace it
* whole. A mounted one is repainted in place by its plugin's
* `$.ui.blit`. On a surface whose table lacks it the tree is refused.
*/
type: 'Raster';
props: RasterProps;
/**
* Whose Raster: the plugin whose hook drew the element, stamped by the
* runtime as the tree leaves it; the one plugin whose blit reaches it.
*/
raster: {
plugin: string;
};
children?: undefined;
} | {
/**
* A picture, the terminal surface's alone: `props.source` drawn over a
* box of cells where the terminal can, `props.alt` where it cannot.
*
* A leaf: hooks above wrap or replace it whole; a press other plugins
* should see goes on an enclosing Button; keyed, its plugin's
* `$.ui.blit` swaps it. On a surface without it the tree is refused.
*/
type: 'Image';
props: ImageProps;
/**
* Whose Image: the plugin whose hook drew the element, stamped by the
* runtime as the tree leaves it; the one plugin whose blit reaches it.
*/
image: {
plugin: string;
};
children?: undefined;
} | {
/**
* The component core draws itself, with the props held under `ref`.
*/
type: 'engine';
/**
* Which drawing: the number core answered from `next(e)`, under which
* it holds the props it received; 0 draws the original props.
*/
ref: number;
};
RenderEventName type
#
line 8361
In the first published surface (2.1.259)
The render event: ui.render, one event for every component that has a render site.
export type RenderEventName = 'ui.render';
RenderInput type
#
line 8367
In the first published surface (2.1.259)
The input of ui.render: a union discriminated by component, one member per RenderComponent and per RenderSurface.
export type RenderInput<C extends RenderComponent = RenderComponent, P extends RenderSurface = RenderSurface> = C extends RenderComponent ? P extends RenderSurface ? RenderInputOf<C, P> : never : never;
RenderInputOf type
#
line 8372
In the first published surface (2.1.259)
One ui.render input, for a component narrowed to one surface.
34 lines
export type RenderInputOf<C extends RenderComponent, P extends RenderSurface> = {
/**
* Where the tree will be drawn; one literal per member, so
* `if (e.surface === "terminal")` narrows `e` and `$.ui.resolve(e)`.
*
* Over the wire it is what the client declared, a rendering fact and not a
* trust signal: do not key policy on it.
*/
surface: P;
/**
* Which component this instance is; the key a matcher narrows on.
*/
component: C;
/**
* The instance: the tool_use_id for a dialog or tool row, the message id
* for a message, the agent id for a spinner.
*
* Two drawings of one component are two instances.
*/
requestId: string;
/**
* The size of what the surface draws into, in character cells, and whether
* its layout docks a pane; absent where no surface has measured.
*
* Part of the envelope: a rewrite keeps it. On the terminal, the interactive
* screen's, where a change of width re-draws every hooked site once the
* resize settles; on a remote surface, what it reported.
*/
viewport?: RenderViewport;
/**
* The component's plain-data props.
*/
props: RenderPropsOf[C];
};
RenderNode type
#
line 8410
In the first published surface (2.1.259)
A node of a render tree: an element, or a string (text).
export type RenderNode = RenderElement | string;
RenderPropsOf type
#
line 8420
In the first published surface (2.1.259) · changed in 2.1.260, 2.1.265, 2.1.267, 2.1.268, 2.1.269, 2.1.271, 2.1.274, 2.1.275, 2.1.277
The plain-data props of each renderable component, as ui.render sees them under e.props; a hook rewrites them with next({ ...e, props }).
A rewrite is validated by the component and an invalid one draws the original. This table is the plugin-facing render contract; the author's file notes which surfaces raise each member (RENDER_SURFACES_OF).
551 lines
export type RenderPropsOf = {
/**
* The dialog the AskUserQuestion tool opens.
*
* Raised on every surface.
*/
AskUserQuestion: {
/**
* The name of the tool whose call opened the dialog (`AskUserQuestion`).
*/
tool: string;
/**
* The tool's `questions` input, as the dialog will draw them; a rewrite
* must still fit the tool's schema or the original is drawn.
*/
questions: unknown[];
/**
* The call's `metadata.source` (who asked) when the model gave one.
* Analytics only; never drawn.
*/
metadataSource?: string;
};
/**
* A user-role transcript row: the person's prompt (`> ...`), a background
* task's notification, or a message another agent, teammate or session sent.
*
* `origin`, `task` and `from` tell them apart and are read-only; a rewrite
* of `text` draws in the row alone: the stored message, and the model's
* framing of another party's words as that party's, stay as they were.
*
* Raised on every surface.
*/
UserMessage: {
/**
* What the row shows: the prompt as typed, a notification's summary, or
* a message's body less the engine's framing (summary line included).
*
* A rewrite is printable, bounded text and draws where the engine draws
* the body; a teammate block of several frames or with a summary line
* keeps the engine's drawing, one string not being those parts.
*/
text: string;
/**
* Where the stored message came from, as `prompt.submit` named it: the
* composer's, a task notification's, a peer's, a channel's, a plugin's.
*
* `unclassified` for a teammate's (its drain stamps none) and for a
* message stored before stamps. Read-only.
*/
origin: PromptOrigin;
/**
* Whether the view draws the row in full: the ctrl+o transcript,
* `--verbose`, a surface with no ctrl+o (an export). Read-only.
*
* False, a message row is one dim line naming its sender; a hook that
* draws a compact row of its own passes when true, so ctrl+o shows all.
*/
isExpanded: boolean;
/**
* What a notification row (`origin.kind` `task-notification`) reports
* on: its background task; absent on every other row. Read-only.
*/
task?: UserMessageTask;
/**
* Who sent the message the row carries: another agent of this session, a
* teammate, another session, a channel; absent otherwise. Read-only.
*/
from?: UserMessageFrom;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* One text block of an assistant reply in the transcript; a rewrite
* changes the drawing and leaves the stored message alone (ctrl+o).
*
* Raised on every surface.
*/
AssistantMessage: {
/**
* The block's text, markdown, as the surface's transcript will draw it:
* what it hides of a reply (the terminal's, a `<context>` block) is gone.
*/
text: string;
/**
* True on the block that draws the bullet opening a reply.
*/
isFirstOfReply: boolean;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* A tool call's row in the transcript (`Bash(ls -la)` and its result); the
* call was decided by `tool.call`, so a rewrite here changes the row alone.
*
* Raised on every surface.
*/
ToolUse: {
/**
* The id `tool.call` carried for this call (`e.tool_use_id` there); the
* same value as the row's `requestId`, where it is looked for. Read-only.
*/
tool_use_id: string;
/**
* Which one the row draws (`Bash`, `Read`, a plugin's tool), as
* `tool.call` named it.
*/
tool: string;
/**
* The call's input, as the model sent it.
*/
input: unknown;
/**
* True while the call is still running.
*/
isRunning: boolean;
/**
* True when the call ended in an error (a refusal at the dialog is one).
*/
isErrored: boolean;
/**
* True when an abort ended the call: the user's Esc or a plugin's
* `$.turn.abort` cut it while it ran, or dropped it before it ran.
*
* The row draws `Interrupted` for it, as the transcript marker does.
*/
isInterrupted: boolean;
/**
* The stored result once the call has resolved (`{ stdout, stderr, ... }`
* for Bash: `BuiltinToolResults[tool]`); undefined while it runs.
*
* For a call that errored, was refused or an abort cut, it is the text
* the model read (an `isInterrupted` call: the abort's own). An expanded
* group's rows draw it inline; a standalone row's is its own `ToolResult`.
*/
output?: unknown;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* The result block drawn under a standalone tool row in the transcript,
* which the tool's own result renderer draws from `output`.
*
* A rewrite of `output` is checked against the tool's output schema (one
* that does not fit draws nothing; one the renderer cannot read hits the
* row's error boundary). The stored result is untouched.
*
* Raised on every surface.
*/
ToolResult: {
/**
* The id `tool.call` carried for the call this result belongs to
* (`e.tool_use_id` there); the same value as `requestId`. Read-only.
*/
tool_use_id: string;
/**
* Which one the result belongs to (`Bash`, `Read`, a plugin's tool).
* Read-only.
*/
tool: string;
/**
* The tool's own result object (`{ stdout, stderr, interrupted, ... }` for
* Bash), the same one `ToolUse.output` carries; a rewrite is drawn.
*
* A built-in tool's is `BuiltinToolResults[tool]`, the record
* `tool.call` resolved as `result`.
*/
output: unknown;
/**
* True when the call ended in an error, which draws the error text and not
* `output`. Read-only.
*/
isErrored: boolean;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* A run of tool calls the transcript folds into one count line (`Read 3
* files, ran 2 shell commands`): reads, searches, listings.
*
* A hook that sets `isExpanded` unfolds the group where it is, and each row
* it unfolds into is a `ToolUse` drawing a `ToolUse` hook then sees.
*
* Raised on every surface.
*/
ToolGroup: {
/**
* In the order the model made them.
*/
calls: ReadonlyArray<ToolGroupCall>;
/**
* True while the group is the live one: a call in it may still be
* running and the model's next call may join it.
*/
isActive: boolean;
/**
* Whether each call draws as its own `ToolUse` row (true under
* `--verbose` and in the ctrl+o transcript) or the group draws one line.
*
* The one prop of the three a rewrite changes on the screen.
*/
isExpanded: boolean;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* The output row a slash command printed in the transcript, under its echo
* (`/cost`'s lines, the `text` a `command.run` hook answered).
*
* What the run resolved as text, a `local` command's or a plugin's alike. A
* rewrite of `text` draws there and the stored row keeps what the model
* reads; a hook's own tree draws in the row's place, the transcript's width.
*
* Raised on every surface.
*/
CommandOutput: {
/**
* Which one printed the row, as `command.run` named it (no slash); a
* hook on its own command matches by it.
*
* Read-only: a rewrite carries it on as received; one that changes or
* drops it is refused and the engine draws its own row.
*/
command: string;
/**
* The arguments the run had, as the echo above the row shows them
* (`***` for a command that marks its arguments sensitive). Read-only.
*/
args: string;
/**
* The row's text: what the command printed, or the `text` a hook
* answered under its plugin's name; markdown, as the row draws it.
*/
text: string;
/**
* True when the row is the run's error line (a command that threw),
* which draws in the error colour and not dim. Read-only.
*/
isErrored: boolean;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* One row of the live tool-progress region under a running tool call; today
* the run-in-background pill. One instance per row.
*
* A union on `kind`: other progress kinds join as their props become plain
* data, each with its own fields, so a hook matches `{ props: { kind:
* "background_hint" } }` or branches on `e.props.kind` and stays right.
*
* Raised on the terminal surface only.
*/
ToolProgress: {
/**
* The tool call the row belongs to, as `tool.call` and the `ToolUse` row
* carry it. Read-only: a rewrite carries it on as received.
*
* While several foreground calls share one pill, the first of them.
*/
tool_use_id: string;
/**
* Which progress row: the run-in-background pill. Read-only.
*/
kind: 'background_hint';
/**
* The pill's text as the engine draws it, dim, under the tool call:
* `(ctrl+b to run in background)`, or with the person's own binding.
*
* A rewrite is drawn in its place, dim; `""` draws nothing. A hook that
* returns a tree draws that instead.
*/
hint: string;
};
/**
* The line that animates while a turn runs (`Sauteing... (12s, 300
* tokens)`); on the desktop, the row that carries the turn's mark.
*
* Reads `word` (or `message` while one overrides it), `suffix`, then what
* the surface keeps and no prop carries: elapsed time, tokens, effort. A
* hook rewrites the first three, or draws a tree in place of all of it.
*
* Raised on the terminal and desktop surfaces only.
*/
Spinner: {
/**
* Animated by the line (`Sauteing`), as sampled for this turn.
*
* On the desktop, what the row says its step is doing (`Creating
* notes.md`), or `Working` while the row shows no words.
*/
word: string;
/**
* The text drawn instead of the word while a state overrides it, else null.
*/
message: string | null;
/**
* What the engine draws right after the word or message to say the turn is
* still going: one ellipsis character.
*
* Left off a text that already ends in an ellipsis, so a rewritten
* `message` ending in one shows one. A rewrite is drawn as given (`""`
* draws the text bare, `" ~"` draws `Sauteing ~`); left out, the engine's.
*/
suffix: string;
/**
* What the turn is doing. The desktop tells `thinking`, `requesting`,
* `tool-use` and `responding` apart and never says `tool-input`.
*/
mode: 'requesting' | 'responding' | 'thinking' | 'tool-input' | 'tool-use';
};
/**
* The line that closes a turn in the transcript (`Baked for 3s`); a
* remote surface draws its own footer.
*
* Raised on the terminal surface only.
*/
TurnDuration: {
/**
* The past-tense word the line drew (`Baked`), as sampled for this line.
*/
word: string;
/**
* The turn's duration in milliseconds, as the line formats it (`3s`,
* `1m 4s`).
*/
durationMs: number;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* One dim status line under the logo (the model source, an experiment
* enrollment, a settings hint), with a trailing `/command`.
*
* Raised on the terminal surface only.
*/
InfoNotice: {
/**
* The notice's text, flattened to one string.
*/
text: string;
/**
* The slash command appended after the text, or null when the notice has
* none.
*/
command: string | null;
/**
* Which of its rows the transcript's viewport shows now: `null` while
* drawn outside it, absent where the surface does not say. Read-only.
*
* Reported once drawn and again when it changes: on a scroll, for the
* messages at the viewport's edges only. A rewrite carries it on as
* received; one that changes or drops it is refused.
*/
onScreen?: OnScreen | null;
};
/**
* The dim mode labels at the right of the prompt footer (`focus`, `memory
* paused`), joined by ` & `. One instance.
*
* A hook adds a mode by rewriting `modes`, removes one by filtering, or
* draws its own tree.
*
* Raised on the terminal and desktop surfaces only.
*/
SessionMode: {
/**
* The labels the footer shows, in order; empty when there are none.
*/
modes: readonly string[];
};
/**
* The dim hint line under the prompt (`? for shortcuts`, `esc to
* interrupt`, the pills beside them). One instance.
*
* A hook rewrites `hint`, drawn in the line's place, or draws its own tree;
* `isDraft` and `isWorking` say what the line is for. On the terminal, until
* a new answer lands the last keeps its row (the engine's line before any).
*
* Raised on the terminal and desktop surfaces only.
*/
PromptHint: {
/**
* True while the prompt holds typed text. Read-only.
*/
isDraft: boolean;
/**
* True while a model turn is running. Read-only.
*/
isWorking: boolean;
/**
* The line's text as the engine draws it; one string, so a rewrite
* replaces the line.
*
* Read from the drawn line the way the screen reader reads it, one space
* between parts.
*/
hint: string;
};
/**
* The band directly above the prompt input, where the surveys draw; the
* engine draws nothing of its own here.
*
* A hook draws a tree, or passes; one instance. The person collapses it
* (ctrl+x ctrl+a, `[-]`) or focuses it (a click, ctrl+x tab): an Input
* types, a Button arms the hotkeys, a tree taller than it scrolls.
*
* Raised on the terminal and desktop surfaces only.
*/
AbovePrompt: {
/**
* True while a survey holds the band; a hook yields to it. Read-only.
*/
hasSurvey: boolean;
/**
* True while a model turn is running. Read-only.
*/
isWorking: boolean;
/**
* Rows the band may take: in fullscreen, what the bottom slot has left
* above the prompt; otherwise the terminal's height. Read-only.
*
* That slot is capped at half the terminal's rows, the prompt's included.
* A tree of at most `maxRows` rows shows whole; a taller one scrolls in a
* window of `scroll.bodyRows`, and a bare digit arms no Button's hotkey.
*/
maxRows: number;
/**
* Cells across the band: the terminal's width, or the transcript
* column's while a `Pane` is docked beside it. Read-only.
*
* A tree wider than this wraps or truncates as its Text props say; size
* a table or a rule to it rather than to `viewport.columns`.
*/
bodyColumns: number;
/**
* The band's window over a tree taller than `maxRows`: engine-owned,
* moved by the wheel, and by the person's keys while the band is focused.
*
* `bodyRows` is `maxRows` less the `n more` row. Read-only.
*/
scroll: SiteScroll;
/**
* Which transcript is on screen above the band: the main conversation's
* (no `agentId`) or one agent's, opened from the tasks list.
*
* The same band under either; a switch re-runs the hook with the new
* view. Read-only: a rewrite carries it on as received; one that changes
* or drops it is refused, the hook that passed it failing.
*/
view: SiteView;
};
/**
* The framed region a plugin opened with `$.ui.open({ id })`: one instance
* per id (`requestId`), its body the hook's tree, one shown, the rest tabs.
*
* Placed by the surface (docked in fullscreen, else above the prompt) and
* keyed by the person (ctrl+x tab, Esc), who closes it from the engine's mark
* or ctrl+x x: `ui.close` with origin `person`, which a hook may refuse.
*
* Raised on every surface.
*/
Pane: {
/**
* Its tab's label while more than one pane is open (with one, the engine
* draws no title): the `title` it was opened with, or its id.
*
* A click on a tab, or Tab onto it and Enter, shows that pane. Read-only
* here; another `$.ui.open` (or a hook on `ui.open`) retitles.
*/
title: string;
/**
* True while the person has given the pane the keyboard: Tab walks its
* elements, a Button's `hotkey` presses it, the arrows scroll. Read-only.
*/
isFocused: boolean;
/**
* Cells across the body, inside the frame. Read-only.
*/
bodyColumns: number;
/**
* Where the surface seated the pane: `dock` beside the transcript (the
* terminal in fullscreen from 110 columns), or `inline` above the prompt.
*
* Read-only: a rewrite carries it on as received; one that changes or
* drops it is refused, the hook that passed it failing.
*/
placement: 'dock' | 'inline';
/**
* The body's window over the tree: engine-owned, moved by the person's
* keys while the pane is focused. Read-only.
*/
scroll: SiteScroll;
/**
* Which transcript is on screen beside the pane: the main conversation's
* (no `agentId`) or one agent's, opened from the tasks list.
*
* The pane stays open across a switch, one instance re-rendered for the
* view, so a hook draws for the agent in view. Read-only: a rewrite carries
* it on as received; one that changes or drops it is refused.
*/
view: SiteView;
};
};
RenderResultOf type
#
line 8976
In the first published surface (2.1.259)
What a ui.render hook returns and what next(e) resolves to: a RenderElement tree, the same for every component.
export type RenderResultOf = {
[C in RenderComponent]: RenderElement;
};
RenderSurface type
#
line 8992
In the first published surface (2.1.259) · changed in 2.1.268, 2.1.273
Where a render event's component is drawn: terminal is Ink, which draws the hook's whole tree; the rest are remote surfaces drawing it themselves.
desktop is Claude Code Desktop, mobile the Claude mobile app, vscode Claude Code for VS Code. A remote surface asks over the wire (ui_render), draws with the props the hook handed core, and draws the tree where it has a slot for it.
Each surface's ask is its own evaluation, since a tree may hold an element only some surfaces draw (Svg, Client).
export type RenderSurface = 'terminal' | 'desktop' | 'mobile' | 'vscode';
RenderViewport type
#
line 9002
In the first published surface (2.1.259) · changed in 2.1.275
The size of what a surface draws into, in character cells of the surface's monospace metric, and whether its layout docks a pane.
On the terminal, the conversation's columns and screen rows; on a remote surface, the pane's width and height over the advance and line height of its code font. Cell-based until the first element lays out in pixels.
27 lines
export type RenderViewport = {
/**
* Cells across. A tree wider than this wraps or truncates, as its Text
* props say.
*/
columns: number;
/**
* Cells down the whole surface, not the room left for this component.
*
* Informational: a change of height alone re-draws nothing and keys no
* new evaluation, so a hook reads it as of the last width or props change.
*/
rows: number;
/**
* Whether this surface docks a pane beside the transcript, so a pane a
* plugin opens unasked is a sidebar, not a takeover; absent is unknown.
*
* What `command.run`'s `presentation.isFullscreen` says. The terminal always
* says: `true` fullscreen, `false` on the main screen, fixed per session; a
* remote surface once its client reports it with the size, absent before.
*
* @remarks A remote surface that reports it places panes (`$.ui.open` is
* placed there); the mobile app reports `false`. A change re-draws.
* @example if (e.viewport?.isFullscreen === true) void $.ui.open({ id })
*/
isFullscreen?: boolean;
};
ResolveInput type
#
line 9038
Added in 2.1.267
The input of ui.resolve: which surface's elements, for which component; a union with one member per surface (ResolveInputOf).
Resolved when the plugins load, ahead of any drawing, so it names the surface and the component and not the props; a ui.render argument is one (it carries both), which is what $.ui.resolve(e) takes.
export type ResolveInput<C extends RenderComponent = RenderComponent, P extends RenderSurface = RenderSurface> = P extends RenderSurface ? ResolveInputOf<C, P> : never;
ResolveInputOf type
#
line 9043
Added in 2.1.267
One ui.resolve input, for a component on one surface.
export type ResolveInputOf<C extends RenderComponent, P extends RenderSurface> = {
/**
* Where the table draws; one literal per member, so a hook that narrows
* it narrows the table `next(e)` resolves to.
*/
surface: P;
/**
* Which drawing the table is resolved for; the key a matcher narrows on.
*/
component: C;
};
ResultOf type
#
line 9059
In the first published surface (2.1.259) · changed in 2.1.265
What each event's hook returns, and what its next(e) resolves to, by event name.
export type ResultOf = EngineResultOf & ClassicResultOf & {
[N in OpEventName]: OpEventResult<N>;
} & {
[N in NounEventName]: NounEventResult<N>;
};
SDKAssistantMessageError type
#
line 9065
Added in 2.1.265 · changed in 2.1.267, 2.1.268
type SDKAssistantMessageError = 'authentication_failed' | 'oauth_org_not_allowed' | 'account_on_hold' | 'verification_required' | 'billing_error' | 'rate_limit' | 'overloaded' | 'invalid_request' | 'model_not_found' | 'server_error' | 'unknown' | 'max_output_tokens' | 'cloud_credential_error';
Select type
#
line 9070
In the first published surface (2.1.259)
The members of T assignable to S; all of T when none is.
type Select<T, S> = [Extract<T, S>] extends [never] ? T : Extract<T, S>;
Selected type
#
line 9076
Added in 2.1.265
The events a pattern selects, as a union of names: the one named, every one under a glob's namespace, or every one a negation does not exclude.
export type Selected<P extends string> = P extends '*' ? EventName : P extends `!${infer Negated}` ? Exclude<EventName, Selected<Negated>> : P extends `${infer Prefix}.*` ? Extract<EventName, `${Prefix}.${string}`> : Extract<EventName, P>;
Selection type
#
line 9082
In the first published surface (2.1.259)
The literal each tag key of I is held to by matcher M: one-of arrays flattened, RegExps widened to unknown.
type Selection<I, M> = {
[K in keyof M & TagKeys<I>]: Literal<M[K] extends readonly (infer One)[] ? One : M[K]>;
};
SelectOption type
#
line 9090
Added in 2.1.260
One option of a Select: the value onSelect and ui.select carry, and the text drawn for it (the value when absent).
export type SelectOption = {
value: string;
label?: string;
};
SelectProps type
#
line 9103
Added in 2.1.260 · changed in 2.1.271
The props of Select, every surface's one-of-several picker: an address, a label, the options, the one selected, the closure a pick runs. A leaf.
Focused through the same ring as Button (abovePrompt:focus); keys reach it only while it has focus (arrows move, Enter picks) and Esc always returns to the prompt; a pick raises ui.select, its bottom onSelect.
33 lines
export type SelectProps = {
/**
* The element's address: `e.element` at `ui.select`, what a matcher names.
*/
key: string;
/**
* Text drawn before the current value.
*/
label?: string;
/**
* What can be picked, in the order drawn; at least one, values unique.
*/
options: readonly SelectOption[];
/**
* Which option is selected when drawn; the person's pick replaces it
* until the hook draws another.
*/
value?: string;
/**
* The site's focus ring starts here when the site takes the keyboard,
* instead of on nothing, as the DOM's `autofocus`: Enter acts on it at once.
*
* A pane opened with `focus`, or the person's focus chord or click, is the
* take. Of several in one site the first drawn wins; it raises `ui.focus`,
* origin this plugin. A ring the person has moved stays where it was put.
*/
autoFocus?: true;
/**
* Runs on a pick with the option's value, in the plugin's own environment:
* the bottom of a `ui.select` chain. No model turn unless it asks one.
*/
onSelect: (value: string, e: UiSelectArgument) => void;
};
SessionAttachInput type
#
line 9145
Added in 2.1.269
The input of session.attach: a surface joined the session's roster of attached clients (a phone opened the session; the desktop app connected).
A remote client attaches by saying so (ui_attach) or by its first ask to draw; the terminal's attachment is the REPL's binding and raises nothing. Every field is the engine's: a hook observes, next(e) passes them on.
16 lines
export type SessionAttachInput = {
/**
* Where the client draws: what it declared, a rendering fact.
*/
surface: RenderSurface;
/**
* The client's own id, unique in the roster; two phones are two clients on
* one surface. A client that never named itself is `<surface>:default`.
*/
clientId: string;
/**
* The size the client draws into, in character cells, and whether its
* layout docks a pane, when it said.
*/
viewport?: RenderViewport;
};
SessionAttachResult type
#
line 9166
Added in 2.1.269
What a session.attach hook returns and what next(e) resolves to: { clientId }, echoed by core; a hook's own value changes nothing.
export type SessionAttachResult = {
clientId: string;
};
SessionAuthorization type
#
line 9177
Added in 2.1.268
What $.session.authorize() answers: an opaque handle for the session's Anthropic credential and its kind, or null when there is none to hold.
The secret itself stays with the engine; the handle is its plugin-side face, spent through $.http.fetch(url, { auth: handle }).
export type SessionAuthorization = {
handle: string;
kind: 'bearer' | 'api-key';
} | null;
SessionCompactArgs type
#
line 9186
Added in 2.1.267
session.compact's input as a plugin's $.session.compact(args) takes it: trigger (plugin), messages and agentId are the engine's.
export type SessionCompactArgs = {
/**
* What the summary should keep or stress, as typed after `/compact`;
* absent, the engine's own compaction prompt alone.
*/
instructions?: string;
};
SessionCompacted type
#
line 9198
Added in 2.1.267 · changed in 2.1.280
A compaction that stands: the conversation as it reads afterwards, and the counts and request usage the engine recorded when it was the one compacting.
34 lines
export type SessionCompacted = {
/**
* The conversation after the compaction, oldest first: from core, its
* summary and the messages it kept; from a hook, whatever it hands up.
*
* What the transcript becomes (kept, on `precompute`, for the compaction
* that comes). A message with the engine's `handle` stands as the engine
* has it; one without is built from its `role`, `text` and tool blocks.
*/
messages: readonly SessionMessage[];
/**
* The conversation's size before, in tokens; absent when core did not
* record it.
*/
tokensBefore?: number;
/**
* Its size afterwards, in tokens; absent on `precompute` and when core
* did not record it.
*/
tokensAfter?: number;
/**
* What the compaction's own model request cost (ModelUsage), when core
* made one: the summarizer's token counts as the API reported them.
*
* Absent when a hook answered in core's place, when core reused a summary
* already computed, and when the response reported none. Accounting only:
* the session's cost ledger (`session.measure`'s `cost`) already holds it.
*
* @example
* const { usage } = await next(e); if (usage) spent += usage.output_tokens
*/
usage?: ModelUsage;
skip?: undefined;
};
SessionCompactInput type
#
line 9237
Added in 2.1.267
The input of session.compact: one compaction of the conversation, about to run; messages is the transcript it runs over.
31 lines
export type SessionCompactInput = {
/**
* What is compacting (SessionCompactTrigger); the key a matcher narrows
* on. Pinned: `next(e)` passes it on as received.
*/
trigger: SessionCompactTrigger;
/**
* The id of the loop compacting, for a subagent's or a fork's own
* transcript; absent for the main conversation (tool.call's `agentId`).
*
* Pinned: left out of a rewrite it is put back, changed it fails the hook.
* `e.messages` is this loop's transcript; `$.session.messages()` stays the
* main conversation, and `$.session.messages({ agentId })` reads this one.
*/
agentId?: string;
/**
* What the summary should keep or stress: the text after `/compact`, a
* plugin's, or absent.
*
* `next({ ...e, instructions })` changes what the summarizer is told.
*/
instructions?: string;
/**
* The transcript being compacted, in `$.session.messages()`'s shape, each
* message carrying the engine's `handle`; a subagent's own under `agentId`.
*
* `next({ ...e, messages })` changes what is summarized: a message kept
* with its handle is the engine's own, whole; one without is read as built.
*/
messages: readonly SessionMessage[];
};
SessionCompactResult type
#
line 9275
Added in 2.1.267
What a session.compact hook returns and what next(e) resolves to: the compaction ({ messages, tokensBefore?, tokensAfter?, usage? }) or a skip.
There is no summary string: the summary is a message.
export type SessionCompactResult = SessionCompacted | SessionCompactSkipped;
SessionCompactSkipped type
#
line 9283
Added in 2.1.267
A compaction vetoed: on precompute nothing is computed or kept; on any other trigger the conversation stays as it is and one line says why.
Core answers it too, when a classic PreCompact hook blocks.
export type SessionCompactSkipped = {
/**
* Why, as the notice reads.
*/
skip: string;
messages?: undefined;
};
SessionCompactTrigger type
#
line 9298
Added in 2.1.267
Who compacts: the person's /compact (manual), the engine at its threshold or on a prompt too long (auto), a plugin, or a precompute.
precompute is the one dispatch that installs nothing: its result is kept for the compaction that comes, if the conversation it ran over still leads.
export type SessionCompactTrigger = 'manual' | 'auto' | 'plugin' | 'precompute';
SessionContextBreakdown type
#
line 9308
Added in 2.1.271 · changed in 2.1.280
The context window broken down as /context breaks it down: the rows, the grid and the lists beneath it, in the SDK's get_context_usage shape.
Less that reply's internal-build sections. Token counts are the engine's estimates as numbers, never formatted: a full breakdown counts with the token-count API where it can, a summary one estimates throughout.
75 lines
export type SessionContextBreakdown = {
/**
* One row per category, the free space and the compaction buffer among
* them; `kind` says which is which.
*/
categories: ContextCategory[];
/**
* Tokens in use, unclamped: past `rawMaxTokens` when over the window.
*/
totalTokens: number;
/**
* The window measured against, the same figure as `rawMaxTokens`.
*/
maxTokens: number;
/**
* The window measured against, in tokens: the model's limit, or a smaller
* compaction window (`autocompactSource` says which).
*/
rawMaxTokens: number;
/**
* How that window was settled (ContextWindowSource); the SDK's reply
* carries it under this name too, outside its typed schema.
*/
autocompactSource: ContextWindowSource;
/**
* `totalTokens` over `rawMaxTokens` as a whole percentage, 0 to 100 and
* past it when over.
*/
percentage: number;
/**
* The grid, row by row: 10 by 10, 20 by 10 for a window of a million or
* more, 5 wide when asked for under 80 `columns`.
*/
gridRows: ContextGridSquare[][];
/**
* Which model the breakdown was computed for, as `/model` shows it.
*/
model: string;
/**
* Each memory file in the context, with its path and tokens.
*/
memoryFiles: ContextMemoryFile[];
/**
* Each MCP tool's schema, with its server and tokens.
*/
mcpTools: ContextMcpTool[];
/**
* The custom agents the Agent tool describes, each with its tokens.
*/
agents: ContextAgent[];
/**
* The slash-command listing, counted; absent when the session lists none.
*/
slashCommands?: ContextSlashCommands;
/**
* The skill listing, counted, with one entry per skill; absent when the
* session lists none.
*/
skills?: ContextSkills;
/**
* The token count at which auto-compaction runs; absent when it is off.
*/
autoCompactThreshold?: number;
/**
* Whether auto-compaction is on for the session.
*/
isAutoCompactEnabled: boolean;
/**
* The token counts (ModelUsage) the live window's last API response
* reported, or null before one came back.
*
* The breakdown's `Messages` row is reconciled to it.
*/
apiUsage: ModelUsage | null;
};
SessionContextUsage type
#
line 9392
Added in 2.1.267 · changed in 2.1.268, 2.1.271
The live context window as the status line reads it, and by category as /context breaks it down when the call asked ({ breakdown }).
tokens and percent are the last API response's input side against the model's window, absent until the first response of the live window: a fresh session, or one just compacted, until its next response.
26 lines
export type SessionContextUsage = {
/**
* Input tokens the last response was answered over: uncached, cache-written
* and cache-read together (the status line's `total_input_tokens`).
*/
tokens?: number;
/**
* The context window of the session's model, in tokens (the status line's
* `context_window_size`).
*/
window: number;
/**
* `tokens` over `window` as a whole percentage, 0 to 100 (the status
* line's `used_percentage`).
*/
percent?: number;
/**
* The window by category, as /context breaks it down: present only when
* the call passed `breakdown`, and only with a session bound.
*
* It measures against the compaction window (`rawMaxTokens`), which may be
* smaller than `window`, and estimates every category, so its
* `totalTokens` need not equal `tokens`.
*/
breakdown?: SessionContextBreakdown;
};
SessionCost type
#
line 9422
Added in 2.1.267 · changed in 2.1.268
What the session has cost, as /cost and the status line total it.
export type SessionCost = {
/**
* US dollars, summed over every priced API response this session.
*/
usd: number;
};
SessionCronSummary type
#
line 9429
Added in 2.1.265
15 lines
type SessionCronSummary = {
id: string;
/**
* Cron expression, e.g. "0 9 * * 1-5".
*/
schedule: string;
/**
* False for one-shot wakeups whose cron field encodes a single fire time; true for tasks that re-fire on every match.
*/
recurring: boolean;
/**
* Prompt text submitted when the cron fires. Capped at 1000 chars; clipped values append an in-string "... [+N chars]" marker.
*/
prompt: string;
};
SessionDetachInput type
#
line 9449
Added in 2.1.269
The input of session.detach: a client left the session's roster. Every field is the engine's: a hook observes, and next(e) passes them on.
14 lines
export type SessionDetachInput = {
/**
* Where the client drew.
*/
surface: RenderSurface;
/**
* The id it attached under.
*/
clientId: string;
/**
* Why it left: it detached, or the session ended under it.
*/
reason: SessionDetachReason;
};
SessionDetachReason type
#
line 9468
Added in 2.1.269
Why a client left the roster: detach, it said so (ui_detach); end, the session ended with it still attached.
export type SessionDetachReason = 'detach' | 'end';
SessionDetachResult type
#
line 9474
Added in 2.1.269
What a session.detach hook returns and what next(e) resolves to: { clientId }, echoed by core; a hook's own value changes nothing.
export type SessionDetachResult = {
clientId: string;
};
SessionEndHookInput type
#
line 9478
Added in 2.1.265
type SessionEndHookInput = BaseHookInput & {
hook_event_name: 'SessionEnd';
reason: ExitReason;
};
SessionEndInput type
#
line 9491
Added in 2.1.275
The input of session.end: the session is ending, why, and how to come back to it; every field is the engine's: a hook observes, next(e) passes it on.
One short wall-clock bound (1.5 s by default) covers every hook, its $ waits and core, and next.budget reads it: at it next.signal aborts, a $ call in flight with it; only a process a command let go of outlives it.
19 lines
export type SessionEndInput = {
/**
* Why it ends (SessionEndReason), the word the classic SessionEnd hook
* receives as its `reason`.
*
* `clear` is how a hook sees a `/clear`: the conversation ends, the process
* goes on under a new session id, and no `session.start` fires for it.
*/
reason: SessionEndReason;
/**
* The ending session's id (`$.session.id()` until now); after a `/clear`
* or a resume the process goes on under another.
*/
sessionId: string;
/**
* What `claude --resume` takes to return to it.
*/
resume: SessionResume;
};
SessionEndReason type
#
line 9519
Added in 2.1.275
Why the session ended: the classic SessionEnd hook's own reason, word for word.
prompt_input_exit, the person left (/exit, ctrl+c, ctrl+d); clear, a /clear started a fresh one; resume, another took its place; logout; other, a -p run finished or the process got SIGINT, SIGTERM or SIGHUP.
export type SessionEndReason = ClassicHookInputs['SessionEnd']['reason'];
SessionEndResult type
#
line 9525
Added in 2.1.275
What a session.end hook returns and what next(e) resolves to: { sessionId }, echoed by core; a hook's own value changes nothing.
export type SessionEndResult = {
sessionId: string;
};
SessionMeasureInput type
#
line 9537
Added in 2.1.275
The input of session.measure: what $.session.usage() answers at this moment, and which of its units moved since the last measurement a hook saw.
The same figures the op reads, without context.breakdown: call $.session.usage({ breakdown }) from the hook when the categories matter. Every field is the engine's: a hook observes, and next(e) passes them on.
27 lines
export type SessionMeasureInput = {
/**
* The live context window (`$.session.usage()`'s `context`): the window,
* and its fill once a response of the live window reported one.
*
* Never carries `breakdown` here.
*/
context: SessionContextUsage;
/**
* The rate-limit windows the last response reported, each with its
* `percentUsed`; empty off a subscription or before the first reading.
*/
rateLimits: SessionRateLimit[];
/**
* What the session has cost so far; absent where the host keeps no ledger.
*/
cost?: SessionCost;
/**
* Which units differ from the last measurement raised (UsageUnit), never
* empty; the first measurement names every unit it has a figure for.
*
* `context`: the fill moved; `rateLimits`: a window moved a whole point,
* appeared or left, or the account's limit status changed; `cost`: the
* total grew.
*/
changed: UsageUnit[];
};
SessionMeasureResult type
#
line 9569
Added in 2.1.275
What a session.measure hook returns and what next(e) resolves to: { changed }, echoed by core; a hook's own value changes nothing.
export type SessionMeasureResult = {
changed: UsageUnit[];
};
SessionMessage type
#
line 9576
In the first published surface (2.1.259) · changed in 2.1.267
One message of the transcript as $.session.messages() returns it.
27 lines
export type SessionMessage = {
/**
* Who wrote it.
*/
role: 'user' | 'assistant';
/**
* Its text blocks joined; '' when it has none.
*/
text: string;
/**
* The tool_use blocks of an assistant message, each with its outcome
* (`result`, `text`, `isError`) once the transcript holds it.
*/
toolUses: ToolUseSummary[];
/**
* The tool_result blocks of a user message: `{ tool_use_id, text, isError,
* result }`.
*/
toolResults?: ToolResultSummary[];
/**
* An opaque token the engine stamps on a message it hands a
* `session.compact` hook, so a list handed back maps to its own messages.
*
* Absent on `$.session.messages()` and on a message a hook built.
*/
handle?: string;
};
SessionMessagesAgentArgs type
#
line 9608
Added in 2.1.280
A $.session.messages call for the rows (SessionMessage) of the main conversation or of one agent's: agentId alone, no as.
type SessionMessagesAgentArgs = {
/**
* Whose conversation; absent, the main one.
*/
agentId?: string;
/**
* Left out: the rows.
*/
as?: undefined;
};
SessionMessagesApiArgs type
#
line 9623
Added in 2.1.280
A $.session.messages call for the Messages API form (ApiMessage) of the main conversation or, with agentId, of one of this session's agents'.
type SessionMessagesApiArgs = {
/**
* `"api"`.
*/
as: 'api';
/**
* Whose conversation; absent, the main one.
*/
agentId?: string;
};
SessionMessagesApiResult type
#
line 9641
Added in 2.1.280
What $.session.messages({ as: "api", agentId }) resolves to: the agent's conversation as ApiMessage, or { deny } (SessionMessagesDeny).
Array.isArray tells the two apart; without agentId it is always the messages.
type SessionMessagesApiResult = ApiMessage[] | SessionMessagesDeny;
SessionMessagesArgs type
#
line 9647
Added in 2.1.280
What $.session.messages(args) takes and a session.messages hook reads on e: whose conversation (agentId) and in which form (as).
16 lines
type SessionMessagesArgs = {
/**
* Whose conversation to read: the id `tool.call`, `turn.step` and
* `turn.complete` carry inside that agent's loop. Absent, the main one.
*
* A subagent (foreground or background), a fork, or a teammate running in
* this process; `$.agent.list()` lists it, an Agent tool use's `toolUses`
* entry names it. Not an agent a workflow run filed under the run.
*/
agentId?: string;
/**
* `"api"` for the Messages API form (ApiMessage: `{ role, content }` with
* the content blocks intact); absent, the rows (SessionMessage).
*/
as?: 'api';
};
SessionMessagesCall type
#
line 9668
Added in 2.1.280
$.session.messages: the main conversation's rows with no argument, with { as: "api" } its Messages API form; with agentId an agent's, or deny.
type SessionMessagesCall = {
(): Promise<SessionMessage[]>;
(args: SessionMessagesMainApiArgs): Promise<ApiMessage[]>;
(args: SessionMessagesApiArgs): Promise<SessionMessagesApiResult>;
(args: SessionMessagesAgentArgs): Promise<SessionMessagesResult>;
(args: SessionMessagesArgs): Promise<SessionMessagesValue>;
};
SessionMessagesDeny type
#
line 9684
Added in 2.1.280
What $.session.messages({ agentId }) resolves to when the id names no conversation this session can read: why not, in deny.
The id is not one of this session's agents, the agent runs in another process (a pane-hosted teammate), or it finished and the session reads no saved transcript back for it (none saved; a workflow run's). Never main.
type SessionMessagesDeny = {
/**
* Why no conversation was read, naming the id.
*/
deny: string;
};
SessionMessagesMainApiArgs type
#
line 9695
Added in 2.1.280
A $.session.messages({ as: "api" }) call naming no agent: the main conversation, whose answer is always the messages (ApiMessage).
type SessionMessagesMainApiArgs = {
/**
* `"api"`.
*/
as: 'api';
/**
* Left out: the main conversation.
*/
agentId?: undefined;
};
SessionMessagesResult type
#
line 9713
Added in 2.1.280
What $.session.messages({ agentId }) resolves to: the messages (SessionMessage), or { deny } (SessionMessagesDeny).
Without agentId it is always the messages; with one the session cannot read, the deny. Array.isArray tells the two apart.
type SessionMessagesResult = SessionMessage[] | SessionMessagesDeny;