Follow Discord
Sweep 25 Sep 2026 · 19:33Z Build v2.1.283 504 read Stable v2.1.274 Latest v2.1.283 Next v2.1.283 Feeds RSS JSON llms.txt llms-full.txt Unofficial
Mods API · 03 of 03

Types

Every declaration in the file, verbatim, with the doc comment above it.

Declarations570over 12 pages
Mined from2.1.283the shipped binary

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, 401 to 450 of 570

StreamHookBody type # line 10588

Added in 2.1.269

What a hook on a streaming event evaluates to: the async generator an async function* makes, yielding C and returning R or nothing.

Returning nothing lets its last next(e)'s result stand. A plain function is a type error here even when it returns next(e): the hook is the generator, not a function that hands one back.

  export type StreamHookBody<C, R> = AsyncGenerator<C, R | void> & {
      /**
       * Absent on a generator; present on `next(e)`, which is not a hook body.
       */
      readonly result?: never;
  };

StreamingEventName type # line 10604

Added in 2.1.269 · changed in 2.1.280

The events that stream: their hooks are async generators, next(e) is the stream of everything beneath, and the result is what it returns.

Two events stream: turn.step, the model's response arriving in pieces, where a hook that saw it whole could not change what had already been shown; and process.spawn, a call on $ whose child's output arrives in pieces for as long as the child runs.

  export type StreamingEventName = 'turn.step' | 'process.spawn';

StreamNext type # line 10618

Added in 2.1.269 · changed in 2.1.275, 2.1.280

The rest of the chain as a hook on a streaming event receives it: Next, except that next(e) is the stream beneath (HookStream), not a promise.

Each call opens a fresh stream (for turn.step a model request, for process.spawn a child), so a hook that calls it twice makes two. Not calling it yields the hook's own chunks and result; nothing beneath runs.

17 lines
  export type StreamNext<N extends StreamingEventName = StreamingEventName, E = Args<N>, O = EventResult<N>, S extends {
      [K in N]?: unknown;
  } = {
      [K in N]: Args<K>;
  }> = Pick<Next<N, E, O, S>, 'signal' | 'is' | 'event' | 'origin' | 'budget'> & {
      (e: E): HookStream<Chunk<N>, O>;
      /**
       * Continues this dispatch at a tier, as Next's `to`: the stream beneath
       * with the links between this hook's tier and that one skipped.
       */
      readonly to: (e: E, tier: TargetTier) => HookStream<Chunk<N>, O>;
      /**
       * What settled beneath on the latest `next()` stream, as Next's; a
       * streaming link's entry counts the chunks it yielded up (`chunks`).
       */
      readonly trace: readonly TraceEntry<N, E, O>[];
  };

StyledElement type # line 10644

Added in 2.1.271

The shape a Box and a Text share in a render tree: allowlisted props, an optional hover, the group stamp a hover.scope earns, and children.

Tag is which of the two; Hover is that element's hover props. Every surface draws both: Ink's Box and Text on the terminal, a flex div and a styled span on the desktop.

26 lines
  type StyledElement<Tag extends 'Box' | 'Text', Hover> = {
      type: Tag;
      /**
       * A Box's layout, position, spacing and border props and the `key` that
       * makes it a hover scope; a Text's colors and styles. Others are refused.
       */
      props?: Record<string, string | number | boolean>;
      /**
       * Style overrides the surface applies while the pointer is over the
       * nearest keyed Box, or over any member of the group `scope` names.
       *
       * Plain data, no hook. Nothing that moves a sibling: `borderStyle`
       * restyles a border the Box has, `display` only reveals a Box drawn
       * `"none"` (under a keyed Box or in a scope), an offset moves a placed Box.
       */
      hover?: Hover;
      /**
       * Whose group `hover.scope` names; absent without a `scope`.
       */
      group?: PluginStamp;
      /**
       * In order: a Box holds elements and strings (core wraps each string in
       * a Text); a Text holds strings and inline elements, never an engine node.
       */
      children?: RenderNode[];
  };

SubagentStartHookInput type # line 10671

Added in 2.1.265

  type SubagentStartHookInput = BaseHookInput & {
      hook_event_name: 'SubagentStart';
      agent_id: string;
      agent_type: string;
  };

SubagentStopHookInput type # line 10677

Added in 2.1.265

19 lines
  type SubagentStopHookInput = BaseHookInput & {
      hook_event_name: 'SubagentStop';
      stop_hook_active: boolean;
      agent_id: string;
      agent_transcript_path: string;
      agent_type: string;
      /**
       * Text content of the last assistant message before stopping. Avoids the need to read and parse the transcript file.
       */
      last_assistant_message?: string;
      /**
       * In-flight background work (running/pending + backgrounded) registered in this session. Lets hooks distinguish "session is done" from "session is paused waiting for background work to wake it". Empty array when nothing is in flight.
       */
      background_tasks?: BackgroundTaskSummary[];
      /**
       * Session-scoped cron tasks (CronCreate, ScheduleWakeup, /loop) that will wake this session later. Empty array when none are scheduled.
       */
      session_crons?: SessionCronSummary[];
  };

SvgProps type # line 10705

In the first published surface (2.1.259) · changed in 2.1.268

The props of Svg, the remote surfaces' vector leaf: the markup is the element's data, as a string is a Text's, drawn isolated.

A leaf: no children. The surface never lets the markup reach the page (the engine bounds it; the desktop and the editor draw it as an image, or in a sandboxed frame when isInteractive; the mobile app in a web view).

28 lines
  export type SvgProps = {
      /**
       * The SVG document, `<svg ...>...</svg>`, at most 131072 characters.
       */
      source: string;
      /**
       * What the drawing says, for a reader that cannot see it; required, since
       * a surface without the element draws nothing else of it.
       */
      alt: string;
      /**
       * CSS pixels; absent, the box takes the markup's own width up to the slot.
       */
      width?: number;
      /**
       * CSS pixels; absent, the markup's own height at the drawn width.
       */
      height?: number;
      /**
       * `true` draws the SVG in a script-less sandboxed frame so hover, CSS
       * `:hover`, SMIL animation and `<title>` tooltips work; absent, an image.
       *
       * It never enables script or event-handler attributes (the frame has no
       * allow-scripts and the scrub strips them); presses that other plugins
       * should observe go on an enclosing element.
       */
      isInteractive?: boolean;
  };

TagKeys type # line 10738

In the first published surface (2.1.259)

The keys of I a matcher may select variants by: literal-valued in every variant, and one literal per variant (IsDiscriminant).

  type TagKeys<I> = {
      [K in MatcherKeys<I>]: IsLiteralValued<MatcherValueOf<I, K>> extends true ? IsDiscriminant<I, K> extends true ? K : never : never;
  }[MatcherKeys<I>];

TargetTier type # line 10746

Added in 2.1.267

A tier next.to(e, tier) may name: one a floor can reach past a tier of less authority to, so never prepend or user, which nothing skips to.

  export type TargetTier = Exclude<Tier, 'prepend' | 'user'>;

TaskCompletedHookInput type # line 10748

Added in 2.1.265

  type TaskCompletedHookInput = BaseHookInput & {
      hook_event_name: 'TaskCompleted';
      task_id: string;
      task_subject: string;
      task_description?: string;
      teammate_name?: string;
      /**
       * @deprecated Sessions have a single implicit team; this carries the session-derived team name and will be removed in a future release.
       */
      team_name?: string;
  };

TaskCreatedHookInput type # line 10760

Added in 2.1.265

  type TaskCreatedHookInput = BaseHookInput & {
      hook_event_name: 'TaskCreated';
      task_id: string;
      task_subject: string;
      task_description?: string;
      teammate_name?: string;
      /**
       * @deprecated Sessions have a single implicit team; this carries the session-derived team name and will be removed in a future release.
       */
      team_name?: string;
  };

TeammateIdleHookInput type # line 10772

Added in 2.1.265

  type TeammateIdleHookInput = BaseHookInput & {
      hook_event_name: 'TeammateIdle';
      teammate_name: string;
      /**
       * @deprecated Sessions have a single implicit team; this carries the session-derived team name and will be removed in a future release.
       */
      team_name: string;
  };

TextHoverProps type # line 10785

Added in 2.1.267 · changed in 2.1.271

The Text props a hover may override (its colors and styles, not its wrapping) and scope, the hover group it joins; a Button's label too.

19 lines
  export type TextHoverProps = {
      /**
       * Names a hover group of this plugin's: every element it draws with the
       * same `scope`, in any site on the surface, lights while any is hovered.
       *
       * Another plugin's elements under the same string are a different group.
       * One to 64 characters, no control characters; no keyed Box needed. On the
       * terminal a Text nested in a Text follows its group but cannot heat it.
       */
      scope?: string;
      color?: string;
      backgroundColor?: string;
      dimColor?: boolean;
      bold?: boolean;
      italic?: boolean;
      underline?: boolean;
      strikethrough?: boolean;
      inverse?: boolean;
  };

TextProps type # line 10809

In the first published surface (2.1.259) · changed in 2.1.267

The props of Text: the color and style props of Ink's Text a tree may set. Colors are a theme key or a raw color.

19 lines
  export type TextProps = {
      /**
       * Style overrides applied by the surface while the pointer is over the
       * nearest enclosing keyed `Box`, or, given a `scope`, over its group.
       *
       * No hook runs and nothing crosses to the plugin. Refused outside a keyed
       * Box unless it names a `scope`.
       */
      hover?: TextHoverProps;
      color?: string;
      backgroundColor?: string;
      dimColor?: boolean;
      bold?: boolean;
      italic?: boolean;
      underline?: boolean;
      strikethrough?: boolean;
      inverse?: boolean;
      wrap?: 'wrap' | 'end' | 'middle' | 'truncate' | 'truncate-start' | 'truncate-middle' | 'truncate-end';
  };

Tier type # line 10837

Added in 2.1.271

One of the chain's five tiers (TIERS), outermost first; on every next.trace entry, and what next.to(e, tier) names.

prepend and append are the managed plugins an administrator lists, user everything a person installs, builtin the plugins bundled in the binary, core the engine's innermost link.

  export type Tier = (typeof TIERS)[number];

TIERS const # line 10847

Added in 2.1.267

The chain's five tiers, outermost first: earlier is outer is more authority, and same-event hooks nest in this order and no other way.

The managed plugins an administrator prepends, everything a person installs, the managed plugins appended, the plugins bundled in the binary, the engine's innermost link; a built-in's $ calls still raise everywhere.

  const TIERS: readonly ["prepend", "user", "append", "builtin", "core"];

Timer type # line 10852

In the first published surface (2.1.259)

A pending timer from $.clock.after / $.clock.every.

  export type Timer = {
      /**
       * Stops it; a stopped timer never fires again.
       */
      cancel: () => void;
  };

TimerCall type # line 10863

In the first published surface (2.1.259)

A timer on $.clock (after, every): fn runs after ms milliseconds, once or until cancel().

  export type TimerCall = (ms: number, fn: () => void) => Timer;

ToastOptions type # line 10868

In the first published surface (2.1.259)

Options of $.ui.toast.

  export type ToastOptions = {
      /**
       * How long the line stays, in milliseconds; default 4000.
       */
      timeoutMs?: number;
  };

ToolCallArgs type # line 10881

In the first published surface (2.1.259) · changed in 2.1.267

tool.call's input as the call takes it: tool_use_id and agentId may ride along (a hook passing its event's input on) and are dropped.

The run gets its own id and runs in the session's loop.

  export type ToolCallArgs = ToolCallEnvelope extends infer I ? I extends ToolCallEnvelope ? Omit<I, 'tool_use_id'> & ToolCallReserved<I['tool']> : never : never;

ToolCallEnvelope type # line 10891

Added in 2.1.267

The envelope the two tool events share: the tool, the id of this call, and the tool's arguments spread beside them (e.command for Bash).

A union discriminated by tool: after if (e.tool === "Bash"), e.command is a string and a rewrite is checked against Bash's schema. The e of classic.PreToolUse exactly; tool.call's adds the loop (ToolCallInput).

  export type ToolCallEnvelope = BuiltinToolCallInput | McpToolCallInput;

ToolCallInput type # line 10901

In the first published surface (2.1.259) · changed in 2.1.267

The input of tool.call: the tool, the id of this call, the tool's arguments beside them (e.command for Bash), and agentId in a subagent.

A union discriminated by tool: after if (e.tool === "Bash"), e.command is a string and a rewrite is checked against Bash's schema. tool, tool_use_id and agentId are reserved: a rewrite of any is refused.

  export type ToolCallInput = ToolCallEnvelope & AgentLoop;

ToolCallOverloads type # line 10907

Added in 2.1.260

$.tool.call(input): resolves with result typed for the tool input names (ToolCallResult), or loosely for an input that names none literally.

  type ToolCallOverloads = {
      <T extends string>(input: ToolCallArgs & ToolNamed<T>): Promise<ToolCallResult<T>>;
      (input: ToolCallArgs): Promise<ToolCallResult>;
  };

ToolCallReserved type # line 10920

In the first published surface (2.1.259)

The keys tool.call's input carries beside the tool's own arguments, none of which the tool sees (the engine strips them before the tool runs).

consent is the person's own words for the press that raised the call (The user pressed "1: Yes" on ...): the run's context carries it as a human turn, which the permission path reads as the user's request.

  export type ToolCallReserved<T> = {
      tool: T;
      tool_use_id?: string;
      consent?: string;
  };

ToolCallResult type # line 10937

In the first published surface (2.1.259) · changed in 2.1.260, 2.1.280

What a tool.call hook returns and what next(e) and $.tool.call(input) resolve to: the tool's result ({ result, context? }) or { deny }.

From core the result is { ref, result, text } or, when the tool reported an error, { ref, result, text, isError }, either with isReadOnly when the tool held the input it ran read-only; ref names core's messages.

86 lines
  export type ToolCallResult<Name extends string = string> = {
      /**
       * Refuses the call: the model receives the text as an error result.
       * Absent when the call was answered.
       */
      deny: string;
      result?: undefined;
      context?: undefined;
      ref?: undefined;
      text?: undefined;
      isError?: undefined;
      isReadOnly?: undefined;
  } | {
      /**
       * The tool's output: from core the tool's record, typed per built-in
       * tool once `e.tool` and `isError` are narrowed; from a hook, its own.
       *
       * Core validates a hook's answer against the tool's output schema when
       * it has one, maps it for the model with the tool's own mapper, and
       * records it in the transcript as the tool's result. Absent on a deny.
       */
      result: ToolResultOf<Name>;
      /**
       * What the model reads after the tool's result and the user never
       * sees. From core, none.
       *
       * One reminder, as a PostToolUse hook's is, after the managed tier's
       * review; none on a plugin's own `$.tool.call`. Kept whole from `next`,
       * none empty, any length: past 100,000 (200,000 together) head + path.
       */
      context?: readonly string[];
      /**
       * Set by core on what `next(e)` resolves to: names the messages core
       * produced for the call (they stay on the host side).
       *
       * A hook that returns the object it got makes core use them verbatim.
       * Absent on a hook's own `{ result }` and on a deny.
       */
      ref?: number;
      /**
       * Set by core: the result as the model reads it (text blocks joined),
       * present whatever the tool, where `result`'s shape varies per tool.
       *
       * Absent on a hook's own `{ result }`.
       */
      text?: string;
      /**
       * Set by core, present only when the tool held the input it executed
       * read-only by its own check (the one its permissions use).
       *
       * It speaks for this call as run, rewrites included, not for calls it
       * causes (a subagent's tools raise their own `tool.call`); for an MCP
       * tool, its server's declaration. Bash `ls`: set; a hook's own: never.
       */
      isReadOnly?: true;
      isError?: undefined;
      deny?: undefined;
  } | {
      /**
       * Set by core, present only when the tool reported an error (it threw,
       * was interrupted, or answered an error): `text` is what the model read.
       */
      isError: true;
      /**
       * What the transcript stored for the errored call: the error text, or
       * undefined when nothing was stored; never the tool's typed record.
       */
      result: unknown;
      /**
       * The error as the model reads it.
       */
      text?: string;
      /**
       * As on an answered result: names the messages core produced.
       */
      ref?: number;
      /**
       * As on an answered result.
       */
      context?: readonly string[];
      /**
       * As on an answered result: the tool held the input it ran read-only.
       */
      isReadOnly?: true;
      deny?: undefined;
  };

ToolCheckArgs type # line 11028

Added in 2.1.269

tool.check's input as $.tool.check takes it: the tool and its arguments; tool_use_id is the engine's to set, never a query's.

  type ToolCheckArgs = Pick<ToolCheckInput, 'tool' | 'input'>;

ToolCheckDecision type # line 11034

Added in 2.1.269

The verdict of tool.check: run the tool, put it to the mode's decider (the dialog, the auto-mode classifier, a headless host), or refuse it.

  type ToolCheckDecision = 'allow' | 'ask' | 'deny';

ToolCheckInput type # line 11043

Added in 2.1.269

The input of tool.check: the tool, its arguments, and the call's id when the engine is deciding a real call.

All three are the question's identity and are pinned: a hook decides about this call, it does not change it (tool.call rewrites a call).

19 lines
  type ToolCheckInput = {
      /**
       * As the model names it (`Bash`, `mcp__server__tool`); the key a matcher
       * narrows on.
       */
      tool: string;
      /**
       * The tool's arguments as the permission decision reads them
       * (`{ command }` for Bash, `{ file_path, ... }` for the file tools).
       */
      input: unknown;
      /**
       * The call being decided, on a real call only; absent on a query.
       *
       * `next.origin` names who raised it: `{ plugin: 'engine', tier: 'core' }`
       * for the model's own call, the plugin for its `$.tool.call` or its query.
       */
      tool_use_id?: string;
  };

ToolCheckResult type # line 11071

Added in 2.1.269

What a tool.check hook returns and what next(e) resolves to: the verdict, why, and the settings rule behind it when one decided.

From core, the engine's declarative decision for the session's mode and rules. A hook may answer any verdict in either direction; the last word up the chain is the decision.

18 lines
  type ToolCheckResult = {
      /**
       * `allow` runs the tool; `ask` puts it to the mode's decider; `deny`
       * refuses it, the reason the model's error.
       */
      decision: ToolCheckDecision;
      /**
       * Why, in a sentence: from core the rule or check that decided; from a
       * hook, what the model reads on a deny and the dialog shows on an ask.
       */
      reason?: string;
      /**
       * The settings rule that decided, as written (`Bash(git push:*)`).
       *
       * Absent for a mode or a tool's own check.
       */
      rule?: string;
  };

ToolDeferral type # line 11096

Added in 2.1.277

Where a tool.describe answer places the tool: true behind ToolSearch (its schema loads when the model asks for it), false in the prompt's list.

Left out of an answer, the placement beneath stands.

  export type ToolDeferral = boolean;

ToolDescribeInput type # line 11102

In the first published surface (2.1.259) · changed in 2.1.267, 2.1.277

The input of tool.describe: one tool's description, at the moment the engine first renders the tool's schema for the model.

27 lines
  export type ToolDescribeInput = {
      /**
       * As the model sees the name (`Bash`, `mcp__server__tool`); the key a
       * matcher narrows on.
       */
      tool: string;
      /**
       * The tool's description as it computed it.
       */
      description: string;
      /**
       * Present, and true, when the engine lists the tool behind ToolSearch (its
       * schema loads when the model asks for it by name); absent for one listed.
       *
       * By the engine's rule an MCP server's tool, or one that asks to be,
       * unless a rule keeps it in front.
       */
      isDeferred?: true;
      /**
       * Who provides this tool: the plugin and its tier; `{ plugin: "engine",
       * tier: "core" }` for a built-in. Pinned: a rewrite is refused.
       *
       * A configured MCP server's tool is `mcp:<server>`, in `prepend` when the
       * policy settings source configures the server, else `user`.
       */
      provider: Origin;
  };

ToolDescribeResult type # line 11138

In the first published surface (2.1.259) · changed in 2.1.277

What a tool.describe hook returns: the description the model sees for that tool and, when the hook moves it, where the tool waits (ToolDeferral).

{ description } alone, or { ...(await next(e)), description }, changes the text and keeps the engine's placement; isDeferred: true puts the tool behind ToolSearch, isDeferred: false puts its schema in the prompt's list.

  export type ToolDescribeResult = {
      description: string;
      isDeferred?: ToolDeferral;
  };

ToolEnvelope type # line 11147

In the first published surface (2.1.259)

{ tool, tool_use_id, ...args } as one flat object type, generic over the tool name and its parsed arguments.

  type ToolEnvelope<Name, Arguments> = {
      /**
       * The name of the tool being called (`Bash`, `mcp__<server>__<tool>`);
       * comparing it narrows `e`. Reserved: a rewrite of it is ignored by core.
       */
      tool: Name;
      /**
       * The tool_use block's id: the same at every event of the call and in
       * `$.ui.notice`. Reserved: a rewrite of it is ignored by core.
       */
      tool_use_id: string;
  } & Arguments;

ToolGroupCall type # line 11163

In the first published surface (2.1.259) · changed in 2.1.260, 2.1.268

One tool call of a ToolGroup, as ui.render sees it under calls.

33 lines
  export type ToolGroupCall = {
      /**
       * The id `tool.call` carried for this call (`e.tool_use_id` there), so a
       * hook that saw the call finds its row in the group. Read-only.
       *
       * Absent on a desktop host that predates it.
       */
      tool_use_id?: string;
      /**
       * Which one the call ran (`Bash`, `Read`, `Grep`, ...).
       */
      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.
       */
      isErrored: boolean;
      /**
       * True when an abort ended the call, as on `ToolUse`.
       */
      isInterrupted: boolean;
      /**
       * As on `ToolUse`; undefined while the call runs.
       */
      output?: unknown;
  };

ToolInfo type # line 11200

In the first published surface (2.1.259)

One tool as $.tool.list() returns it.

15 lines
  export type ToolInfo = {
      /**
       * What the model calls it by.
       */
      name: string;
      /**
       * What it does, in the tool's own words (its description; a first sentence at
       * most for MCP tools without one).
       */
      description: string;
      /**
       * True for an MCP server's tool.
       */
      mcp: boolean;
  };

ToolInputOf type # line 11222

In the first published surface (2.1.259)

{ tool, tool_use_id, ...args } as one flat object type.

The docs of tool and tool_use_id live on the keyof operand: a mapped type takes its properties' docs from there.

  export type ToolInputOf<Name extends string, Arguments> = {
      [K in keyof ToolEnvelope<Name, Arguments>]: ToolEnvelope<Name, Arguments>[K];
  };

ToolNamed type # line 11230

Added in 2.1.260

An input that names its tool as the literal T: what next and $.tool.call read to type the call's result per tool (NextResultFor).

  type ToolNamed<T extends string> = {
      /**
       * The name of the tool being called (`Bash`).
       */
      readonly tool: T;
  };

ToolResultOf type # line 11245

Added in 2.1.260

The structured result of the tool named Name: its BuiltinToolResults entry for a built-in tool, else unknown.

Agent's is its entry or an AgentCallRecord (what a plugin-raised call answers). unknown covers an MCP tool, a name the results table lacks (one merged into the inputs table alone too), and Name left at string.

  export type ToolResultOf<Name extends string> = string extends Name ? unknown : Name extends keyof BuiltinToolResults & string ? BuiltinToolResults[Name] | (Name extends 'Agent' ? AgentCallRecord : never) : unknown;

ToolResultSummary type # line 11250

In the first published surface (2.1.259) · changed in 2.1.260, 2.1.268

One tool_result block of a user message.

23 lines
  export type ToolResultSummary = {
      /**
       * The id of the call this result answers (`tool.call`'s `e.tool_use_id`).
       */
      tool_use_id: string;
      /**
       * The result as the model read it (text blocks joined).
       */
      text: string;
      /**
       * True when the tool reported an error.
       */
      isError: boolean;
      /**
       * What the transcript stored for the call: the tool's record on an answered
       * one (`tool.call`'s `result`), the error text when `isError`.
       *
       * Absent when nothing was stored. Headless (`-p`), a tool may store the
       * record less its bulk (Bash blanks `stdout`), and a subagent's transcript
       * stores none; `text` is what the model read either way.
       */
      result?: unknown;
  };

ToolSpec type # line 11277

In the first published surface (2.1.259)

What $.tool.register takes.

17 lines
  export type ToolSpec = {
      /**
       * The tool's short name (letters, digits, `_`, `-`; up to 64); the model
       * calls it as `mcp__<plugin>__<name>`.
       */
      name: string;
      /**
       * What the tool does, for the model (and the person where tools are
       * listed); an unpaired surrogate half in it is drawn as U+FFFD.
       */
      description: string;
      /**
       * A JSON schema object for the input (`{ type: "object", properties,
       * required }`); default `{ type: "object" }`.
       */
      inputSchema?: Record<string, unknown>;
  };

ToolUseSummary type # line 11299

In the first published surface (2.1.259) · changed in 2.1.260, 2.1.268, 2.1.280

One tool_use block of an assistant message, with its outcome once the transcript holds the call's tool_result (paired by tool_use_id).

51 lines
  export type ToolUseSummary = {
      /**
       * The call's id, as `tool.call` carried it (`e.tool_use_id` there).
       */
      tool_use_id: string;
      /**
       * Which one was called (`Read`, `Bash`, `mcp__server__tool`), as
       * `tool.call` named it (`e.tool` there).
       */
      tool: string;
      /**
       * The arguments the model gave it.
       */
      input: Record<string, unknown>;
      /**
       * What the transcript stored for the call: the tool's record on an answered
       * one (`tool.call`'s `result`), the error text on a refused or errored one.
       *
       * Absent while the call is in flight or when nothing was stored. Headless
       * (`-p`), a tool may store the record less its bulk (Bash blanks `stdout`)
       * and a subagent's transcript stores none; `text` holds either way.
       */
      result?: unknown;
      /**
       * The result as the model read it; absent while the call is in flight.
       */
      text?: string;
      /**
       * Present only when the tool reported an error, as on `tool.call`'s result.
       */
      isError?: true;
      /**
       * On an Agent tool use, the id of the agent it spawned: what
       * `$.session.messages({ agentId })` reads and its `turn.complete` carries.
       *
       * Known while the session tracks the run and once the call is answered
       * (from what it stored). Absent on every other tool, and on an Agent call
       * the session refused before an agent started.
       *
       * @example
       * if (use.agentId) child = await $.session.messages({ agentId: use.agentId })
       */
      agentId?: string;
      /**
       * On an answered Agent tool use that ran to completion, how long the agent
       * ran, in milliseconds, as the call's stored record has it.
       *
       * Absent while it runs, on a background launch, and on every other tool.
       */
      durationMs?: number;
  };

TraceEntry type # line 11358

Added in 2.1.265 · changed in 2.1.267, 2.1.269

One settled run of a link beneath the caller, as next.trace lists it: data, not a handle.

received and returned are the live references where the hook runs beside the chain; in a hooks module its own copies, as e is.

38 lines
  export type TraceEntry<N extends EventName = EventName, E = Args<N>, O = NextResult<N>> = {
      /**
       * The link's place in the chain, 0 the outermost.
       */
      readonly index: number;
      /**
       * The hook's plugin; `"engine"` for the engine's own core or bottom.
       */
      readonly plugin: string;
      /**
       * The link's tier (Tier); `"core"` for the engine's own core or bottom.
       */
      readonly tier: Tier;
      readonly event: N;
      readonly outcome: TraceOutcome;
      /**
       * Why the link was skipped without running, when it was: `bypassed by
       * <plugin>`, whose `next.to` went beneath this tier. Absent when it ran.
       */
      readonly reason?: string;
      /**
       * Its own wall time, its `next()` calls' time in flight taken out.
       *
       * The engine entry's is everything beneath the last hook: in a hooks
       * module, the host round trip.
       */
      readonly ms: number;
      /**
       * How many chunks the link yielded up, on a streaming event; absent on
       * every other. A link left mid-stream counts what it yielded before.
       */
      readonly chunks?: number;
      readonly received: E;
      /**
       * What the link settled on; undefined when it was skipped or rejected.
       */
      readonly returned: O | undefined;
  };

TraceOutcome type # line 11410

Added in 2.1.265 · changed in 2.1.267, 2.1.268

What the chain decided for one link, as next.trace names it.

returned: its result stood; passed: it returned, by reference, what its last next() resolved to (a hooks module's hook answers with a copy of its own, so it reads returned); skipped: it failed before next, or a next.to above continued beneath its tier (reason says which), and beneath ran in its place; kept: it failed after next, and that run's result stands; expired: its budget ran out (what stands follows skipped/kept); caught: it threw or its budget ran out, and its .catch handler's result stands; rejected: the link rejected; the deepest such entry is where the rejection came from, and the ones above it let it pass.

  export type TraceOutcome = 'caught' | 'expired' | 'kept' | 'passed' | 'rejected' | 'returned' | 'skipped';

TurnCompleteFields type # line 11416

In the first published surface (2.1.259) · changed in 2.1.267, 2.1.268, 2.1.269

What every turn.complete carries whatever its reason: the answer, the duration, the interrupt flag, the turn's id, its loop and what it cost.

37 lines
  type TurnCompleteFields = {
      /**
       * The assistant's final visible text this turn ("" if none, e.g.
       * thinking-only).
       */
      answer: string;
      /**
       * Wall-clock length of the turn in milliseconds.
       */
      durationMs: number;
      /**
       * True when the turn ended by interruption (`reason === 'aborted'`).
       */
      isAborted: boolean;
      /**
       * The turn's id, the same one its `turn.start` and every `turn.step`
       * carried; a subagent's run raises no `turn.start`, its steps carry it.
       */
      turnId: string;
      /**
       * The loop the turn ran in: a subagent's id, as `$.agent.spawn` resolves
       * it, each run of its loop one turn; absent on the main loop.
       *
       * Pinned: a different value is refused, one left out is kept. Every hook
       * sees a subagent's turn, so a hook that spawns sees its children's turns
       * too and bounds itself.
       */
      agentId?: string;
      /**
       * What the turn cost: its real requests' token counts, plus what a made-up
       * response's stop stated, summed, and the model of the last that counted.
       *
       * A response a `turn.step` hook made up adds nothing unless its stop states
       * usage; absent when nothing counted (an interrupt, an API error).
       */
      usage?: TurnUsage;
  };

TurnCompleteInput type # line 11460

In the first published surface (2.1.259)

The input of turn.complete: the assistant's final message of a turn, at the moment the turn ends (where the turn's duration is reported).

reason says why it ended; refusal exists on a refusal alone.

  export type TurnCompleteInput = TurnCompleteFields & (TurnCompleteRefused | TurnCompleteUnrefused);

TurnCompleteReason type # line 11466

In the first published surface (2.1.259)

Why a turn ended: the model answered, the user interrupted it, the model refused with no fallback model to retry on, or an API error ended it.

  export type TurnCompleteReason = 'answer' | 'aborted' | 'refusal' | 'error';

TurnCompleteRefused type # line 11472

In the first published surface (2.1.259)

The end of a turn the model refused with no fallback model to retry on: what the API said of the refusal rides along.

  type TurnCompleteRefused = {
      reason: 'refusal';
      refusal: TurnRefusal;
  };

TurnCompleteResult type # line 11484

In the first published surface (2.1.259) · changed in 2.1.267

What a turn.complete hook returns and what next(e) resolves to: { text }; a text other than a main-loop answer's is shown beneath it.

Core fills usage from e.usage when the turn had one; a hook above reads it, and one that answers its own may leave it out.

  export type TurnCompleteResult = {
      text: string;
      usage?: TurnUsage;
  };

TurnCompleteUnrefused type # line 11493

In the first published surface (2.1.259)

The end of a turn that was not a refusal: answered, interrupted, or dead on an API error (retries exhausted, the context limit), nothing more.

  type TurnCompleteUnrefused = {
      reason: Exclude<TurnCompleteReason, 'refusal'>;
  };

TurnRefusal type # line 11501

In the first published surface (2.1.259)

What the API said about a refusal that ended a turn: the classifier's category and its explanation, each null when the API sent none.

  export type TurnRefusal = {
      category: string | null;
      explanation: string | null;
  };
Feedback