textInputTypes.ts
types/textInputTypes.ts
No strong subsystem tag
388
Lines
11628
Bytes
14
Exports
10
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 388 lines, 10 detected imports, and 14 detected exports.
Important relationships
Detected exports
InlineGhostTextBaseTextInputPropsVimTextInputPropsVimModeBaseInputStateTextInputStateVimInputStatePromptInputModeEditablePromptInputModeQueuePriorityQueuedCommandisValidImagePastegetImagePasteIdsOrphanedPermission
Keywords
readonlyinputtextwhenvoidoptionalcallbackmodecommandcursor
Detected imports
@anthropic-ai/sdk/resources/messages.mjscryptoreact../entrypoints/agentSdkTypes.js../ink.js../utils/config.js../utils/imageResizer.js../utils/textHighlighting.js./ids.js./message.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
import type { ContentBlockParam } from '@anthropic-ai/sdk/resources/messages.mjs'
import type { UUID } from 'crypto'
import type React from 'react'
import type { PermissionResult } from '../entrypoints/agentSdkTypes.js'
import type { Key } from '../ink.js'
import type { PastedContent } from '../utils/config.js'
import type { ImageDimensions } from '../utils/imageResizer.js'
import type { TextHighlight } from '../utils/textHighlighting.js'
import type { AgentId } from './ids.js'
import type { AssistantMessage, MessageOrigin } from './message.js'
/**
* Inline ghost text for mid-input command autocomplete
*/
export type InlineGhostText = {
/** The ghost text to display (e.g., "mit" for /commit) */
readonly text: string
/** The full command name (e.g., "commit") */
readonly fullCommand: string
/** Position in the input where the ghost text should appear */
readonly insertPosition: number
}
/**
* Base props for text input components
*/
export type BaseTextInputProps = {
/**
* Optional callback for handling history navigation on up arrow at start of input
*/
readonly onHistoryUp?: () => void
/**
* Optional callback for handling history navigation on down arrow at end of input
*/
readonly onHistoryDown?: () => void
/**
* Text to display when `value` is empty.
*/
readonly placeholder?: string
/**
* Allow multi-line input via line ending with backslash (default: `true`)
*/
readonly multiline?: boolean
/**
* Listen to user's input. Useful in case there are multiple input components
* at the same time and input must be "routed" to a specific component.
*/
readonly focus?: boolean
/**
* Replace all chars and mask the value. Useful for password inputs.
*/
readonly mask?: string
/**
* Whether to show cursor and allow navigation inside text input with arrow keys.
*/
readonly showCursor?: boolean
/**
* Highlight pasted text
*/
readonly highlightPastedText?: boolean
/**
* Value to display in a text input.
*/
readonly value: string
/**
* Function to call when value updates.
*/
readonly onChange: (value: string) => void
/**
* Function to call when `Enter` is pressed, where first argument is a value of the input.
*/
readonly onSubmit?: (value: string) => void
/**
* Function to call when Ctrl+C is pressed to exit.
*/
readonly onExit?: () => void
/**
* Optional callback to show exit message
*/
readonly onExitMessage?: (show: boolean, key?: string) => void
/**
* Optional callback to show custom message
*/
// readonly onMessage?: (show: boolean, message?: string) => void
/**
* Optional callback to reset history position
*/
readonly onHistoryReset?: () => void
/**
* Optional callback when input is cleared (e.g., double-escape)
*/
readonly onClearInput?: () => void
/**
* Number of columns to wrap text at
*/
readonly columns: number
/**
* Maximum visible lines for the input viewport. When the wrapped input
* exceeds this many lines, only lines around the cursor are rendered.
*/
readonly maxVisibleLines?: number
/**
* Optional callback when an image is pasted
*/
readonly onImagePaste?: (
base64Image: string,
mediaType?: string,
filename?: string,
dimensions?: ImageDimensions,
sourcePath?: string,
) => void
/**
* Optional callback when a large text (over 800 chars) is pasted
*/
readonly onPaste?: (text: string) => void
/**
* Callback when the pasting state changes
*/
readonly onIsPastingChange?: (isPasting: boolean) => void
/**
* Whether to disable cursor movement for up/down arrow keys
*/
readonly disableCursorMovementForUpDownKeys?: boolean
/**
* Skip the text-level double-press escape handler. Set this when a
* keybinding context (e.g. Autocomplete) owns escape — the keybinding's
* stopImmediatePropagation can't shield the text input because child
* effects register useInput listeners before parent effects.
*/
readonly disableEscapeDoublePress?: boolean
/**
* The offset of the cursor within the text
*/
readonly cursorOffset: number
/**
* Callback to set the offset of the cursor
*/
onChangeCursorOffset: (offset: number) => void
/**
* Optional hint text to display after command input
* Used for showing available arguments for commands
*/
readonly argumentHint?: string
/**
* Optional callback for undo functionality
*/
readonly onUndo?: () => void
/**
* Whether to render the text with dim color
*/
readonly dimColor?: boolean
/**
* Optional text highlights for search results or other highlighting
*/
readonly highlights?: TextHighlight[]
/**
* Optional custom React element to render as placeholder.
* When provided, overrides the standard `placeholder` string rendering.
*/
readonly placeholderElement?: React.ReactNode
/**
* Optional inline ghost text for mid-input command autocomplete
*/
readonly inlineGhostText?: InlineGhostText
/**
* Optional filter applied to raw input before key routing. Return the
* (possibly transformed) input string; returning '' for a non-empty
* input drops the event.
*/
readonly inputFilter?: (input: string, key: Key) => string
}
/**
* Extended props for VimTextInput
*/
export type VimTextInputProps = BaseTextInputProps & {
/**
* Initial vim mode to use
*/
readonly initialMode?: VimMode
/**
* Optional callback for mode changes
*/
readonly onModeChange?: (mode: VimMode) => void
}
/**
* Vim editor modes
*/
export type VimMode = 'INSERT' | 'NORMAL'
/**
* Common properties for input hook results
*/
export type BaseInputState = {
onInput: (input: string, key: Key) => void
renderedValue: string
offset: number
setOffset: (offset: number) => void
/** Cursor line (0-indexed) within the rendered text, accounting for wrapping. */
cursorLine: number
/** Cursor column (display-width) within the current line. */
cursorColumn: number
/** Character offset in the full text where the viewport starts (0 when no windowing). */
viewportCharOffset: number
/** Character offset in the full text where the viewport ends (text.length when no windowing). */
viewportCharEnd: number
// For paste handling
isPasting?: boolean
pasteState?: {
chunks: string[]
timeoutId: ReturnType<typeof setTimeout> | null
}
}
/**
* State for text input
*/
export type TextInputState = BaseInputState
/**
* State for vim input with mode
*/
export type VimInputState = BaseInputState & {
mode: VimMode
setMode: (mode: VimMode) => void
}
/**
* Input modes for the prompt
*/
export type PromptInputMode =
| 'bash'
| 'prompt'
| 'orphaned-permission'
| 'task-notification'
export type EditablePromptInputMode = Exclude<
PromptInputMode,
`${string}-notification`
>
/**
* Queue priority levels. Same semantics in both normal and proactive mode.
*
* - `now` — Interrupt and send immediately. Aborts any in-flight tool
* call (equivalent to Esc + send). Consumers (print.ts,
* REPL.tsx) subscribe to queue changes and abort when they
* see a 'now' command.
* - `next` — Mid-turn drain. Let the current tool call finish, then
* send this message between the tool result and the next API
* round-trip. Wakes an in-progress SleepTool call.
* - `later` — End-of-turn drain. Wait for the current turn to finish,
* then process as a new query. Wakes an in-progress SleepTool
* call (query.ts upgrades the drain threshold after sleep so
* the message is attached to the same turn).
*
* The SleepTool is only available in proactive mode, so "wakes SleepTool"
* is a no-op in normal mode.
*/
export type QueuePriority = 'now' | 'next' | 'later'
/**
* Queued command type
*/
export type QueuedCommand = {
value: string | Array<ContentBlockParam>
mode: PromptInputMode
/** Defaults to the priority implied by `mode` when enqueued. */
priority?: QueuePriority
uuid?: UUID
orphanedPermission?: OrphanedPermission
/** Raw pasted contents including images. Images are resized at execution time. */
pastedContents?: Record<number, PastedContent>
/**
* The input string before [Pasted text #N] placeholders were expanded.
* Used for ultraplan keyword detection so pasted content containing the
* keyword does not trigger a CCR session. Falls back to `value` when
* unset (bridge/UDS/MCP sources have no paste expansion).
*/
preExpansionValue?: string
/**
* When true, the input is treated as plain text even if it starts with `/`.
* Used for remotely-received messages (e.g. bridge/CCR) that should not
* trigger local slash commands or skills.
*/
skipSlashCommands?: boolean
/**
* When true, slash commands are dispatched but filtered through
* isBridgeSafeCommand() — 'local-jsx' and terminal-only commands return
* a helpful error instead of executing. Set by the Remote Control bridge
* inbound path so mobile/web clients can run skills and benign commands
* without re-exposing the PR #19134 bug (/model popping the local picker).
*/
bridgeOrigin?: boolean
/**
* When true, the resulting UserMessage gets `isMeta: true` — hidden in the
* transcript UI but visible to the model. Used by system-generated prompts
* (proactive ticks, teammate messages, resource updates) that route through
* the queue instead of calling `onQuery` directly.
*/
isMeta?: boolean
/**
* Provenance of this command. Stamped onto the resulting UserMessage so the
* transcript records origin structurally (not just via XML tags in content).
* undefined = human (keyboard).
*/
origin?: MessageOrigin
/**
* Workload tag threaded through to cc_workload= in the billing-header
* attribution block. The queue is the async boundary between the cron
* scheduler firing and the turn actually running — a user prompt can slip
* in between — so the tag rides on the QueuedCommand itself and is only
* hoisted into bootstrap state when THIS command is dequeued.
*/
workload?: string
/**
* Agent that should receive this notification. Undefined = main thread.
* Subagents run in-process and share the module-level command queue; the
* drain gate in query.ts filters by this field so a subagent's background
* task notifications don't leak into the coordinator's context (PR #18453
* unified the queue but lost the isolation the dual-queue accidentally had).
*/
agentId?: AgentId
}
/**
* Type guard for image PastedContent with non-empty data. Empty-content
* images (e.g. from a 0-byte file drag) yield empty base64 strings that
* the API rejects with `image cannot be empty`. Use this at every site
* that converts PastedContent → ImageBlockParam so the filter and the
* ID list stay in sync.
*/
export function isValidImagePaste(c: PastedContent): boolean {
return c.type === 'image' && c.content.length > 0
}
/** Extract image paste IDs from a QueuedCommand's pastedContents. */
export function getImagePasteIds(
pastedContents: Record<number, PastedContent> | undefined,
): number[] | undefined {
if (!pastedContents) {
return undefined
}
const ids = Object.values(pastedContents)
.filter(isValidImagePaste)
.map(c => c.id)
return ids.length > 0 ? ids : undefined
}
export type OrphanedPermission = {
permissionResult: PermissionResult
assistantMessage: AssistantMessage
}