Add 5 pi extensions: pi-subagents, pi-crew, rpiv-pi, pi-interactive-shell, pi-intercom
This commit is contained in:
484
extensions/pi-interactive-shell/tool-schema.ts
Normal file
484
extensions/pi-interactive-shell/tool-schema.ts
Normal file
@@ -0,0 +1,484 @@
|
||||
import { Type } from "typebox";
|
||||
|
||||
export const TOOL_NAME = "interactive_shell";
|
||||
export const TOOL_LABEL = "Interactive Shell";
|
||||
|
||||
export const TOOL_DESCRIPTION = `Run an interactive CLI coding agent in an overlay.
|
||||
|
||||
Use this ONLY for delegating tasks to other AI coding agents (Claude Code, Cursor CLI, Gemini CLI, Codex, etc.) that have their own TUI and benefit from user interaction.
|
||||
|
||||
DO NOT use this for regular bash commands - use the standard bash tool instead.
|
||||
|
||||
MODES:
|
||||
- interactive (default): User supervises and controls the session
|
||||
- hands-free: Agent monitors with periodic updates, user can take over anytime by typing
|
||||
- dispatch: Agent is notified on completion via triggerTurn (no polling needed)
|
||||
- monitor: Run in background and wake the agent on structured monitor events (stream, poll-diff, or file-watch)
|
||||
|
||||
RECOMMENDED DEFAULT FOR DELEGATED TASKS:
|
||||
- For fire-and-forget delegations and QA-style checks, prefer mode="dispatch".
|
||||
- Dispatch is the safest choice when the agent should continue immediately and be notified automatically on completion.
|
||||
|
||||
The user will see the process in an overlay. They can:
|
||||
- Watch output in real-time
|
||||
- Scroll through output (Shift+Up/Down)
|
||||
- Transfer output to you (Ctrl+T) - closes overlay and sends output as your context
|
||||
- Background (Ctrl+B) - dismiss overlay, keep process running
|
||||
- Detach (Ctrl+Q) for menu: transfer/background/kill
|
||||
- In hands-free mode: type anything to take over control
|
||||
|
||||
HANDS-FREE MODE (NON-BLOCKING):
|
||||
When mode="hands-free", the tool returns IMMEDIATELY with a sessionId.
|
||||
The overlay opens for the user to watch, but you (the agent) get control back right away.
|
||||
|
||||
Workflow:
|
||||
1. Start session: interactive_shell({ command: 'pi "Fix bugs"', mode: "hands-free" })
|
||||
-> Returns immediately with sessionId
|
||||
2. Check status/output: interactive_shell({ sessionId: "calm-reef" })
|
||||
-> Returns current status and any new output since last check
|
||||
3. When task is done: interactive_shell({ sessionId: "calm-reef", kill: true })
|
||||
-> Kills session and returns final output
|
||||
|
||||
The user sees the overlay and can:
|
||||
- Watch output in real-time
|
||||
- Take over by typing (you'll see "user-takeover" status on next query)
|
||||
- Kill/background via Ctrl+Q
|
||||
|
||||
QUERYING SESSION STATUS:
|
||||
- interactive_shell({ sessionId: "calm-reef" }) - get status + rendered terminal output (default: 20 lines, 5KB)
|
||||
- interactive_shell({ sessionId: "calm-reef", outputLines: 50 }) - get more lines (max: 200)
|
||||
- interactive_shell({ sessionId: "calm-reef", outputMaxChars: 20000 }) - get more content (max: 50KB)
|
||||
- interactive_shell({ sessionId: "calm-reef", outputOffset: 0, outputLines: 50 }) - pagination (lines 0-49)
|
||||
- interactive_shell({ sessionId: "calm-reef", incremental: true }) - get next N unseen lines (server tracks position)
|
||||
- interactive_shell({ sessionId: "calm-reef", drain: true }) - only NEW output since last query (raw stream)
|
||||
- interactive_shell({ sessionId: "calm-reef", kill: true }) - end session
|
||||
- interactive_shell({ sessionId: "calm-reef", input: "..." }) - send input
|
||||
- interactive_shell({ monitorStatus: true, monitorSessionId: "calm-reef" }) - query monitor lifecycle/state
|
||||
- interactive_shell({ monitorEvents: true, monitorSessionId: "calm-reef" }) - query monitor event history
|
||||
- interactive_shell({ monitorEvents: true, monitorSessionId: "calm-reef", monitorSinceEventId: 42 }) - fetch events after a cursor
|
||||
- interactive_shell({ monitorEvents: true, monitorSessionId: "calm-reef", monitorTriggerId: "error" }) - filter monitor history by trigger id
|
||||
- interactive_shell({ monitorEvents: true, monitorSessionId: "calm-reef", monitorEventLimit: 50, monitorEventOffset: 20 }) - paginate monitor history
|
||||
|
||||
IMPORTANT: Don't query too frequently! Wait 30-60 seconds between status checks.
|
||||
The user is watching the overlay in real-time - you're just checking in periodically.
|
||||
|
||||
RATE LIMITING:
|
||||
Queries are limited to once every 60 seconds (configurable). If you query too soon,
|
||||
the tool will automatically wait until the limit expires before returning.
|
||||
|
||||
SENDING INPUT:
|
||||
- interactive_shell({ sessionId: "calm-reef", input: "/help", submit: true }) - type text and press Enter
|
||||
- interactive_shell({ sessionId: "calm-reef", inputKeys: ["ctrl+c"] }) - named keys
|
||||
- interactive_shell({ sessionId: "calm-reef", inputKeys: ["up", "up", "enter"] }) - multiple keys
|
||||
- interactive_shell({ sessionId: "calm-reef", inputHex: ["0x1b", "0x5b", "0x41"] }) - raw escape sequences
|
||||
- interactive_shell({ sessionId: "calm-reef", inputPaste: "multiline\\ntext" }) - bracketed paste (prevents auto-execution)
|
||||
|
||||
Named keys for inputKeys: up, down, left, right, enter, escape, tab, backspace, ctrl+c, ctrl+d, etc.
|
||||
Modifiers: ctrl+x, alt+x, shift+tab, ctrl+alt+delete (or c-x, m-x, s-tab syntax)
|
||||
For editor-based TUIs like pi, raw \`input\` only types text. It does NOT submit by itself. Prefer \`submit: true\` or \`inputKeys: ["enter"]\` instead of relying on \`\\n\`.
|
||||
|
||||
TIMEOUT (for TUI commands that don't exit cleanly):
|
||||
Use timeout to auto-kill after N milliseconds. Useful for capturing output from commands like "pi --help":
|
||||
- interactive_shell({ command: "pi --help", mode: "hands-free", timeout: 5000 })
|
||||
|
||||
DISPATCH MODE (NON-BLOCKING, NO POLLING):
|
||||
When mode="dispatch", the tool returns IMMEDIATELY with a sessionId.
|
||||
You do NOT need to poll. You'll be notified automatically when the session completes.
|
||||
|
||||
Workflow:
|
||||
1. Start session: interactive_shell({ command: 'pi "Fix bugs"', mode: "dispatch" })
|
||||
-> Returns immediately with sessionId
|
||||
2. Do other work - no polling needed
|
||||
3. When complete, you receive a notification with the session output
|
||||
|
||||
Dispatch defaults autoExitOnQuiet to true (opt-out with handsFree.autoExitOnQuiet: false).
|
||||
You can still query with sessionId if needed, but it's not required.
|
||||
|
||||
BACKGROUND DISPATCH (HEADLESS):
|
||||
Start a session without any overlay. Process runs headlessly, agent notified on completion:
|
||||
- interactive_shell({ command: 'pi "fix bugs"', mode: "dispatch", background: true })
|
||||
|
||||
MONITOR MODE (EVENT-DRIVEN, HEADLESS):
|
||||
Run a background process and wake the agent on structured monitor triggers:
|
||||
- interactive_shell({ command: 'npm test --watch', mode: "monitor", monitor: { strategy: "stream", triggers: [{ id: "fail", literal: "FAIL" }] } })
|
||||
- interactive_shell({ command: 'npm run dev', mode: "monitor", monitor: { strategy: "stream", triggers: [{ id: "warn", regex: "/error|warn/i" }] } })
|
||||
- interactive_shell({ command: 'curl -sf http://localhost:3000/health', mode: "monitor", monitor: { strategy: "poll-diff", triggers: [{ id: "changed", regex: "/./" }], poll: { intervalMs: 5000 } } })
|
||||
- interactive_shell({ mode: "monitor", monitor: { strategy: "file-watch", fileWatch: { path: "./uploads", recursive: true, events: ["rename", "change"] }, triggers: [{ id: "pdf", regex: "/\\.pdf$/i" }] } })
|
||||
|
||||
AGENT-INITIATED BACKGROUND:
|
||||
Dismiss an existing overlay, keep the process running in background:
|
||||
- interactive_shell({ sessionId: "calm-reef", background: true })
|
||||
|
||||
ATTACH (REATTACH TO BACKGROUND SESSION):
|
||||
Open an overlay for a background session:
|
||||
- interactive_shell({ attach: "calm-reef" }) - interactive (blocking)
|
||||
- interactive_shell({ attach: "calm-reef", mode: "hands-free" }) - hands-free (poll)
|
||||
- interactive_shell({ attach: "calm-reef", mode: "dispatch" }) - dispatch (non-blocking, notified)
|
||||
|
||||
LIST BACKGROUND SESSIONS:
|
||||
- interactive_shell({ listBackground: true })
|
||||
|
||||
DISMISS BACKGROUND SESSIONS:
|
||||
- interactive_shell({ dismissBackground: true }) - kill running, remove exited, clear all
|
||||
- interactive_shell({ dismissBackground: "calm-reef" }) - dismiss specific session
|
||||
|
||||
When using raw \`command\`, this tool does NOT inject prompts for you.
|
||||
If you want to start with a prompt, include it in the command using the CLI's own prompt form.
|
||||
Structured \`spawn\` also supports a \`prompt\` field for Pi, Codex, Claude, and Cursor using their native startup prompt forms.
|
||||
|
||||
Examples:
|
||||
- pi "Scan the current codebase"
|
||||
- claude "Check the current directory and summarize"
|
||||
- interactive_shell({ spawn: { agent: "codex" }, mode: "dispatch" })
|
||||
- interactive_shell({ spawn: { agent: "cursor", prompt: "Review the diffs" }, mode: "dispatch" })
|
||||
- interactive_shell({ spawn: { agent: "claude", prompt: "Review the diffs" }, mode: "dispatch" })
|
||||
- interactive_shell({ spawn: { mode: "fork" } }) // pi-only fork of the current persisted session
|
||||
- gemini (interactive, idle)
|
||||
- aider --yes-always (hands-free, auto-approve)
|
||||
- pi --help (with timeout: 5000 to capture help output)`;
|
||||
|
||||
export const toolParameters = Type.Object({
|
||||
command: Type.Optional(
|
||||
Type.String({
|
||||
description: "The raw CLI command to run (e.g., 'pi \"Fix the bug\"'). Use this for arbitrary CLIs. Mutually exclusive with 'spawn'.",
|
||||
}),
|
||||
),
|
||||
spawn: Type.Optional(
|
||||
Type.Object({
|
||||
agent: Type.Optional(Type.Union([
|
||||
Type.Literal("pi"),
|
||||
Type.Literal("codex"),
|
||||
Type.Literal("claude"),
|
||||
Type.Literal("cursor"),
|
||||
], {
|
||||
description: "Spawn agent to launch. Defaults to the configured spawn.defaultAgent.",
|
||||
})),
|
||||
mode: Type.Optional(Type.Union([
|
||||
Type.Literal("fresh"),
|
||||
Type.Literal("fork"),
|
||||
], {
|
||||
description: "Spawn mode. 'fork' is only supported for pi and requires a persisted current session.",
|
||||
})),
|
||||
worktree: Type.Optional(Type.Boolean({
|
||||
description: "Launch in a separate git worktree. Defaults to spawn.worktree from config.",
|
||||
})),
|
||||
prompt: Type.Optional(Type.String({
|
||||
description: "Optional startup prompt for pi, codex, claude, or cursor. Uses each CLI's native prompt-bearing startup form.",
|
||||
})),
|
||||
}, {
|
||||
description: "Structured spawn request for pi, codex, claude, or cursor. Use this instead of building the command string manually when you want the extension's spawn defaults, Pi-only fork behavior, worktree support, or native startup prompts.",
|
||||
}),
|
||||
),
|
||||
sessionId: Type.Optional(
|
||||
Type.String({
|
||||
description: "Session ID to interact with an existing hands-free session",
|
||||
}),
|
||||
),
|
||||
kill: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "Kill the session (requires sessionId). Use when task appears complete.",
|
||||
}),
|
||||
),
|
||||
outputLines: Type.Optional(
|
||||
Type.Number({
|
||||
description: "Number of lines to return when querying (default: 20, max: 200)",
|
||||
}),
|
||||
),
|
||||
outputMaxChars: Type.Optional(
|
||||
Type.Number({
|
||||
description: "Max chars to return when querying (default: 5KB, max: 50KB)",
|
||||
}),
|
||||
),
|
||||
outputOffset: Type.Optional(
|
||||
Type.Number({
|
||||
description: "Line offset for pagination (0-indexed). Use with outputLines to read specific ranges.",
|
||||
}),
|
||||
),
|
||||
drain: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "If true, return only NEW output since last query (raw stream). More token-efficient for repeated polling.",
|
||||
}),
|
||||
),
|
||||
incremental: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "If true, return next N lines not yet seen. Server tracks position - just keep calling to paginate through output.",
|
||||
}),
|
||||
),
|
||||
settings: Type.Optional(
|
||||
Type.Object({
|
||||
updateInterval: Type.Optional(
|
||||
Type.Number({ description: "Change max update interval for existing session (ms)" }),
|
||||
),
|
||||
quietThreshold: Type.Optional(
|
||||
Type.Number({ description: "Change quiet threshold for existing session (ms)" }),
|
||||
),
|
||||
}),
|
||||
),
|
||||
input: Type.Optional(
|
||||
Type.String({ description: "Raw text to send to the session (requires sessionId). This only types the text; it does not submit it. Use submit=true or inputKeys:['enter'] when you want to press Enter." }),
|
||||
),
|
||||
submit: Type.Optional(
|
||||
Type.Boolean({ description: "Press Enter after sending any input. Prefer this when submitting slash commands or prompts to editor-based TUIs like pi. (requires sessionId)" }),
|
||||
),
|
||||
inputKeys: Type.Optional(
|
||||
Type.Array(Type.String(), {
|
||||
description: "Named keys with modifier support: up, down, enter, ctrl+c, alt+x, shift+tab, ctrl+alt+delete, etc. (requires sessionId)",
|
||||
}),
|
||||
),
|
||||
inputHex: Type.Optional(
|
||||
Type.Array(Type.String(), {
|
||||
description: "Hex bytes to send as raw escape sequences (e.g., ['0x1b', '0x5b', '0x41'] for ESC[A). (requires sessionId)",
|
||||
}),
|
||||
),
|
||||
inputPaste: Type.Optional(
|
||||
Type.String({
|
||||
description: "Text to paste with bracketed paste mode - prevents shells from auto-executing multiline input. (requires sessionId)",
|
||||
}),
|
||||
),
|
||||
cwd: Type.Optional(
|
||||
Type.String({
|
||||
description: "Working directory for the command",
|
||||
}),
|
||||
),
|
||||
name: Type.Optional(
|
||||
Type.String({
|
||||
description: "Optional session name (used for session IDs)",
|
||||
}),
|
||||
),
|
||||
reason: Type.Optional(
|
||||
Type.String({
|
||||
description:
|
||||
"Brief explanation shown in the overlay header only (not passed to the subprocess)",
|
||||
}),
|
||||
),
|
||||
mode: Type.Optional(
|
||||
Type.Union([
|
||||
Type.Literal("interactive"),
|
||||
Type.Literal("hands-free"),
|
||||
Type.Literal("dispatch"),
|
||||
Type.Literal("monitor"),
|
||||
], {
|
||||
description: "Mode: 'interactive' (default, user controls), 'hands-free' (agent monitors, user can take over), 'dispatch' (agent notified on completion, no polling needed), or 'monitor' (headless structured event monitor with stream/poll-diff/file-watch strategies).",
|
||||
}),
|
||||
),
|
||||
monitor: Type.Optional(
|
||||
Type.Object({
|
||||
strategy: Type.Optional(Type.Union([
|
||||
Type.Literal("stream"),
|
||||
Type.Literal("poll-diff"),
|
||||
Type.Literal("file-watch"),
|
||||
], {
|
||||
description: "Monitor strategy. stream = line-based trigger matching. poll-diff = periodic snapshot diffing. file-watch = first-class filesystem watch events.",
|
||||
})),
|
||||
triggers: Type.Array(Type.Object({
|
||||
id: Type.String({ description: "Unique trigger id used in emitted event payloads." }),
|
||||
literal: Type.Optional(Type.String({ description: "Literal substring trigger." })),
|
||||
regex: Type.Optional(Type.String({ description: "Regex trigger string. Supports /pattern/flags format." })),
|
||||
cooldownMs: Type.Optional(Type.Number({ description: "Optional per-trigger cooldown window in ms." })),
|
||||
threshold: Type.Optional(Type.Object({
|
||||
captureGroup: Type.Number({ description: "Regex capture group index parsed as number (requires regex matcher)." }),
|
||||
op: Type.Union([
|
||||
Type.Literal("lt"),
|
||||
Type.Literal("lte"),
|
||||
Type.Literal("gt"),
|
||||
Type.Literal("gte"),
|
||||
], { description: "Threshold operator." }),
|
||||
value: Type.Number({ description: "Threshold numeric value." }),
|
||||
})),
|
||||
}), {
|
||||
description: "Named trigger definitions. Each trigger must define exactly one matcher: literal or regex.",
|
||||
}),
|
||||
fileWatch: Type.Optional(Type.Object({
|
||||
path: Type.String({ description: "Path to watch for strategy='file-watch'. Relative paths resolve from cwd." }),
|
||||
recursive: Type.Optional(Type.Boolean({ description: "Watch subdirectories recursively (platform-dependent support)." })),
|
||||
events: Type.Optional(Type.Array(Type.Union([
|
||||
Type.Literal("rename"),
|
||||
Type.Literal("change"),
|
||||
]), { description: "Filesystem event names to emit." })),
|
||||
})),
|
||||
poll: Type.Optional(Type.Object({
|
||||
intervalMs: Type.Optional(Type.Number({ description: "Poll interval in ms for strategy='poll-diff' (default: 5000)." })),
|
||||
})),
|
||||
persistence: Type.Optional(Type.Object({
|
||||
stopAfterFirstEvent: Type.Optional(Type.Boolean({ description: "Stop monitor after first emitted event." })),
|
||||
maxEvents: Type.Optional(Type.Number({ description: "Maximum emitted events before monitor stops." })),
|
||||
})),
|
||||
throttle: Type.Optional(Type.Object({
|
||||
dedupeExactLine: Type.Optional(Type.Boolean({ description: "Suppress repeated exact line/diff payloads (default: true)." })),
|
||||
cooldownMs: Type.Optional(Type.Number({ description: "Optional global cooldown in ms across triggers." })),
|
||||
})),
|
||||
detector: Type.Optional(Type.Object({
|
||||
detectorCommand: Type.String({ description: "External detector command. Receives JSON candidate event on stdin and returns JSON decision on stdout." }),
|
||||
timeoutMs: Type.Optional(Type.Number({ description: "Detector command timeout in ms (default: 3000)." })),
|
||||
})),
|
||||
}, {
|
||||
description: "Structured monitor configuration required when mode='monitor'.",
|
||||
}),
|
||||
),
|
||||
background: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "Run without overlay (with mode='dispatch' or mode='monitor') or dismiss existing overlay (with sessionId). Process runs in background, user can /attach.",
|
||||
}),
|
||||
),
|
||||
attach: Type.Optional(
|
||||
Type.String({
|
||||
description: "Background session ID to reattach. Opens overlay with the specified mode.",
|
||||
}),
|
||||
),
|
||||
listBackground: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "List all background sessions.",
|
||||
}),
|
||||
),
|
||||
dismissBackground: Type.Optional(
|
||||
Type.Union([Type.Boolean(), Type.String()], {
|
||||
description: "Dismiss background sessions. true = all, string = specific session ID. Kills running sessions, removes exited ones.",
|
||||
}),
|
||||
),
|
||||
monitorStatus: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "Query monitor lifecycle/state summary. Requires monitorSessionId or sessionId.",
|
||||
}),
|
||||
),
|
||||
monitorEvents: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "Query structured monitor event history instead of session output. Requires monitorSessionId or sessionId.",
|
||||
}),
|
||||
),
|
||||
monitorSessionId: Type.Optional(
|
||||
Type.String({
|
||||
description: "Target monitor session for monitorStatus/monitorEvents queries.",
|
||||
}),
|
||||
),
|
||||
monitorEventLimit: Type.Optional(
|
||||
Type.Number({
|
||||
description: "Max monitor events to return (default: 20).",
|
||||
}),
|
||||
),
|
||||
monitorEventOffset: Type.Optional(
|
||||
Type.Number({
|
||||
description: "How many newest monitor events to skip before returning results (default: 0).",
|
||||
}),
|
||||
),
|
||||
monitorSinceEventId: Type.Optional(
|
||||
Type.Number({
|
||||
description: "Only return monitor events with eventId greater than this cursor.",
|
||||
}),
|
||||
),
|
||||
monitorTriggerId: Type.Optional(
|
||||
Type.String({
|
||||
description: "Filter monitor events to a specific trigger id.",
|
||||
}),
|
||||
),
|
||||
handsFree: Type.Optional(
|
||||
Type.Object({
|
||||
updateMode: Type.Optional(
|
||||
Type.String({
|
||||
description: "Update mode: 'on-quiet' (default, emit when output stops) or 'interval' (emit on fixed schedule)",
|
||||
}),
|
||||
),
|
||||
updateInterval: Type.Optional(
|
||||
Type.Number({ description: "Max interval between updates in ms (default: 60000)" }),
|
||||
),
|
||||
quietThreshold: Type.Optional(
|
||||
Type.Number({ description: "Silence duration before emitting update in on-quiet mode (default: 8000ms)" }),
|
||||
),
|
||||
gracePeriod: Type.Optional(
|
||||
Type.Number({ description: "Startup grace period before autoExitOnQuiet can kill the session (default: 15000ms)" }),
|
||||
),
|
||||
updateMaxChars: Type.Optional(
|
||||
Type.Number({ description: "Max chars per update (default: 1500)" }),
|
||||
),
|
||||
maxTotalChars: Type.Optional(
|
||||
Type.Number({ description: "Total char budget for all updates (default: 100000). Updates stop including content when exhausted." }),
|
||||
),
|
||||
autoExitOnQuiet: Type.Optional(
|
||||
Type.Boolean({
|
||||
description: "Auto-kill session when output stops (after quietThreshold). Defaults to false. Set to true for fire-and-forget single-task delegations.",
|
||||
}),
|
||||
),
|
||||
}),
|
||||
),
|
||||
handoffPreview: Type.Optional(
|
||||
Type.Object({
|
||||
enabled: Type.Optional(Type.Boolean({ description: "Include last N lines in tool result details" })),
|
||||
lines: Type.Optional(Type.Number({ description: "Tail lines to include (default from config)" })),
|
||||
maxChars: Type.Optional(
|
||||
Type.Number({ description: "Max chars to include in tail preview (default from config)" }),
|
||||
),
|
||||
}),
|
||||
),
|
||||
handoffSnapshot: Type.Optional(
|
||||
Type.Object({
|
||||
enabled: Type.Optional(Type.Boolean({ description: "Write a transcript snapshot on detach/exit" })),
|
||||
lines: Type.Optional(Type.Number({ description: "Tail lines to capture (default from config)" })),
|
||||
maxChars: Type.Optional(Type.Number({ description: "Max chars to write (default from config)" })),
|
||||
}),
|
||||
),
|
||||
timeout: Type.Optional(
|
||||
Type.Number({
|
||||
description: "Auto-kill process after N milliseconds. Useful for TUI commands that don't exit cleanly (e.g., 'pi --help')",
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
/** Parsed tool parameters type */
|
||||
export interface ToolParams {
|
||||
command?: string;
|
||||
spawn?: { agent?: "pi" | "codex" | "claude" | "cursor"; mode?: "fresh" | "fork"; worktree?: boolean; prompt?: string };
|
||||
sessionId?: string;
|
||||
kill?: boolean;
|
||||
outputLines?: number;
|
||||
outputMaxChars?: number;
|
||||
outputOffset?: number;
|
||||
drain?: boolean;
|
||||
incremental?: boolean;
|
||||
settings?: { updateInterval?: number; quietThreshold?: number };
|
||||
input?: string;
|
||||
submit?: boolean;
|
||||
inputKeys?: string[];
|
||||
inputHex?: string[];
|
||||
inputPaste?: string;
|
||||
cwd?: string;
|
||||
name?: string;
|
||||
reason?: string;
|
||||
mode?: "interactive" | "hands-free" | "dispatch" | "monitor";
|
||||
background?: boolean;
|
||||
monitor?: {
|
||||
strategy?: "stream" | "poll-diff" | "file-watch";
|
||||
triggers: Array<{
|
||||
id: string;
|
||||
literal?: string;
|
||||
regex?: string;
|
||||
cooldownMs?: number;
|
||||
threshold?: { captureGroup: number; op: "lt" | "lte" | "gt" | "gte"; value: number };
|
||||
}>;
|
||||
fileWatch?: { path: string; recursive?: boolean; events?: Array<"rename" | "change"> };
|
||||
poll?: { intervalMs?: number };
|
||||
persistence?: { stopAfterFirstEvent?: boolean; maxEvents?: number };
|
||||
throttle?: { dedupeExactLine?: boolean; cooldownMs?: number };
|
||||
detector?: { detectorCommand: string; timeoutMs?: number };
|
||||
};
|
||||
attach?: string;
|
||||
listBackground?: boolean;
|
||||
dismissBackground?: boolean | string;
|
||||
monitorStatus?: boolean;
|
||||
monitorEvents?: boolean;
|
||||
monitorSessionId?: string;
|
||||
monitorEventLimit?: number;
|
||||
monitorEventOffset?: number;
|
||||
monitorSinceEventId?: number;
|
||||
monitorTriggerId?: string;
|
||||
handsFree?: {
|
||||
updateMode?: "on-quiet" | "interval";
|
||||
updateInterval?: number;
|
||||
quietThreshold?: number;
|
||||
gracePeriod?: number;
|
||||
updateMaxChars?: number;
|
||||
maxTotalChars?: number;
|
||||
autoExitOnQuiet?: boolean;
|
||||
};
|
||||
handoffPreview?: { enabled?: boolean; lines?: number; maxChars?: number };
|
||||
handoffSnapshot?: { enabled?: boolean; lines?: number; maxChars?: number };
|
||||
timeout?: number;
|
||||
}
|
||||
Reference in New Issue
Block a user