diff --git a/README.md b/README.md index 336a017..f6f85ec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # bb plugins -Four bb plugins I use for product design work, kept together with the few build and repository tools they share. [![CI](https://github.com/brsbl/bb-plugins/actions/workflows/ci.yml/badge.svg)](https://github.com/brsbl/bb-plugins/actions/workflows/ci.yml) +Five bb plugins I use for product design work, kept together with the few build and repository tools they share. [![CI](https://github.com/brsbl/bb-plugins/actions/workflows/ci.yml/badge.svg)](https://github.com/brsbl/bb-plugins/actions/workflows/ci.yml) [bb](https://getbb.app) is an agentic IDE for running coding agents across projects, threads, and environments. Its plugins can add UI, commands, skills, and server capabilities; this repository is where I build and maintain mine. @@ -38,6 +38,16 @@ Lets you peek at a thread's status and repository context without leaving the si Install: `bb plugin install git:https://github.com/brsbl/bb-plugins.git@plugin/thread-hover-cards --yes` +### Thread Organizer + +Files new threads into the right existing work section while preserving native titles and every manual override. + +![Thread Organizer settings in bb](plugins/thread-organizer/docs/screenshot.png) + +[Source](plugins/thread-organizer) · [README](plugins/thread-organizer/README.md) + +Install: `bb plugin install git:https://github.com/brsbl/bb-plugins.git@plugin/thread-organizer --yes` + ### UI Patterns Puts proven UI components and interaction guidance within reach of both designers and agents. diff --git a/package-lock.json b/package-lock.json index e9a711b..8da825e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4005,6 +4005,10 @@ "resolved": "plugins/thread-hover-cards", "link": true }, + "node_modules/bb-plugin-thread-organizer": { + "resolved": "plugins/thread-organizer", + "link": true + }, "node_modules/bb-plugin-ui-patterns": { "resolved": "plugins/ui-patterns", "link": true @@ -6678,6 +6682,26 @@ "bbPluginSdk": "^0.4.0" } }, + "plugins/thread-organizer": { + "name": "bb-plugin-thread-organizer", + "version": "0.1.0", + "license": "UNLICENSED", + "devDependencies": { + "@bb/plugin-sdk": "file:../../tooling/vendor/bb-plugin-sdk-0.4.0.tgz", + "@types/better-sqlite3": "^7.6.12", + "@types/node": "^22.0.0", + "better-sqlite3": "^12.10.0", + "cron-parser": "^5.5.0", + "hono": "^4.11.9", + "typescript": "^5.7.0", + "vitest": "^4.1.8", + "zod": "^4.3.6" + }, + "engines": { + "bb": ">=0.0.34", + "bbPluginSdk": "^0.4.0" + } + }, "plugins/ui-patterns": { "name": "bb-plugin-ui-patterns", "version": "0.1.0", diff --git a/plugins/thread-organizer/README.md b/plugins/thread-organizer/README.md new file mode 100644 index 0000000..4de7de7 --- /dev/null +++ b/plugins/thread-organizer/README.md @@ -0,0 +1,62 @@ +# Thread Organizer + +Thread Organizer files new bb threads into existing work sections while leaving manual organization in control. It starts in observe mode and never creates sections, backfills old threads, or runs a hidden classification agent. + +![Thread Organizer settings in bb](docs/screenshot.png) + +## Install + +```bash +bb plugin install git:https://github.com/brsbl/bb-plugins.git@plugin/thread-organizer --yes +``` + +## Use + +Leave the plugin in its default `observe` mode first and inspect its decisions: + +```bash +bb plugin logs thread-organizer -f +``` + +When the proposals look right, enable changes: + +```bash +bb plugin config thread-organizer set mode apply +``` + +The setting takes effect immediately. + +| Existing section | Automatic use | +| --- | --- | +| `bb` or `bb quick fixes` | bb engineering work | +| `Extensions` | Plugins, skills, automations, and agent tooling | +| `Design` | Design systems, UI patterns, information architecture, and API-surface work | +| `Writing` | Articles, positioning, copy, and editorial work | +| `QA` | Never; reserved for manual phase management | + +Threads that do not clear the confidence threshold stay unsectioned. Pinning remains independent priority state, and archiving remains completion state. + +## Behavior + +| Moment | Evaluation | +| --- | --- | +| Creation | Uses project identity and the prompt-derived title fallback for an early section proposal | +| Activation | Retries prompt history briefly when the initial prompt was not yet available | +| First completed turn | Refines the section and repairs a still-missing title | +| Later turns | Re-evaluates at turns 5, 15, 25, and every ten completed turns thereafter | + +New placements require at least `0.85` confidence with a `0.20` lead over the next rule. Moving a plugin-managed thread requires `0.92` confidence, a `0.25` lead, and the same result at two consecutive scheduled evaluations. + +Only visible, ordinary user root threads created while the plugin is loaded are tracked. Hidden workers, children, forks, side chats, plugin-originated threads, archived threads, deleted threads, and terminal error states are excluded. + +An explicit creation-time title or section is locked. After the plugin writes a field, any different value is treated as a manual or external override and locks that field permanently. Native bb titles therefore win, and section changes are never cleared automatically. + +## Develop + +From the monorepo root: + +```bash +npm ci +npm run check --workspace=bb-plugin-thread-organizer +bb plugin install "path:$PWD/plugins/thread-organizer" --yes +``` diff --git a/plugins/thread-organizer/core.test.ts b/plugins/thread-organizer/core.test.ts new file mode 100644 index 0000000..3f380b4 --- /dev/null +++ b/plugins/thread-organizer/core.test.ts @@ -0,0 +1,206 @@ +import { describe, expect, it } from "vitest"; + +import { + advanceEvaluationMilestone, + classifySection, + deriveTaskTitle, + isEligibleThread, + resolveSectionId, +} from "./core.js"; + +describe("thread eligibility", () => { + const eligible = { + archivedAt: null, + childOrigin: null, + deletedAt: null, + originKind: null, + originPluginId: null, + parentThreadId: null, + sourceThreadId: null, + status: "idle" as const, + visibility: "visible" as const, + }; + + it("accepts ordinary root threads, including pinned threads by implication", () => { + expect(isEligibleThread(eligible)).toBe(true); + }); + + it.each([ + { ...eligible, archivedAt: 1 }, + { ...eligible, deletedAt: 1 }, + { ...eligible, parentThreadId: "thr_parent" }, + { ...eligible, sourceThreadId: "thr_source" }, + { ...eligible, originKind: "side-chat" as const }, + { ...eligible, childOrigin: "fork" as const }, + { ...eligible, originPluginId: "automations" }, + { ...eligible, status: "error" as const }, + { ...eligible, visibility: "hidden" as const }, + ])("rejects protected thread shape %#", (thread) => { + expect(isEligibleThread(thread)).toBe(false); + }); +}); + +describe("section classification", () => { + it.each([ + { + expected: "bb", + projectName: "bb", + texts: ["Review the recent plugin API changes and harden them."], + title: "Plugin API review and hardening", + }, + { + expected: "bb", + projectName: "bb", + texts: ["can you make a prod build from latest origin/main?"], + title: "bb integration branch", + }, + { + expected: "extensions", + projectName: "Personal", + texts: [ + "Create a bb plugin that automatically renames and reorganizes threads.", + ], + title: "Auto Rename and Reorganize", + }, + { + expected: "extensions", + projectName: "bb plugins", + texts: ["Design and implement the Omegacode plugin workflow overview."], + title: "Omegacode workflow overview design pass", + }, + { + expected: "extensions", + projectName: "Design Doctrine", + texts: ["Rewrite the doctrine docs."], + title: "Rewrite doctrine docs", + }, + { + expected: "design", + projectName: "UI Pattern Atlas", + texts: ["Take over the UI Patterns work."], + title: "atlas", + }, + { + expected: "design", + projectName: "moss", + texts: ["Continue the design↔code system work."], + title: "design↔code", + }, + { + expected: "design", + projectName: "moss", + texts: ["Spec the right API surface for the Moss agent."], + title: "Moss Agent API Surface", + }, + { + expected: "writing", + projectName: "moss", + texts: ["Help me work on positioning for Moss."], + title: "moss positioning", + }, + { + expected: "writing", + projectName: "Personal", + texts: ["Write a blog post about creating loops."], + title: "Creating Loops Blog Post", + }, + { + expected: "bb", + projectName: "bb", + texts: ["https://github.com/ymichael/bb/issues/603"], + title: "Issue 603", + }, + ])("classifies $title as $expected", ({ expected, projectName, texts }) => { + expect(classifySection({ projectName, texts })?.target).toBe(expected); + }); + + it("abstains from weak personal-workspace intent", () => { + expect( + classifySection({ + projectName: "Personal", + texts: ["clean up disk space and CPU"], + }), + ).toBeNull(); + }); + + it("surfaces a low margin instead of hiding mixed bb design intent", () => { + const decision = classifySection({ + projectName: "bb", + texts: ["Design a durable UI pattern system."], + }); + expect(decision).toMatchObject({ + runnerUp: "bb", + target: "design", + }); + expect(decision?.margin).toBeCloseTo(0.05); + }); +}); + +describe("existing section resolution", () => { + it("supports the bb quick fixes migration alias", () => { + expect( + resolveSectionId( + [ + { id: "sec_bb", name: "bb quick fixes" }, + { id: "sec_design", name: "Design" }, + ], + "bb", + ), + ).toBe("sec_bb"); + }); + + it("fails closed when both bb aliases exist", () => { + expect( + resolveSectionId( + [ + { id: "sec_bb", name: "bb" }, + { id: "sec_old", name: "bb quick fixes" }, + ], + "bb", + ), + ).toBeNull(); + }); + + it("never treats QA as a target alias", () => { + expect( + resolveSectionId([{ id: "sec_qa", name: "QA" }], "design"), + ).toBeNull(); + }); +}); + +describe("conservative title repair", () => { + it.each([ + ["can you optimize my CI?", "Optimize CI"], + ["Please fix the external file nav.", "Fix External File Nav"], + ["take over tools hub refactor PR", "Take Over Tools Hub Refactor"], + ["clean up disk space and CPU", "Clean Up Disk Space"], + ])("derives %s", (prompt, expected) => { + expect(deriveTaskTitle(prompt)?.title).toBe(expected); + }); + + it.each([ + "continue", + "root cause this", + "https://github.com/ymichael/bb/issues/603", + "create a bb plugin", + "what should we do next?", + ])("abstains from %s", (prompt) => { + expect(deriveTaskTitle(prompt)).toBeNull(); + }); +}); + +describe("turn milestones", () => { + it.each([ + [1, 1, 5], + [1, 4, 5], + [1, 5, 15], + [5, 14, 15], + [5, 15, 25], + [15, 37, 45], + ])( + "advances current %i after %i completed turns to %i", + (current, turns, expected) => { + expect(advanceEvaluationMilestone(current, turns)).toBe(expected); + }, + ); +}); diff --git a/plugins/thread-organizer/core.ts b/plugins/thread-organizer/core.ts new file mode 100644 index 0000000..7142639 --- /dev/null +++ b/plugins/thread-organizer/core.ts @@ -0,0 +1,390 @@ +export const SECTION_TARGETS = [ + "bb", + "extensions", + "design", + "writing", +] as const; + +export type SectionTarget = (typeof SECTION_TARGETS)[number]; + +export interface OrganizableThread { + archivedAt: number | null; + childOrigin: "fork" | "side-chat" | null; + deletedAt: number | null; + originKind: "fork" | "side-chat" | null; + originPluginId: string | null; + parentThreadId: string | null; + sourceThreadId: string | null; + status: "active" | "error" | "idle" | "starting" | "stopping"; + visibility: "hidden" | "visible"; +} + +export interface SectionClassification { + confidence: number; + margin: number; + reasons: string[]; + runnerUp: SectionTarget | null; + target: SectionTarget; +} + +export interface SectionDescriptor { + id: string; + name: string; +} + +export interface TitleCandidate { + confidence: number; + title: string; +} + +const SECTION_ALIASES: Record = { + bb: ["bb", "bb quick fixes"], + design: ["design"], + extensions: ["extensions"], + writing: ["writing"], +}; + +const LOW_INFORMATION = new Set([ + "continue", + "do it", + "fix", + "go ahead", + "help", + "help me", + "investigate", + "ok", + "okay", + "proceed", + "root cause this", + "sounds good", + "yes", +]); + +const ACTION_PATTERNS: Array<{ + expression: RegExp; + title: string; +}> = [ + { expression: /^take\s+over\b/i, title: "Take Over" }, + { expression: /^clean\s+up\b/i, title: "Clean Up" }, + { expression: /^root\s+cause\b/i, title: "Investigate" }, + { expression: /^investigate\b/i, title: "Investigate" }, + { expression: /^implement\b/i, title: "Implement" }, + { expression: /^optimize\b/i, title: "Optimize" }, + { expression: /^reorganize\b/i, title: "Reorganize" }, + { expression: /^refactor\b/i, title: "Refactor" }, + { expression: /^analyze\b/i, title: "Analyze" }, + { expression: /^create\b/i, title: "Create" }, + { expression: /^design\b/i, title: "Design" }, + { expression: /^rewrite\b/i, title: "Rewrite" }, + { expression: /^refresh\b/i, title: "Refresh" }, + { expression: /^profile\b/i, title: "Profile" }, + { expression: /^review\b/i, title: "Review" }, + { expression: /^rename\b/i, title: "Rename" }, + { expression: /^update\b/i, title: "Update" }, + { expression: /^render\b/i, title: "Render" }, + { expression: /^archive\b/i, title: "Archive" }, + { expression: /^debug\b/i, title: "Debug" }, + { expression: /^build\b/i, title: "Build" }, + { expression: /^write\b/i, title: "Write" }, + { expression: /^style\b/i, title: "Style" }, + { expression: /^move\b/i, title: "Move" }, + { expression: /^open\b/i, title: "Open" }, + { expression: /^audit\b/i, title: "Audit" }, + { expression: /^add\b/i, title: "Add" }, + { expression: /^fix\b/i, title: "Fix" }, +]; + +const GENERIC_TITLE_WORDS = new Set([ + "agent", + "automation", + "bb", + "issue", + "plugin", + "problem", + "task", + "thing", + "this", + "thread", +]); + +const TITLE_CONNECTORS = new Set([ + "and", + "for", + "from", + "in", + "of", + "on", + "or", + "to", + "with", +]); + +const TITLE_ACRONYMS = new Set([ + "api", + "bb", + "ci", + "cpu", + "css", + "ds", + "html", + "http", + "https", + "mcp", + "pr", + "qa", + "sdk", + "ui", + "url", + "ux", +]); + +function normalize(value: string): string { + return value + .normalize("NFKC") + .replace(/\r\n?/g, "\n") + .replace(/[ \t]+/g, " ") + .trim() + .toLowerCase(); +} + +function matches(value: string, expression: RegExp): boolean { + expression.lastIndex = 0; + return expression.test(value); +} + +export function isSubstantiveText(value: string): boolean { + const normalized = normalize(value) + .replace(/^\/[a-z0-9:_-]+\s*/i, "") + .replace(/[.!?]+$/g, "") + .trim(); + if (normalized.length < 4 || LOW_INFORMATION.has(normalized)) return false; + return !/^(?:https?:\/\/\S+|@[a-z0-9:_-]+)$/i.test(normalized); +} + +export function isEligibleThread(thread: OrganizableThread): boolean { + return ( + thread.visibility === "visible" && + thread.parentThreadId === null && + thread.sourceThreadId === null && + thread.originKind === null && + thread.childOrigin === null && + thread.originPluginId === null && + thread.archivedAt === null && + thread.deletedAt === null && + thread.status !== "error" && + thread.status !== "stopping" + ); +} + +function setScore( + scores: Map, + target: SectionTarget, + confidence: number, + reason: string, +): void { + const current = scores.get(target); + if (current === undefined || confidence > current.confidence) { + scores.set(target, { confidence, reasons: [reason] }); + return; + } + if (confidence === current.confidence && !current.reasons.includes(reason)) { + current.reasons.push(reason); + } +} + +export function classifySection(input: { + projectName: string; + texts: string[]; +}): SectionClassification | null { + const project = normalize(input.projectName); + const substantive = input.texts.filter(isSubstantiveText).map(normalize); + const corpus = substantive.join("\n"); + const scores = new Map< + SectionTarget, + { confidence: number; reasons: string[] } + >(); + + if ( + matches( + corpus, + /\b(blog(?:\s+post)?|article|essay|positioning|product copy|website copy|editorial)\b/i, + ) + ) { + setScore(scores, "writing", 0.96, "explicit editorial intent"); + } + + if ( + project === "ui pattern atlas" || + matches( + corpus, + /\b(design system|ui patterns?|information architecture|interaction model|product direction|api surface|figma)\b|design\s*[↔<>-]\s*code/i, + ) + ) { + setScore( + scores, + "design", + project === "ui pattern atlas" ? 0.97 : 0.95, + project === "ui pattern atlas" + ? "design project identity" + : "durable design-system intent", + ); + } + + if ( + ["bb plugins", "prompt shaper"].includes(project) || + (project !== "bb" && + matches( + corpus, + /\b(bb\s+plugin|plugin|skill|automation|agent tool|agent tooling)\b/i, + )) + ) { + setScore( + scores, + "extensions", + project === "bb plugins" || project === "prompt shaper" ? 0.98 : 0.96, + project === "bb plugins" || project === "prompt shaper" + ? "extension project identity" + : "explicit extension intent", + ); + } else if (project === "design doctrine") { + setScore(scores, "extensions", 0.9, "extension project identity"); + } + + if (project === "bb") { + setScore(scores, "bb", 0.9, "bb project identity"); + if ( + matches( + corpus, + /\b(fix|debug|investigate|implement|build|review|refactor|test|ci|server|daemon|sync|branch|pull request|pr\s*#?\d+|issue\s*#?\d+)\b/i, + ) + ) { + setScore(scores, "bb", 0.96, "bb engineering intent"); + } + } + + const ranked = [...scores.entries()] + .map(([target, value]) => ({ target, ...value })) + .sort( + (left, right) => + right.confidence - left.confidence || + left.target.localeCompare(right.target), + ); + const winner = ranked[0]; + if (winner === undefined) return null; + const runnerUp = ranked[1] ?? null; + return { + confidence: winner.confidence, + margin: winner.confidence - (runnerUp?.confidence ?? 0), + reasons: winner.reasons, + runnerUp: runnerUp?.target ?? null, + target: winner.target, + }; +} + +export function resolveSectionId( + sections: SectionDescriptor[], + target: SectionTarget, +): string | null { + const aliases = new Set(SECTION_ALIASES[target]); + const matches = sections.filter((section) => + aliases.has(normalize(section.name)), + ); + return matches.length === 1 ? matches[0]!.id : null; +} + +function stripPromptPreamble(value: string): string { + let result = value + .normalize("NFKC") + .replace(/\r\n?/g, "\n") + .replace(/^\s*(?:[-*]|\d+[.)])\s+/, "") + .replace(/^\/[a-z0-9:_-]+\s+/i, "") + .trim(); + const preambles = [ + /^(?:can|could|would)\s+you\s+/i, + /^can\s+i\s+/i, + /^please\s+/i, + /^i\s+(?:want|need)\s+to\s+/i, + /^i(?:'d| would)\s+like\s+to\s+/i, + /^help\s+me\s+(?:to\s+)?/i, + /^let(?:'s| us)\s+/i, + ]; + for (const preamble of preambles) result = result.replace(preamble, ""); + return result.trim(); +} + +function displayTitleWord(word: string, index: number): string { + const lower = word.toLowerCase(); + if (TITLE_ACRONYMS.has(lower)) return lower.toUpperCase(); + if (index > 0 && TITLE_CONNECTORS.has(lower)) return lower; + if (/[0-9↔<>+#./-]/.test(word) && /[A-Z]/.test(word)) return word; + return `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}`; +} + +export function deriveTaskTitle(value: string): TitleCandidate | null { + let prompt = stripPromptPreamble(value); + if ( + prompt.length === 0 || + /^(?:https?:\/\/|@)/i.test(prompt) || + !isSubstantiveText(prompt) + ) { + return null; + } + + const action = ACTION_PATTERNS.find(({ expression }) => + matches(prompt, expression), + ); + if (action === undefined) return null; + prompt = prompt.replace(action.expression, "").trim(); + prompt = prompt + .split(/\b(?:so that|because|and then|then|which|that)\b|[\n.!?;:]/i, 1)[0]! + .replace(/^[\s"'`([{]+|[\s"'`\])}]+$/g, "") + .trim(); + + const words = + prompt.match(/[A-Za-z0-9][A-Za-z0-9+#./↔<>-]*/g)?.filter(Boolean) ?? []; + while ( + words.length > 0 && + /^(?:a|an|my|our|the|this|these|those)$/i.test(words[0]!) + ) { + words.shift(); + } + + const actionWordCount = action.title.split(/\s+/).length; + const objectWords = words.slice(0, Math.max(1, 5 - actionWordCount)); + while ( + objectWords.length > 0 && + TITLE_CONNECTORS.has(objectWords.at(-1)!.toLowerCase()) + ) { + objectWords.pop(); + } + const specificWords = objectWords.filter((word) => { + const normalized = word.toLowerCase(); + return ( + !GENERIC_TITLE_WORDS.has(normalized) && + !TITLE_CONNECTORS.has(normalized) && + normalized.length > 1 + ); + }); + if (objectWords.length === 0 || specificWords.length === 0) return null; + + const objectTitle = objectWords + .map((word, index) => displayTitleWord(word, index + actionWordCount)) + .join(" "); + return { + confidence: 0.92, + title: `${action.title} ${objectTitle}`.trim(), + }; +} + +export function nextEvaluationMilestone(current: number): number { + return current <= 1 ? 5 : current + 10; +} + +export function advanceEvaluationMilestone( + current: number, + completedTurns: number, +): number { + let next = current; + while (next <= completedTurns) next = nextEvaluationMilestone(next); + return next; +} diff --git a/plugins/thread-organizer/docs/screenshot.png b/plugins/thread-organizer/docs/screenshot.png new file mode 100644 index 0000000..5504fa9 Binary files /dev/null and b/plugins/thread-organizer/docs/screenshot.png differ diff --git a/plugins/thread-organizer/package.json b/plugins/thread-organizer/package.json new file mode 100644 index 0000000..98d9c1f --- /dev/null +++ b/plugins/thread-organizer/package.json @@ -0,0 +1,42 @@ +{ + "name": "bb-plugin-thread-organizer", + "version": "0.1.0", + "description": "Organizes new bb threads into existing sections while preserving manual changes.", + "type": "module", + "license": "UNLICENSED", + "files": [ + "dist", + "docs", + "README.md" + ], + "scripts": { + "build": "node ../../tooling/build-plugin.mjs", + "check": "npm run typecheck && npm run build && npm test", + "test": "vitest run", + "typecheck": "tsc --noEmit" + }, + "engines": { + "bb": ">=0.0.34", + "bbPluginSdk": "^0.4.0" + }, + "bb": { + "name": "Thread Organizer", + "description": "Organizes new bb threads into existing sections while preserving manual changes.", + "branding": { + "icon": "FolderTree" + }, + "server": "./server.ts", + "skills": [] + }, + "devDependencies": { + "@bb/plugin-sdk": "file:../../tooling/vendor/bb-plugin-sdk-0.4.0.tgz", + "@types/better-sqlite3": "^7.6.12", + "@types/node": "^22.0.0", + "better-sqlite3": "^12.10.0", + "cron-parser": "^5.5.0", + "hono": "^4.11.9", + "typescript": "^5.7.0", + "vitest": "^4.1.8", + "zod": "^4.3.6" + } +} diff --git a/plugins/thread-organizer/server.test.ts b/plugins/thread-organizer/server.test.ts new file mode 100644 index 0000000..786edf0 --- /dev/null +++ b/plugins/thread-organizer/server.test.ts @@ -0,0 +1,505 @@ +import { + createFakePluginHost, + makeThreadResponse, +} from "@bb/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; + +import plugin from "./server.js"; + +const sections = [ + { id: "sec_bb", name: "bb" }, + { id: "sec_design", name: "Design" }, + { id: "sec_extensions", name: "Extensions" }, + { id: "sec_qa", name: "QA" }, + { id: "sec_writing", name: "Writing" }, +]; + +function promptEntry(text: string, createdAt = 1) { + return { + id: `prompt_${createdAt}`, + createdAt, + input: [{ type: "text" as const, text }], + }; +} + +function completedEvent(seq: number) { + return { + id: `event_${seq}`, + createdAt: seq, + data: { providerThreadId: null, status: "completed" as const }, + scope: { kind: "thread" as const }, + seq, + threadId: "thr_test", + type: "turn/completed" as const, + }; +} + +function createHarness(input?: { + mode?: "apply" | "observe"; + projectName?: string; + prompt?: string; + thread?: Parameters[0]; +}) { + const prompt = + input?.prompt ?? + "Create a bb plugin that automatically organizes new threads."; + let thread = makeThreadResponse({ + id: "thr_test", + projectId: "proj_test", + status: "starting", + title: null, + titleFallback: prompt, + ...input?.thread, + }); + const events: ReturnType[] = []; + let promptHistory = [promptEntry(prompt)]; + const update = vi.fn( + async (args: { + sectionId?: string | null; + threadId: string; + title?: string | null; + }) => { + thread = makeThreadResponse({ + ...thread, + ...(Object.hasOwn(args, "sectionId") + ? { sectionId: args.sectionId ?? null } + : {}), + ...(Object.hasOwn(args, "title") + ? { title: args.title ?? null } + : {}), + updatedAt: thread.updatedAt + 1, + }); + return thread; + }, + ); + const host = createFakePluginHost({ + pluginId: "thread-organizer", + settings: { mode: input?.mode ?? "observe" }, + sdk: { + projects: { + get: async () => ({ + id: "proj_test", + name: input?.projectName ?? "Personal", + }), + }, + threadSections: { list: async () => sections }, + threads: { + events: { + wait: async (args: { afterSeq?: string }) => { + const after = Number(args.afterSeq ?? 0); + return events.find((event) => event.seq > after) ?? null; + }, + }, + get: async () => thread, + promptHistory: async () => promptHistory, + update, + }, + }, + }); + + return { + ...host, + addCompletedTurn(seq: number) { + events.push(completedEvent(seq)); + thread = makeThreadResponse({ ...thread, status: "idle" }); + }, + currentThread() { + return thread; + }, + setPromptHistory(...texts: string[]): void { + promptHistory = texts.map((text, index) => + promptEntry(text, index + 1), + ); + }, + setThread( + changes: Partial>, + ): void { + thread = makeThreadResponse({ ...thread, ...changes }); + }, + update, + }; +} + +describe("Thread Organizer plugin", () => { + it("registers a headless observe-mode lifecycle", async () => { + const { bb, harness } = createHarness(); + plugin(bb); + + expect(harness.inspection.registrations.settingsDescriptors).toMatchObject({ + mode: { default: "observe", options: ["observe", "apply"] }, + }); + expect(harness.inspection.registrations.threadEventHandlers).toMatchObject({ + "thread.active": 1, + "thread.archived": 1, + "thread.created": 1, + "thread.deleted": 1, + "thread.idle": 1, + }); + expect(harness.inspection.registrations.cli).toBeNull(); + expect(harness.inspection.registrations.rpcMethods).toEqual([]); + await harness.lifecycle.dispose(); + }); + + it("logs a recommendation without changing a thread in observe mode", async () => { + const { bb, harness, currentThread, update } = createHarness(); + plugin(bb); + + await harness.behavior.emitThreadEvent("thread.created", { + thread: currentThread(), + }); + + expect(update).not.toHaveBeenCalled(); + expect(harness.inspection.logEntries).toContainEqual( + expect.objectContaining({ + level: "info", + message: expect.stringContaining( + "mode=observe action=propose-section target=extensions", + ), + }), + ); + await harness.lifecycle.dispose(); + }); + + it("classifies personal-workspace threads without a project GET", async () => { + const { bb, harness, currentThread } = createHarness({ + thread: { projectId: "proj_personal" }, + }); + plugin(bb); + + await harness.behavior.emitThreadEvent("thread.created", { + thread: currentThread(), + }); + + expect( + harness.inspection.sdk.callsTo("projects.get"), + ).toHaveLength(0); + expect(harness.inspection.logEntries).toContainEqual( + expect.objectContaining({ + message: expect.stringContaining( + "mode=observe action=propose-section target=extensions", + ), + }), + ); + await harness.lifecycle.dispose(); + }); + + it("places a new unsectioned plugin thread in Extensions in apply mode", async () => { + const { bb, harness, currentThread, update } = createHarness({ + mode: "apply", + }); + plugin(bb); + + await harness.behavior.emitThreadEvent("thread.created", { + thread: currentThread(), + }); + + expect(update).toHaveBeenCalledWith({ + threadId: "thr_test", + sectionId: "sec_extensions", + }); + await harness.lifecycle.dispose(); + }); + + it("never changes an explicit creation-time section", async () => { + const { bb, harness, currentThread, update } = createHarness({ + mode: "apply", + thread: { sectionId: "sec_qa" }, + }); + plugin(bb); + + await harness.behavior.emitThreadEvent("thread.created", { + thread: currentThread(), + }); + + expect(update).not.toHaveBeenCalled(); + await harness.lifecycle.dispose(); + }); + + it("locks title and section management after manual overrides", async () => { + const organizer = createHarness({ mode: "apply" }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + expect(organizer.currentThread().sectionId).toBe("sec_extensions"); + + organizer.setThread({ + sectionId: "sec_qa", + status: "active", + title: "My Manual Title", + }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + + expect(organizer.update).toHaveBeenCalledTimes(1); + expect(organizer.harness.inspection.logEntries).toContainEqual( + expect.objectContaining({ + message: expect.stringContaining( + "action=manual-lock title=true section=true", + ), + }), + ); + await organizer.harness.lifecycle.dispose(); + }); + + it("repairs a missing title only after the first completed turn", async () => { + const organizer = createHarness({ + mode: "apply", + projectName: "Personal", + prompt: "Please fix the external file nav.", + }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + expect(organizer.update).not.toHaveBeenCalled(); + + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: null, + thread: organizer.currentThread(), + }); + expect(organizer.update).not.toHaveBeenCalled(); + + organizer.addCompletedTurn(10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + + expect(organizer.update).toHaveBeenCalledWith({ + threadId: "thr_test", + title: "Fix External File Nav", + }); + await organizer.harness.lifecycle.dispose(); + }); + + it("evaluates at turns 1 and 5, not every idle transition", async () => { + const organizer = createHarness({ mode: "observe" }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + + for (let turn = 1; turn <= 5; turn += 1) { + organizer.addCompletedTurn(turn * 10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + } + + const turnProposals = organizer.harness.inspection.logEntries.filter( + ({ message }) => + message.includes("phase=turn") && + message.includes("action=propose-section"), + ); + expect(turnProposals).toHaveLength(2); + await organizer.harness.lifecycle.dispose(); + }); + + it("moves a managed section after two due evaluations of clear recent intent", async () => { + const initialPrompt = "Write a blog post about organizing bb threads."; + const organizer = createHarness({ + mode: "apply", + projectName: "Personal", + prompt: initialPrompt, + thread: { + projectId: "proj_personal", + title: "Write Thread Organization Blog Post", + }, + }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + expect(organizer.currentThread().sectionId).toBe("sec_writing"); + + organizer.setPromptHistory( + initialPrompt, + "Create a bb plugin for automatic thread organization.", + ); + organizer.setThread({ status: "active" }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + organizer.addCompletedTurn(10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + expect(organizer.currentThread().sectionId).toBe("sec_writing"); + + for (let turn = 2; turn <= 5; turn += 1) { + organizer.setThread({ status: "active" }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + organizer.addCompletedTurn(turn * 10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + } + + expect(organizer.currentThread().sectionId).toBe("sec_extensions"); + expect( + organizer.update.mock.calls.filter( + ([args]) => args.sectionId !== undefined, + ), + ).toEqual([ + [{ threadId: "thr_test", sectionId: "sec_writing" }], + [{ threadId: "thr_test", sectionId: "sec_extensions" }], + ]); + await organizer.harness.lifecycle.dispose(); + }); + + it("abstains from moving on mixed recent section intent", async () => { + const initialPrompt = "Write a blog post about organizing bb threads."; + const organizer = createHarness({ + mode: "apply", + projectName: "Personal", + prompt: initialPrompt, + }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + + organizer.setPromptHistory( + initialPrompt, + "Write a blog post about creating a bb plugin.", + ); + organizer.addCompletedTurn(10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + for (let turn = 2; turn <= 5; turn += 1) { + organizer.addCompletedTurn(turn * 10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + } + + expect(organizer.currentThread().sectionId).toBe("sec_writing"); + expect( + organizer.update.mock.calls.filter( + ([args]) => args.sectionId !== undefined, + ), + ).toEqual([ + [{ threadId: "thr_test", sectionId: "sec_writing" }], + ]); + await organizer.harness.lifecycle.dispose(); + }); + + it("preserves a pending move across an unclassifiable active phase", async () => { + const organizer = createHarness({ + mode: "apply", + projectName: "Personal", + prompt: "Plan quarterly work.", + thread: { + projectId: "proj_personal", + title: "Quarterly Plan", + }, + }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + expect(organizer.currentThread().sectionId).toBeNull(); + + organizer.setPromptHistory( + "Create a bb plugin for automatic thread organization.", + ); + organizer.setThread({ status: "active" }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + expect(organizer.currentThread().sectionId).toBe("sec_extensions"); + + organizer.addCompletedTurn(10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + + organizer.setPromptHistory("Write a blog post about bb workflows."); + for (let turn = 2; turn <= 5; turn += 1) { + organizer.setThread({ status: "active" }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + organizer.addCompletedTurn(turn * 10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + } + expect(organizer.currentThread().sectionId).toBe("sec_extensions"); + + organizer.setPromptHistory("ok"); + organizer.setThread({ status: "active" }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + + organizer.setPromptHistory("Write a blog post about bb workflows."); + for (let turn = 6; turn <= 15; turn += 1) { + organizer.setThread({ status: "active" }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + organizer.addCompletedTurn(turn * 10); + await organizer.harness.behavior.emitThreadEvent("thread.idle", { + lastAssistantText: "Done.", + thread: organizer.currentThread(), + }); + } + + expect(organizer.currentThread().sectionId).toBe("sec_writing"); + await organizer.harness.lifecycle.dispose(); + }); + + it("ignores hidden and plugin-originated workers", async () => { + const organizer = createHarness({ + mode: "apply", + thread: { originPluginId: "automations", visibility: "hidden" }, + }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + + expect(organizer.update).not.toHaveBeenCalled(); + expect( + organizer.harness.inspection.sdk.callsTo("threads.get"), + ).toHaveLength(0); + await organizer.harness.lifecycle.dispose(); + }); + + it("forgets archived threads", async () => { + const organizer = createHarness({ mode: "observe" }); + plugin(organizer.bb); + await organizer.harness.behavior.emitThreadEvent("thread.created", { + thread: organizer.currentThread(), + }); + const callsBeforeArchive = + organizer.harness.inspection.sdk.callsTo("threads.get").length; + + organizer.setThread({ archivedAt: 10, status: "idle" }); + await organizer.harness.behavior.emitThreadEvent("thread.archived", { + thread: organizer.currentThread(), + }); + organizer.setThread({ archivedAt: null, status: "active" }); + await organizer.harness.behavior.emitThreadEvent("thread.active", { + thread: organizer.currentThread(), + }); + + expect( + organizer.harness.inspection.sdk.callsTo("threads.get"), + ).toHaveLength(callsBeforeArchive); + await organizer.harness.lifecycle.dispose(); + }); +}); diff --git a/plugins/thread-organizer/server.ts b/plugins/thread-organizer/server.ts new file mode 100644 index 0000000..407322a --- /dev/null +++ b/plugins/thread-organizer/server.ts @@ -0,0 +1,547 @@ +import type { BbPluginApi } from "@bb/plugin-sdk"; + +import { + advanceEvaluationMilestone, + classifySection, + deriveTaskTitle, + isEligibleThread, + isSubstantiveText, + resolveSectionId, + type SectionClassification, +} from "./core.js"; + +const STATE_PREFIX = "thread:v1:"; +const PERSONAL_PROJECT_ID = "proj_personal"; +const NEW_SECTION_CONFIDENCE = 0.85; +const NEW_SECTION_MARGIN = 0.2; +const MOVE_SECTION_CONFIDENCE = 0.92; +const MOVE_SECTION_MARGIN = 0.25; +const TITLE_CONFIDENCE = 0.9; +const MAX_COMPLETED_EVENT_DRAIN = 100; + +type Thread = Awaited>; +type EvaluationPhase = "active" | "created" | "settings" | "turn"; + +interface ThreadState { + completedTurns: number; + createdAt: number; + hasAppliedSection: boolean; + hasAppliedTitle: boolean; + lastAppliedSectionId: string | null; + lastAppliedTitle: string | null; + lastCompletedSeq: number; + nextEvaluationTurn: number; + pendingSectionId: string | null; + pendingSectionStreak: number; + sectionLocked: boolean; + titleLocked: boolean; + version: 1; +} + +function stateKey(threadId: string): string { + return `${STATE_PREFIX}${threadId}`; +} + +function initialState(thread: Thread): ThreadState { + return { + completedTurns: 0, + createdAt: thread.createdAt, + hasAppliedSection: false, + hasAppliedTitle: false, + lastAppliedSectionId: null, + lastAppliedTitle: null, + lastCompletedSeq: 0, + nextEvaluationTurn: 1, + pendingSectionId: null, + pendingSectionStreak: 0, + sectionLocked: thread.sectionId !== null, + titleLocked: thread.title !== null, + version: 1, + }; +} + +function isThreadState(value: unknown): value is ThreadState { + if (typeof value !== "object" || value === null) return false; + const state = value as Partial; + return ( + state.version === 1 && + typeof state.completedTurns === "number" && + typeof state.createdAt === "number" && + typeof state.hasAppliedSection === "boolean" && + typeof state.hasAppliedTitle === "boolean" && + (typeof state.lastAppliedSectionId === "string" || + state.lastAppliedSectionId === null) && + (typeof state.lastAppliedTitle === "string" || + state.lastAppliedTitle === null) && + typeof state.lastCompletedSeq === "number" && + typeof state.nextEvaluationTurn === "number" && + (typeof state.pendingSectionId === "string" || + state.pendingSectionId === null) && + typeof state.pendingSectionStreak === "number" && + typeof state.sectionLocked === "boolean" && + typeof state.titleLocked === "boolean" + ); +} + +function syncManualLocks(state: ThreadState, thread: Thread): boolean { + let changed = false; + if (!state.titleLocked) { + const externalTitle = + state.hasAppliedTitle + ? thread.title !== state.lastAppliedTitle + : thread.title !== null; + if (externalTitle) { + state.titleLocked = true; + changed = true; + } + } + if (!state.sectionLocked) { + const externalSection = + state.hasAppliedSection + ? thread.sectionId !== state.lastAppliedSectionId + : thread.sectionId !== null; + if (externalSection) { + state.sectionLocked = true; + changed = true; + } + } + return changed; +} + +function promptTexts( + history: Awaited< + ReturnType + >, +): string[] { + return [...history] + .sort((left, right) => left.createdAt - right.createdAt) + .flatMap((entry) => + entry.input.flatMap((item) => + item.type === "text" && item.visibility !== "agent-only" + ? [item.text] + : [], + ), + ); +} + +function mostRecentSubstantiveText(texts: string[]): string | null { + for (let index = texts.length - 1; index >= 0; index -= 1) { + const text = texts[index]!; + if (isSubstantiveText(text)) return text; + } + return null; +} + +function classificationSummary(decision: SectionClassification): string { + return [ + `target=${decision.target}`, + `confidence=${decision.confidence.toFixed(2)}`, + `margin=${decision.margin.toFixed(2)}`, + `reason=${decision.reasons.join(",")}`, + ].join(" "); +} + +function delay(milliseconds: number): Promise { + return new Promise((resolve) => setTimeout(resolve, milliseconds)); +} + +export default function plugin(bb: BbPluginApi): void { + const settings = bb.settings.define({ + mode: { + type: "select", + label: "Mode", + description: + "Observe logs recommendations without changing threads. Apply enables high-confidence updates.", + options: ["observe", "apply"], + default: "observe", + }, + }); + const queues = new Map>(); + let disposed = false; + + async function readState(threadId: string): Promise { + const stored = await bb.storage.kv.get(stateKey(threadId)); + if (stored === undefined) return null; + if (isThreadState(stored)) return stored; + bb.log.warn(`thread=${threadId} action=ignore-invalid-state`); + return null; + } + + async function saveState( + threadId: string, + state: ThreadState, + ): Promise { + await bb.storage.kv.set(stateKey(threadId), state); + } + + function enqueue(threadId: string, work: () => Promise): Promise { + const previous = queues.get(threadId) ?? Promise.resolve(); + const current = previous + .catch(() => undefined) + .then(async () => { + if (!disposed) await work(); + }) + .catch((error: unknown) => { + const message = error instanceof Error ? error.message : String(error); + bb.log.error(`thread=${threadId} action=queue-failed error=${message}`); + }) + .finally(() => { + if (queues.get(threadId) === current) queues.delete(threadId); + }); + queues.set(threadId, current); + return current; + } + + async function loadContextTexts( + thread: Thread, + attempts: number, + ): Promise { + let loaded: string[] = []; + for (let attempt = 0; attempt < attempts; attempt += 1) { + try { + loaded = promptTexts( + await bb.sdk.threads.promptHistory({ + threadId: thread.id, + limit: "6", + }), + ); + } catch (error: unknown) { + const message = error instanceof Error ? error.message : String(error); + bb.log.debug( + `thread=${thread.id} action=prompt-history-unavailable attempt=${attempt + 1} error=${message}`, + ); + } + if (loaded.some(isSubstantiveText) || attempt === attempts - 1) break; + await delay(attempt === 0 ? 150 : 600); + } + return loaded; + } + + async function applySection( + thread: Thread, + state: ThreadState, + phase: EvaluationPhase, + decision: SectionClassification, + targetSectionId: string, + mode: string, + ): Promise { + if (state.sectionLocked) return; + + const movingManagedSection = thread.sectionId !== null; + if ( + movingManagedSection && + (!state.hasAppliedSection || phase !== "turn") + ) { + return; + } + const minimumConfidence = movingManagedSection + ? MOVE_SECTION_CONFIDENCE + : NEW_SECTION_CONFIDENCE; + const minimumMargin = movingManagedSection + ? MOVE_SECTION_MARGIN + : NEW_SECTION_MARGIN; + if ( + decision.confidence < minimumConfidence || + decision.margin < minimumMargin + ) { + state.pendingSectionId = null; + state.pendingSectionStreak = 0; + return; + } + if (thread.sectionId === targetSectionId) { + state.pendingSectionId = null; + state.pendingSectionStreak = 0; + return; + } + + if (movingManagedSection) { + if (state.pendingSectionId === targetSectionId) { + state.pendingSectionStreak += 1; + } else { + state.pendingSectionId = targetSectionId; + state.pendingSectionStreak = 1; + } + if (state.pendingSectionStreak < 2) return; + } + + if (mode !== "apply") { + bb.log.info( + `thread=${thread.id} phase=${phase} mode=observe action=propose-section ${classificationSummary(decision)}`, + ); + return; + } + + const fresh = (await bb.sdk.threads.get({ + threadId: thread.id, + })) as Thread; + syncManualLocks(state, fresh); + if ( + state.sectionLocked || + !isEligibleThread(fresh) || + fresh.sectionId !== thread.sectionId + ) { + return; + } + const updated = await bb.sdk.threads.update({ + threadId: thread.id, + sectionId: targetSectionId, + }); + state.hasAppliedSection = true; + state.lastAppliedSectionId = updated.sectionId; + state.pendingSectionId = null; + state.pendingSectionStreak = 0; + bb.log.info( + `thread=${thread.id} phase=${phase} mode=apply action=section-updated ${classificationSummary(decision)}`, + ); + } + + async function applyTitle( + thread: Thread, + state: ThreadState, + phase: EvaluationPhase, + texts: string[], + mode: string, + ): Promise { + if (phase !== "turn" || state.titleLocked || thread.title !== null) return; + const source = + texts.find(isSubstantiveText) ?? thread.titleFallback ?? undefined; + if (source === undefined) return; + const candidate = deriveTaskTitle(source); + if (candidate === null || candidate.confidence < TITLE_CONFIDENCE) return; + + if (mode !== "apply") { + bb.log.info( + `thread=${thread.id} phase=${phase} mode=observe action=propose-title confidence=${candidate.confidence.toFixed(2)} title=${JSON.stringify(candidate.title)}`, + ); + return; + } + + const fresh = (await bb.sdk.threads.get({ + threadId: thread.id, + })) as Thread; + syncManualLocks(state, fresh); + if (state.titleLocked || !isEligibleThread(fresh) || fresh.title !== null) { + return; + } + const updated = await bb.sdk.threads.update({ + threadId: thread.id, + title: candidate.title, + }); + state.hasAppliedTitle = true; + state.lastAppliedTitle = updated.title; + bb.log.info( + `thread=${thread.id} phase=${phase} mode=apply action=title-updated confidence=${candidate.confidence.toFixed(2)} title=${JSON.stringify(candidate.title)}`, + ); + } + + async function evaluate( + threadId: string, + phase: EvaluationPhase, + ): Promise { + const state = await readState(threadId); + if (state === null) return; + const thread = (await bb.sdk.threads.get({ threadId })) as Thread; + const locksChanged = syncManualLocks(state, thread); + if (locksChanged) { + bb.log.info( + `thread=${threadId} action=manual-lock title=${state.titleLocked} section=${state.sectionLocked}`, + ); + } + if (thread.archivedAt !== null || thread.deletedAt !== null) { + await bb.storage.kv.delete(stateKey(threadId)); + return; + } + if (!isEligibleThread(thread)) { + await saveState(threadId, state); + return; + } + + const attempts = phase === "active" ? 3 : 1; + const historyTexts = await loadContextTexts(thread, attempts); + const texts = [ + ...(thread.title === null ? [] : [thread.title]), + ...(thread.titleFallback === null ? [] : [thread.titleFallback]), + ...historyTexts, + ]; + const latestPromptText = mostRecentSubstantiveText(historyTexts); + const sectionTexts = + phase === "turn" && + state.hasAppliedSection && + thread.sectionId !== null + ? latestPromptText === null + ? [] + : [latestPromptText] + : texts; + const { mode } = await settings.get(); + const movingManagedSection = + state.hasAppliedSection && thread.sectionId !== null; + + if ( + !state.sectionLocked && + (!movingManagedSection || phase === "turn") + ) { + try { + const projectName = + thread.projectId === PERSONAL_PROJECT_ID + ? "Personal" + : ( + await bb.sdk.projects.get({ + projectId: thread.projectId, + }) + ).name; + const decision = classifySection({ + projectName, + texts: sectionTexts, + }); + if (decision !== null) { + const sectionId = resolveSectionId( + await bb.sdk.threadSections.list(), + decision.target, + ); + if (sectionId === null) { + bb.log.warn( + `thread=${threadId} phase=${phase} action=section-unavailable target=${decision.target}`, + ); + } else { + await applySection( + thread, + state, + phase, + decision, + sectionId, + mode, + ); + } + } else { + state.pendingSectionId = null; + state.pendingSectionStreak = 0; + } + } catch (error: unknown) { + const message = error instanceof Error ? error.message : String(error); + bb.log.warn( + `thread=${threadId} phase=${phase} action=section-evaluation-failed error=${message}`, + ); + } + } + + try { + await applyTitle(thread, state, phase, historyTexts, mode); + } catch (error: unknown) { + const message = error instanceof Error ? error.message : String(error); + bb.log.warn( + `thread=${threadId} phase=${phase} action=title-evaluation-failed error=${message}`, + ); + } + await saveState(threadId, state); + } + + async function consumeCompletedTurns( + threadId: string, + state: ThreadState, + ): Promise { + let drained = 0; + while (drained < MAX_COMPLETED_EVENT_DRAIN) { + const event = await bb.sdk.threads.events.wait({ + threadId, + type: "turn/completed", + waitMs: "1", + ...(state.lastCompletedSeq === 0 + ? {} + : { afterSeq: String(state.lastCompletedSeq) }), + }); + if (event === null) break; + state.lastCompletedSeq = event.seq; + if ( + event.type === "turn/completed" && + event.data.status === "completed" + ) { + state.completedTurns += 1; + } + drained += 1; + } + if (drained === MAX_COMPLETED_EVENT_DRAIN) { + bb.log.warn( + `thread=${threadId} action=turn-drain-capped limit=${MAX_COMPLETED_EVENT_DRAIN}`, + ); + } + } + + bb.events.on("thread.created", ({ thread }) => + enqueue(thread.id, async () => { + if (!isEligibleThread(thread)) return; + if ((await readState(thread.id)) !== null) return; + await saveState(thread.id, initialState(thread)); + await evaluate(thread.id, "created"); + }), + ); + + bb.events.on("thread.active", ({ thread }) => + enqueue(thread.id, async () => { + if ((await readState(thread.id)) === null) return; + await evaluate(thread.id, "active"); + }), + ); + + bb.events.on("thread.idle", ({ thread }) => + enqueue(thread.id, async () => { + const state = await readState(thread.id); + if (state === null) return; + try { + await consumeCompletedTurns(thread.id, state); + } catch (error: unknown) { + const message = error instanceof Error ? error.message : String(error); + bb.log.warn( + `thread=${thread.id} action=turn-count-failed error=${message}`, + ); + } + const due = state.completedTurns >= state.nextEvaluationTurn; + if (due) { + state.nextEvaluationTurn = advanceEvaluationMilestone( + state.nextEvaluationTurn, + state.completedTurns, + ); + } + await saveState(thread.id, state); + if (due) await evaluate(thread.id, "turn"); + }), + ); + + const forget = (threadId: string) => + enqueue(threadId, async () => { + await bb.storage.kv.delete(stateKey(threadId)); + }); + bb.events.on("thread.archived", ({ thread }) => forget(thread.id)); + bb.events.on("thread.deleted", ({ thread }) => forget(thread.id)); + + settings.onChange((next, previous) => { + if (next.mode === previous.mode) return; + bb.log.info(`action=mode-changed previous=${previous.mode} next=${next.mode}`); + if (next.mode !== "apply") return; + void bb.storage.kv + .list(STATE_PREFIX) + .then((keys) => + Promise.all( + keys.map((key) => + enqueue(key.slice(STATE_PREFIX.length), () => + evaluate(key.slice(STATE_PREFIX.length), "settings"), + ), + ), + ), + ) + .catch((error: unknown) => { + const message = error instanceof Error ? error.message : String(error); + bb.log.error(`action=apply-mode-evaluation-failed error=${message}`); + }); + }); + + bb.onDispose(() => { + disposed = true; + }); + void settings + .get() + .then(({ mode }) => bb.log.info(`Thread Organizer loaded mode=${mode}`)) + .catch((error: unknown) => { + const message = error instanceof Error ? error.message : String(error); + bb.log.warn(`action=mode-read-failed error=${message}`); + }); +} diff --git a/plugins/thread-organizer/tsconfig.json b/plugins/thread-organizer/tsconfig.json new file mode 100644 index 0000000..db529e7 --- /dev/null +++ b/plugins/thread-organizer/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": [ + "ES2022" + ], + "module": "ESNext", + "moduleResolution": "Bundler", + "baseUrl": ".", + "paths": { + "@bb/plugin-sdk": [ + "./types/bb-plugin-sdk.d.ts" + ], + "@bb/plugin-sdk/app": [ + "./types/bb-plugin-sdk-app.d.ts" + ] + }, + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "types": [ + "node", + "vitest/globals" + ] + }, + "include": [ + "*.ts" + ] +} diff --git a/plugins/thread-organizer/types/bb-plugin-sdk-app.d.ts b/plugins/thread-organizer/types/bb-plugin-sdk-app.d.ts new file mode 100644 index 0000000..22cf8e7 --- /dev/null +++ b/plugins/thread-organizer/types/bb-plugin-sdk-app.d.ts @@ -0,0 +1,794 @@ +// Portable type declarations for `@bb/plugin-sdk`. Unpublished BB +// workspace contracts are flattened; public subpaths may reuse the +// package root without requiring any other @bb/* package. +// +// Confused by the API, or need a symbol that isn't here? Clone the BB repo +// and read the real source: https://github.com/ymichael/bb + +import * as react from 'react'; +import { ComponentType, ReactNode } from 'react'; + +/** A JSON-safe path segment reported by a Standard Schema validation issue. */ +type PluginRpcIssuePathSegment = string | number; +/** Validator-neutral validation detail carried by an RPC error envelope. */ +interface PluginRpcValidationIssue { + message: string; + path?: PluginRpcIssuePathSegment[]; +} +/** Stable wire error categories for plugin RPC. */ +type PluginRpcErrorCode = "invalid_json" | "invalid_input" | "handler_error" | "invalid_output" | "non_json_result" | "unknown_method"; +/** Structured RPC failure returned as `{ ok: false, error }`. */ +interface PluginRpcError { + code: PluginRpcErrorCode; + message: string; + issues?: PluginRpcValidationIssue[]; +} +/** + * The validator-neutral subset of Standard Schema v1 used by plugin RPC. + * Zod 4 schemas implement this interface directly; other validators can do + * the same without becoming part of BB's public protocol. + */ +interface StandardSchemaV1 { + readonly "~standard": { + readonly version: 1; + readonly vendor: string; + readonly validate: (value: unknown) => StandardSchemaV1Result | Promise>; + readonly types?: { + readonly input: Input; + readonly output: Output; + }; + }; +} +type StandardSchemaV1Result = { + readonly value: Output; + readonly issues?: undefined; +} | { + readonly issues: readonly StandardSchemaV1Issue[]; +}; +interface StandardSchemaV1Issue { + readonly message: string; + readonly path?: PropertyKey | readonly (PropertyKey | { + readonly key: PropertyKey; + })[]; +} +type StandardSchemaV1InferInput = NonNullable["input"]; +type StandardSchemaV1InferOutput = NonNullable["output"]; +interface PluginRpcMethodContract { + readonly input: InputSchema; + readonly output: OutputSchema; +} +type PluginRpcContract = Readonly>; +type PluginRpcHandlers = { + [Method in keyof Contract]: (input: StandardSchemaV1InferOutput) => StandardSchemaV1InferInput | Promise>; +}; +type PluginRpcCallInput = StandardSchemaV1InferInput; +type PluginRpcCallArgs = null extends PluginRpcCallInput ? [input?: PluginRpcCallInput] : [input: PluginRpcCallInput]; +type PluginRpcResult = StandardSchemaV1InferOutput; + +/** + * A value that survives a JSON round trip without coercion or data loss. + * + * Host boundaries still validate values at runtime because TypeScript cannot + * exclude non-finite numbers and plugin bundles can bypass static types. + */ +type JsonValue = string | number | boolean | null | JsonValue[] | { + [key: string]: JsonValue; +}; + +/** + * The `@bb/plugin-sdk/app` contract (plugin design §5.2) — pure types with no + * side effects. The BB app imports these to keep its real implementation in + * sync (`satisfies PluginSdkApp`). Plugin authors import the same shapes through + * `@bb/plugin-sdk/app`. + * + * Per-slot props are versioned contracts: additive-only within an SDK major. + */ +/** Props passed to a `homepageSection` component. */ +interface PluginHomepageSectionProps { + /** Project in view on the compose surface; null when none is selected. */ + projectId: string | null; +} +/** + * Props passed to a `settingsSection` component. + * + * Deliberately empty in V1; versioned additive like the other slot props. + */ +interface PluginSettingsSectionProps { +} +/** Props passed to a `navPanel` component (it owns its whole route). */ +interface PluginNavPanelProps { + /** + * The route remainder after the panel root, "" at the root. The panel's + * route is `/plugins///*`, so a deep link like + * `/plugins/notes/notes/work/ideas.md` renders the panel with + * `subPath: "work/ideas.md"`. Navigate within the panel via + * `useBbNavigate().toPluginPanel(path, { subPath })` — browser + * back/forward then walks panel-internal history. + */ + subPath: string; +} +/** Props passed to a panel tab opened by a `threadPanelAction`. */ +interface PluginThreadPanelProps { + threadId: string; + /** + * The JSON value the action's `openPanel` call passed (round-tripped + * through persistence, so the tab restores across reloads); null when the + * action opened the panel without params. + */ + params: JsonValue | null; +} +interface PluginPendingInteractionView { + id: string; + threadId: string; + title: string; + payload: JsonValue; + createdAt: number; + expiresAt: number | null; +} +interface PluginPendingInteractionProps { + interaction: PluginPendingInteractionView; + submit(value: JsonValue): Promise; + cancel(): Promise; +} +/** + * Props for a `sidebarFooterAction` — host-rendered (no plugin component). + * Deliberately empty; the registration's `run` carries the behavior. + */ +interface PluginSidebarFooterActionProps { +} +/** + * Where a file being opened by a `fileOpener` lives. `path` semantics follow + * the source: workspace paths are relative to the environment's worktree, + * thread-storage paths are relative to the thread's storage root, host paths + * are absolute on the thread's host. + */ +interface PluginFileOpenerSource { + kind: "workspace" | "host" | "thread-storage"; + threadId: string | null; + environmentId: string | null; + projectId: string | null; +} +/** Props passed to a `fileOpener` component (rendered as a panel file tab). */ +interface PluginFileOpenerProps { + path: string; + source: PluginFileOpenerSource; +} +/** + * Message context passed to a `messageDirective` component — the assistant + * (or nested agent) message that contained the directive. + */ +interface PluginMessageDirectiveMessage { + id: string; + threadId: string; + turnId: string | null; + projectId: string | null; +} +/** + * Open a worktree-relative file in the host's workspace file viewer. Returns + * true when the host accepted the path; false when the path is invalid or the + * viewer declined it. + */ +type PluginMessageDirectiveOpenWorkspaceFile = (path: string) => boolean; +/** + * Props passed to a `messageDirective` component. Attributes are untrusted + * strings parsed from the directive; the plugin validates its own fields. + */ +interface PluginMessageDirectiveProps { + /** Parsed, untrusted directive attributes (e.g. `{ file: "demo.html" }`). */ + attributes: Readonly>; + /** Original directive source text (useful for diagnostics / crash fallback). */ + source: string; + message: PluginMessageDirectiveMessage; + /** + * Opens a worktree-relative file in the host's workspace file viewer. Null + * when the message surface has no workspace viewer available. + */ + openWorkspaceFile: PluginMessageDirectiveOpenWorkspaceFile | null; +} +interface PluginHomepageSectionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + title: string; + component: ComponentType; +} +interface PluginSettingsSectionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Optional host-rendered section heading. */ + title?: string; + /** + * Optional one-line host-rendered subheading under `title`, in the built-in + * SettingsSection idiom (ignored when `title` is absent). + */ + description?: string; + component: ComponentType; +} +interface PluginNavPanelRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon: string; + /** URL segment under `/plugins//`; letters, digits, `-`, `_`. */ + path: string; + component: ComponentType; + /** + * Optional component rendered on the right side of the shared title bar + * (e.g. a sync button or a count). Contained separately from the body: a + * throwing headerContent is hidden without breaking the title bar. + */ + headerContent?: ComponentType; +} +/** Context handed to a `threadPanelAction`'s `run`. */ +interface PluginThreadPanelActionContext { + /** The thread whose panel launcher invoked the action. */ + threadId: string; + /** + * Open a tab in the thread's side panel rendering this action's + * `component`. `title` labels the tab (default: the action's `title`); + * `params` must be JSON-serializable — it is persisted with the tab and + * reaches the component as its `params` prop. Opening with params + * identical to an already-open tab of this action focuses that tab + * (updating its title) instead of duplicating it. May be called more than + * once (different params ⇒ multiple tabs) or not at all. + */ + openPanel(options?: { + title?: string; + params?: JsonValue; + }): void; +} +interface PluginThreadPanelActionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Label of the action row in the panel's new-tab launcher. */ + title: string; + /** + * Icon hint (BB icon name) used when the plugin ships no logo; the + * launcher row and opened tabs prefer the plugin's logo. + */ + icon?: string; + /** Rendered inside every panel tab this action opens. */ + component: ComponentType; + /** + * How the host frames the tab content. "padded" (default) wraps the + * component in the panel's scroll container with standard padding — + * right for document-like content. "flush" gives the component the full + * tab area (no padding, definite height, no host scrolling) — right for + * app-like content that manages its own layout, such as + * `experimental_ThreadChat`. + */ + layout?: "padded" | "flush"; + /** + * Runs when the user activates the action: call your RPC methods, show a + * toast, and/or open panel tabs via `context.openPanel`. Omitted = + * immediately open a panel tab with defaults. Errors (sync or async) are + * contained and logged; they never break the launcher. + */ + run?(context: PluginThreadPanelActionContext): void | Promise; +} +interface PluginPendingInteractionRegistration { + /** Matches `rendererId` passed to `bb.ui.requestInput`. */ + id: string; + component: ComponentType; +} +/** Context handed to a `sidebarFooterAction`'s `run`. */ +interface PluginSidebarFooterActionContext { + /** + * Navigate to this plugin's Settings detail page + * (`/settings/plugins/`), where declarative settings and + * `settingsSection` slots render. + */ + openSettings(): void; +} +/** + * An icon button in the app sidebar footer (next to Settings / bug report). + * Host-rendered for consistent chrome — plugins supply icon, label, and + * `run` behavior only. + */ +interface PluginSidebarFooterActionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Tooltip and accessible label for the icon button. */ + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon: string; + /** + * Runs when the user activates the action (e.g. call `openSettings()`, + * open a panel via other surfaces, toast). Errors (sync or async) are + * contained and logged; they never break the sidebar. + */ + run(context: PluginSidebarFooterActionContext): void | Promise; +} +/** + * Register this plugin as a viewer/editor for file extensions. The user + * picks (and can set as default) an opener per extension via the file tab's + * "Open with" menu; matching files opened in the panel then render + * `component` in a plugin tab instead of the built-in preview. Applies to + * working-tree, host, and thread-storage files — never to git-ref snapshots + * (diff views always use the built-in preview). The built-in preview stays + * one menu click away, and a missing/disabled opener falls back to it. + */ +interface PluginFileOpenerRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Label in the "Open with" menu (e.g. "Notes editor"). */ + title: string; + /** Lowercase extensions without the dot (e.g. ["md", "mdx"]). */ + extensions: readonly string[]; + component: ComponentType; +} +/** + * Register a leaf message directive rendered inside assistant (and nested + * agent) message Markdown. `id` is the directive name: `inline-vis` matches + * `::inline-vis{file="demo.html"}`. + */ +interface PluginMessageDirectiveRegistration { + /** + * The directive name. Lowercase kebab-case beginning with a letter. + */ + id: string; + component: ComponentType; +} +/** + * A narrow, stable reference to one rendered chat message — NOT an internal + * timeline row. `sourceSeqEnd` is the last source event sequence the message + * covers, the anchor the server accepts for provider-history forks. + */ +interface ThreadChatMessageReference { + id: string; + threadId: string; + role: "user" | "assistant"; + /** Visible text of the message. */ + text: string; + sourceSeqEnd: number; +} +interface PluginMessageActionThreadPanelOptions { + /** A `threadPanelAction` id registered by this same plugin. */ + actionId: string; + title?: string; + params?: JsonValue; +} +/** Context handed to a `messageAction`'s `run`. */ +interface PluginMessageActionContext { + /** The thread whose timeline surfaced the action. */ + threadId: string; + message: ThreadChatMessageReference; + /** + * Present only when the action was invoked from the text-selection menu; + * the exact text the user highlighted inside `message`. + */ + selectedText?: string; + /** + * Open one of this plugin's `threadPanelAction` components in the current + * thread's side panel — the registration-callback equivalent of + * `useBbNavigate().experimental_openThreadPanel`. Returns true when the host + * accepted (the action id exists and the surface has a panel); false + * otherwise. + */ + openPanel(options: PluginMessageActionThreadPanelOptions): boolean; +} +/** + * An action on chat messages: an icon button in the per-message action bar + * (user and assistant messages) and an entry in the assistant-message + * text-selection menu. Host-rendered chrome — the plugin supplies title, + * icon hint, and `run` behavior only. + */ +interface PluginMessageActionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Tooltip / menu label for the action. */ + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon?: string; + /** + * Runs when the user activates the action. Errors (sync or async) are + * contained and logged; they never break the timeline. + */ + run(context: PluginMessageActionContext): void | Promise; +} +interface PluginAppSlots { + homepageSection(registration: PluginHomepageSectionRegistration): void; + settingsSection(registration: PluginSettingsSectionRegistration): void; + navPanel(registration: PluginNavPanelRegistration): void; + threadPanelAction(registration: PluginThreadPanelActionRegistration): void; + pendingInteraction(registration: PluginPendingInteractionRegistration): void; + sidebarFooterAction(registration: PluginSidebarFooterActionRegistration): void; + fileOpener(registration: PluginFileOpenerRegistration): void; + messageDirective(registration: PluginMessageDirectiveRegistration): void; + experimental_messageAction(registration: PluginMessageActionRegistration): void; +} +interface PluginAppComposer { + customize(registration: ComposerCustomization): void; +} +/** Stable lifecycle values for one content-script instance in one bb client. */ +interface PluginContentScriptContext { + /** The id of the plugin that owns this script. */ + readonly pluginId: string; + /** Monotonic per-client generation, starting at 1. */ + readonly generation: number; + /** Aborted before cleanup begins on replacement, deactivation, or teardown. */ + readonly signal: AbortSignal; +} +/** Cleanup returned by a frontend content script. */ +type PluginContentScriptDisposer = () => void | Promise; +/** + * Trusted same-origin JavaScript/TypeScript mounted once per active frontend + * generation in each bb app window or browser tab. + */ +interface PluginContentScriptRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** + * Install behavior into the bb app shell. The host awaits a returned + * promise, contains failures, and calls the returned disposer exactly once. + */ + mount(context: PluginContentScriptContext): void | PluginContentScriptDisposer | Promise; +} +/** Experimental lifecycle surface for trusted frontend content scripts. */ +interface PluginAppContentScripts { + register(registration: PluginContentScriptRegistration): void; +} +interface PluginAppBuilder { + slots: PluginAppSlots; + composer: PluginAppComposer; + experimental_contentScripts: PluginAppContentScripts; +} +type PluginAppSetup = (app: PluginAppBuilder) => void; +/** + * The opaque product of `definePluginApp` — a plugin's `app.tsx` default + * export. The host re-runs `setup` against a fresh collector on every + * (re)interpretation, replacing that plugin's registrations wholesale. + */ +interface PluginAppDefinition { + /** Brand the host checks before interpreting a bundle's default export. */ + readonly __bbPluginApp: true; + readonly setup: PluginAppSetup; +} +interface PluginRpcClient { + /** + * Invoke one of the plugin's `bb.rpc` methods (POST + * /api/v1/plugins/<id>/rpc/<method>). Resolves with the method's + * inferred output; rejects with an `Error` carrying the server's message, + * stable `code`, and validation `issues` when present. + */ + call>(method: Method, ...args: PluginRpcCallArgs): Promise>; +} +interface PluginSettingsState { + /** + * Effective non-secret setting values (secret settings are excluded — + * read them server-side). Undefined while loading or unavailable. + */ + values: Record | undefined; + isLoading: boolean; +} +/** State of the app's shared realtime connection to the bb server. */ +type PluginRealtimeConnectionState = "connecting" | "connected" | "reconnecting"; +/** Where `useComposer()` writes. */ +type PluginComposerScope = { + kind: "thread"; + threadId: string; +} | { + kind: "queued-message"; + threadId: string; + queuedMessageId: string; +} | { + kind: "side-chat"; + projectId: string; + parentThreadId: string; + tabId: string; + childThreadId: string | null; +} | { + kind: "new-thread"; + /** Root compose's effective selected project; null only while unresolved. */ + projectId: string | null; +}; +/** One plugin-owned composer customization registration. */ +interface ComposerCustomization { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Composer kinds where this customization is active; omit for all kinds. */ + scopes?: readonly PluginComposerScope["kind"][]; + actions?: readonly { + id: string; + component: ComponentType; + }[]; + banners?: readonly { + id: string; + /** Host chrome around the banner. Defaults to `"card"`. */ + chrome?: "card" | "bare"; + component: ComponentType; + }[]; + plusMenu?: readonly ComposerPlusMenuItem[]; + richText?: ComposerRichTextSpec; +} +/** Host-rendered menu row in the composer's `+` menu. */ +interface ComposerPlusMenuItem { + id: string; + label: string; + /** BB icon name; unknown names fall back to the generic plugin icon. */ + icon?: string; + /** Accessible description for the host-rendered row. */ + description?: string; + disabled?: boolean | ((view: ComposerView) => boolean); + run(context: { + composer: PluginComposerApi; + view: ComposerView; + }): void | Promise; +} +/** Reactive read-side of the composer a plugin surface is mounted in. */ +interface ComposerView { + scope: PluginComposerScope; + layout: "expanded" | "compact" | "zen"; + draft: { + text: string; + isEmpty: boolean; + attachmentCount: number; + }; + run: { + isRunning: boolean; + isSubmitting: boolean; + }; +} +interface ComposerRichTextSpec { + /** Content-derived paint: match ranges receive `className`; text is never mutated. */ + effects?: readonly { + id: string; + /** Plain-text offsets into the current structured draft. */ + match(text: string): readonly { + from: number; + to: number; + }[]; + className: string; + }[]; + /** Debounced, read-only observation of the structured draft. */ + onDraftChange?(draft: ComposerStructuredDraft, view: ComposerView): void; +} +interface ComposerStructuredDraft { + text: string; + mentions: readonly { + from: number; + to: number; + provider: string; + id: string; + label: string; + }[]; +} +/** Host-rendered paint applied to the editable composer text. */ +interface PluginComposerTextEffect { + className: string; +} +/** Host-rendered status that temporarily replaces a thread's draft glyph. */ +interface PluginComposerThreadRowStatus { + /** BB icon-name hint; unknown names fall back to the generic plugin icon. */ + icon: string; + /** Accessible label for the status glyph. */ + label: string; + /** Semantic host color for the status glyph. Defaults to the neutral tone. */ + tone?: "default" | "success"; +} +/** An @-mention pill bound to one of the calling plugin's mention providers. */ +interface PluginComposerMention { + /** Mention provider id registered by THIS plugin via `bb.ui.registerMentionProvider`. */ + provider: string; + /** Item id your provider's `resolve` will receive at send time. */ + id: string; + /** Pill text shown in the composer. */ + label: string; +} +/** + * Programmatic access to the chat composer draft — the same shared draft the + * built-in "Add to chat" affordances (file preview, diff, terminal selections) + * write to. While a queued message is being edited, writes land in that + * message's inline editor. In a side chat, writes land in the visible side-chat + * draft. Otherwise, inside a thread context writes land in that thread's draft; + * anywhere else (nav panel, homepage section) they seed the new-thread composer + * draft, which persists until the user sends or clears it. + */ +interface PluginComposerApi { + scope: PluginComposerScope; + /** Current plain text for this composer scope. */ + readonly text: string; + /** + * Replace the draft's plain text. Attachments are preserved. Inline mentions + * outside the changed range are preserved and rebased; mentions overlapped + * by the replacement are removed because their text representation changed. + */ + setText(next: string): void; + /** + * Replace the draft's plain text from the latest committed value. Uses the + * same structured-state reconciliation as `setText`. + */ + updateText(updater: (current: string) => string): void; + /** Clear plain text without clearing independently attached files. */ + clear(): void; + /** + * Apply a host-rendered effect to this composer's editable text, or clear it. + * Effects are scoped to the calling plugin and automatically clear when the + * slot unmounts or its composer scope changes. + */ + setTextEffect(effect: PluginComposerTextEffect | null): void; + /** + * Lock or unlock editing for this composer. Locks are scoped to the calling + * plugin and automatically release when the slot unmounts or its composer + * scope changes. + */ + setInputLock(locked: boolean): void; + /** + * Replace this composer's thread-row draft glyph with a host-rendered status, + * or clear it. New-thread composers have no row, so calls are a no-op. + * Side-chat and queued side-chat scopes decorate the visible parent-thread + * row. Status is scoped to the calling plugin and automatically clears when + * the slot unmounts or its composer scope changes. + */ + setThreadRowStatus(status: PluginComposerThreadRowStatus | null): void; + /** + * Append text to the draft as a `> ` blockquote block and focus the + * composer. Blank text is a no-op. This is the "reference this selection + * in chat" primitive. + */ + addQuote(text: string): void; + /** + * Insert an @-mention pill that resolves through this plugin's mention + * provider at send time — the durable way to reference an entity whose + * content should be fetched fresh when the message is sent. + */ + insertMention(mention: PluginComposerMention): void; + /** Focus the composer caret at the end of the draft. */ + focus(): void; +} +/** + * A consumer-supplied action on the messages of one `ThreadChat` instance, + * rendered in the embedded timeline's per-message action bar alongside the + * native and slot-registered actions. Unlike the `messageAction` slot this is + * scoped to the rendering component, not registered globally. + */ +interface ThreadChatMessageAction { + /** Unique within this ThreadChat instance; letters, digits, `-`, `_`. */ + id: string; + /** Tooltip / menu label for the action. */ + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon?: string; + /** + * Message roles the action applies to. Omitted = both user and assistant + * messages. + */ + roles?: readonly ("user" | "assistant")[]; + /** + * Runs when the user activates the action. Errors (sync or async) are + * contained and logged; they never break the timeline. + */ + run(message: ThreadChatMessageReference): void | Promise; +} +/** + * Props of the host-owned `ThreadChat` component — one thread's chat + * (timeline, and for the composer variants the full send/queue/draft + * engine), rendered by the BB app inside a plugin slot. This is the + * deliberate exception to the no-host-components rule (§5.5): a stable + * product capability, not a UI kit. Versioned additive like slot props; + * internal timeline rows, query hooks, and prompt-box configuration are + * deliberately not exposed. + */ +interface ThreadChatProps { + threadId: string; + /** + * "full" (default) is the page presentation (centered reading width); + * "compact" is the side-panel presentation; "timeline" renders the + * transcript without a composer. + */ + variant?: "full" | "compact" | "timeline"; + /** + * "contained" (default) fills and scrolls inside a bounded parent; + * "document" grows with its content and defers scrolling to the page. + */ + layout?: "contained" | "document"; + /** Bump to focus the composer (ignored by `variant: "timeline"`). */ + focusRequest?: number; + className?: string; + /** Rendered above the conversation, scrolling with it. */ + leadingContent?: ReactNode; + /** + * Actions rendered in this instance's per-message action bar (see + * {@link ThreadChatMessageAction}). + */ + messageActions?: readonly ThreadChatMessageAction[]; +} +/** + * Props of the host-owned `Markdown` component — bb's chat message renderer + * (the same typography, spacing, and code styling as timeline messages). + * Use it wherever plugin UI quotes or previews message content so it reads + * like the rest of the chat. Like `ThreadChat`, this is a stable product + * capability, not a UI kit; renderer internals stay private. + */ +interface MarkdownProps { + /** Markdown source, rendered exactly like a chat message body. */ + content: string; + className?: string; +} +/** Current app selection, derived from the route. */ +interface BbContext { + projectId: string | null; + threadId: string | null; +} +interface BbNavigate { + toThread(threadId: string): void; + toProject(projectId: string): void; + /** + * Navigate to one of this plugin's own nav panels by its `path`. + * `subPath` targets a location inside the panel (the component's + * `subPath` prop); `replace` swaps the current history entry instead of + * pushing — use it for redirects so back does not bounce. + */ + toPluginPanel(path: string, options?: { + subPath?: string; + replace?: boolean; + }): void; + /** + * Navigate to the root compose surface (the new-thread screen). Pass + * `initialPrompt` to seed the composer draft and `focusPrompt` to focus the + * composer on arrival — the pairing behind "Create via chat" style entry + * points that drop the user into chat with a prefilled prompt. + */ + toCompose(options?: { + initialPrompt?: string; + focusPrompt?: boolean; + }): void; + /** + * Open one of this plugin's registered thread-panel actions in the current + * thread surface. Returns false when the surface has no thread side panel or + * the action is unavailable. + */ + experimental_openThreadPanel(options: { + actionId: string; + title?: string; + params?: JsonValue; + }): boolean; +} +/** + * Everything `@bb/plugin-sdk/app` resolves to at runtime. The BB app builds + * the real implementation and `satisfies` this interface; `bb plugin build` + * shims the specifier to that object on `globalThis.__bbPluginRuntime`. + */ +interface PluginSdkApp { + definePluginApp(setup: PluginAppSetup): PluginAppDefinition; + useRpc(): PluginRpcClient; + useRealtime(channel: string, handler: (payload: unknown) => void): void; + /** + * Observe the same shared connection that delivers `useRealtime` signals. + * Use a subsequent transition to `connected` to reconcile server state that + * may have changed while ephemeral signals could not be delivered. The first + * connection can transition from `connecting` and is not a reconnection. + */ + useRealtimeConnectionState(): PluginRealtimeConnectionState; + useSettings(): PluginSettingsState; + useBbContext(): BbContext; + useBbNavigate(): BbNavigate; + useComposer(): PluginComposerApi; + /** + * The host-owned chat component (see {@link ThreadChatProps}). Together + * with `Markdown`, the only components the SDK ships — everything else + * stays vendored per §5.5. + */ + experimental_ThreadChat: ComponentType; + /** + * The host-owned chat-message markdown renderer (see + * {@link MarkdownProps}). + */ + experimental_Markdown: ComponentType; + useComposerView(): ComposerView; +} + +declare const definePluginApp: (setup: PluginAppSetup) => PluginAppDefinition; +declare const experimental_ThreadChat: react.ComponentType; +declare const experimental_Markdown: react.ComponentType; +declare const useRpc: , StandardSchemaV1>>>>() => PluginRpcClient; +declare const useRealtime: (channel: string, handler: (payload: unknown) => void) => void; +declare const useRealtimeConnectionState: () => PluginRealtimeConnectionState; +declare const useSettings: () => PluginSettingsState; +declare const useBbContext: () => BbContext; +declare const useBbNavigate: () => BbNavigate; +declare const useComposer: () => PluginComposerApi; +declare const useComposerView: () => ComposerView; + +export { definePluginApp, experimental_Markdown, experimental_ThreadChat, useBbContext, useBbNavigate, useComposer, useComposerView, useRealtime, useRealtimeConnectionState, useRpc, useSettings }; +export type { BbContext, BbNavigate, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, JsonValue, MarkdownProps, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageActionThreadPanelOptions, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginRealtimeConnectionState, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps }; diff --git a/plugins/thread-organizer/types/bb-plugin-sdk.d.ts b/plugins/thread-organizer/types/bb-plugin-sdk.d.ts new file mode 100644 index 0000000..8125dda --- /dev/null +++ b/plugins/thread-organizer/types/bb-plugin-sdk.d.ts @@ -0,0 +1,11762 @@ +// Portable type declarations for `@bb/plugin-sdk`. Unpublished BB +// workspace contracts are flattened; public subpaths may reuse the +// package root without requiring any other @bb/* package. +// +// Confused by the API, or need a symbol that isn't here? Clone the BB repo +// and read the real source: https://github.com/ymichael/bb + +import { ComponentType, ReactNode } from 'react'; +import Database from 'better-sqlite3'; +import { Context } from 'hono'; +import * as z from 'zod'; +import { z as z$1 } from 'zod'; + +/** + * A value that survives a JSON round trip without coercion or data loss. + * + * Host boundaries still validate values at runtime because TypeScript cannot + * exclude non-finite numbers and plugin bundles can bypass static types. + */ +type JsonValue$1 = string | number | boolean | null | JsonValue$1[] | { + [key: string]: JsonValue$1; +}; + +/** A JSON-safe path segment reported by a Standard Schema validation issue. */ +type PluginRpcIssuePathSegment = string | number; +/** Validator-neutral validation detail carried by an RPC error envelope. */ +interface PluginRpcValidationIssue { + message: string; + path?: PluginRpcIssuePathSegment[]; +} +/** Stable wire error categories for plugin RPC. */ +type PluginRpcErrorCode = "invalid_json" | "invalid_input" | "handler_error" | "invalid_output" | "non_json_result" | "unknown_method"; +/** Structured RPC failure returned as `{ ok: false, error }`. */ +interface PluginRpcError { + code: PluginRpcErrorCode; + message: string; + issues?: PluginRpcValidationIssue[]; +} +/** + * The validator-neutral subset of Standard Schema v1 used by plugin RPC. + * Zod 4 schemas implement this interface directly; other validators can do + * the same without becoming part of BB's public protocol. + */ +interface StandardSchemaV1 { + readonly "~standard": { + readonly version: 1; + readonly vendor: string; + readonly validate: (value: unknown) => StandardSchemaV1Result | Promise>; + readonly types?: { + readonly input: Input; + readonly output: Output; + }; + }; +} +type StandardSchemaV1Result = { + readonly value: Output; + readonly issues?: undefined; +} | { + readonly issues: readonly StandardSchemaV1Issue[]; +}; +interface StandardSchemaV1Issue { + readonly message: string; + readonly path?: PropertyKey | readonly (PropertyKey | { + readonly key: PropertyKey; + })[]; +} +type StandardSchemaV1InferInput = NonNullable["input"]; +type StandardSchemaV1InferOutput = NonNullable["output"]; +interface PluginRpcMethodContract { + readonly input: InputSchema; + readonly output: OutputSchema; +} +type PluginRpcContract = Readonly>; +/** Define a shared RPC contract while preserving exact method/schema types. */ +declare function defineRpcContract(contract: Contract): Contract; +type PluginRpcHandlers = { + [Method in keyof Contract]: (input: StandardSchemaV1InferOutput) => StandardSchemaV1InferInput | Promise>; +}; +type PluginRpcCallInput = StandardSchemaV1InferInput; +type PluginRpcCallArgs = null extends PluginRpcCallInput ? [input?: PluginRpcCallInput] : [input: PluginRpcCallInput]; +type PluginRpcResult = StandardSchemaV1InferOutput; + +/** + * The `@bb/plugin-sdk/app` contract (plugin design §5.2) — pure types with no + * side effects. The BB app imports these to keep its real implementation in + * sync (`satisfies PluginSdkApp`). Plugin authors import the same shapes through + * `@bb/plugin-sdk/app`. + * + * Per-slot props are versioned contracts: additive-only within an SDK major. + */ +/** Props passed to a `homepageSection` component. */ +interface PluginHomepageSectionProps { + /** Project in view on the compose surface; null when none is selected. */ + projectId: string | null; +} +/** + * Props passed to a `settingsSection` component. + * + * Deliberately empty in V1; versioned additive like the other slot props. + */ +interface PluginSettingsSectionProps { +} +/** Props passed to a `navPanel` component (it owns its whole route). */ +interface PluginNavPanelProps { + /** + * The route remainder after the panel root, "" at the root. The panel's + * route is `/plugins///*`, so a deep link like + * `/plugins/notes/notes/work/ideas.md` renders the panel with + * `subPath: "work/ideas.md"`. Navigate within the panel via + * `useBbNavigate().toPluginPanel(path, { subPath })` — browser + * back/forward then walks panel-internal history. + */ + subPath: string; +} +/** Props passed to a panel tab opened by a `threadPanelAction`. */ +interface PluginThreadPanelProps { + threadId: string; + /** + * The JSON value the action's `openPanel` call passed (round-tripped + * through persistence, so the tab restores across reloads); null when the + * action opened the panel without params. + */ + params: JsonValue$1 | null; +} +interface PluginPendingInteractionView { + id: string; + threadId: string; + title: string; + payload: JsonValue$1; + createdAt: number; + expiresAt: number | null; +} +interface PluginPendingInteractionProps { + interaction: PluginPendingInteractionView; + submit(value: JsonValue$1): Promise; + cancel(): Promise; +} +/** + * Props for a `sidebarFooterAction` — host-rendered (no plugin component). + * Deliberately empty; the registration's `run` carries the behavior. + */ +interface PluginSidebarFooterActionProps { +} +/** + * Where a file being opened by a `fileOpener` lives. `path` semantics follow + * the source: workspace paths are relative to the environment's worktree, + * thread-storage paths are relative to the thread's storage root, host paths + * are absolute on the thread's host. + */ +interface PluginFileOpenerSource { + kind: "workspace" | "host" | "thread-storage"; + threadId: string | null; + environmentId: string | null; + projectId: string | null; +} +/** Props passed to a `fileOpener` component (rendered as a panel file tab). */ +interface PluginFileOpenerProps { + path: string; + source: PluginFileOpenerSource; +} +/** + * Message context passed to a `messageDirective` component — the assistant + * (or nested agent) message that contained the directive. + */ +interface PluginMessageDirectiveMessage { + id: string; + threadId: string; + turnId: string | null; + projectId: string | null; +} +/** + * Open a worktree-relative file in the host's workspace file viewer. Returns + * true when the host accepted the path; false when the path is invalid or the + * viewer declined it. + */ +type PluginMessageDirectiveOpenWorkspaceFile = (path: string) => boolean; +/** + * Props passed to a `messageDirective` component. Attributes are untrusted + * strings parsed from the directive; the plugin validates its own fields. + */ +interface PluginMessageDirectiveProps { + /** Parsed, untrusted directive attributes (e.g. `{ file: "demo.html" }`). */ + attributes: Readonly>; + /** Original directive source text (useful for diagnostics / crash fallback). */ + source: string; + message: PluginMessageDirectiveMessage; + /** + * Opens a worktree-relative file in the host's workspace file viewer. Null + * when the message surface has no workspace viewer available. + */ + openWorkspaceFile: PluginMessageDirectiveOpenWorkspaceFile | null; +} +interface PluginHomepageSectionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + title: string; + component: ComponentType; +} +interface PluginSettingsSectionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Optional host-rendered section heading. */ + title?: string; + /** + * Optional one-line host-rendered subheading under `title`, in the built-in + * SettingsSection idiom (ignored when `title` is absent). + */ + description?: string; + component: ComponentType; +} +interface PluginNavPanelRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon: string; + /** URL segment under `/plugins//`; letters, digits, `-`, `_`. */ + path: string; + component: ComponentType; + /** + * Optional component rendered on the right side of the shared title bar + * (e.g. a sync button or a count). Contained separately from the body: a + * throwing headerContent is hidden without breaking the title bar. + */ + headerContent?: ComponentType; +} +/** Context handed to a `threadPanelAction`'s `run`. */ +interface PluginThreadPanelActionContext { + /** The thread whose panel launcher invoked the action. */ + threadId: string; + /** + * Open a tab in the thread's side panel rendering this action's + * `component`. `title` labels the tab (default: the action's `title`); + * `params` must be JSON-serializable — it is persisted with the tab and + * reaches the component as its `params` prop. Opening with params + * identical to an already-open tab of this action focuses that tab + * (updating its title) instead of duplicating it. May be called more than + * once (different params ⇒ multiple tabs) or not at all. + */ + openPanel(options?: { + title?: string; + params?: JsonValue$1; + }): void; +} +interface PluginThreadPanelActionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Label of the action row in the panel's new-tab launcher. */ + title: string; + /** + * Icon hint (BB icon name) used when the plugin ships no logo; the + * launcher row and opened tabs prefer the plugin's logo. + */ + icon?: string; + /** Rendered inside every panel tab this action opens. */ + component: ComponentType; + /** + * How the host frames the tab content. "padded" (default) wraps the + * component in the panel's scroll container with standard padding — + * right for document-like content. "flush" gives the component the full + * tab area (no padding, definite height, no host scrolling) — right for + * app-like content that manages its own layout, such as + * `experimental_ThreadChat`. + */ + layout?: "padded" | "flush"; + /** + * Runs when the user activates the action: call your RPC methods, show a + * toast, and/or open panel tabs via `context.openPanel`. Omitted = + * immediately open a panel tab with defaults. Errors (sync or async) are + * contained and logged; they never break the launcher. + */ + run?(context: PluginThreadPanelActionContext): void | Promise; +} +interface PluginPendingInteractionRegistration { + /** Matches `rendererId` passed to `bb.ui.requestInput`. */ + id: string; + component: ComponentType; +} +/** Context handed to a `sidebarFooterAction`'s `run`. */ +interface PluginSidebarFooterActionContext { + /** + * Navigate to this plugin's Settings detail page + * (`/settings/plugins/`), where declarative settings and + * `settingsSection` slots render. + */ + openSettings(): void; +} +/** + * An icon button in the app sidebar footer (next to Settings / bug report). + * Host-rendered for consistent chrome — plugins supply icon, label, and + * `run` behavior only. + */ +interface PluginSidebarFooterActionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Tooltip and accessible label for the icon button. */ + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon: string; + /** + * Runs when the user activates the action (e.g. call `openSettings()`, + * open a panel via other surfaces, toast). Errors (sync or async) are + * contained and logged; they never break the sidebar. + */ + run(context: PluginSidebarFooterActionContext): void | Promise; +} +/** + * Register this plugin as a viewer/editor for file extensions. The user + * picks (and can set as default) an opener per extension via the file tab's + * "Open with" menu; matching files opened in the panel then render + * `component` in a plugin tab instead of the built-in preview. Applies to + * working-tree, host, and thread-storage files — never to git-ref snapshots + * (diff views always use the built-in preview). The built-in preview stays + * one menu click away, and a missing/disabled opener falls back to it. + */ +interface PluginFileOpenerRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Label in the "Open with" menu (e.g. "Notes editor"). */ + title: string; + /** Lowercase extensions without the dot (e.g. ["md", "mdx"]). */ + extensions: readonly string[]; + component: ComponentType; +} +/** + * Register a leaf message directive rendered inside assistant (and nested + * agent) message Markdown. `id` is the directive name: `inline-vis` matches + * `::inline-vis{file="demo.html"}`. + */ +interface PluginMessageDirectiveRegistration { + /** + * The directive name. Lowercase kebab-case beginning with a letter. + */ + id: string; + component: ComponentType; +} +/** + * A narrow, stable reference to one rendered chat message — NOT an internal + * timeline row. `sourceSeqEnd` is the last source event sequence the message + * covers, the anchor the server accepts for provider-history forks. + */ +interface ThreadChatMessageReference { + id: string; + threadId: string; + role: "user" | "assistant"; + /** Visible text of the message. */ + text: string; + sourceSeqEnd: number; +} +interface PluginMessageActionThreadPanelOptions { + /** A `threadPanelAction` id registered by this same plugin. */ + actionId: string; + title?: string; + params?: JsonValue$1; +} +/** Context handed to a `messageAction`'s `run`. */ +interface PluginMessageActionContext { + /** The thread whose timeline surfaced the action. */ + threadId: string; + message: ThreadChatMessageReference; + /** + * Present only when the action was invoked from the text-selection menu; + * the exact text the user highlighted inside `message`. + */ + selectedText?: string; + /** + * Open one of this plugin's `threadPanelAction` components in the current + * thread's side panel — the registration-callback equivalent of + * `useBbNavigate().experimental_openThreadPanel`. Returns true when the host + * accepted (the action id exists and the surface has a panel); false + * otherwise. + */ + openPanel(options: PluginMessageActionThreadPanelOptions): boolean; +} +/** + * An action on chat messages: an icon button in the per-message action bar + * (user and assistant messages) and an entry in the assistant-message + * text-selection menu. Host-rendered chrome — the plugin supplies title, + * icon hint, and `run` behavior only. + */ +interface PluginMessageActionRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Tooltip / menu label for the action. */ + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon?: string; + /** + * Runs when the user activates the action. Errors (sync or async) are + * contained and logged; they never break the timeline. + */ + run(context: PluginMessageActionContext): void | Promise; +} +interface PluginAppSlots { + homepageSection(registration: PluginHomepageSectionRegistration): void; + settingsSection(registration: PluginSettingsSectionRegistration): void; + navPanel(registration: PluginNavPanelRegistration): void; + threadPanelAction(registration: PluginThreadPanelActionRegistration): void; + pendingInteraction(registration: PluginPendingInteractionRegistration): void; + sidebarFooterAction(registration: PluginSidebarFooterActionRegistration): void; + fileOpener(registration: PluginFileOpenerRegistration): void; + messageDirective(registration: PluginMessageDirectiveRegistration): void; + experimental_messageAction(registration: PluginMessageActionRegistration): void; +} +interface PluginAppComposer { + customize(registration: ComposerCustomization): void; +} +/** Stable lifecycle values for one content-script instance in one bb client. */ +interface PluginContentScriptContext { + /** The id of the plugin that owns this script. */ + readonly pluginId: string; + /** Monotonic per-client generation, starting at 1. */ + readonly generation: number; + /** Aborted before cleanup begins on replacement, deactivation, or teardown. */ + readonly signal: AbortSignal; +} +/** Cleanup returned by a frontend content script. */ +type PluginContentScriptDisposer = () => void | Promise; +/** + * Trusted same-origin JavaScript/TypeScript mounted once per active frontend + * generation in each bb app window or browser tab. + */ +interface PluginContentScriptRegistration { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** + * Install behavior into the bb app shell. The host awaits a returned + * promise, contains failures, and calls the returned disposer exactly once. + */ + mount(context: PluginContentScriptContext): void | PluginContentScriptDisposer | Promise; +} +/** Experimental lifecycle surface for trusted frontend content scripts. */ +interface PluginAppContentScripts { + register(registration: PluginContentScriptRegistration): void; +} +interface PluginAppBuilder { + slots: PluginAppSlots; + composer: PluginAppComposer; + experimental_contentScripts: PluginAppContentScripts; +} +type PluginAppSetup = (app: PluginAppBuilder) => void; +/** + * The opaque product of `definePluginApp` — a plugin's `app.tsx` default + * export. The host re-runs `setup` against a fresh collector on every + * (re)interpretation, replacing that plugin's registrations wholesale. + */ +interface PluginAppDefinition { + /** Brand the host checks before interpreting a bundle's default export. */ + readonly __bbPluginApp: true; + readonly setup: PluginAppSetup; +} +interface PluginRpcClient { + /** + * Invoke one of the plugin's `bb.rpc` methods (POST + * /api/v1/plugins/<id>/rpc/<method>). Resolves with the method's + * inferred output; rejects with an `Error` carrying the server's message, + * stable `code`, and validation `issues` when present. + */ + call>(method: Method, ...args: PluginRpcCallArgs): Promise>; +} +interface PluginSettingsState { + /** + * Effective non-secret setting values (secret settings are excluded — + * read them server-side). Undefined while loading or unavailable. + */ + values: Record | undefined; + isLoading: boolean; +} +/** State of the app's shared realtime connection to the bb server. */ +type PluginRealtimeConnectionState = "connecting" | "connected" | "reconnecting"; +/** Where `useComposer()` writes. */ +type PluginComposerScope = { + kind: "thread"; + threadId: string; +} | { + kind: "queued-message"; + threadId: string; + queuedMessageId: string; +} | { + kind: "side-chat"; + projectId: string; + parentThreadId: string; + tabId: string; + childThreadId: string | null; +} | { + kind: "new-thread"; + /** Root compose's effective selected project; null only while unresolved. */ + projectId: string | null; +}; +/** One plugin-owned composer customization registration. */ +interface ComposerCustomization { + /** Unique within the plugin; letters, digits, `-`, `_`. */ + id: string; + /** Composer kinds where this customization is active; omit for all kinds. */ + scopes?: readonly PluginComposerScope["kind"][]; + actions?: readonly { + id: string; + component: ComponentType; + }[]; + banners?: readonly { + id: string; + /** Host chrome around the banner. Defaults to `"card"`. */ + chrome?: "card" | "bare"; + component: ComponentType; + }[]; + plusMenu?: readonly ComposerPlusMenuItem[]; + richText?: ComposerRichTextSpec; +} +/** Host-rendered menu row in the composer's `+` menu. */ +interface ComposerPlusMenuItem { + id: string; + label: string; + /** BB icon name; unknown names fall back to the generic plugin icon. */ + icon?: string; + /** Accessible description for the host-rendered row. */ + description?: string; + disabled?: boolean | ((view: ComposerView) => boolean); + run(context: { + composer: PluginComposerApi; + view: ComposerView; + }): void | Promise; +} +/** Reactive read-side of the composer a plugin surface is mounted in. */ +interface ComposerView { + scope: PluginComposerScope; + layout: "expanded" | "compact" | "zen"; + draft: { + text: string; + isEmpty: boolean; + attachmentCount: number; + }; + run: { + isRunning: boolean; + isSubmitting: boolean; + }; +} +interface ComposerRichTextSpec { + /** Content-derived paint: match ranges receive `className`; text is never mutated. */ + effects?: readonly { + id: string; + /** Plain-text offsets into the current structured draft. */ + match(text: string): readonly { + from: number; + to: number; + }[]; + className: string; + }[]; + /** Debounced, read-only observation of the structured draft. */ + onDraftChange?(draft: ComposerStructuredDraft, view: ComposerView): void; +} +interface ComposerStructuredDraft { + text: string; + mentions: readonly { + from: number; + to: number; + provider: string; + id: string; + label: string; + }[]; +} +/** Host-rendered paint applied to the editable composer text. */ +interface PluginComposerTextEffect { + className: string; +} +/** Host-rendered status that temporarily replaces a thread's draft glyph. */ +interface PluginComposerThreadRowStatus { + /** BB icon-name hint; unknown names fall back to the generic plugin icon. */ + icon: string; + /** Accessible label for the status glyph. */ + label: string; + /** Semantic host color for the status glyph. Defaults to the neutral tone. */ + tone?: "default" | "success"; +} +/** An @-mention pill bound to one of the calling plugin's mention providers. */ +interface PluginComposerMention { + /** Mention provider id registered by THIS plugin via `bb.ui.registerMentionProvider`. */ + provider: string; + /** Item id your provider's `resolve` will receive at send time. */ + id: string; + /** Pill text shown in the composer. */ + label: string; +} +/** + * Programmatic access to the chat composer draft — the same shared draft the + * built-in "Add to chat" affordances (file preview, diff, terminal selections) + * write to. While a queued message is being edited, writes land in that + * message's inline editor. In a side chat, writes land in the visible side-chat + * draft. Otherwise, inside a thread context writes land in that thread's draft; + * anywhere else (nav panel, homepage section) they seed the new-thread composer + * draft, which persists until the user sends or clears it. + */ +interface PluginComposerApi { + scope: PluginComposerScope; + /** Current plain text for this composer scope. */ + readonly text: string; + /** + * Replace the draft's plain text. Attachments are preserved. Inline mentions + * outside the changed range are preserved and rebased; mentions overlapped + * by the replacement are removed because their text representation changed. + */ + setText(next: string): void; + /** + * Replace the draft's plain text from the latest committed value. Uses the + * same structured-state reconciliation as `setText`. + */ + updateText(updater: (current: string) => string): void; + /** Clear plain text without clearing independently attached files. */ + clear(): void; + /** + * Apply a host-rendered effect to this composer's editable text, or clear it. + * Effects are scoped to the calling plugin and automatically clear when the + * slot unmounts or its composer scope changes. + */ + setTextEffect(effect: PluginComposerTextEffect | null): void; + /** + * Lock or unlock editing for this composer. Locks are scoped to the calling + * plugin and automatically release when the slot unmounts or its composer + * scope changes. + */ + setInputLock(locked: boolean): void; + /** + * Replace this composer's thread-row draft glyph with a host-rendered status, + * or clear it. New-thread composers have no row, so calls are a no-op. + * Side-chat and queued side-chat scopes decorate the visible parent-thread + * row. Status is scoped to the calling plugin and automatically clears when + * the slot unmounts or its composer scope changes. + */ + setThreadRowStatus(status: PluginComposerThreadRowStatus | null): void; + /** + * Append text to the draft as a `> ` blockquote block and focus the + * composer. Blank text is a no-op. This is the "reference this selection + * in chat" primitive. + */ + addQuote(text: string): void; + /** + * Insert an @-mention pill that resolves through this plugin's mention + * provider at send time — the durable way to reference an entity whose + * content should be fetched fresh when the message is sent. + */ + insertMention(mention: PluginComposerMention): void; + /** Focus the composer caret at the end of the draft. */ + focus(): void; +} +/** + * A consumer-supplied action on the messages of one `ThreadChat` instance, + * rendered in the embedded timeline's per-message action bar alongside the + * native and slot-registered actions. Unlike the `messageAction` slot this is + * scoped to the rendering component, not registered globally. + */ +interface ThreadChatMessageAction { + /** Unique within this ThreadChat instance; letters, digits, `-`, `_`. */ + id: string; + /** Tooltip / menu label for the action. */ + title: string; + /** Icon hint (BB icon name); unknown names fall back to a generic icon. */ + icon?: string; + /** + * Message roles the action applies to. Omitted = both user and assistant + * messages. + */ + roles?: readonly ("user" | "assistant")[]; + /** + * Runs when the user activates the action. Errors (sync or async) are + * contained and logged; they never break the timeline. + */ + run(message: ThreadChatMessageReference): void | Promise; +} +/** + * Props of the host-owned `ThreadChat` component — one thread's chat + * (timeline, and for the composer variants the full send/queue/draft + * engine), rendered by the BB app inside a plugin slot. This is the + * deliberate exception to the no-host-components rule (§5.5): a stable + * product capability, not a UI kit. Versioned additive like slot props; + * internal timeline rows, query hooks, and prompt-box configuration are + * deliberately not exposed. + */ +interface ThreadChatProps { + threadId: string; + /** + * "full" (default) is the page presentation (centered reading width); + * "compact" is the side-panel presentation; "timeline" renders the + * transcript without a composer. + */ + variant?: "full" | "compact" | "timeline"; + /** + * "contained" (default) fills and scrolls inside a bounded parent; + * "document" grows with its content and defers scrolling to the page. + */ + layout?: "contained" | "document"; + /** Bump to focus the composer (ignored by `variant: "timeline"`). */ + focusRequest?: number; + className?: string; + /** Rendered above the conversation, scrolling with it. */ + leadingContent?: ReactNode; + /** + * Actions rendered in this instance's per-message action bar (see + * {@link ThreadChatMessageAction}). + */ + messageActions?: readonly ThreadChatMessageAction[]; +} +/** + * Props of the host-owned `Markdown` component — bb's chat message renderer + * (the same typography, spacing, and code styling as timeline messages). + * Use it wherever plugin UI quotes or previews message content so it reads + * like the rest of the chat. Like `ThreadChat`, this is a stable product + * capability, not a UI kit; renderer internals stay private. + */ +interface MarkdownProps { + /** Markdown source, rendered exactly like a chat message body. */ + content: string; + className?: string; +} +/** Current app selection, derived from the route. */ +interface BbContext { + projectId: string | null; + threadId: string | null; +} +interface BbNavigate { + toThread(threadId: string): void; + toProject(projectId: string): void; + /** + * Navigate to one of this plugin's own nav panels by its `path`. + * `subPath` targets a location inside the panel (the component's + * `subPath` prop); `replace` swaps the current history entry instead of + * pushing — use it for redirects so back does not bounce. + */ + toPluginPanel(path: string, options?: { + subPath?: string; + replace?: boolean; + }): void; + /** + * Navigate to the root compose surface (the new-thread screen). Pass + * `initialPrompt` to seed the composer draft and `focusPrompt` to focus the + * composer on arrival — the pairing behind "Create via chat" style entry + * points that drop the user into chat with a prefilled prompt. + */ + toCompose(options?: { + initialPrompt?: string; + focusPrompt?: boolean; + }): void; + /** + * Open one of this plugin's registered thread-panel actions in the current + * thread surface. Returns false when the surface has no thread side panel or + * the action is unavailable. + */ + experimental_openThreadPanel(options: { + actionId: string; + title?: string; + params?: JsonValue$1; + }): boolean; +} +/** + * Everything `@bb/plugin-sdk/app` resolves to at runtime. The BB app builds + * the real implementation and `satisfies` this interface; `bb plugin build` + * shims the specifier to that object on `globalThis.__bbPluginRuntime`. + */ +interface PluginSdkApp { + definePluginApp(setup: PluginAppSetup): PluginAppDefinition; + useRpc(): PluginRpcClient; + useRealtime(channel: string, handler: (payload: unknown) => void): void; + /** + * Observe the same shared connection that delivers `useRealtime` signals. + * Use a subsequent transition to `connected` to reconcile server state that + * may have changed while ephemeral signals could not be delivered. The first + * connection can transition from `connecting` and is not a reconnection. + */ + useRealtimeConnectionState(): PluginRealtimeConnectionState; + useSettings(): PluginSettingsState; + useBbContext(): BbContext; + useBbNavigate(): BbNavigate; + useComposer(): PluginComposerApi; + /** + * The host-owned chat component (see {@link ThreadChatProps}). Together + * with `Markdown`, the only components the SDK ships — everything else + * stays vendored per §5.5. + */ + experimental_ThreadChat: ComponentType; + /** + * The host-owned chat-message markdown renderer (see + * {@link MarkdownProps}). + */ + experimental_Markdown: ComponentType; + useComposerView(): ComposerView; +} + +/** + * App-wide server-backed preferences. + * Client-local settings stay in the frontend localStorage helpers instead. + */ +declare const appSettingsSchema: z$1.ZodObject<{ + caffeinate: z$1.ZodBoolean; + showKeyboardHints: z$1.ZodBoolean; + showUnhandledProviderEvents: z$1.ZodBoolean; + codexMemoryEnabled: z$1.ZodBoolean; + claudeCodeMemoryEnabled: z$1.ZodBoolean; + codexSubagentsDisabled: z$1.ZodBoolean; + claudeCodeSubagentsDisabled: z$1.ZodBoolean; + claudeCodeWorkflowsDisabled: z$1.ZodBoolean; +}, z$1.core.$strict>; +type AppSettings = z$1.infer; + +declare const appKeybindingOverridesSchema: z$1.ZodArray; + shortcut: z$1.ZodNullable>; +}, z$1.core.$strict>>; +type AppKeybindingOverrides = z$1.infer; + +declare const appThemeSchema: z$1.ZodObject<{ + themeId: z$1.ZodString; + customCss: z$1.ZodNullable; + faviconColor: z$1.ZodEnum<{ + default: "default"; + red: "red"; + orange: "orange"; + yellow: "yellow"; + green: "green"; + teal: "teal"; + blue: "blue"; + purple: "purple"; + pink: "pink"; + }>; +}, z$1.core.$strip>; +type AppTheme = z$1.infer; +/** + * The complete appearance selection a client sends when changing the palette + * and/or favicon tint. The server validates `themeId` (built-in id or an + * existing custom theme) and resolves the CSS from disk for custom themes. + * Callers changing only one facet must carry the other facet forward explicitly. + */ +declare const appThemeSelectionSchema: z$1.ZodObject<{ + themeId: z$1.ZodString; + faviconColor: z$1.ZodEnum<{ + default: "default"; + red: "red"; + orange: "orange"; + yellow: "yellow"; + green: "green"; + teal: "teal"; + blue: "blue"; + purple: "purple"; + pink: "pink"; + }>; +}, z$1.core.$strip>; +type AppThemeSelection = z$1.infer; + +declare const changedMessageSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"changed">; + entity: z$1.ZodLiteral<"thread">; + id: z$1.ZodOptional; + metadata: z$1.ZodOptional; + eventTypes: z$1.ZodOptional>>>>; + hasPendingInteraction: z$1.ZodOptional; + projectId: z$1.ZodOptional; + }, z$1.core.$strict>>; + changes: z$1.ZodReadonly>>; +}, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"changed">; + entity: z$1.ZodLiteral<"project">; + id: z$1.ZodOptional; + changes: z$1.ZodReadonly>>; +}, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"changed">; + entity: z$1.ZodLiteral<"environment">; + id: z$1.ZodOptional; + changes: z$1.ZodReadonly>>; +}, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"changed">; + entity: z$1.ZodLiteral<"host">; + id: z$1.ZodOptional; + changes: z$1.ZodReadonly>>; +}, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"changed">; + entity: z$1.ZodLiteral<"system">; + changes: z$1.ZodReadonly>>; +}, z$1.core.$strict>], "entity">; +type ChangedMessage = z$1.infer; + +declare const environmentSchema: z$1.ZodObject<{ + id: z$1.ZodString; + name: z$1.ZodNullable; + projectId: z$1.ZodString; + hostId: z$1.ZodString; + path: z$1.ZodNullable; + managed: z$1.ZodBoolean; + isGitRepo: z$1.ZodBoolean; + isWorktree: z$1.ZodBoolean; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + branchName: z$1.ZodNullable; + baseBranch: z$1.ZodNullable; + defaultBranch: z$1.ZodNullable; + mergeBaseBranch: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + ready: "ready"; + retiring: "retiring"; + destroying: "destroying"; + destroyed: "destroyed"; + }>; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; +}, z$1.core.$strip>; +type Environment = z$1.infer; + +/** + * User-opt-in experiments (the Settings → Experiments toggles). Distinct from + * `FeatureFlags`: flags are operator-set via env at server start, experiments + * are user-toggled at runtime and persisted server-side so server-owned + * policy (e.g. skill injection) can honor them. + * + * Every experiment defaults to off — opting in is the point. + */ +declare const experimentsSchema: z$1.ZodObject<{ + claudeCodeMockCliTraffic: z$1.ZodBoolean; + plugins: z$1.ZodBoolean; + sideChatPlugin: z$1.ZodBoolean; +}, z$1.core.$strip>; +type Experiments = z$1.infer; + +declare const hostSchema: z$1.ZodObject<{ + id: z$1.ZodString; + name: z$1.ZodString; + type: z$1.ZodEnum<{ + persistent: "persistent"; + }>; + status: z$1.ZodEnum<{ + connected: "connected"; + disconnected: "disconnected"; + }>; + lastSeenAt: z$1.ZodNullable; + lastRejectedProtocolVersion: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; +}, z$1.core.$strip>; +type Host = z$1.infer; + +interface JsonObject { + [key: string]: JsonValue; +} +type JsonValue = string | number | boolean | null | JsonValue[] | JsonObject; + +declare const pendingInteractionResolutionSchema: z$1.ZodUnion; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"allow_for_session">; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"deny">; +}, z$1.core.$strip>], "decision">, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"user_answer">; + answers: z$1.ZodRecord; + freeText: z$1.ZodOptional; + }, z$1.core.$strip>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin_submitted">; +}, z$1.core.$strip>]>; +type PendingInteractionResolution = z$1.infer; +declare const providerPendingInteractionSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + interrupted: "interrupted"; + resolving: "resolving"; + resolved: "resolved"; + }>; + statusReason: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + expiresAt: z$1.ZodOptional>; + resolvedAt: z$1.ZodNullable; + turnId: z$1.ZodString; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodString; + providerRequestId: z$1.ZodString; + origin: z$1.ZodOptional; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodString; + providerRequestId: z$1.ZodString; + }, z$1.core.$strip>>; + payload: z$1.ZodUnion; + subject: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + itemId: z$1.ZodString; + command: z$1.ZodString; + cwd: z$1.ZodNullable; + actions: z$1.ZodArray; + command: z$1.ZodString; + name: z$1.ZodString; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"listFiles">; + command: z$1.ZodString; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"search">; + command: z$1.ZodString; + query: z$1.ZodNullable; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"unknown">; + command: z$1.ZodString; + }, z$1.core.$strip>], "type">>; + sessionGrant: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"file_change">; + itemId: z$1.ZodString; + writeScope: z$1.ZodNullable; + sessionGrant: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"permission_grant">; + itemId: z$1.ZodString; + toolName: z$1.ZodNullable; + permissions: z$1.ZodObject<{ + network: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>; + }, z$1.core.$strip>], "kind">; + reason: z$1.ZodNullable; + availableDecisions: z$1.ZodArray>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"user_question">; + questions: z$1.ZodArray; + multiSelect: z$1.ZodBoolean; + options: z$1.ZodOptional; + }, z$1.core.$strip>>>; + allowFreeText: z$1.ZodBoolean; + }, z$1.core.$strip>>; + }, z$1.core.$strip>]>; + resolution: z$1.ZodNullable; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"allow_for_session">; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"deny">; + }, z$1.core.$strip>], "decision">, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"user_answer">; + answers: z$1.ZodRecord; + freeText: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>]>>; +}, z$1.core.$strip>; +type ProviderPendingInteraction = z$1.infer; +declare const pluginPendingInteractionSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + interrupted: "interrupted"; + resolving: "resolving"; + resolved: "resolved"; + }>; + statusReason: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + expiresAt: z$1.ZodOptional>; + resolvedAt: z$1.ZodNullable; + turnId: z$1.ZodNullable; + origin: z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + rendererId: z$1.ZodString; + }, z$1.core.$strip>; + payload: z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + title: z$1.ZodString; + data: z$1.ZodType>; + }, z$1.core.$strip>; + resolution: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type PluginPendingInteraction = z$1.infer; +type PendingInteraction = ProviderPendingInteraction | PluginPendingInteraction; + +declare const projectSourceSchema: z$1.ZodObject<{ + id: z$1.ZodString; + projectId: z$1.ZodString; + isDefault: z$1.ZodBoolean; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + type: z$1.ZodLiteral<"local_path">; + hostId: z$1.ZodString; + path: z$1.ZodString; +}, z$1.core.$strip>; +type ProjectSource = z$1.infer; + +declare const resolvedThreadExecutionOptionsSchema: z$1.ZodObject<{ + seq: z$1.ZodOptional; + model: z$1.ZodString; + serviceTier: z$1.ZodEnum<{ + default: "default"; + fast: "fast"; + }>; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + permissionMode: z$1.ZodEnum<{ + full: "full"; + auto: "auto"; + "accept-edits": "accept-edits"; + }>; + source: z$1.ZodEnum<{ + "client/thread/start": "client/thread/start"; + "client/turn/requested": "client/turn/requested"; + "client/turn/start": "client/turn/start"; + }>; +}, z$1.core.$strip>; +type ResolvedThreadExecutionOptions = z$1.infer; +declare const projectExecutionDefaultsSchema: z$1.ZodObject<{ + providerId: z$1.ZodString; + model: z$1.ZodString; + serviceTier: z$1.ZodEnum<{ + default: "default"; + fast: "fast"; + }>; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + permissionMode: z$1.ZodEnum<{ + full: "full"; + auto: "auto"; + "accept-edits": "accept-edits"; + }>; +}, z$1.core.$strip>; +type ProjectExecutionDefaults = z$1.infer; + +/** All thread events — provider-originated or system-originated. */ +declare const threadEventSchema: z$1.ZodPipe; + threadId: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"thread/identity">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"turn/started">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"turn/completed">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodNullable; + status: z$1.ZodEnum<{ + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + error: z$1.ZodOptional>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"turn/input/accepted">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + clientRequestId: z$1.ZodString; + scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"turn">; + turnId: z$1.ZodString; + }, z$1.core.$strip>], "kind">; +}, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"thread/name/updated">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + threadName: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"thread/compacted">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"thread/goal/updated">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + objective: z$1.ZodString; + status: z$1.ZodEnum<{ + paused: "paused"; + active: "active"; + budgetLimited: "budgetLimited"; + complete: "complete"; + }>; + tokenBudget: z$1.ZodNullable; + tokensUsed: z$1.ZodNumber; + timeUsedSeconds: z$1.ZodNumber; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"thread/goal/cleared">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/started">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + item: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"userMessage">; + id: z$1.ZodString; + content: z$1.ZodArray; + text: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + }, z$1.core.$strip>], "type">>; + clientRequestId: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"agentMessage">; + id: z$1.ZodString; + text: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"commandExecution">; + id: z$1.ZodString; + command: z$1.ZodString; + cwd: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + approvalStatus: z$1.ZodNullable>; + aggregatedOutput: z$1.ZodOptional; + exitCode: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + truncation: z$1.ZodOptional>; + result: z$1.ZodOptional>; + resultText: z$1.ZodOptional>; + }, z$1.core.$strip>>; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"fileChange">; + id: z$1.ZodString; + changes: z$1.ZodArray; + movePath: z$1.ZodOptional; + diff: z$1.ZodOptional; + }, z$1.core.$strip>>; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + approvalStatus: z$1.ZodNullable>; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"webSearch">; + id: z$1.ZodString; + queries: z$1.ZodArray; + resultText: z$1.ZodNullable; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"webFetch">; + id: z$1.ZodString; + url: z$1.ZodString; + prompt: z$1.ZodNullable; + pattern: z$1.ZodNullable; + resultText: z$1.ZodNullable; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"imageView">; + id: z$1.ZodString; + path: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"toolCall">; + id: z$1.ZodString; + server: z$1.ZodOptional; + tool: z$1.ZodString; + arguments: z$1.ZodOptional>; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + result: z$1.ZodOptional; + error: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + truncation: z$1.ZodOptional>; + result: z$1.ZodOptional>; + resultText: z$1.ZodOptional>; + }, z$1.core.$strip>>; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"reasoning">; + id: z$1.ZodString; + summary: z$1.ZodArray; + content: z$1.ZodArray; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"plan">; + id: z$1.ZodString; + text: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"contextCompaction">; + id: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"backgroundTask">; + id: z$1.ZodString; + taskType: z$1.ZodString; + description: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + taskStatus: z$1.ZodEnum<{ + pending: "pending"; + running: "running"; + paused: "paused"; + completed: "completed"; + failed: "failed"; + killed: "killed"; + stopped: "stopped"; + }>; + skipTranscript: z$1.ZodBoolean; + workflowName: z$1.ZodOptional; + workflow: z$1.ZodOptional; + }, z$1.core.$strip>>; + agents: z$1.ZodArray; + model: z$1.ZodString; + attempt: z$1.ZodNumber; + cached: z$1.ZodBoolean; + lastProgressAt: z$1.ZodNumber; + phaseIndex: z$1.ZodOptional; + phaseTitle: z$1.ZodOptional; + agentType: z$1.ZodOptional; + isolation: z$1.ZodOptional; + queuedAt: z$1.ZodOptional; + startedAt: z$1.ZodOptional; + lastToolName: z$1.ZodOptional; + lastToolSummary: z$1.ZodOptional; + promptPreview: z$1.ZodOptional; + resultPreview: z$1.ZodOptional; + error: z$1.ZodOptional; + tokens: z$1.ZodOptional; + toolCalls: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + usage: z$1.ZodOptional>; + summary: z$1.ZodOptional; + error: z$1.ZodOptional; + outputFile: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>], "type">; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/completed">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + item: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"userMessage">; + id: z$1.ZodString; + content: z$1.ZodArray; + text: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + }, z$1.core.$strip>], "type">>; + clientRequestId: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"agentMessage">; + id: z$1.ZodString; + text: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"commandExecution">; + id: z$1.ZodString; + command: z$1.ZodString; + cwd: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + approvalStatus: z$1.ZodNullable>; + aggregatedOutput: z$1.ZodOptional; + exitCode: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + truncation: z$1.ZodOptional>; + result: z$1.ZodOptional>; + resultText: z$1.ZodOptional>; + }, z$1.core.$strip>>; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"fileChange">; + id: z$1.ZodString; + changes: z$1.ZodArray; + movePath: z$1.ZodOptional; + diff: z$1.ZodOptional; + }, z$1.core.$strip>>; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + approvalStatus: z$1.ZodNullable>; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"webSearch">; + id: z$1.ZodString; + queries: z$1.ZodArray; + resultText: z$1.ZodNullable; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"webFetch">; + id: z$1.ZodString; + url: z$1.ZodString; + prompt: z$1.ZodNullable; + pattern: z$1.ZodNullable; + resultText: z$1.ZodNullable; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"imageView">; + id: z$1.ZodString; + path: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"toolCall">; + id: z$1.ZodString; + server: z$1.ZodOptional; + tool: z$1.ZodString; + arguments: z$1.ZodOptional>; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + result: z$1.ZodOptional; + error: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + truncation: z$1.ZodOptional>; + result: z$1.ZodOptional>; + resultText: z$1.ZodOptional>; + }, z$1.core.$strip>>; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"reasoning">; + id: z$1.ZodString; + summary: z$1.ZodArray; + content: z$1.ZodArray; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"plan">; + id: z$1.ZodString; + text: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"contextCompaction">; + id: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"backgroundTask">; + id: z$1.ZodString; + taskType: z$1.ZodString; + description: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + taskStatus: z$1.ZodEnum<{ + pending: "pending"; + running: "running"; + paused: "paused"; + completed: "completed"; + failed: "failed"; + killed: "killed"; + stopped: "stopped"; + }>; + skipTranscript: z$1.ZodBoolean; + workflowName: z$1.ZodOptional; + workflow: z$1.ZodOptional; + }, z$1.core.$strip>>; + agents: z$1.ZodArray; + model: z$1.ZodString; + attempt: z$1.ZodNumber; + cached: z$1.ZodBoolean; + lastProgressAt: z$1.ZodNumber; + phaseIndex: z$1.ZodOptional; + phaseTitle: z$1.ZodOptional; + agentType: z$1.ZodOptional; + isolation: z$1.ZodOptional; + queuedAt: z$1.ZodOptional; + startedAt: z$1.ZodOptional; + lastToolName: z$1.ZodOptional; + lastToolSummary: z$1.ZodOptional; + promptPreview: z$1.ZodOptional; + resultPreview: z$1.ZodOptional; + error: z$1.ZodOptional; + tokens: z$1.ZodOptional; + toolCalls: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + usage: z$1.ZodOptional>; + summary: z$1.ZodOptional; + error: z$1.ZodOptional; + outputFile: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>], "type">; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/agentMessage/delta">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + delta: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/commandExecution/outputDelta">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + delta: z$1.ZodString; + reset: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/fileChange/outputDelta">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + delta: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/reasoning/summaryTextDelta">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + delta: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/reasoning/textDelta">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + delta: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/plan/delta">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + delta: z$1.ZodString; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/mcpToolCall/progress">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + message: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/toolCall/progress">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + itemId: z$1.ZodString; + message: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/backgroundTask/progress">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + item: z$1.ZodObject<{ + type: z$1.ZodLiteral<"backgroundTask">; + id: z$1.ZodString; + taskType: z$1.ZodString; + description: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + taskStatus: z$1.ZodEnum<{ + pending: "pending"; + running: "running"; + paused: "paused"; + completed: "completed"; + failed: "failed"; + killed: "killed"; + stopped: "stopped"; + }>; + skipTranscript: z$1.ZodBoolean; + workflowName: z$1.ZodOptional; + workflow: z$1.ZodOptional; + }, z$1.core.$strip>>; + agents: z$1.ZodArray; + model: z$1.ZodString; + attempt: z$1.ZodNumber; + cached: z$1.ZodBoolean; + lastProgressAt: z$1.ZodNumber; + phaseIndex: z$1.ZodOptional; + phaseTitle: z$1.ZodOptional; + agentType: z$1.ZodOptional; + isolation: z$1.ZodOptional; + queuedAt: z$1.ZodOptional; + startedAt: z$1.ZodOptional; + lastToolName: z$1.ZodOptional; + lastToolSummary: z$1.ZodOptional; + promptPreview: z$1.ZodOptional; + resultPreview: z$1.ZodOptional; + error: z$1.ZodOptional; + tokens: z$1.ZodOptional; + toolCalls: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + usage: z$1.ZodOptional>; + summary: z$1.ZodOptional; + error: z$1.ZodOptional; + outputFile: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"item/backgroundTask/completed">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + item: z$1.ZodObject<{ + type: z$1.ZodLiteral<"backgroundTask">; + id: z$1.ZodString; + taskType: z$1.ZodString; + description: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + failed: "failed"; + interrupted: "interrupted"; + }>; + taskStatus: z$1.ZodEnum<{ + pending: "pending"; + running: "running"; + paused: "paused"; + completed: "completed"; + failed: "failed"; + killed: "killed"; + stopped: "stopped"; + }>; + skipTranscript: z$1.ZodBoolean; + workflowName: z$1.ZodOptional; + workflow: z$1.ZodOptional; + }, z$1.core.$strip>>; + agents: z$1.ZodArray; + model: z$1.ZodString; + attempt: z$1.ZodNumber; + cached: z$1.ZodBoolean; + lastProgressAt: z$1.ZodNumber; + phaseIndex: z$1.ZodOptional; + phaseTitle: z$1.ZodOptional; + agentType: z$1.ZodOptional; + isolation: z$1.ZodOptional; + queuedAt: z$1.ZodOptional; + startedAt: z$1.ZodOptional; + lastToolName: z$1.ZodOptional; + lastToolSummary: z$1.ZodOptional; + promptPreview: z$1.ZodOptional; + resultPreview: z$1.ZodOptional; + error: z$1.ZodOptional; + tokens: z$1.ZodOptional; + toolCalls: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + usage: z$1.ZodOptional>; + summary: z$1.ZodOptional; + error: z$1.ZodOptional; + outputFile: z$1.ZodOptional; + parentToolCallId: z$1.ZodOptional; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"thread/tokenUsage/updated">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + tokenUsage: z$1.ZodObject<{ + total: z$1.ZodObject<{ + totalTokens: z$1.ZodNumber; + inputTokens: z$1.ZodNumber; + cachedInputTokens: z$1.ZodNumber; + outputTokens: z$1.ZodNumber; + reasoningOutputTokens: z$1.ZodNumber; + }, z$1.core.$strip>; + last: z$1.ZodObject<{ + totalTokens: z$1.ZodNumber; + inputTokens: z$1.ZodNumber; + cachedInputTokens: z$1.ZodNumber; + outputTokens: z$1.ZodNumber; + reasoningOutputTokens: z$1.ZodNumber; + }, z$1.core.$strip>; + modelContextWindow: z$1.ZodNullable; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"thread/contextWindowUsage/updated">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + contextWindowUsage: z$1.ZodObject<{ + usedTokens: z$1.ZodNullable; + modelContextWindow: z$1.ZodNullable; + estimated: z$1.ZodBoolean; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"turn/plan/updated">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + plan: z$1.ZodArray>; + }, z$1.core.$strip>>; + explanation: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"turn/diff/updated">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + diff: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"provider/error">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + message: z$1.ZodString; + detail: z$1.ZodOptional; + willRetry: z$1.ZodOptional; + errorInfo: z$1.ZodOptional; + providerCode: z$1.ZodNullable; + httpStatusCode: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"provider/warning">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + category: z$1.ZodEnum<{ + deprecation: "deprecation"; + config: "config"; + general: "general"; + }>; + summary: z$1.ZodOptional; + details: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"provider/modelFallback">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + originalModel: z$1.ZodString; + fallbackModel: z$1.ZodString; + reason: z$1.ZodEnum<{ + refusal: "refusal"; + provider: "provider"; + }>; + message: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"provider/unhandled">; + threadId: z$1.ZodString; + providerThreadId: z$1.ZodString; + providerId: z$1.ZodString; + rawType: z$1.ZodString; + rawEvent: z$1.ZodObject<{ + jsonrpc: z$1.ZodLiteral<"2.0">; + id: z$1.ZodOptional>; + method: z$1.ZodString; + params: z$1.ZodOptional>>; + }, z$1.core.$strip>; + parentToolCallId: z$1.ZodOptional; +}, z$1.core.$strip>], "type">, z$1.ZodObject<{ + scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"turn">; + turnId: z$1.ZodString; + }, z$1.core.$strip>], "kind">; +}, z$1.core.$strip>>, z$1.ZodIntersection; + threadId: z$1.ZodString; + direction: z$1.ZodLiteral<"outbound">; + source: z$1.ZodEnum<{ + spawn: "spawn"; + tell: "tell"; + }>; + initiator: z$1.ZodEnum<{ + system: "system"; + user: "user"; + agent: "agent"; + }>; + request: z$1.ZodObject<{ + method: z$1.ZodEnum<{ + "thread/start": "thread/start"; + "turn/start": "turn/start"; + }>; + params: z$1.ZodRecord; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"client/turn/requested">; + threadId: z$1.ZodString; + direction: z$1.ZodLiteral<"outbound">; + requestId: z$1.ZodString; + source: z$1.ZodEnum<{ + spawn: "spawn"; + tell: "tell"; + }>; + initiator: z$1.ZodEnum<{ + system: "system"; + user: "user"; + agent: "agent"; + }>; + senderThreadId: z$1.ZodNullable; + systemMessageKind: z$1.ZodOptional>; + systemMessageSubject: z$1.ZodOptional; + threadId: z$1.ZodString; + threadName: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread-batch">; + count: z$1.ZodNumber; + }, z$1.core.$strip>], "kind">>>; + input: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + inputGroups: z$1.ZodOptional>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>>>; + target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread-start">; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"new-turn">; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"auto">; + expectedTurnId: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"steer">; + expectedTurnId: z$1.ZodNullable; + }, z$1.core.$strip>], "kind">; + request: z$1.ZodObject<{ + method: z$1.ZodEnum<{ + "thread/start": "thread/start"; + "turn/start": "turn/start"; + }>; + params: z$1.ZodRecord; + }, z$1.core.$strip>; + execution: z$1.ZodObject<{ + seq: z$1.ZodOptional; + model: z$1.ZodString; + serviceTier: z$1.ZodEnum<{ + default: "default"; + fast: "fast"; + }>; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + source: z$1.ZodEnum<{ + "client/thread/start": "client/thread/start"; + "client/turn/requested": "client/turn/requested"; + "client/turn/start": "client/turn/start"; + }>; + permissionMode: z$1.ZodEnum<{ + readonly: "readonly"; + full: "full"; + auto: "auto"; + "accept-edits": "accept-edits"; + "workspace-write": "workspace-write"; + }>; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"client/turn/start">; + threadId: z$1.ZodString; + direction: z$1.ZodLiteral<"outbound">; + source: z$1.ZodEnum<{ + spawn: "spawn"; + tell: "tell"; + }>; + initiator: z$1.ZodEnum<{ + system: "system"; + user: "user"; + agent: "agent"; + }>; + request: z$1.ZodObject<{ + method: z$1.ZodEnum<{ + "thread/start": "thread/start"; + "turn/start": "turn/start"; + }>; + params: z$1.ZodRecord; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/error">; + threadId: z$1.ZodString; + code: z$1.ZodOptional; + message: z$1.ZodString; + detail: z$1.ZodOptional; + reconnectAttempt: z$1.ZodOptional; + reconnectTotal: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/manager/user_message">; + threadId: z$1.ZodString; + text: z$1.ZodString; + toolCallId: z$1.ZodOptional; + turnId: z$1.ZodOptional; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/thread/interrupted">; + threadId: z$1.ZodString; + reason: z$1.ZodEnum<{ + "manual-stop": "manual-stop"; + "host-daemon-restarted": "host-daemon-restarted"; + "provider-turn-idle": "provider-turn-idle"; + }>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/operation">; + threadId: z$1.ZodString; + operation: z$1.ZodString; + status: z$1.ZodString; + message: z$1.ZodString; + operationId: z$1.ZodString; + metadata: z$1.ZodOptional>>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/permissionGrant/lifecycle">; + threadId: z$1.ZodString; + interactionId: z$1.ZodString; + providerId: z$1.ZodString; + providerRequestId: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + interrupted: "interrupted"; + resolving: "resolving"; + resolved: "resolved"; + }>; + resolution: z$1.ZodDefault; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"allow_for_session">; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"deny">; + }, z$1.core.$strip>], "decision">>>; + statusReason: z$1.ZodDefault>; + subject: z$1.ZodObject<{ + kind: z$1.ZodLiteral<"permission_grant">; + itemId: z$1.ZodString; + toolName: z$1.ZodNullable; + permissions: z$1.ZodObject<{ + network: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/userQuestion/lifecycle">; + threadId: z$1.ZodString; + interactionId: z$1.ZodString; + providerId: z$1.ZodString; + providerRequestId: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + interrupted: "interrupted"; + resolving: "resolving"; + resolved: "resolved"; + }>; + resolution: z$1.ZodDefault; + answers: z$1.ZodRecord; + freeText: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>>; + statusReason: z$1.ZodDefault>; + payload: z$1.ZodObject<{ + kind: z$1.ZodLiteral<"user_question">; + questions: z$1.ZodArray; + multiSelect: z$1.ZodBoolean; + options: z$1.ZodOptional; + }, z$1.core.$strip>>>; + allowFreeText: z$1.ZodBoolean; + }, z$1.core.$strip>>; + }, z$1.core.$strip>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/thread-provisioning">; + threadId: z$1.ZodString; + provisioningId: z$1.ZodString; + status: z$1.ZodEnum<{ + completed: "completed"; + failed: "failed"; + active: "active"; + cancelled: "cancelled"; + }>; + environmentId: z$1.ZodString; + entries: z$1.ZodArray; + key: z$1.ZodString; + text: z$1.ZodString; + startedAt: z$1.ZodOptional; + status: z$1.ZodOptional>; + metadata: z$1.ZodOptional>; + }, z$1.core.$strip>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"system/provider-turn-watchdog">; + threadId: z$1.ZodString; + reason: z$1.ZodLiteral<"provider-turn-idle">; + thresholdMs: z$1.ZodNumber; + elapsedMs: z$1.ZodNumber; + activeTurnId: z$1.ZodString; + activeTurnStartedAt: z$1.ZodNumber; + lastActivityEventSequence: z$1.ZodNumber; + lastActivityEventType: z$1.ZodString; + lastActivityEventAt: z$1.ZodNumber; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodNullable; + firedAt: z$1.ZodNumber; +}, z$1.core.$strip>]>, z$1.ZodObject<{ + scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"turn">; + turnId: z$1.ZodString; + }, z$1.core.$strip>], "kind">; +}, z$1.core.$strip>>]>>; +type ThreadEvent = z$1.infer; +type ThreadEventType = ThreadEvent["type"]; + +declare const providerInfoSchema: z$1.ZodObject<{ + id: z$1.ZodString; + displayName: z$1.ZodString; + logoUrl: z$1.ZodNullable; + capabilities: z$1.ZodObject<{ + supportsArchive: z$1.ZodBoolean; + supportsRename: z$1.ZodBoolean; + supportsServiceTier: z$1.ZodBoolean; + supportsUserQuestion: z$1.ZodBoolean; + supportsFork: z$1.ZodBoolean; + supportedPermissionModes: z$1.ZodArray>; + }, z$1.core.$strip>; + composerActions: z$1.ZodArray; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plan">; + command: z$1.ZodObject<{ + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + trailingText: z$1.ZodString; + }, z$1.core.$strip>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"goal">; + command: z$1.ZodObject<{ + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + trailingText: z$1.ZodString; + }, z$1.core.$strip>; + }, z$1.core.$strip>], "kind">>; + available: z$1.ZodBoolean; +}, z$1.core.$strip>; +type ProviderInfo = z$1.infer; + +declare const threadEventScopeSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; +}, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"turn">; + turnId: z$1.ZodString; +}, z$1.core.$strip>], "kind">; +type ThreadEventScope = z$1.infer; + +type ThreadEventByType = { + [TType in ThreadEventType]: Extract; +}; +type ThreadEventForType = ThreadEventByType[TType]; +type StoredThreadEventDataFromEvent = Omit; +interface ThreadEventRowBase { + id: string; + scope: ThreadEventScope; + threadId: string; + seq: number; + createdAt: number; +} +type ThreadEventRowFromEvent = ThreadEventRowBase & { + type: TEvent["type"]; + data: StoredThreadEventDataFromEvent; +}; +type ThreadEventRowOfType = ThreadEventRowFromEvent>; +type ThreadEventRow = { + [TType in ThreadEventType]: ThreadEventRowOfType; +}[ThreadEventType]; + +declare const threadStatusSchema: z$1.ZodEnum<{ + error: "error"; + active: "active"; + starting: "starting"; + idle: "idle"; + stopping: "stopping"; +}>; +type ThreadStatus = z$1.infer; + +declare const threadTimelinePendingTodosSchema: z$1.ZodObject<{ + sourceSeq: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + items: z$1.ZodArray; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type ThreadTimelinePendingTodos = z$1.infer; + +declare const threadQueuedMessageSchema: z$1.ZodObject<{ + id: z$1.ZodString; + content: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + model: z$1.ZodString; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + permissionMode: z$1.ZodEnum<{ + full: "full"; + auto: "auto"; + "accept-edits": "accept-edits"; + }>; + serviceTier: z$1.ZodEnum<{ + default: "default"; + fast: "fast"; + }>; + groupWithNext: z$1.ZodBoolean; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; +}, z$1.core.$strip>; +type ThreadQueuedMessage = z$1.infer; + +declare const workspaceFileListResponseSchema: z$1.ZodObject<{ + files: z$1.ZodArray>; + truncated: z$1.ZodBoolean; +}, z$1.core.$strip>; +type WorkspaceFileListResponse = z$1.infer; +declare const workspacePathListResponseSchema: z$1.ZodObject<{ + paths: z$1.ZodArray; + path: z$1.ZodString; + name: z$1.ZodString; + score: z$1.ZodNumber; + positions: z$1.ZodArray; + }, z$1.core.$strip>>; + truncated: z$1.ZodBoolean; +}, z$1.core.$strip>; +type WorkspacePathListResponse = z$1.infer; + +declare const createProjectSourceRequestSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + hostId: z$1.ZodString; + type: z$1.ZodLiteral<"local_path">; + path: z$1.ZodPipe>; +}, z$1.core.$strict>, z$1.ZodObject<{ + hostId: z$1.ZodString; + type: z$1.ZodLiteral<"clone">; + targetPath: z$1.ZodOptional>>; + remoteUrl: z$1.ZodOptional; +}, z$1.core.$strict>], "type">; +type CreateProjectSourceRequest = z$1.infer; +declare const createProjectRequestSchema: z$1.ZodObject<{ + name: z$1.ZodString; + source: z$1.ZodObject<{ + hostId: z$1.ZodString; + type: z$1.ZodLiteral<"local_path">; + path: z$1.ZodPipe>; + }, z$1.core.$strict>; +}, z$1.core.$strip>; +type CreateProjectRequest = z$1.infer; +declare const threadSectionSchema: z$1.ZodObject<{ + id: z$1.ZodString; + name: z$1.ZodString; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; +}, z$1.core.$strict>; +type ThreadSectionResponse = z$1.infer; +declare const createThreadSectionRequestSchema: z$1.ZodObject<{ + name: z$1.ZodString; +}, z$1.core.$strict>; +type CreateThreadSectionRequest = z$1.infer; +declare const updateThreadSectionRequestSchema: z$1.ZodObject<{ + id: z$1.ZodString; + name: z$1.ZodString; +}, z$1.core.$strict>; +type UpdateThreadSectionRequest = z$1.infer; +declare const deleteThreadSectionRequestSchema: z$1.ZodObject<{ + id: z$1.ZodString; +}, z$1.core.$strict>; +type DeleteThreadSectionRequest = z$1.infer; +declare const threadSectionMutationResponseSchema: z$1.ZodObject<{ + id: z$1.ZodString; + name: z$1.ZodString; + updatedThreadCount: z$1.ZodNumber; +}, z$1.core.$strict>; +type ThreadSectionMutationResponse = z$1.infer; +declare const reorderProjectRequestSchema: z$1.ZodObject<{ + previousProjectId: z$1.ZodNullable; + nextProjectId: z$1.ZodNullable; +}, z$1.core.$strip>; +type ReorderProjectRequest = z$1.infer; +declare const projectListQuerySchema: z$1.ZodObject<{ + include: z$1.ZodOptional; + includePersonal: z$1.ZodOptional>; +}, z$1.core.$strip>; +type ProjectListQuery = z$1.infer; +declare const projectFilesQuerySchema: z$1.ZodObject<{ + query: z$1.ZodOptional>; + limit: z$1.ZodOptional>; + hostId: z$1.ZodOptional; + environmentId: z$1.ZodOptional, z$1.ZodOptional>>; +}, z$1.core.$strip>; +type ProjectFilesQuery = z$1.infer; +declare const projectPathsQuerySchema: z$1.ZodObject<{ + query: z$1.ZodOptional>; + limit: z$1.ZodOptional>; + includeFiles: z$1.ZodEnum<{ + true: "true"; + false: "false"; + }>; + includeDirectories: z$1.ZodEnum<{ + true: "true"; + false: "false"; + }>; + hostId: z$1.ZodOptional; + environmentId: z$1.ZodOptional, z$1.ZodOptional>>; +}, z$1.core.$strip>; +type ProjectPathsQuery = z$1.infer; +declare const projectFileContentQuerySchema: z$1.ZodObject<{ + path: z$1.ZodString; + hostId: z$1.ZodOptional; + environmentId: z$1.ZodOptional, z$1.ZodOptional>>; +}, z$1.core.$strip>; +type ProjectFileContentQuery = z$1.infer; +declare const projectBranchesQuerySchema: z$1.ZodObject<{ + query: z$1.ZodOptional; + limit: z$1.ZodOptional; + hostId: z$1.ZodString; + selectedBranch: z$1.ZodOptional; +}, z$1.core.$strip>; +type ProjectBranchesQuery = z$1.infer; +declare const projectBranchesResponseSchema: z$1.ZodObject<{ + branches: z$1.ZodArray; + branchesTruncated: z$1.ZodBoolean; + checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"branch">; + branchName: z$1.ZodString; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"detached">; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unborn">; + branchName: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unknown">; + reason: z$1.ZodString; + }, z$1.core.$strip>], "kind">; + defaultBranch: z$1.ZodNullable; + defaultBranchRelation: z$1.ZodNullable>; + hasUncommittedChanges: z$1.ZodBoolean; + operation: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"none">; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"merge">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"rebase">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"cherry-pick">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"revert">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unknown">; + reason: z$1.ZodString; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>], "kind">; + originDefaultBranch: z$1.ZodNullable; + remoteBranches: z$1.ZodArray; + remoteBranchesTruncated: z$1.ZodBoolean; + selectedBranch: z$1.ZodNullable; + }, z$1.core.$strip>>; + defaultWorktreeBaseBranch: z$1.ZodNullable; +}, z$1.core.$strip>; +type ProjectBranchesResponse = z$1.infer; +declare const promptHistoryQuerySchema: z$1.ZodObject<{ + limit: z$1.ZodOptional; +}, z$1.core.$strip>; +type PromptHistoryQuery = z$1.infer; +declare const promptHistoryResponseSchema: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; +}, z$1.core.$strip>>; +type PromptHistoryResponse = z$1.infer; +declare const updateProjectRequestSchema: z$1.ZodObject<{ + name: z$1.ZodOptional; +}, z$1.core.$strip>; +type UpdateProjectRequest = z$1.infer; +declare const updateProjectSourceRequestSchema: z$1.ZodObject<{ + type: z$1.ZodLiteral<"local_path">; + path: z$1.ZodOptional>>; + isDefault: z$1.ZodOptional>; +}, z$1.core.$strict>; +type UpdateProjectSourceRequest = z$1.infer; +declare const commandListResponseSchema: z$1.ZodObject<{ + commands: z$1.ZodArray; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + description: z$1.ZodNullable; + argumentHint: z$1.ZodNullable; + pluginId: z$1.ZodOptional; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type CommandListResponse = z$1.infer; +/** Query for the complete command catalog available to a project and provider. */ +declare const projectCommandsQuerySchema: z$1.ZodObject<{ + provider: z$1.ZodString; + hostId: z$1.ZodOptional; + environmentId: z$1.ZodOptional, z$1.ZodOptional>>; +}, z$1.core.$strict>; +type ProjectCommandsQuery = z$1.infer; +declare const projectResponseSchema: z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodEnum<{ + standard: "standard"; + personal: "personal"; + }>; + name: z$1.ZodString; + gitRemoteUrl: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + sources: z$1.ZodArray; + hostId: z$1.ZodString; + path: z$1.ZodString; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type ProjectResponse = z$1.infer; +declare const projectWithThreadsResponseSchema: z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodEnum<{ + standard: "standard"; + personal: "personal"; + }>; + name: z$1.ZodString; + gitRemoteUrl: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + sources: z$1.ZodArray; + hostId: z$1.ZodString; + path: z$1.ZodString; + }, z$1.core.$strip>>; + threads: z$1.ZodArray; + providerId: z$1.ZodString; + title: z$1.ZodNullable; + titleFallback: z$1.ZodNullable; + sectionId: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + }>; + parentThreadId: z$1.ZodNullable; + sourceThreadId: z$1.ZodNullable; + originKind: z$1.ZodNullable>; + childOrigin: z$1.ZodNullable>; + originPluginId: z$1.ZodNullable; + visibility: z$1.ZodEnum<{ + visible: "visible"; + hidden: "hidden"; + }>; + archivedAt: z$1.ZodNullable; + pinnedAt: z$1.ZodNullable; + deletedAt: z$1.ZodNullable; + lastReadAt: z$1.ZodNullable; + latestAttentionAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + runtime: z$1.ZodObject<{ + displayStatus: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + "host-reconnecting": "host-reconnecting"; + "waiting-for-host": "waiting-for-host"; + }>; + hostReconnectGraceExpiresAt: z$1.ZodNullable; + }, z$1.core.$strip>; + activity: z$1.ZodObject<{ + activeWorkflowCount: z$1.ZodNumber; + activeBackgroundAgentCount: z$1.ZodNumber; + activeBackgroundCommandCount: z$1.ZodNumber; + activePlanModeCount: z$1.ZodNumber; + activeGoalCount: z$1.ZodNumber; + }, z$1.core.$strip>; + pinSortKey: z$1.ZodNullable; + hasPendingInteraction: z$1.ZodBoolean; + environmentHostId: z$1.ZodNullable; + environmentName: z$1.ZodNullable; + environmentBranchName: z$1.ZodNullable; + environmentWorkspaceDisplayKind: z$1.ZodEnum<{ + "managed-worktree": "managed-worktree"; + "unmanaged-worktree": "unmanaged-worktree"; + other: "other"; + }>; + }, z$1.core.$strip>>; + defaultExecutionOptions: z$1.ZodNullable; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + permissionMode: z$1.ZodEnum<{ + "accept-edits": "accept-edits"; + auto: "auto"; + full: "full"; + }>; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type ProjectWithThreadsResponse = z$1.infer; +declare const uploadedPromptAttachmentSchema: z$1.ZodObject<{ + type: z$1.ZodEnum<{ + localImage: "localImage"; + localFile: "localFile"; + }>; + path: z$1.ZodString; + name: z$1.ZodString; + mimeType: z$1.ZodOptional; + sizeBytes: z$1.ZodNumber; +}, z$1.core.$strip>; +type UploadedPromptAttachment = z$1.infer; +declare const copyProjectAttachmentsRequestSchema: z$1.ZodObject<{ + sourceProjectId: z$1.ZodString; + paths: z$1.ZodArray; +}, z$1.core.$strict>; +type CopyProjectAttachmentsRequest = z$1.infer; + +declare const updateEnvironmentRequestSchema: z$1.ZodObject<{ + mergeBaseBranch: z$1.ZodOptional>; + name: z$1.ZodOptional>; +}, z$1.core.$strip>; +type UpdateEnvironmentRequest = z$1.infer; +/** + * Query for searching paths in an environment's workspace. Unlike the + * project-scoped variant this needs no `environmentId` — the environment is + * the route param — and is project-agnostic, so it works for projectless + * (personal) environments too. + */ +declare const environmentPathsQuerySchema: z$1.ZodObject<{ + query: z$1.ZodOptional; + limit: z$1.ZodOptional; + includeFiles: z$1.ZodEnum<{ + true: "true"; + false: "false"; + }>; + includeDirectories: z$1.ZodEnum<{ + true: "true"; + false: "false"; + }>; +}, z$1.core.$strip>; +type EnvironmentPathsQuery = z$1.infer; +declare const environmentDiffBranchesQuerySchema: z$1.ZodObject<{ + query: z$1.ZodOptional; + limit: z$1.ZodOptional; + selectedBranch: z$1.ZodOptional; +}, z$1.core.$strip>; +type EnvironmentDiffBranchesQuery = z$1.infer; +declare const environmentDiffBranchesResponseSchema: z$1.ZodObject<{ + branches: z$1.ZodArray; + branchesTruncated: z$1.ZodBoolean; + remoteBranches: z$1.ZodArray; + remoteBranchesTruncated: z$1.ZodBoolean; + selectedBranch: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type EnvironmentDiffBranchesResponse = z$1.infer; +declare const environmentStatusQuerySchema: z$1.ZodObject<{ + mergeBaseBranch: z$1.ZodOptional>; +}, z$1.core.$strip>; +type EnvironmentStatusQuery = z$1.infer; +declare const environmentDiffQuerySchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + target: z$1.ZodLiteral<"uncommitted">; +}, z$1.core.$strip>, z$1.ZodObject<{ + target: z$1.ZodLiteral<"branch_committed">; + mergeBaseBranch: z$1.ZodPipe; +}, z$1.core.$strip>, z$1.ZodObject<{ + target: z$1.ZodLiteral<"all">; + mergeBaseBranch: z$1.ZodPipe; +}, z$1.core.$strip>, z$1.ZodObject<{ + target: z$1.ZodLiteral<"commit">; + sha: z$1.ZodString; +}, z$1.core.$strip>], "target">; +type EnvironmentDiffQuery = z$1.infer; +/** + * Query for fetching a single file's contents at one side of a diff target. + * Used by the diff card to reparse the card's patch with full old/new contents + * so `@pierre/diffs` can render expand-context buttons between hunks. + * + * For `branch_committed` / `all`, callers pass the resolved merge-base SHA + * (`mergeBaseRef`, surfaced by `workspace.diff`) rather than the branch name + * — the diff itself was computed against that SHA, so reading the old side + * from the same SHA keeps the file content aligned with the hunk line + * numbers. Reading from the branch tip is wrong whenever the branch has + * moved past the merge-base since the file existed there. + */ +declare const environmentDiffFileQuerySchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + target: z$1.ZodLiteral<"uncommitted">; + path: z$1.ZodString; + side: z$1.ZodEnum<{ + new: "new"; + old: "old"; + }>; +}, z$1.core.$strip>, z$1.ZodObject<{ + target: z$1.ZodLiteral<"branch_committed">; + mergeBaseRef: z$1.ZodString; + path: z$1.ZodString; + side: z$1.ZodEnum<{ + new: "new"; + old: "old"; + }>; +}, z$1.core.$strip>, z$1.ZodObject<{ + target: z$1.ZodLiteral<"all">; + mergeBaseRef: z$1.ZodString; + path: z$1.ZodString; + side: z$1.ZodEnum<{ + new: "new"; + old: "old"; + }>; +}, z$1.core.$strip>, z$1.ZodObject<{ + target: z$1.ZodLiteral<"commit">; + sha: z$1.ZodString; + path: z$1.ZodString; + side: z$1.ZodEnum<{ + new: "new"; + old: "old"; + }>; +}, z$1.core.$strip>], "target">; +type EnvironmentDiffFileQuery = z$1.infer; +declare const environmentDiffFileResponseSchema: z$1.ZodObject<{ + path: z$1.ZodString; + content: z$1.ZodString; + contentEncoding: z$1.ZodEnum<{ + utf8: "utf8"; + base64: "base64"; + }>; + mimeType: z$1.ZodOptional; + sizeBytes: z$1.ZodNumber; +}, z$1.core.$strip>; +type EnvironmentDiffFileResponse = z$1.infer; +declare const environmentArchiveThreadsResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + archivedThreadIds: z$1.ZodArray; +}, z$1.core.$strip>; +type EnvironmentArchiveThreadsResponse = z$1.infer; +declare const pullRequestMergeMethodSchema: z$1.ZodEnum<{ + merge: "merge"; + rebase: "rebase"; + squash: "squash"; +}>; +type PullRequestMergeMethod = z$1.infer; +declare const commitActionResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + action: z$1.ZodLiteral<"commit">; + message: z$1.ZodString; + commitSha: z$1.ZodString; + commitSubject: z$1.ZodString; +}, z$1.core.$strip>; +type CommitActionResponse = z$1.infer; +declare const squashMergeActionResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + action: z$1.ZodLiteral<"squash_merge">; + merged: z$1.ZodBoolean; + message: z$1.ZodString; + commitSha: z$1.ZodString; + commitSubject: z$1.ZodString; +}, z$1.core.$strip>; +type SquashMergeActionResponse = z$1.infer; +declare const pullRequestReadyActionResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + action: z$1.ZodLiteral<"pull_request_ready">; + message: z$1.ZodString; +}, z$1.core.$strip>; +type PullRequestReadyActionResponse = z$1.infer; +declare const pullRequestMergeActionResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + action: z$1.ZodLiteral<"pull_request_merge">; + method: z$1.ZodEnum<{ + merge: "merge"; + rebase: "rebase"; + squash: "squash"; + }>; + message: z$1.ZodString; +}, z$1.core.$strip>; +type PullRequestMergeActionResponse = z$1.infer; +declare const pullRequestDraftActionResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + action: z$1.ZodLiteral<"pull_request_draft">; + message: z$1.ZodString; +}, z$1.core.$strip>; +type PullRequestDraftActionResponse = z$1.infer; +declare const environmentStatusResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + workspace: z$1.ZodObject<{ + workingTree: z$1.ZodObject<{ + insertions: z$1.ZodNumber; + deletions: z$1.ZodNumber; + files: z$1.ZodArray; + insertions: z$1.ZodNullable; + deletions: z$1.ZodNullable; + }, z$1.core.$strip>>; + hasUncommittedChanges: z$1.ZodBoolean; + state: z$1.ZodEnum<{ + clean: "clean"; + untracked: "untracked"; + dirty_uncommitted: "dirty_uncommitted"; + committed_unmerged: "committed_unmerged"; + dirty_and_committed_unmerged: "dirty_and_committed_unmerged"; + }>; + }, z$1.core.$strip>; + checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"branch">; + branchName: z$1.ZodString; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"detached">; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unborn">; + branchName: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unknown">; + reason: z$1.ZodString; + }, z$1.core.$strip>], "kind">; + branch: z$1.ZodObject<{ + currentBranch: z$1.ZodNullable; + defaultBranch: z$1.ZodString; + }, z$1.core.$strip>; + mergeBase: z$1.ZodNullable; + insertions: z$1.ZodNullable; + deletions: z$1.ZodNullable; + }, z$1.core.$strip>>; + mergeBaseBranch: z$1.ZodString; + baseRef: z$1.ZodNullable; + aheadCount: z$1.ZodNumber; + behindCount: z$1.ZodNumber; + hasCommittedUnmergedChanges: z$1.ZodBoolean; + commits: z$1.ZodArray>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"not_applicable">; + reason: z$1.ZodEnum<{ + non_git_environment: "non_git_environment"; + }>; + message: z$1.ZodString; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + unknown: "unknown"; + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; +}, z$1.core.$strict>], "outcome">; +/** + * Structured pull-request lookup outcome. "absent" is a real answer — the + * host checked and the branch has no PR (non-git environments resolve to + * "absent" without a daemon call). "unavailable" means the lookup itself + * failed (gh missing, not authenticated, timeout, unreachable workspace), so + * callers must not render it as "no PR exists". + */ +declare const environmentPullRequestResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + pullRequest: z$1.ZodObject<{ + number: z$1.ZodNumber; + title: z$1.ZodString; + state: z$1.ZodEnum<{ + merged: "merged"; + draft: "draft"; + open: "open"; + closed: "closed"; + }>; + url: z$1.ZodString; + baseRefName: z$1.ZodString; + headRefName: z$1.ZodString; + updatedAt: z$1.ZodString; + checks: z$1.ZodObject<{ + state: z$1.ZodEnum<{ + unknown: "unknown"; + pending: "pending"; + passing: "passing"; + failing: "failing"; + no_checks: "no_checks"; + }>; + totalCount: z$1.ZodNumber; + passedCount: z$1.ZodNumber; + failedCount: z$1.ZodNumber; + pendingCount: z$1.ZodNumber; + }, z$1.core.$strict>; + review: z$1.ZodObject<{ + state: z$1.ZodEnum<{ + none: "none"; + approved: "approved"; + changes_requested: "changes_requested"; + review_required: "review_required"; + review_requested: "review_requested"; + }>; + reviewRequestCount: z$1.ZodNumber; + }, z$1.core.$strict>; + mergeability: z$1.ZodObject<{ + state: z$1.ZodEnum<{ + unknown: "unknown"; + draft: "draft"; + mergeable: "mergeable"; + conflicts: "conflicts"; + blocked: "blocked"; + }>; + mergeStateStatus: z$1.ZodNullable>; + mergeable: z$1.ZodNullable>; + }, z$1.core.$strict>; + attention: z$1.ZodEnum<{ + none: "none"; + merged: "merged"; + draft: "draft"; + closed: "closed"; + changes_requested: "changes_requested"; + review_requested: "review_requested"; + conflicts: "conflicts"; + blocked: "blocked"; + checks_failed: "checks_failed"; + checks_pending: "checks_pending"; + ready_to_merge: "ready_to_merge"; + }>; + }, z$1.core.$strict>; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"absent">; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + message: z$1.ZodString; +}, z$1.core.$strict>], "outcome">; +type EnvironmentPullRequestResponse = z$1.infer; +declare const environmentDiffResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + diff: z$1.ZodObject<{ + diff: z$1.ZodString; + truncated: z$1.ZodBoolean; + shortstat: z$1.ZodString; + files: z$1.ZodString; + mergeBaseRef: z$1.ZodNullable; + }, z$1.core.$strip>; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"not_applicable">; + reason: z$1.ZodEnum<{ + non_git_environment: "non_git_environment"; + }>; + message: z$1.ZodString; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + unknown: "unknown"; + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; +}, z$1.core.$strict>], "outcome">; +type EnvironmentDiffResponse = z$1.infer; +declare const environmentDiffFilesResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + files: z$1.ZodArray; + changeKind: z$1.ZodEnum<{ + deleted: "deleted"; + added: "added"; + modified: "modified"; + renamed: "renamed"; + copied: "copied"; + type_changed: "type_changed"; + }>; + additions: z$1.ZodNumber; + deletions: z$1.ZodNumber; + binary: z$1.ZodBoolean; + origin: z$1.ZodEnum<{ + untracked: "untracked"; + tracked: "tracked"; + }>; + loadMode: z$1.ZodEnum<{ + auto: "auto"; + on_demand: "on_demand"; + too_large: "too_large"; + }>; + }, z$1.core.$strip>>; + shortstat: z$1.ZodString; + mergeBaseRef: z$1.ZodNullable; + initialPatches: z$1.ZodArray>; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"not_applicable">; + reason: z$1.ZodEnum<{ + non_git_environment: "non_git_environment"; + too_many_files: "too_many_files"; + }>; + message: z$1.ZodString; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + unknown: "unknown"; + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; +}, z$1.core.$strict>], "outcome">; +type EnvironmentDiffFilesResponse = z$1.infer; +declare const environmentDiffPatchResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + patches: z$1.ZodArray>; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"not_applicable">; + reason: z$1.ZodEnum<{ + non_git_environment: "non_git_environment"; + }>; + message: z$1.ZodString; +}, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + unknown: "unknown"; + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; +}, z$1.core.$strict>], "outcome">; +type EnvironmentDiffPatchResponse = z$1.infer; +/** + * Body for `POST /diff/patch`: the diff target plus the list of new paths whose + * patches the client wants. A POST (not GET) because the repeated `paths` array + * cannot survive flat query parsing. The client supplies only new paths; the + * server re-derives each file's rename/copy pairing (`previousPath`) from its + * own TOC. + */ +declare const environmentDiffPatchRequestSchema: z$1.ZodObject<{ + target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"uncommitted">; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"branch_committed">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"all">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"commit">; + sha: z$1.ZodString; + }, z$1.core.$strip>], "type">; + paths: z$1.ZodArray; +}, z$1.core.$strict>; +type EnvironmentDiffPatchRequest = z$1.infer; +type EnvironmentStatusResponse = z$1.infer; + +declare const providerUsageResponseSchema: z$1.ZodObject<{ + codex: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + status: z$1.ZodLiteral<"ok">; + accountEmail: z$1.ZodNullable; + planLabel: z$1.ZodNullable; + windows: z$1.ZodArray; + cost: z$1.ZodOptional>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"not_installed">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"unauthenticated">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"expired">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"error">; + message: z$1.ZodString; + }, z$1.core.$strip>], "status">; + claudeCode: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + status: z$1.ZodLiteral<"ok">; + accountEmail: z$1.ZodNullable; + planLabel: z$1.ZodNullable; + windows: z$1.ZodArray; + cost: z$1.ZodOptional>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"not_installed">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"unauthenticated">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"expired">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"error">; + message: z$1.ZodString; + }, z$1.core.$strip>], "status">; + cursor: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + status: z$1.ZodLiteral<"ok">; + accountEmail: z$1.ZodNullable; + planLabel: z$1.ZodNullable; + windows: z$1.ZodArray; + cost: z$1.ZodOptional>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"not_installed">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"unauthenticated">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"expired">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"error">; + message: z$1.ZodString; + }, z$1.core.$strip>], "status">; +}, z$1.core.$strip>; +type ProviderUsageResponse = z$1.infer; +type HostDaemonCommandTransport = "settled" | "onlineRpc"; +type HostDaemonCommandEnvironmentLane = "read" | "write"; +type HostDaemonFlushEventsBeforeResult = boolean | "when-initiated"; +interface HostDaemonCommandDescriptor { + type: Type; + schema: Schema; + resultSchema: ResultSchema; + transport: Transport; + retryable: Retryable; + flushEventsBeforeResult: HostDaemonFlushEventsBeforeResult; + envLane: HostDaemonCommandEnvironmentLane | null; +} +declare const hostDaemonCommandRegistry: { + "thread.start": HostDaemonCommandDescriptor<"thread.start", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + projectId: z$1.ZodString; + providerId: z$1.ZodString; + acpLaunchSpec: z$1.ZodOptional; + env: z$1.ZodRecord; + cwd: z$1.ZodOptional; + modelCli: z$1.ZodOptional; + selectFlag: z$1.ZodOptional; + primaryModels: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodTransform<{ + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + } | undefined, { + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + }>>>; + reasoningCli: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + nativeReasoning: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + permissionCli: z$1.ZodOptional>; + workspaceWrite: z$1.ZodOptional>; + readonly: z$1.ZodOptional>; + insertAfterArgs: z$1.ZodOptional; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + options: z$1.ZodIntersection; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + claudeCodePermissionMode: z$1.ZodOptional>; + claudeCodeMockCliTraffic: z$1.ZodOptional>; + workflowsEnabled: z$1.ZodBoolean; + memoryEnabled: z$1.ZodOptional; + providerSubagentsEnabled: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"accept-edits">; + permissionScope: z$1.ZodLiteral<"workspace">; + approvalReviewer: z$1.ZodLiteral<"user">; + permissionEscalation: z$1.ZodEnum<{ + ask: "ask"; + deny: "deny"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"auto">; + permissionScope: z$1.ZodLiteral<"workspace">; + approvalReviewer: z$1.ZodLiteral<"automatic">; + permissionEscalation: z$1.ZodEnum<{ + ask: "ask"; + deny: "deny"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"full">; + permissionScope: z$1.ZodLiteral<"full">; + approvalReviewer: z$1.ZodNull; + permissionEscalation: z$1.ZodNull; + }, z$1.core.$strip>], "permissionMode">>; + instructions: z$1.ZodString; + dynamicTools: z$1.ZodArray>; + injectedSkillSources: z$1.ZodArray; + treeHash: z$1.ZodString; + entryPath: z$1.ZodString; + sourceType: z$1.ZodEnum<{ + builtin: "builtin"; + "data-dir": "data-dir"; + }>; + }, z$1.core.$strict>, z$1.ZodObject<{ + name: z$1.ZodString; + description: z$1.ZodString; + kind: z$1.ZodLiteral<"workspace-path">; + sourceType: z$1.ZodLiteral<"project">; + sourceRootPath: z$1.ZodString; + skillFilePath: z$1.ZodString; + }, z$1.core.$strict>], "kind">>; + disallowedTools: z$1.ZodOptional>; + instructionMode: z$1.ZodEnum<{ + append: "append"; + replace: "replace"; + }>; + type: z$1.ZodLiteral<"thread.start">; + requestId: z$1.ZodString; + input: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + builtin: "builtin"; + project: "project"; + user: "user"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + inputGroups: z$1.ZodOptional>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + builtin: "builtin"; + project: "project"; + user: "user"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>>>; + threadStoragePath: z$1.ZodOptional; + fork: z$1.ZodOptional>; + }, z$1.core.$strict>, z$1.ZodObject<{ + providerThreadId: z$1.ZodString; + }, z$1.core.$strip>, "settled", false>; + "turn.submit": HostDaemonCommandDescriptor<"turn.submit", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + type: z$1.ZodLiteral<"turn.submit">; + requestId: z$1.ZodString; + input: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + builtin: "builtin"; + project: "project"; + user: "user"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + inputGroups: z$1.ZodOptional>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + builtin: "builtin"; + project: "project"; + user: "user"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>>>; + options: z$1.ZodIntersection; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + claudeCodePermissionMode: z$1.ZodOptional>; + claudeCodeMockCliTraffic: z$1.ZodOptional>; + workflowsEnabled: z$1.ZodBoolean; + memoryEnabled: z$1.ZodOptional; + providerSubagentsEnabled: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"accept-edits">; + permissionScope: z$1.ZodLiteral<"workspace">; + approvalReviewer: z$1.ZodLiteral<"user">; + permissionEscalation: z$1.ZodEnum<{ + ask: "ask"; + deny: "deny"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"auto">; + permissionScope: z$1.ZodLiteral<"workspace">; + approvalReviewer: z$1.ZodLiteral<"automatic">; + permissionEscalation: z$1.ZodEnum<{ + ask: "ask"; + deny: "deny"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"full">; + permissionScope: z$1.ZodLiteral<"full">; + approvalReviewer: z$1.ZodNull; + permissionEscalation: z$1.ZodNull; + }, z$1.core.$strip>], "permissionMode">>; + acpLaunchSpec: z$1.ZodOptional; + env: z$1.ZodRecord; + cwd: z$1.ZodOptional; + modelCli: z$1.ZodOptional; + selectFlag: z$1.ZodOptional; + primaryModels: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodTransform<{ + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + } | undefined, { + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + }>>>; + reasoningCli: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + nativeReasoning: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + permissionCli: z$1.ZodOptional>; + workspaceWrite: z$1.ZodOptional>; + readonly: z$1.ZodOptional>; + insertAfterArgs: z$1.ZodOptional; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + resumeContext: z$1.ZodObject<{ + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + instructionMode: z$1.ZodEnum<{ + append: "append"; + replace: "replace"; + }>; + projectId: z$1.ZodString; + providerId: z$1.ZodString; + acpLaunchSpec: z$1.ZodOptional; + env: z$1.ZodRecord; + cwd: z$1.ZodOptional; + modelCli: z$1.ZodOptional; + selectFlag: z$1.ZodOptional; + primaryModels: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodTransform<{ + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + } | undefined, { + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + }>>>; + reasoningCli: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + nativeReasoning: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + permissionCli: z$1.ZodOptional>; + workspaceWrite: z$1.ZodOptional>; + readonly: z$1.ZodOptional>; + insertAfterArgs: z$1.ZodOptional; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + instructions: z$1.ZodString; + dynamicTools: z$1.ZodArray>; + injectedSkillSources: z$1.ZodArray; + treeHash: z$1.ZodString; + entryPath: z$1.ZodString; + sourceType: z$1.ZodEnum<{ + builtin: "builtin"; + "data-dir": "data-dir"; + }>; + }, z$1.core.$strict>, z$1.ZodObject<{ + name: z$1.ZodString; + description: z$1.ZodString; + kind: z$1.ZodLiteral<"workspace-path">; + sourceType: z$1.ZodLiteral<"project">; + sourceRootPath: z$1.ZodString; + skillFilePath: z$1.ZodString; + }, z$1.core.$strict>], "kind">>; + disallowedTools: z$1.ZodOptional>; + providerThreadId: z$1.ZodString; + }, z$1.core.$strict>; + target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + mode: z$1.ZodLiteral<"start">; + }, z$1.core.$strip>, z$1.ZodObject<{ + mode: z$1.ZodLiteral<"auto">; + expectedTurnId: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + mode: z$1.ZodLiteral<"steer">; + expectedTurnId: z$1.ZodNullable; + }, z$1.core.$strip>], "mode">; + }, z$1.core.$strict>, z$1.ZodObject<{ + appliedAs: z$1.ZodEnum<{ + steer: "steer"; + "new-turn": "new-turn"; + }>; + }, z$1.core.$strip>, "settled", false>; + "thread.stop": HostDaemonCommandDescriptor<"thread.stop", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + type: z$1.ZodLiteral<"thread.stop">; + }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, "settled", false>; + "thread.goal.clear": HostDaemonCommandDescriptor<"thread.goal.clear", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + type: z$1.ZodLiteral<"thread.goal.clear">; + options: z$1.ZodIntersection; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + claudeCodePermissionMode: z$1.ZodOptional>; + claudeCodeMockCliTraffic: z$1.ZodOptional>; + workflowsEnabled: z$1.ZodBoolean; + memoryEnabled: z$1.ZodOptional; + providerSubagentsEnabled: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"accept-edits">; + permissionScope: z$1.ZodLiteral<"workspace">; + approvalReviewer: z$1.ZodLiteral<"user">; + permissionEscalation: z$1.ZodEnum<{ + ask: "ask"; + deny: "deny"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"auto">; + permissionScope: z$1.ZodLiteral<"workspace">; + approvalReviewer: z$1.ZodLiteral<"automatic">; + permissionEscalation: z$1.ZodEnum<{ + ask: "ask"; + deny: "deny"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + permissionMode: z$1.ZodLiteral<"full">; + permissionScope: z$1.ZodLiteral<"full">; + approvalReviewer: z$1.ZodNull; + permissionEscalation: z$1.ZodNull; + }, z$1.core.$strip>], "permissionMode">>; + acpLaunchSpec: z$1.ZodOptional; + env: z$1.ZodRecord; + cwd: z$1.ZodOptional; + modelCli: z$1.ZodOptional; + selectFlag: z$1.ZodOptional; + primaryModels: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodTransform<{ + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + } | undefined, { + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + }>>>; + reasoningCli: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + nativeReasoning: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + permissionCli: z$1.ZodOptional>; + workspaceWrite: z$1.ZodOptional>; + readonly: z$1.ZodOptional>; + insertAfterArgs: z$1.ZodOptional; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + resumeContext: z$1.ZodObject<{ + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + instructionMode: z$1.ZodEnum<{ + append: "append"; + replace: "replace"; + }>; + projectId: z$1.ZodString; + providerId: z$1.ZodString; + acpLaunchSpec: z$1.ZodOptional; + env: z$1.ZodRecord; + cwd: z$1.ZodOptional; + modelCli: z$1.ZodOptional; + selectFlag: z$1.ZodOptional; + primaryModels: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodTransform<{ + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + } | undefined, { + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + }>>>; + reasoningCli: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + nativeReasoning: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + permissionCli: z$1.ZodOptional>; + workspaceWrite: z$1.ZodOptional>; + readonly: z$1.ZodOptional>; + insertAfterArgs: z$1.ZodOptional; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + instructions: z$1.ZodString; + dynamicTools: z$1.ZodArray>; + injectedSkillSources: z$1.ZodArray; + treeHash: z$1.ZodString; + entryPath: z$1.ZodString; + sourceType: z$1.ZodEnum<{ + builtin: "builtin"; + "data-dir": "data-dir"; + }>; + }, z$1.core.$strict>, z$1.ZodObject<{ + name: z$1.ZodString; + description: z$1.ZodString; + kind: z$1.ZodLiteral<"workspace-path">; + sourceType: z$1.ZodLiteral<"project">; + sourceRootPath: z$1.ZodString; + skillFilePath: z$1.ZodString; + }, z$1.core.$strict>], "kind">>; + disallowedTools: z$1.ZodOptional>; + providerThreadId: z$1.ZodString; + }, z$1.core.$strict>; + }, z$1.core.$strict>, z$1.ZodObject<{ + cleared: z$1.ZodBoolean; + }, z$1.core.$strict>, "settled", false>; + "thread.plan.cancel": HostDaemonCommandDescriptor<"thread.plan.cancel", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + type: z$1.ZodLiteral<"thread.plan.cancel">; + expectedTurnId: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + cancelled: z$1.ZodBoolean; + }, z$1.core.$strict>, "settled", false>; + "thread.rename": HostDaemonCommandDescriptor<"thread.rename", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + type: z$1.ZodLiteral<"thread.rename">; + title: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, "settled", false>; + "thread.archive": HostDaemonCommandDescriptor<"thread.archive", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"thread.archive">; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, "settled", false>; + "thread.unarchive": HostDaemonCommandDescriptor<"thread.unarchive", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + type: z$1.ZodLiteral<"thread.unarchive">; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, "settled", false>; + "interactive.resolve": HostDaemonCommandDescriptor<"interactive.resolve", z$1.ZodObject<{ + environmentId: z$1.ZodString; + threadId: z$1.ZodString; + type: z$1.ZodLiteral<"interactive.resolve">; + interactionId: z$1.ZodString; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodString; + providerRequestId: z$1.ZodString; + resolution: z$1.ZodUnion; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"allow_for_session">; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"deny">; + }, z$1.core.$strip>], "decision">, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"user_answer">; + answers: z$1.ZodRecord; + freeText: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin_submitted">; + }, z$1.core.$strip>]>; + }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, "settled", false>; + "codex.inference.complete": HostDaemonCommandDescriptor<"codex.inference.complete", z$1.ZodObject<{ + type: z$1.ZodLiteral<"codex.inference.complete">; + model: z$1.ZodString; + prompt: z$1.ZodString; + outputSchema: z$1.ZodType>; + timeoutMs: z$1.ZodNumber; + }, z$1.core.$strict>, z$1.ZodObject<{ + model: z$1.ZodString; + value: z$1.ZodType>; + }, z$1.core.$strip>, "settled", false>; + "codex.voice.transcribe": HostDaemonCommandDescriptor<"codex.voice.transcribe", z$1.ZodObject<{ + type: z$1.ZodLiteral<"codex.voice.transcribe">; + model: z$1.ZodString; + audioBase64: z$1.ZodString; + mimeType: z$1.ZodString; + filename: z$1.ZodString; + prompt: z$1.ZodNullable; + timeoutMs: z$1.ZodNumber; + }, z$1.core.$strict>, z$1.ZodObject<{ + model: z$1.ZodString; + text: z$1.ZodString; + }, z$1.core.$strip>, "settled", false>; + "environment.provision": HostDaemonCommandDescriptor<"environment.provision", z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + environmentId: z$1.ZodString; + type: z$1.ZodLiteral<"environment.provision">; + initiator: z$1.ZodNullable>; + workspaceProvisionType: z$1.ZodLiteral<"unmanaged">; + path: z$1.ZodString; + checkout: z$1.ZodOptional; + name: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"new">; + name: z$1.ZodString; + baseBranch: z$1.ZodString; + }, z$1.core.$strict>], "kind">>; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodString; + type: z$1.ZodLiteral<"environment.provision">; + initiator: z$1.ZodNullable>; + sourcePath: z$1.ZodString; + targetPath: z$1.ZodString; + branchName: z$1.ZodString; + baseBranch: z$1.ZodNullable; + setupTimeoutMs: z$1.ZodNumber; + workspaceProvisionType: z$1.ZodLiteral<"managed-worktree">; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodString; + type: z$1.ZodLiteral<"environment.provision">; + initiator: z$1.ZodNullable>; + workspaceProvisionType: z$1.ZodLiteral<"personal">; + targetPath: z$1.ZodString; + }, z$1.core.$strict>], "workspaceProvisionType">, z$1.ZodObject<{ + path: z$1.ZodString; + isGitRepo: z$1.ZodBoolean; + isWorktree: z$1.ZodBoolean; + branchName: z$1.ZodNullable; + defaultBranch: z$1.ZodNullable; + transcript: z$1.ZodArray; + key: z$1.ZodString; + text: z$1.ZodString; + startedAt: z$1.ZodOptional; + status: z$1.ZodOptional>; + metadata: z$1.ZodOptional>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, "settled", false>; + "project.clone": HostDaemonCommandDescriptor<"project.clone", z$1.ZodObject<{ + type: z$1.ZodLiteral<"project.clone">; + remoteUrl: z$1.ZodString; + projectSlug: z$1.ZodString; + targetPath: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + path: z$1.ZodString; + gitRemoteUrl: z$1.ZodNullable; + }, z$1.core.$strict>, "settled", false>; + "environment.provision.cancel": HostDaemonCommandDescriptor<"environment.provision.cancel", z$1.ZodObject<{ + environmentId: z$1.ZodString; + type: z$1.ZodLiteral<"environment.provision.cancel">; + }, z$1.core.$strict>, z$1.ZodObject<{ + aborted: z$1.ZodBoolean; + }, z$1.core.$strip>, "settled", false>; + "environment.destroy": HostDaemonCommandDescriptor<"environment.destroy", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"environment.destroy">; + }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, "settled", false>; + "workspace.commit": HostDaemonCommandDescriptor<"workspace.commit", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.commit">; + message: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + commitSha: z$1.ZodString; + commitSubject: z$1.ZodString; + }, z$1.core.$strip>, "settled", false>; + "workspace.squash_merge": HostDaemonCommandDescriptor<"workspace.squash_merge", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.squash_merge">; + targetBranch: z$1.ZodString; + commitMessage: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + commitSha: z$1.ZodString; + commitSubject: z$1.ZodString; + merged: z$1.ZodBoolean; + }, z$1.core.$strip>, "settled", false>; + "workspace.pull_request_action": HostDaemonCommandDescriptor<"workspace.pull_request_action", z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.pull_request_action">; + operation: z$1.ZodLiteral<"ready">; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.pull_request_action">; + operation: z$1.ZodLiteral<"draft">; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.pull_request_action">; + operation: z$1.ZodLiteral<"merge">; + method: z$1.ZodEnum<{ + merge: "merge"; + squash: "squash"; + rebase: "rebase"; + }>; + }, z$1.core.$strict>], "operation">, z$1.ZodObject<{}, z$1.core.$strict>, "settled", false>; + "host.list_files": HostDaemonCommandDescriptor<"host.list_files", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.list_files">; + path: z$1.ZodString; + query: z$1.ZodOptional; + limit: z$1.ZodNumber; + }, z$1.core.$strip>, z$1.ZodObject<{ + files: z$1.ZodArray>; + truncated: z$1.ZodBoolean; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.list_paths": HostDaemonCommandDescriptor<"host.list_paths", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.list_paths">; + path: z$1.ZodString; + query: z$1.ZodOptional; + limit: z$1.ZodNumber; + includeFiles: z$1.ZodBoolean; + includeDirectories: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + paths: z$1.ZodArray; + path: z$1.ZodString; + name: z$1.ZodString; + score: z$1.ZodNumber; + positions: z$1.ZodArray; + }, z$1.core.$strip>>; + truncated: z$1.ZodBoolean; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.mkdir": HostDaemonCommandDescriptor<"host.mkdir", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.mkdir">; + path: z$1.ZodString; + rootPath: z$1.ZodOptional; + recursive: z$1.ZodBoolean; + }, z$1.core.$strict>, z$1.ZodObject<{ + ok: z$1.ZodLiteral; + }, z$1.core.$strict>, "onlineRpc", false>; + "host.move_path": HostDaemonCommandDescriptor<"host.move_path", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.move_path">; + sourcePath: z$1.ZodString; + destinationPath: z$1.ZodString; + rootPath: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + ok: z$1.ZodLiteral; + }, z$1.core.$strict>, "onlineRpc", false>; + "host.remove_path": HostDaemonCommandDescriptor<"host.remove_path", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.remove_path">; + path: z$1.ZodString; + rootPath: z$1.ZodOptional; + recursive: z$1.ZodBoolean; + }, z$1.core.$strict>, z$1.ZodObject<{ + ok: z$1.ZodLiteral; + }, z$1.core.$strict>, "onlineRpc", false>; + "host.browse_directory": HostDaemonCommandDescriptor<"host.browse_directory", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.browse_directory">; + path: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + directory: z$1.ZodString; + parent: z$1.ZodNullable; + entries: z$1.ZodArray; + name: z$1.ZodString; + path: z$1.ZodString; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.paths_exist": HostDaemonCommandDescriptor<"host.paths_exist", z$1.ZodObject<{ + paths: z$1.ZodPipe, z$1.ZodTransform>; + type: z$1.ZodLiteral<"host.paths_exist">; + }, z$1.core.$strict>, z$1.ZodObject<{ + existence: z$1.ZodRecord; + }, z$1.core.$strip>, "onlineRpc", true>; + "project.inspect": HostDaemonCommandDescriptor<"project.inspect", z$1.ZodObject<{ + type: z$1.ZodLiteral<"project.inspect">; + path: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + path: z$1.ZodString; + gitRemoteUrl: z$1.ZodNullable; + }, z$1.core.$strict>, "onlineRpc", true>; + "project.clone_default_path": HostDaemonCommandDescriptor<"project.clone_default_path", z$1.ZodObject<{ + type: z$1.ZodLiteral<"project.clone_default_path">; + projectSlug: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + path: z$1.ZodString; + }, z$1.core.$strict>, "onlineRpc", true>; + "host.pick_folder": HostDaemonCommandDescriptor<"host.pick_folder", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.pick_folder">; + }, z$1.core.$strict>, z$1.ZodObject<{ + path: z$1.ZodNullable; + }, z$1.core.$strip>, "onlineRpc", false>; + "host.caffeinate": HostDaemonCommandDescriptor<"host.caffeinate", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.caffeinate">; + enabled: z$1.ZodBoolean; + }, z$1.core.$strict>, z$1.ZodObject<{ + enabled: z$1.ZodBoolean; + supported: z$1.ZodBoolean; + }, z$1.core.$strict>, "onlineRpc", false>; + "connect-tunnel.ensure-identity": HostDaemonCommandDescriptor<"connect-tunnel.ensure-identity", z$1.ZodObject<{ + type: z$1.ZodLiteral<"connect-tunnel.ensure-identity">; + }, z$1.core.$strict>, z$1.ZodObject<{ + label: z$1.ZodString; + baseDomain: z$1.ZodString; + }, z$1.core.$strict>, "onlineRpc", true>; + "host.list_commands": HostDaemonCommandDescriptor<"host.list_commands", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.list_commands">; + providerId: z$1.ZodString; + cwd: z$1.ZodNullable; + }, z$1.core.$strict>, z$1.ZodObject<{ + commands: z$1.ZodArray; + origin: z$1.ZodEnum<{ + project: "project"; + user: "user"; + }>; + description: z$1.ZodNullable; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.list_branches": HostDaemonCommandDescriptor<"host.list_branches", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.list_branches">; + path: z$1.ZodString; + query: z$1.ZodOptional; + selectedBranch: z$1.ZodOptional; + limit: z$1.ZodNumber; + }, z$1.core.$strip>, z$1.ZodObject<{ + branches: z$1.ZodArray; + branchesTruncated: z$1.ZodBoolean; + checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"branch">; + branchName: z$1.ZodString; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"detached">; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unborn">; + branchName: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unknown">; + reason: z$1.ZodString; + }, z$1.core.$strip>], "kind">; + defaultBranch: z$1.ZodNullable; + defaultBranchRelation: z$1.ZodNullable>; + hasUncommittedChanges: z$1.ZodBoolean; + operation: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"none">; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"merge">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"rebase">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"cherry-pick">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"revert">; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unknown">; + reason: z$1.ZodString; + hasConflicts: z$1.ZodBoolean; + }, z$1.core.$strip>], "kind">; + originDefaultBranch: z$1.ZodNullable; + remoteBranches: z$1.ZodArray; + remoteBranchesTruncated: z$1.ZodBoolean; + selectedBranch: z$1.ZodNullable; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.file_metadata": HostDaemonCommandDescriptor<"host.file_metadata", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.file_metadata">; + path: z$1.ZodString; + rootPath: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + path: z$1.ZodString; + modifiedAtMs: z$1.ZodNumber; + sizeBytes: z$1.ZodNumber; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.read_file": HostDaemonCommandDescriptor<"host.read_file", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.read_file">; + path: z$1.ZodString; + rootPath: z$1.ZodOptional; + ref: z$1.ZodOptional; + }, z$1.core.$strip>, z$1.ZodObject<{ + path: z$1.ZodString; + content: z$1.ZodString; + contentEncoding: z$1.ZodEnum<{ + base64: "base64"; + utf8: "utf8"; + }>; + mimeType: z$1.ZodOptional; + sizeBytes: z$1.ZodNumber; + modifiedAtMs: z$1.ZodOptional; + sha256: z$1.ZodString; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.read_file_relative": HostDaemonCommandDescriptor<"host.read_file_relative", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.read_file_relative">; + rootPath: z$1.ZodString; + path: z$1.ZodString; + dotfiles: z$1.ZodEnum<{ + deny: "deny"; + allow: "allow"; + }>; + }, z$1.core.$strict>, z$1.ZodObject<{ + path: z$1.ZodString; + content: z$1.ZodString; + contentEncoding: z$1.ZodEnum<{ + base64: "base64"; + utf8: "utf8"; + }>; + mimeType: z$1.ZodOptional; + sizeBytes: z$1.ZodNumber; + modifiedAtMs: z$1.ZodOptional; + sha256: z$1.ZodString; + }, z$1.core.$strip>, "onlineRpc", true>; + "host.write_file": HostDaemonCommandDescriptor<"host.write_file", z$1.ZodObject<{ + type: z$1.ZodLiteral<"host.write_file">; + path: z$1.ZodString; + rootPath: z$1.ZodOptional; + content: z$1.ZodString; + contentEncoding: z$1.ZodEnum<{ + base64: "base64"; + utf8: "utf8"; + }>; + createParents: z$1.ZodBoolean; + expectedSha256: z$1.ZodOptional>; + mode: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"written">; + sha256: z$1.ZodString; + sizeBytes: z$1.ZodNumber; + }, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"conflict">; + currentSha256: z$1.ZodNullable; + }, z$1.core.$strict>], "outcome">, "onlineRpc", false>; + "provider.list_models": HostDaemonCommandDescriptor<"provider.list_models", z$1.ZodObject<{ + type: z$1.ZodLiteral<"provider.list_models">; + providerId: z$1.ZodString; + acpLaunchSpec: z$1.ZodOptional; + env: z$1.ZodRecord; + cwd: z$1.ZodOptional; + modelCli: z$1.ZodOptional; + selectFlag: z$1.ZodOptional; + primaryModels: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodTransform<{ + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + } | undefined, { + listArgs: string[]; + primaryModels: string[]; + selectFlag?: string | undefined; + }>>>; + reasoningCli: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + nativeReasoning: z$1.ZodOptional>; + levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>; + defaultLevel: z$1.ZodOptional>; + }, z$1.core.$strict>>; + permissionCli: z$1.ZodOptional>; + workspaceWrite: z$1.ZodOptional>; + readonly: z$1.ZodOptional>; + insertAfterArgs: z$1.ZodOptional; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + models: z$1.ZodArray; + description: z$1.ZodString; + }, z$1.core.$strip>>; + defaultReasoningEffort: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + isDefault: z$1.ZodBoolean; + }, z$1.core.$strip>>; + selectedOnlyModels: z$1.ZodArray; + description: z$1.ZodString; + }, z$1.core.$strip>>; + defaultReasoningEffort: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + isDefault: z$1.ZodBoolean; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, "onlineRpc", true>; + "known_acp_agents.status": HostDaemonCommandDescriptor<"known_acp_agents.status", z$1.ZodObject<{ + type: z$1.ZodLiteral<"known_acp_agents.status">; + agents: z$1.ZodArray>; + }, z$1.core.$strict>, z$1.ZodObject<{ + agents: z$1.ZodArray; + }, z$1.core.$strict>>; + }, z$1.core.$strict>, "onlineRpc", true>; + "provider.usage": HostDaemonCommandDescriptor<"provider.usage", z$1.ZodObject<{ + type: z$1.ZodLiteral<"provider.usage">; + }, z$1.core.$strict>, z$1.ZodObject<{ + codex: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + status: z$1.ZodLiteral<"ok">; + accountEmail: z$1.ZodNullable; + planLabel: z$1.ZodNullable; + windows: z$1.ZodArray; + cost: z$1.ZodOptional>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"not_installed">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"unauthenticated">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"expired">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"error">; + message: z$1.ZodString; + }, z$1.core.$strip>], "status">; + claudeCode: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + status: z$1.ZodLiteral<"ok">; + accountEmail: z$1.ZodNullable; + planLabel: z$1.ZodNullable; + windows: z$1.ZodArray; + cost: z$1.ZodOptional>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"not_installed">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"unauthenticated">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"expired">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"error">; + message: z$1.ZodString; + }, z$1.core.$strip>], "status">; + cursor: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + status: z$1.ZodLiteral<"ok">; + accountEmail: z$1.ZodNullable; + planLabel: z$1.ZodNullable; + windows: z$1.ZodArray; + cost: z$1.ZodOptional>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"not_installed">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"unauthenticated">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"expired">; + }, z$1.core.$strip>, z$1.ZodObject<{ + status: z$1.ZodLiteral<"error">; + message: z$1.ZodString; + }, z$1.core.$strip>], "status">; + }, z$1.core.$strip>, "onlineRpc", true>; + "provider_cli.status": HostDaemonCommandDescriptor<"provider_cli.status", z$1.ZodObject<{ + type: z$1.ZodLiteral<"provider_cli.status">; + }, z$1.core.$strict>, z$1.ZodRecord, z$1.ZodObject<{ + displayName: z$1.ZodString; + executableName: z$1.ZodString; + executablePath: z$1.ZodNullable; + installed: z$1.ZodBoolean; + installSource: z$1.ZodEnum<{ + external: "external"; + notInstalled: "notInstalled"; + npmGlobal: "npmGlobal"; + }>; + currentVersion: z$1.ZodNullable; + latestVersion: z$1.ZodNullable; + minimumSupportedVersion: z$1.ZodNullable; + npmPackageName: z$1.ZodNullable; + npmGlobalPackageVersion: z$1.ZodNullable; + installAction: z$1.ZodNullable; + label: z$1.ZodEnum<{ + Install: "Install"; + Update: "Update"; + }>; + commandKind: z$1.ZodEnum<{ + exec: "exec"; + shell: "shell"; + }>; + command: z$1.ZodString; + }, z$1.core.$strip>>; + needsUpdate: z$1.ZodBoolean; + versionUnsupported: z$1.ZodBoolean; + }, z$1.core.$strip>>, "onlineRpc", true>; + "provider_cli.install": HostDaemonCommandDescriptor<"provider_cli.install", z$1.ZodObject<{ + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + actionKind: z$1.ZodEnum<{ + install: "install"; + update: "update"; + }>; + type: z$1.ZodLiteral<"provider_cli.install">; + }, z$1.core.$strict>, z$1.ZodObject<{ + events: z$1.ZodArray; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + command: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"output">; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + stream: z$1.ZodEnum<{ + stdout: "stdout"; + stderr: "stderr"; + }>; + text: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"completed">; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + exitCode: z$1.ZodNullable; + signal: z$1.ZodNullable; + success: z$1.ZodBoolean; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"error">; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + message: z$1.ZodString; + }, z$1.core.$strip>], "type">>; + }, z$1.core.$strict>, "onlineRpc", false>; + "workspace.status": HostDaemonCommandDescriptor<"workspace.status", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.status">; + mergeBaseBranch: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + workspaceStatus: z$1.ZodObject<{ + workingTree: z$1.ZodObject<{ + insertions: z$1.ZodNumber; + deletions: z$1.ZodNumber; + files: z$1.ZodArray; + insertions: z$1.ZodNullable; + deletions: z$1.ZodNullable; + }, z$1.core.$strip>>; + hasUncommittedChanges: z$1.ZodBoolean; + state: z$1.ZodEnum<{ + clean: "clean"; + untracked: "untracked"; + dirty_uncommitted: "dirty_uncommitted"; + committed_unmerged: "committed_unmerged"; + dirty_and_committed_unmerged: "dirty_and_committed_unmerged"; + }>; + }, z$1.core.$strip>; + checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"branch">; + branchName: z$1.ZodString; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"detached">; + headSha: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unborn">; + branchName: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"unknown">; + reason: z$1.ZodString; + }, z$1.core.$strip>], "kind">; + branch: z$1.ZodObject<{ + currentBranch: z$1.ZodNullable; + defaultBranch: z$1.ZodString; + }, z$1.core.$strip>; + mergeBase: z$1.ZodNullable; + insertions: z$1.ZodNullable; + deletions: z$1.ZodNullable; + }, z$1.core.$strip>>; + mergeBaseBranch: z$1.ZodString; + baseRef: z$1.ZodNullable; + aheadCount: z$1.ZodNumber; + behindCount: z$1.ZodNumber; + hasCommittedUnmergedChanges: z$1.ZodBoolean; + commits: z$1.ZodArray>; + }, z$1.core.$strip>>; + }, z$1.core.$strip>; + }, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + unknown: "unknown"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; + }, z$1.core.$strict>], "outcome">, "onlineRpc", true>; + "workspace.diff": HostDaemonCommandDescriptor<"workspace.diff", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.diff">; + target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"uncommitted">; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"branch_committed">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"all">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"commit">; + sha: z$1.ZodString; + }, z$1.core.$strip>], "type">; + maxDiffBytes: z$1.ZodNumber; + maxFileListBytes: z$1.ZodNumber; + }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + diff: z$1.ZodObject<{ + diff: z$1.ZodString; + truncated: z$1.ZodBoolean; + shortstat: z$1.ZodString; + files: z$1.ZodString; + mergeBaseRef: z$1.ZodNullable; + }, z$1.core.$strip>; + }, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + unknown: "unknown"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; + }, z$1.core.$strict>], "outcome">, "onlineRpc", true>; + "workspace.diffFiles": HostDaemonCommandDescriptor<"workspace.diffFiles", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.diffFiles">; + target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"uncommitted">; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"branch_committed">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"all">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"commit">; + sha: z$1.ZodString; + }, z$1.core.$strip>], "type">; + }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + files: z$1.ZodArray; + statusLetter: z$1.ZodEnum<{ + M: "M"; + A: "A"; + D: "D"; + R: "R"; + C: "C"; + T: "T"; + }>; + additions: z$1.ZodNumber; + deletions: z$1.ZodNumber; + binary: z$1.ZodBoolean; + origin: z$1.ZodEnum<{ + untracked: "untracked"; + tracked: "tracked"; + }>; + }, z$1.core.$strip>>; + shortstat: z$1.ZodString; + mergeBaseRef: z$1.ZodNullable; + }, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + unknown: "unknown"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; + }, z$1.core.$strict>], "outcome">, "onlineRpc", true>; + "workspace.diffPatch": HostDaemonCommandDescriptor<"workspace.diffPatch", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.diffPatch">; + target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"uncommitted">; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"branch_committed">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"all">; + mergeBaseBranch: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"commit">; + sha: z$1.ZodString; + }, z$1.core.$strip>], "type">; + paths: z$1.ZodArray; + maxBytesPerFile: z$1.ZodNumber; + }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + patches: z$1.ZodArray>; + }, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + failure: z$1.ZodObject<{ + code: z$1.ZodEnum<{ + path_not_found: "path_not_found"; + not_git_repo: "not_git_repo"; + not_worktree: "not_worktree"; + workspace_type_mismatch: "workspace_type_mismatch"; + permission_denied: "permission_denied"; + unknown_environment: "unknown_environment"; + unknown: "unknown"; + }>; + workspacePath: z$1.ZodString; + message: z$1.ZodString; + }, z$1.core.$strict>; + }, z$1.core.$strict>], "outcome">, "onlineRpc", true>; + "workspace.pull_request": HostDaemonCommandDescriptor<"workspace.pull_request", z$1.ZodObject<{ + environmentId: z$1.ZodString; + workspaceContext: z$1.ZodObject<{ + workspacePath: z$1.ZodString; + workspaceProvisionType: z$1.ZodEnum<{ + unmanaged: "unmanaged"; + "managed-worktree": "managed-worktree"; + personal: "personal"; + }>; + }, z$1.core.$strip>; + type: z$1.ZodLiteral<"workspace.pull_request">; + }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"available">; + pullRequest: z$1.ZodObject<{ + number: z$1.ZodNumber; + title: z$1.ZodString; + state: z$1.ZodEnum<{ + OPEN: "OPEN"; + CLOSED: "CLOSED"; + MERGED: "MERGED"; + }>; + url: z$1.ZodString; + isDraft: z$1.ZodBoolean; + baseRefName: z$1.ZodString; + headRefName: z$1.ZodString; + updatedAt: z$1.ZodString; + checks: z$1.ZodArray; + conclusion: z$1.ZodNullable>; + url: z$1.ZodNullable; + }, z$1.core.$strict>>; + reviewDecision: z$1.ZodNullable>; + reviewRequestCount: z$1.ZodNumber; + mergeStateStatus: z$1.ZodNullable>; + mergeable: z$1.ZodNullable>; + }, z$1.core.$strict>; + }, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"absent">; + }, z$1.core.$strict>, z$1.ZodObject<{ + outcome: z$1.ZodLiteral<"unavailable">; + message: z$1.ZodString; + }, z$1.core.$strict>], "outcome">, "onlineRpc", true>; +}; +type HostDaemonCommandRegistry = typeof hostDaemonCommandRegistry; +type AnyHostDaemonCommandDescriptor = HostDaemonCommandRegistry[keyof HostDaemonCommandRegistry]; +type HostDaemonCommandDescriptorForTransport = Extract; +type HostDaemonResultSchemaMapForTransport = { + [Descriptor in HostDaemonCommandDescriptorForTransport as Descriptor["type"]]: Descriptor["resultSchema"]; +}; +type HostDaemonOnlineRpcResultSchemaMap = HostDaemonResultSchemaMapForTransport<"onlineRpc">; +type HostDaemonOnlineRpcResultByType = { + [K in keyof HostDaemonOnlineRpcResultSchemaMap]: z$1.infer; +}; + +declare const pickFolderResponseSchema: z$1.ZodObject<{ + path: z$1.ZodNullable; +}, z$1.core.$strip>; +type PickFolderResponse = z$1.infer; +declare const pathsExistRequestSchema: z$1.ZodObject<{ + paths: z$1.ZodPipe, z$1.ZodTransform>; +}, z$1.core.$strip>; +type PathsExistRequest = z$1.infer; +declare const pathsExistResponseSchema: z$1.ZodObject<{ + existence: z$1.ZodRecord; +}, z$1.core.$strip>; +type PathsExistResponse = z$1.infer; +declare const providerCliStatusResponseSchema: z$1.ZodRecord, z$1.ZodObject<{ + displayName: z$1.ZodString; + executableName: z$1.ZodString; + executablePath: z$1.ZodNullable; + installed: z$1.ZodBoolean; + installSource: z$1.ZodEnum<{ + external: "external"; + notInstalled: "notInstalled"; + npmGlobal: "npmGlobal"; + }>; + currentVersion: z$1.ZodNullable; + latestVersion: z$1.ZodNullable; + minimumSupportedVersion: z$1.ZodNullable; + npmPackageName: z$1.ZodNullable; + npmGlobalPackageVersion: z$1.ZodNullable; + installAction: z$1.ZodNullable; + label: z$1.ZodEnum<{ + Install: "Install"; + Update: "Update"; + }>; + commandKind: z$1.ZodEnum<{ + exec: "exec"; + shell: "shell"; + }>; + command: z$1.ZodString; + }, z$1.core.$strip>>; + needsUpdate: z$1.ZodBoolean; + versionUnsupported: z$1.ZodBoolean; +}, z$1.core.$strip>>; +type ProviderCliStatusResponse = z$1.infer; +declare const providerCliInstallRequestSchema: z$1.ZodObject<{ + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + actionKind: z$1.ZodEnum<{ + install: "install"; + update: "update"; + }>; +}, z$1.core.$strip>; +type ProviderCliInstallRequest = z$1.infer; +declare const providerCliInstallEventSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"started">; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + command: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"output">; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + stream: z$1.ZodEnum<{ + stdout: "stdout"; + stderr: "stderr"; + }>; + text: z$1.ZodString; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"completed">; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + exitCode: z$1.ZodNullable; + signal: z$1.ZodNullable; + success: z$1.ZodBoolean; +}, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"error">; + provider: z$1.ZodEnum<{ + codex: "codex"; + claudeCode: "claudeCode"; + cursor: "cursor"; + }>; + message: z$1.ZodString; +}, z$1.core.$strip>], "type">; +type ProviderCliInstallEvent = z$1.infer; + +interface CreateFilePreviewResponse { + baseUrl: string; + expiresAtMs: number; +} +type HostFileReadResponse = HostDaemonOnlineRpcResultByType["host.read_file"]; +type HostFileWriteResponse = HostDaemonOnlineRpcResultByType["host.write_file"]; +type HostFileListResponse = HostDaemonOnlineRpcResultByType["host.list_files"]; +type HostPathListResponse = HostDaemonOnlineRpcResultByType["host.list_paths"]; +type HostMkdirResponse = HostDaemonOnlineRpcResultByType["host.mkdir"]; +type HostMovePathResponse = HostDaemonOnlineRpcResultByType["host.move_path"]; +type HostRemovePathResponse = HostDaemonOnlineRpcResultByType["host.remove_path"]; + +/** + * Query for `GET /hosts/:id/directory`, the interactive path browser's + * single-level directory read. `path` is an absolute directory on the host; + * omitting it lists the host's home directory (the daemon resolves it, since a + * remote caller cannot know the host's home). + */ +declare const hostDirectoryQuerySchema: z$1.ZodObject<{ + path: z$1.ZodOptional; +}, z$1.core.$strip>; +type HostDirectoryQuery = z$1.infer; +declare const hostDirectoryListingSchema: z$1.ZodObject<{ + directory: z$1.ZodString; + parent: z$1.ZodNullable; + entries: z$1.ZodArray; + name: z$1.ZodString; + path: z$1.ZodString; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type HostDirectoryListing = z$1.infer; +/** Project name is sent so the daemon can derive its host-local checkout path. */ +declare const hostCloneDefaultPathQuerySchema: z$1.ZodObject<{ + projectId: z$1.ZodString; +}, z$1.core.$strip>; +type HostCloneDefaultPathQuery = z$1.infer; +declare const hostCloneDefaultPathResponseSchema: z$1.ZodObject<{ + path: z$1.ZodString; +}, z$1.core.$strict>; +type HostCloneDefaultPathResponse = z$1.infer; +declare const createHostJoinCodeResponseSchema: z$1.ZodObject<{ + joinCode: z$1.ZodString; + hostId: z$1.ZodString; + expiresAt: z$1.ZodNumber; +}, z$1.core.$strip>; +type CreateHostJoinCodeResponse = z$1.infer; +declare const updateHostRequestSchema: z$1.ZodObject<{ + name: z$1.ZodString; +}, z$1.core.$strict>; +type UpdateHostRequest = z$1.infer; +declare const hostRetryUpdateResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; +}, z$1.core.$strict>; +type HostRetryUpdateResponse = z$1.infer; +type HostPathsExistRequest = PathsExistRequest; +type HostPathsExistResponse = PathsExistResponse; +declare const hostPickFolderRequestSchema: z$1.ZodObject<{ + clientHostId: z$1.ZodString; +}, z$1.core.$strict>; +type HostPickFolderRequest = z$1.infer; +type HostPickFolderResponse = PickFolderResponse; +type HostProviderCliStatusResponse = ProviderCliStatusResponse; +type HostProviderCliInstallRequest = ProviderCliInstallRequest; +type HostProviderCliInstallEvent = ProviderCliInstallEvent; + +declare const pluginUpdateCheckEntrySchema: z$1.ZodObject<{ + id: z$1.ZodString; + outcome: z$1.ZodEnum<{ + unavailable: "unavailable"; + incompatible: "incompatible"; + current: "current"; + "update-available": "update-available"; + pinned: "pinned"; + }>; + devMode: z$1.ZodOptional>; + installed: z$1.ZodObject<{ + version: z$1.ZodString; + display: z$1.ZodString; + }, z$1.core.$strip>; + candidate: z$1.ZodOptional>; + blocked: z$1.ZodOptional; + }, z$1.core.$strip>>; + detail: z$1.ZodOptional; +}, z$1.core.$strip>; +type PluginUpdateCheckEntry = z$1.infer; +declare const pluginApplyUpdateResultSchema: z$1.ZodObject<{ + applied: z$1.ZodBoolean; + from: z$1.ZodObject<{ + version: z$1.ZodString; + display: z$1.ZodString; + }, z$1.core.$strip>; + to: z$1.ZodOptional>; + outcome: z$1.ZodEnum<{ + current: "current"; + updated: "updated"; + "rolled-back": "rolled-back"; + }>; + detail: z$1.ZodOptional; +}, z$1.core.$strip>; +type PluginApplyUpdateResult$1 = z$1.infer; +declare const pluginSourceDetailSchema: z$1.ZodObject<{ + requested: z$1.ZodString; + resolved: z$1.ZodString; + integrity: z$1.ZodOptional; + registry: z$1.ZodOptional; + engines: z$1.ZodObject<{ + bb: z$1.ZodOptional; + bbPluginSdk: z$1.ZodOptional; + }, z$1.core.$strip>; + installedAt: z$1.ZodOptional; + history: z$1.ZodArray>; +}, z$1.core.$strip>; +type PluginSourceDetail = z$1.infer; +declare const installedPluginSchema: z$1.ZodObject<{ + id: z$1.ZodString; + source: z$1.ZodString; + rootDir: z$1.ZodString; + version: z$1.ZodString; + provenance: z$1.ZodEnum<{ + builtin: "builtin"; + direct: "direct"; + catalog: "catalog"; + }>; + isOrphanedBuiltin: z$1.ZodBoolean; + catalogEntryId: z$1.ZodOptional; + sourceDisplay: z$1.ZodString; + updateState: z$1.ZodObject<{ + outcome: z$1.ZodOptional>; + availableVersion: z$1.ZodOptional; + blockedVersion: z$1.ZodOptional; + blockedReasons: z$1.ZodOptional>; + lastCheckAt: z$1.ZodOptional; + lastFailure: z$1.ZodOptional>; + }, z$1.core.$strip>; + enabled: z$1.ZodBoolean; + description: z$1.ZodNullable; + name: z$1.ZodNullable; + icon: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + running: "running"; + missing: "missing"; + incompatible: "incompatible"; + disabled: "disabled"; + degraded: "degraded"; + "needs-configuration": "needs-configuration"; + }>; + statusDetail: z$1.ZodNullable; + handlerStats: z$1.ZodObject<{ + count: z$1.ZodNumber; + totalMs: z$1.ZodNumber; + maxMs: z$1.ZodNumber; + errorCount: z$1.ZodNumber; + }, z$1.core.$strip>; + services: z$1.ZodArray; + }, z$1.core.$strip>>; + schedules: z$1.ZodArray; + lastStatus: z$1.ZodNullable>; + lastError: z$1.ZodNullable; + }, z$1.core.$strip>>; + cliCommand: z$1.ZodNullable>; + hasSettings: z$1.ZodBoolean; + app: z$1.ZodObject<{ + hasApp: z$1.ZodBoolean; + bundle: z$1.ZodNullable; + hash: z$1.ZodString; + sdkMajor: z$1.ZodNumber; + sdkVersion: z$1.ZodString; + compatible: z$1.ZodBoolean; + }, z$1.core.$strip>>; + }, z$1.core.$strip>; + logoUrl: z$1.ZodNullable; + logoDarkUrl: z$1.ZodNullable; +}, z$1.core.$strip>; +type InstalledPlugin = z$1.infer; +declare const pluginListResponseSchema: z$1.ZodObject<{ + enabled: z$1.ZodBoolean; + plugins: z$1.ZodArray; + isOrphanedBuiltin: z$1.ZodBoolean; + catalogEntryId: z$1.ZodOptional; + sourceDisplay: z$1.ZodString; + updateState: z$1.ZodObject<{ + outcome: z$1.ZodOptional>; + availableVersion: z$1.ZodOptional; + blockedVersion: z$1.ZodOptional; + blockedReasons: z$1.ZodOptional>; + lastCheckAt: z$1.ZodOptional; + lastFailure: z$1.ZodOptional>; + }, z$1.core.$strip>; + enabled: z$1.ZodBoolean; + description: z$1.ZodNullable; + name: z$1.ZodNullable; + icon: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + running: "running"; + missing: "missing"; + incompatible: "incompatible"; + disabled: "disabled"; + degraded: "degraded"; + "needs-configuration": "needs-configuration"; + }>; + statusDetail: z$1.ZodNullable; + handlerStats: z$1.ZodObject<{ + count: z$1.ZodNumber; + totalMs: z$1.ZodNumber; + maxMs: z$1.ZodNumber; + errorCount: z$1.ZodNumber; + }, z$1.core.$strip>; + services: z$1.ZodArray; + }, z$1.core.$strip>>; + schedules: z$1.ZodArray; + lastStatus: z$1.ZodNullable>; + lastError: z$1.ZodNullable; + }, z$1.core.$strip>>; + cliCommand: z$1.ZodNullable>; + hasSettings: z$1.ZodBoolean; + app: z$1.ZodObject<{ + hasApp: z$1.ZodBoolean; + bundle: z$1.ZodNullable; + hash: z$1.ZodString; + sdkMajor: z$1.ZodNumber; + sdkVersion: z$1.ZodString; + compatible: z$1.ZodBoolean; + }, z$1.core.$strip>>; + }, z$1.core.$strip>; + logoUrl: z$1.ZodNullable; + logoDarkUrl: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type PluginListResponse = z$1.infer; +declare const pluginReloadResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + plugins: z$1.ZodArray; + isOrphanedBuiltin: z$1.ZodBoolean; + catalogEntryId: z$1.ZodOptional; + sourceDisplay: z$1.ZodString; + updateState: z$1.ZodObject<{ + outcome: z$1.ZodOptional>; + availableVersion: z$1.ZodOptional; + blockedVersion: z$1.ZodOptional; + blockedReasons: z$1.ZodOptional>; + lastCheckAt: z$1.ZodOptional; + lastFailure: z$1.ZodOptional>; + }, z$1.core.$strip>; + enabled: z$1.ZodBoolean; + description: z$1.ZodNullable; + name: z$1.ZodNullable; + icon: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + running: "running"; + missing: "missing"; + incompatible: "incompatible"; + disabled: "disabled"; + degraded: "degraded"; + "needs-configuration": "needs-configuration"; + }>; + statusDetail: z$1.ZodNullable; + handlerStats: z$1.ZodObject<{ + count: z$1.ZodNumber; + totalMs: z$1.ZodNumber; + maxMs: z$1.ZodNumber; + errorCount: z$1.ZodNumber; + }, z$1.core.$strip>; + services: z$1.ZodArray; + }, z$1.core.$strip>>; + schedules: z$1.ZodArray; + lastStatus: z$1.ZodNullable>; + lastError: z$1.ZodNullable; + }, z$1.core.$strip>>; + cliCommand: z$1.ZodNullable>; + hasSettings: z$1.ZodBoolean; + app: z$1.ZodObject<{ + hasApp: z$1.ZodBoolean; + bundle: z$1.ZodNullable; + hash: z$1.ZodString; + sdkMajor: z$1.ZodNumber; + sdkVersion: z$1.ZodString; + compatible: z$1.ZodBoolean; + }, z$1.core.$strip>>; + }, z$1.core.$strip>; + logoUrl: z$1.ZodNullable; + logoDarkUrl: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type PluginReloadResponse = z$1.infer; +declare const pluginRemoveResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; +}, z$1.core.$strip>; +type PluginRemoveResponse = z$1.infer; +declare const pluginSettingsResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + schema: z$1.ZodRecord; + secret: z$1.ZodOptional>; + default: z$1.ZodOptional; + label: z$1.ZodString; + description: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"boolean">; + default: z$1.ZodOptional; + label: z$1.ZodString; + description: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"select">; + options: z$1.ZodArray; + default: z$1.ZodOptional; + label: z$1.ZodString; + description: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"project">; + default: z$1.ZodOptional; + label: z$1.ZodString; + description: z$1.ZodOptional; + }, z$1.core.$strict>], "type">>; + values: z$1.ZodRecord>>; +}, z$1.core.$strip>; +type PluginSettingsResponse = z$1.infer; +declare const pluginTokenResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + token: z$1.ZodString; +}, z$1.core.$strip>; +type PluginTokenResponse = z$1.infer; +declare const pluginCatalogStatusSchema: z$1.ZodObject<{ + pluginCount: z$1.ZodNumber; +}, z$1.core.$strip>; +type PluginCatalogStatus = z$1.infer; +declare const pluginCatalogSearchResultSchema: z$1.ZodObject<{ + entryId: z$1.ZodString; + displayName: z$1.ZodString; + description: z$1.ZodString; + icon: z$1.ZodNullable; + category: z$1.ZodString; + source: z$1.ZodString; + installed: z$1.ZodBoolean; + compatible: z$1.ZodBoolean; + incompatibleReason: z$1.ZodNullable; +}, z$1.core.$strip>; +type PluginCatalogSearchResult$1 = z$1.infer; + +declare const systemExecutionOptionsResponseSchema: z$1.ZodObject<{ + providers: z$1.ZodArray; + capabilities: z$1.ZodObject<{ + supportsArchive: z$1.ZodBoolean; + supportsRename: z$1.ZodBoolean; + supportsServiceTier: z$1.ZodBoolean; + supportsUserQuestion: z$1.ZodBoolean; + supportsFork: z$1.ZodBoolean; + supportedPermissionModes: z$1.ZodArray>; + }, z$1.core.$strip>; + composerActions: z$1.ZodArray; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plan">; + command: z$1.ZodObject<{ + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + trailingText: z$1.ZodString; + }, z$1.core.$strip>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"goal">; + command: z$1.ZodObject<{ + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + trailingText: z$1.ZodString; + }, z$1.core.$strip>; + }, z$1.core.$strip>], "kind">>; + available: z$1.ZodBoolean; + }, z$1.core.$strip>>; + models: z$1.ZodArray; + description: z$1.ZodString; + }, z$1.core.$strip>>; + defaultReasoningEffort: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + isDefault: z$1.ZodBoolean; + }, z$1.core.$strip>>; + selectedOnlyModels: z$1.ZodArray; + description: z$1.ZodString; + }, z$1.core.$strip>>; + defaultReasoningEffort: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + isDefault: z$1.ZodBoolean; + }, z$1.core.$strip>>; + modelLoadError: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type SystemExecutionOptionsResponse = z$1.infer; +declare const systemExecutionOptionsQuerySchema: z$1.ZodObject<{ + providerId: z$1.ZodOptional; + hostId: z$1.ZodOptional; + environmentId: z$1.ZodOptional; +}, z$1.core.$strip>; +type SystemExecutionOptionsQuery = z$1.infer; +/** Omission preserves the existing behavior of reading the primary machine. */ +declare const systemUsageLimitsQuerySchema: z$1.ZodObject<{ + hostId: z$1.ZodOptional; +}, z$1.core.$strip>; +type SystemUsageLimitsQuery = z$1.infer; +declare const systemVoiceTranscriptionResponseSchema: z$1.ZodObject<{ + text: z$1.ZodString; +}, z$1.core.$strip>; +type SystemVoiceTranscriptionResponse = z$1.infer; +declare const systemConfigResponseSchema: z$1.ZodObject<{ + generalSettings: z$1.ZodObject<{ + caffeinate: z$1.ZodBoolean; + showKeyboardHints: z$1.ZodBoolean; + showUnhandledProviderEvents: z$1.ZodBoolean; + codexMemoryEnabled: z$1.ZodBoolean; + claudeCodeMemoryEnabled: z$1.ZodBoolean; + codexSubagentsDisabled: z$1.ZodBoolean; + claudeCodeSubagentsDisabled: z$1.ZodBoolean; + claudeCodeWorkflowsDisabled: z$1.ZodBoolean; + }, z$1.core.$strict>; + keybindings: z$1.ZodArray; + desktopOnly: z$1.ZodBoolean; + shortcut: z$1.ZodObject<{ + key: z$1.ZodString; + mod: z$1.ZodBoolean; + meta: z$1.ZodBoolean; + control: z$1.ZodBoolean; + alt: z$1.ZodBoolean; + shift: z$1.ZodBoolean; + }, z$1.core.$strict>; + when: z$1.ZodObject<{ + all: z$1.ZodArray>; + none: z$1.ZodArray>; + }, z$1.core.$strict>; + }, z$1.core.$strict>>; + defaultKeybindings: z$1.ZodArray; + desktopOnly: z$1.ZodBoolean; + shortcut: z$1.ZodObject<{ + key: z$1.ZodString; + mod: z$1.ZodBoolean; + meta: z$1.ZodBoolean; + control: z$1.ZodBoolean; + alt: z$1.ZodBoolean; + shift: z$1.ZodBoolean; + }, z$1.core.$strict>; + when: z$1.ZodObject<{ + all: z$1.ZodArray>; + none: z$1.ZodArray>; + }, z$1.core.$strict>; + }, z$1.core.$strict>>; + keybindingOverrides: z$1.ZodArray; + shortcut: z$1.ZodNullable>; + }, z$1.core.$strict>>; + experiments: z$1.ZodObject<{ + claudeCodeMockCliTraffic: z$1.ZodBoolean; + plugins: z$1.ZodBoolean; + sideChatPlugin: z$1.ZodBoolean; + }, z$1.core.$strip>; + appearance: z$1.ZodObject<{ + themeId: z$1.ZodString; + customCss: z$1.ZodNullable; + faviconColor: z$1.ZodEnum<{ + default: "default"; + red: "red"; + orange: "orange"; + yellow: "yellow"; + green: "green"; + teal: "teal"; + blue: "blue"; + purple: "purple"; + pink: "pink"; + }>; + }, z$1.core.$strip>; + customThemes: z$1.ZodArray; + pluginThemes: z$1.ZodArray; + }, z$1.core.$strip>>; + featureFlags: z$1.ZodObject<{ + placeholder: z$1.ZodBoolean; + }, z$1.core.$strip>; + hostDaemonPort: z$1.ZodNullable; + primaryHostId: z$1.ZodNullable; + primaryHostPlatform: z$1.ZodNullable>; + voiceTranscriptionEnabled: z$1.ZodBoolean; + dataDir: z$1.ZodString; +}, z$1.core.$strip>; +type SystemConfigResponse = z$1.infer; +declare const systemAttentionResponseSchema: z$1.ZodObject<{ + hasAttention: z$1.ZodBoolean; +}, z$1.core.$strip>; +type SystemAttentionResponse = z$1.infer; +/** + * Theme catalog: the on-disk custom-theme directory plus the discovered custom + * themes and the active palette. Drives `bb theme list` / `bb theme dir`. + */ +declare const themeCatalogResponseSchema: z$1.ZodObject<{ + dir: z$1.ZodString; + custom: z$1.ZodArray; + plugins: z$1.ZodArray; + }, z$1.core.$strip>>; + active: z$1.ZodObject<{ + themeId: z$1.ZodString; + customCss: z$1.ZodNullable; + faviconColor: z$1.ZodEnum<{ + default: "default"; + red: "red"; + orange: "orange"; + yellow: "yellow"; + green: "green"; + teal: "teal"; + blue: "blue"; + purple: "purple"; + pink: "pink"; + }>; + }, z$1.core.$strip>; +}, z$1.core.$strip>; +type ThemeCatalogResponse = z$1.infer; +declare const systemVersionResponseSchema: z$1.ZodObject<{ + currentVersion: z$1.ZodString; + latestVersion: z$1.ZodNullable; + source: z$1.ZodLiteral<"npm">; + updateAvailable: z$1.ZodBoolean; + isDevelopment: z$1.ZodBoolean; + upgradeCommand: z$1.ZodString; +}, z$1.core.$strip>; +type SystemVersionResponse = z$1.infer; +declare const systemConfigReloadResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; +}, z$1.core.$strip>; +type SystemConfigReloadResponse = z$1.infer; + +declare const terminalSessionSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodNullable; + environmentId: z$1.ZodNullable; + hostId: z$1.ZodString; + title: z$1.ZodString; + initialCwd: z$1.ZodString; + cols: z$1.ZodNumber; + rows: z$1.ZodNumber; + status: z$1.ZodEnum<{ + starting: "starting"; + disconnected: "disconnected"; + running: "running"; + exited: "exited"; + }>; + exitCode: z$1.ZodNullable; + closeReason: z$1.ZodNullable>; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + lastUserInputAt: z$1.ZodNullable; +}, z$1.core.$strip>; +type TerminalSession = z$1.infer; +declare const terminalListResponseSchema: z$1.ZodObject<{ + sessions: z$1.ZodArray; + environmentId: z$1.ZodNullable; + hostId: z$1.ZodString; + title: z$1.ZodString; + initialCwd: z$1.ZodString; + cols: z$1.ZodNumber; + rows: z$1.ZodNumber; + status: z$1.ZodEnum<{ + starting: "starting"; + disconnected: "disconnected"; + running: "running"; + exited: "exited"; + }>; + exitCode: z$1.ZodNullable; + closeReason: z$1.ZodNullable>; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + lastUserInputAt: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type TerminalListResponse = z$1.infer; +declare const createTerminalRequestSchema: z$1.ZodObject<{ + cols: z$1.ZodNumber; + rows: z$1.ZodNumber; + start: z$1.ZodOptional; + }, z$1.core.$strict>, z$1.ZodObject<{ + mode: z$1.ZodLiteral<"command">; + command: z$1.ZodString; + }, z$1.core.$strict>], "mode">>; + target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"environment">; + environmentId: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"host_path">; + hostId: z$1.ZodString; + cwd: z$1.ZodNullable; + }, z$1.core.$strict>], "kind">; + title: z$1.ZodOptional; +}, z$1.core.$strict>; +type CreateTerminalRequest = z$1.infer; +declare const updateTerminalRequestSchema: z$1.ZodObject<{ + title: z$1.ZodString; +}, z$1.core.$strict>; +type UpdateTerminalRequest = z$1.infer; +declare const terminalInputRequestSchema: z$1.ZodObject<{ + dataBase64: z$1.ZodString; +}, z$1.core.$strict>; +type TerminalInputRequest = z$1.infer; +declare const terminalResizeRequestSchema: z$1.ZodObject<{ + cols: z$1.ZodNumber; + rows: z$1.ZodNumber; +}, z$1.core.$strict>; +type TerminalResizeRequest = z$1.infer; +declare const terminalOutputQuerySchema: z$1.ZodObject<{ + sinceSeq: z$1.ZodOptional>; + tailBytes: z$1.ZodOptional>; + limitChunks: z$1.ZodOptional>; +}, z$1.core.$strict>; +type TerminalOutputQuery = z$1.infer; +declare const terminalOutputResponseSchema: z$1.ZodObject<{ + chunks: z$1.ZodArray>; + nextSeq: z$1.ZodNumber; + truncated: z$1.ZodBoolean; +}, z$1.core.$strict>; +type TerminalOutputResponse = z$1.infer; + +declare const timelineRowStatusSchema: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; +}>; +type TimelineRowStatus = z$1.infer; +declare const timelineRowBaseSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; +}, z$1.core.$strip>; +type TimelineRowBase = z$1.infer; +declare const timelineConversationRowSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"conversation">; + text: z$1.ZodString; + attachments: z$1.ZodNullable; + localImagePaths: z$1.ZodArray; + localFilePaths: z$1.ZodArray; + }, z$1.core.$strip>>; + role: z$1.ZodLiteral<"user">; + initiator: z$1.ZodEnum<{ + user: "user"; + agent: "agent"; + system: "system"; + }>; + senderThreadId: z$1.ZodNullable; + systemMessageKind: z$1.ZodEnum<{ + "ownership-assigned": "ownership-assigned"; + "ownership-removed": "ownership-removed"; + "child-needs-attention": "child-needs-attention"; + "child-completed": "child-completed"; + "child-failed": "child-failed"; + "child-interrupted": "child-interrupted"; + "child-outcome-batch": "child-outcome-batch"; + unlabeled: "unlabeled"; + }>; + systemMessageSubject: z$1.ZodNullable; + threadId: z$1.ZodString; + threadName: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread-batch">; + count: z$1.ZodNumber; + }, z$1.core.$strip>], "kind">>; + turnRequest: z$1.ZodObject<{ + kind: z$1.ZodEnum<{ + message: "message"; + steer: "steer"; + }>; + status: z$1.ZodEnum<{ + pending: "pending"; + accepted: "accepted"; + }>; + }, z$1.core.$strip>; + mentions: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"conversation">; + text: z$1.ZodString; + attachments: z$1.ZodNullable; + localImagePaths: z$1.ZodArray; + localFilePaths: z$1.ZodArray; + }, z$1.core.$strip>>; + role: z$1.ZodLiteral<"assistant">; + turnRequest: z$1.ZodNull; +}, z$1.core.$strip>], "role">; +type TimelineConversationRow = z$1.infer; +declare const timelineSystemRowSchema: z$1.ZodUnion; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"system">; + title: z$1.ZodString; + detail: z$1.ZodNullable; + status: z$1.ZodNullable>; + systemKind: z$1.ZodEnum<{ + error: "error"; + debug: "debug"; + reconnect: "reconnect"; + }>; +}, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"system">; + title: z$1.ZodString; + detail: z$1.ZodNullable; + status: z$1.ZodNullable>; + systemKind: z$1.ZodLiteral<"operation">; + operationKind: z$1.ZodEnum<{ + generic: "generic"; + compaction: "compaction"; + "thread-provisioning": "thread-provisioning"; + "thread-interrupted": "thread-interrupted"; + "provider-unhandled": "provider-unhandled"; + warning: "warning"; + deprecation: "deprecation"; + }>; + completedAt: z$1.ZodNullable; +}, z$1.core.$strip>, z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"system">; + title: z$1.ZodString; + detail: z$1.ZodNullable; + systemKind: z$1.ZodLiteral<"operation">; + operationKind: z$1.ZodLiteral<"parent-change">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + parentChange: z$1.ZodObject<{ + action: z$1.ZodEnum<{ + assign: "assign"; + release: "release"; + transfer: "transfer"; + }>; + previousParentThreadId: z$1.ZodNullable; + previousParentThreadTitle: z$1.ZodNullable; + nextParentThreadId: z$1.ZodNullable; + nextParentThreadTitle: z$1.ZodNullable; + }, z$1.core.$strip>; + completedAt: z$1.ZodNullable; +}, z$1.core.$strip>], "operationKind">]>; +type TimelineSystemRow = z$1.infer; +interface TimelineWorkRowBase extends TimelineRowBase { + kind: "work"; + status: TimelineRowStatus; +} +declare const timelineCommandWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"command">; + callId: z$1.ZodString; + command: z$1.ZodString; + cwd: z$1.ZodNullable; + source: z$1.ZodNullable; + output: z$1.ZodString; + exitCode: z$1.ZodNullable; + completedAt: z$1.ZodNullable; + approvalStatus: z$1.ZodNullable>; + activityIntents: z$1.ZodArray; + command: z$1.ZodString; + name: z$1.ZodString; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"list_files">; + command: z$1.ZodString; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"search">; + command: z$1.ZodString; + query: z$1.ZodNullable; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"unknown">; + command: z$1.ZodString; + }, z$1.core.$strip>], "type">>; +}, z$1.core.$strip>; +type TimelineCommandWorkRow = z$1.infer; +declare const timelineToolWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"tool">; + callId: z$1.ZodString; + toolName: z$1.ZodString; + toolArgs: z$1.ZodNullable>>>; + output: z$1.ZodString; + completedAt: z$1.ZodNullable; + approvalStatus: z$1.ZodNullable>; + activityIntents: z$1.ZodArray; + command: z$1.ZodString; + name: z$1.ZodString; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"list_files">; + command: z$1.ZodString; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"search">; + command: z$1.ZodString; + query: z$1.ZodNullable; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"unknown">; + command: z$1.ZodString; + }, z$1.core.$strip>], "type">>; +}, z$1.core.$strip>; +type TimelineToolWorkRow = z$1.infer; +declare const timelineFileChangeWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"file-change">; + callId: z$1.ZodString; + change: z$1.ZodObject<{ + path: z$1.ZodString; + kind: z$1.ZodNullable; + movePath: z$1.ZodNullable; + diff: z$1.ZodNullable; + diffStats: z$1.ZodObject<{ + added: z$1.ZodNumber; + removed: z$1.ZodNumber; + }, z$1.core.$strip>; + }, z$1.core.$strip>; + stdout: z$1.ZodNullable; + stderr: z$1.ZodNullable; + approvalStatus: z$1.ZodNullable>; +}, z$1.core.$strip>; +type TimelineFileChangeWorkRow = z$1.infer; +declare const timelineWebSearchWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"web-search">; + callId: z$1.ZodString; + queries: z$1.ZodArray; + completedAt: z$1.ZodNullable; +}, z$1.core.$strip>; +type TimelineWebSearchWorkRow = z$1.infer; +declare const timelineWebFetchWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"web-fetch">; + callId: z$1.ZodString; + url: z$1.ZodString; + prompt: z$1.ZodNullable; + pattern: z$1.ZodNullable; + completedAt: z$1.ZodNullable; +}, z$1.core.$strip>; +type TimelineWebFetchWorkRow = z$1.infer; +declare const timelineImageViewWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"image-view">; + callId: z$1.ZodString; + path: z$1.ZodString; + completedAt: z$1.ZodNullable; +}, z$1.core.$strip>; +type TimelineImageViewWorkRow = z$1.infer; +declare const timelineApprovalWorkRowSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"approval">; + interactionId: z$1.ZodString; + target: z$1.ZodObject<{ + itemId: z$1.ZodString; + toolName: z$1.ZodNullable; + }, z$1.core.$strip>; + approvalKind: z$1.ZodLiteral<"file-edit">; + lifecycle: z$1.ZodEnum<{ + denied: "denied"; + waiting: "waiting"; + }>; +}, z$1.core.$strip>, z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"approval">; + interactionId: z$1.ZodString; + target: z$1.ZodObject<{ + itemId: z$1.ZodString; + toolName: z$1.ZodNullable; + }, z$1.core.$strip>; + approvalKind: z$1.ZodLiteral<"permission-grant">; + lifecycle: z$1.ZodEnum<{ + pending: "pending"; + interrupted: "interrupted"; + denied: "denied"; + resolving: "resolving"; + granted: "granted"; + }>; + grantScope: z$1.ZodNullable>; + statusReason: z$1.ZodNullable; +}, z$1.core.$strip>], "approvalKind">; +type TimelineApprovalWorkRow = z$1.infer; +declare const timelineQuestionWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"question">; + interactionId: z$1.ZodString; + lifecycle: z$1.ZodEnum<{ + pending: "pending"; + interrupted: "interrupted"; + resolving: "resolving"; + answered: "answered"; + }>; + questions: z$1.ZodArray; + multiSelect: z$1.ZodBoolean; + options: z$1.ZodOptional; + }, z$1.core.$strip>>>; + allowFreeText: z$1.ZodBoolean; + }, z$1.core.$strip>>; + answers: z$1.ZodNullable; + freeText: z$1.ZodOptional; + }, z$1.core.$strip>>>; + statusReason: z$1.ZodNullable; +}, z$1.core.$strip>; +type TimelineQuestionWorkRow = z$1.infer; +interface TimelineDelegationWorkRow extends TimelineWorkRowBase { + workKind: "delegation"; + callId: string; + toolName: string; + subagentType: string | null; + description: string | null; + output: string; + completedAt: number | null; + childRows: TimelineRow[]; +} +/** + * A provider background task — a dynamic workflow (Claude Code Workflow tool) + * or a backgrounded shell command (Bash run_in_background), discriminated by + * `taskType`. The row outlives its spawning turn: progress and terminal state + * arrive via thread-scoped events folded into this single row. `workflow` is + * the merged phase/agent tree, present only for workflows; null for shell + * commands and for workflows the provider reported no progress records for + * (degraded rendering falls back to description + summary). + */ +declare const timelineWorkflowWorkRowSchema: z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + turnId: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"workflow">; + itemId: z$1.ZodString; + taskType: z$1.ZodString; + workflowName: z$1.ZodNullable; + description: z$1.ZodString; + taskStatus: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + running: "running"; + paused: "paused"; + failed: "failed"; + killed: "killed"; + stopped: "stopped"; + }>; + workflow: z$1.ZodNullable; + }, z$1.core.$strip>>; + agents: z$1.ZodArray; + model: z$1.ZodString; + attempt: z$1.ZodNumber; + cached: z$1.ZodBoolean; + lastProgressAt: z$1.ZodNumber; + phaseIndex: z$1.ZodOptional; + phaseTitle: z$1.ZodOptional; + agentType: z$1.ZodOptional; + isolation: z$1.ZodOptional; + queuedAt: z$1.ZodOptional; + startedAt: z$1.ZodOptional; + lastToolName: z$1.ZodOptional; + lastToolSummary: z$1.ZodOptional; + promptPreview: z$1.ZodOptional; + resultPreview: z$1.ZodOptional; + error: z$1.ZodOptional; + tokens: z$1.ZodOptional; + toolCalls: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + usage: z$1.ZodNullable>; + summary: z$1.ZodNullable; + error: z$1.ZodNullable; + completedAt: z$1.ZodNullable; +}, z$1.core.$strip>; +type TimelineWorkflowWorkRow = z$1.infer; +type TimelineWorkRow = TimelineCommandWorkRow | TimelineToolWorkRow | TimelineFileChangeWorkRow | TimelineWebSearchWorkRow | TimelineWebFetchWorkRow | TimelineImageViewWorkRow | TimelineApprovalWorkRow | TimelineQuestionWorkRow | TimelineDelegationWorkRow | TimelineWorkflowWorkRow; +interface TimelineTurnRow extends TimelineRowBase { + kind: "turn"; + turnId: string; + status: TimelineRowStatus; + summaryCount: number; + completedAt: number | null; + children: TimelineRow[] | null; +} +type TimelineSourceRow = TimelineConversationRow | TimelineWorkRow | TimelineSystemRow; +type TimelineRow = TimelineSourceRow | TimelineTurnRow; + +declare const createThreadRequestSchema: z$1.ZodObject<{ + projectId: z$1.ZodString; + providerId: z$1.ZodOptional; + origin: z$1.ZodEnum<{ + plugin: "plugin"; + app: "app"; + cli: "cli"; + sdk: "sdk"; + }>; + originPluginId: z$1.ZodOptional; + visibility: z$1.ZodOptional>; + title: z$1.ZodOptional; + input: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + model: z$1.ZodOptional; + serviceTier: z$1.ZodOptional>; + reasoningLevel: z$1.ZodOptional>; + permissionMode: z$1.ZodOptional, z$1.ZodLiteral<"workspace-write">]>, z$1.ZodTransform<"accept-edits" | "auto" | "full", "accept-edits" | "auto" | "full" | "workspace-write">>>; + executionInputSources: z$1.ZodOptional>; + model: z$1.ZodOptional>; + serviceTier: z$1.ZodOptional>; + reasoningLevel: z$1.ZodOptional>; + permissionMode: z$1.ZodOptional>; + }, z$1.core.$strict>>; + environment: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"reuse">; + environmentId: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"host">; + hostId: z$1.ZodOptional; + workspace: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + type: z$1.ZodLiteral<"unmanaged">; + path: z$1.ZodNullable; + branch: z$1.ZodOptional; + name: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"new">; + baseBranch: z$1.ZodString; + }, z$1.core.$strict>], "kind">>; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"managed-worktree">; + baseBranch: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"named">; + name: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"default">; + }, z$1.core.$strip>], "kind">; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"personal">; + }, z$1.core.$strip>], "type">; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"project-default">; + }, z$1.core.$strip>], "type">; + parentThreadId: z$1.ZodOptional; + sectionId: z$1.ZodOptional>; + sourceThreadId: z$1.ZodOptional; + sourceSeqEnd: z$1.ZodOptional; + startedOnBehalfOf: z$1.ZodDefault; + senderThreadId: z$1.ZodString; + }, z$1.core.$strip>>>; + originKind: z$1.ZodDefault>>; + childOrigin: z$1.ZodDefault>>; +}, z$1.core.$strip>; +type CreateThreadRequest = z$1.infer; +declare const forkThreadRequestSchema: z$1.ZodObject<{ + sourceThreadId: z$1.ZodString; + sourceSeqEnd: z$1.ZodOptional; + input: z$1.ZodOptional>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>>; + agentContextSeed: z$1.ZodOptional>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">, z$1.ZodObject<{ + visibility: z$1.ZodLiteral<"agent-only">; + }, z$1.core.$strip>>>>; + title: z$1.ZodOptional; + permissionMode: z$1.ZodOptional, z$1.ZodLiteral<"workspace-write">]>, z$1.ZodTransform<"accept-edits" | "auto" | "full", "accept-edits" | "auto" | "full" | "workspace-write">>>; + visibility: z$1.ZodDefault>; + workspace: z$1.ZodDefault>; + origin: z$1.ZodDefault>; + originPluginId: z$1.ZodOptional; +}, z$1.core.$strip>; +type ForkThreadRequest = z$1.infer; +declare const sendMessageRequestSchema: z$1.ZodObject<{ + input: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + model: z$1.ZodOptional; + serviceTier: z$1.ZodOptional>; + reasoningLevel: z$1.ZodOptional>; + permissionMode: z$1.ZodOptional, z$1.ZodLiteral<"workspace-write">]>, z$1.ZodTransform<"accept-edits" | "auto" | "full", "accept-edits" | "auto" | "full" | "workspace-write">>>; + executionInputSources: z$1.ZodOptional>; + serviceTier: z$1.ZodOptional>; + reasoningLevel: z$1.ZodOptional>; + permissionMode: z$1.ZodOptional>; + }, z$1.core.$strict>>; + mode: z$1.ZodEnum<{ + steer: "steer"; + start: "start"; + auto: "auto"; + "queue-if-active": "queue-if-active"; + "steer-if-active": "steer-if-active"; + }>; + senderThreadId: z$1.ZodOptional; +}, z$1.core.$strip>; +type SendMessageRequest = z$1.infer; +declare const createQueuedMessageRequestSchema: z$1.ZodObject<{ + input: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + model: z$1.ZodOptional; + serviceTier: z$1.ZodOptional>; + reasoningLevel: z$1.ZodOptional>; + permissionMode: z$1.ZodOptional, z$1.ZodLiteral<"workspace-write">]>, z$1.ZodTransform<"accept-edits" | "auto" | "full", "accept-edits" | "auto" | "full" | "workspace-write">>>; + executionInputSources: z$1.ZodOptional>; + serviceTier: z$1.ZodOptional>; + reasoningLevel: z$1.ZodOptional>; + permissionMode: z$1.ZodOptional>; + }, z$1.core.$strict>>; + senderThreadId: z$1.ZodOptional; +}, z$1.core.$strip>; +type CreateQueuedMessageRequest = z$1.infer; +declare const updateQueuedMessageRequestSchema: z$1.ZodObject<{ + expectedUpdatedAt: z$1.ZodNumber; + input: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; +}, z$1.core.$strip>; +type UpdateQueuedMessageRequest = z$1.infer; +declare const sendQueuedMessageRequestSchema: z$1.ZodObject<{ + mode: z$1.ZodEnum<{ + steer: "steer"; + auto: "auto"; + }>; +}, z$1.core.$strip>; +type SendQueuedMessageRequest = z$1.infer; +declare const reorderQueuedMessageRequestSchema: z$1.ZodObject<{ + previousQueuedMessageId: z$1.ZodNullable; + nextQueuedMessageId: z$1.ZodNullable; + groupBoundaryQueuedMessageId: z$1.ZodOptional; +}, z$1.core.$strip>; +type ReorderQueuedMessageRequest = z$1.infer; +declare const setQueuedMessageGroupBoundaryRequestSchema: z$1.ZodObject<{ + expectedGroupedPrefixQueuedMessageIds: z$1.ZodArray; + groupBoundaryQueuedMessageId: z$1.ZodString; +}, z$1.core.$strip>; +type SetQueuedMessageGroupBoundaryRequest = z$1.infer; +declare const sendQueuedMessageResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + queuedMessage: z$1.ZodObject<{ + id: z$1.ZodString; + content: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + model: z$1.ZodString; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + permissionMode: z$1.ZodEnum<{ + "accept-edits": "accept-edits"; + auto: "auto"; + full: "full"; + }>; + serviceTier: z$1.ZodEnum<{ + default: "default"; + fast: "fast"; + }>; + groupWithNext: z$1.ZodBoolean; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + }, z$1.core.$strip>; +}, z$1.core.$strip>; +type SendQueuedMessageResponse = z$1.infer; +declare const threadListResponseSchema: z$1.ZodArray; + providerId: z$1.ZodString; + title: z$1.ZodNullable; + titleFallback: z$1.ZodNullable; + sectionId: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + }>; + parentThreadId: z$1.ZodNullable; + sourceThreadId: z$1.ZodNullable; + originKind: z$1.ZodNullable>; + childOrigin: z$1.ZodNullable>; + originPluginId: z$1.ZodNullable; + visibility: z$1.ZodEnum<{ + visible: "visible"; + hidden: "hidden"; + }>; + archivedAt: z$1.ZodNullable; + pinnedAt: z$1.ZodNullable; + deletedAt: z$1.ZodNullable; + lastReadAt: z$1.ZodNullable; + latestAttentionAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + runtime: z$1.ZodObject<{ + displayStatus: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + "host-reconnecting": "host-reconnecting"; + "waiting-for-host": "waiting-for-host"; + }>; + hostReconnectGraceExpiresAt: z$1.ZodNullable; + }, z$1.core.$strip>; + activity: z$1.ZodObject<{ + activeWorkflowCount: z$1.ZodNumber; + activeBackgroundAgentCount: z$1.ZodNumber; + activeBackgroundCommandCount: z$1.ZodNumber; + activePlanModeCount: z$1.ZodNumber; + activeGoalCount: z$1.ZodNumber; + }, z$1.core.$strip>; + pinSortKey: z$1.ZodNullable; + hasPendingInteraction: z$1.ZodBoolean; + environmentHostId: z$1.ZodNullable; + environmentName: z$1.ZodNullable; + environmentBranchName: z$1.ZodNullable; + environmentWorkspaceDisplayKind: z$1.ZodEnum<{ + "managed-worktree": "managed-worktree"; + "unmanaged-worktree": "unmanaged-worktree"; + other: "other"; + }>; +}, z$1.core.$strip>>; +type ThreadListResponse = z$1.infer; +declare const threadSearchResponseSchema: z$1.ZodObject<{ + active: z$1.ZodObject<{ + total: z$1.ZodNumber; + results: z$1.ZodArray; + providerId: z$1.ZodString; + title: z$1.ZodNullable; + titleFallback: z$1.ZodNullable; + sectionId: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + }>; + parentThreadId: z$1.ZodNullable; + sourceThreadId: z$1.ZodNullable; + originKind: z$1.ZodNullable>; + childOrigin: z$1.ZodNullable>; + originPluginId: z$1.ZodNullable; + visibility: z$1.ZodEnum<{ + visible: "visible"; + hidden: "hidden"; + }>; + archivedAt: z$1.ZodNullable; + pinnedAt: z$1.ZodNullable; + deletedAt: z$1.ZodNullable; + lastReadAt: z$1.ZodNullable; + latestAttentionAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + runtime: z$1.ZodObject<{ + displayStatus: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + "host-reconnecting": "host-reconnecting"; + "waiting-for-host": "waiting-for-host"; + }>; + hostReconnectGraceExpiresAt: z$1.ZodNullable; + }, z$1.core.$strip>; + activity: z$1.ZodObject<{ + activeWorkflowCount: z$1.ZodNumber; + activeBackgroundAgentCount: z$1.ZodNumber; + activeBackgroundCommandCount: z$1.ZodNumber; + activePlanModeCount: z$1.ZodNumber; + activeGoalCount: z$1.ZodNumber; + }, z$1.core.$strip>; + pinSortKey: z$1.ZodNullable; + hasPendingInteraction: z$1.ZodBoolean; + environmentHostId: z$1.ZodNullable; + environmentName: z$1.ZodNullable; + environmentBranchName: z$1.ZodNullable; + environmentWorkspaceDisplayKind: z$1.ZodEnum<{ + "managed-worktree": "managed-worktree"; + "unmanaged-worktree": "unmanaged-worktree"; + other: "other"; + }>; + }, z$1.core.$strip>; + matches: z$1.ZodArray; + text: z$1.ZodString; + highlightRanges: z$1.ZodArray>; + sourceSeq: z$1.ZodNullable; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + }, z$1.core.$strict>; + archived: z$1.ZodObject<{ + total: z$1.ZodNumber; + results: z$1.ZodArray; + providerId: z$1.ZodString; + title: z$1.ZodNullable; + titleFallback: z$1.ZodNullable; + sectionId: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + }>; + parentThreadId: z$1.ZodNullable; + sourceThreadId: z$1.ZodNullable; + originKind: z$1.ZodNullable>; + childOrigin: z$1.ZodNullable>; + originPluginId: z$1.ZodNullable; + visibility: z$1.ZodEnum<{ + visible: "visible"; + hidden: "hidden"; + }>; + archivedAt: z$1.ZodNullable; + pinnedAt: z$1.ZodNullable; + deletedAt: z$1.ZodNullable; + lastReadAt: z$1.ZodNullable; + latestAttentionAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + runtime: z$1.ZodObject<{ + displayStatus: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + "host-reconnecting": "host-reconnecting"; + "waiting-for-host": "waiting-for-host"; + }>; + hostReconnectGraceExpiresAt: z$1.ZodNullable; + }, z$1.core.$strip>; + activity: z$1.ZodObject<{ + activeWorkflowCount: z$1.ZodNumber; + activeBackgroundAgentCount: z$1.ZodNumber; + activeBackgroundCommandCount: z$1.ZodNumber; + activePlanModeCount: z$1.ZodNumber; + activeGoalCount: z$1.ZodNumber; + }, z$1.core.$strip>; + pinSortKey: z$1.ZodNullable; + hasPendingInteraction: z$1.ZodBoolean; + environmentHostId: z$1.ZodNullable; + environmentName: z$1.ZodNullable; + environmentBranchName: z$1.ZodNullable; + environmentWorkspaceDisplayKind: z$1.ZodEnum<{ + "managed-worktree": "managed-worktree"; + "unmanaged-worktree": "unmanaged-worktree"; + other: "other"; + }>; + }, z$1.core.$strip>; + matches: z$1.ZodArray; + text: z$1.ZodString; + highlightRanges: z$1.ZodArray>; + sourceSeq: z$1.ZodNullable; + }, z$1.core.$strict>>; + }, z$1.core.$strict>>; + }, z$1.core.$strict>; +}, z$1.core.$strict>; +type ThreadSearchResponse = z$1.infer; +declare const threadResponseSchema: z$1.ZodObject<{ + id: z$1.ZodString; + projectId: z$1.ZodString; + environmentId: z$1.ZodNullable; + providerId: z$1.ZodString; + title: z$1.ZodNullable; + titleFallback: z$1.ZodNullable; + sectionId: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + }>; + parentThreadId: z$1.ZodNullable; + sourceThreadId: z$1.ZodNullable; + originKind: z$1.ZodNullable>; + childOrigin: z$1.ZodNullable>; + originPluginId: z$1.ZodNullable; + visibility: z$1.ZodEnum<{ + visible: "visible"; + hidden: "hidden"; + }>; + archivedAt: z$1.ZodNullable; + pinnedAt: z$1.ZodNullable; + deletedAt: z$1.ZodNullable; + lastReadAt: z$1.ZodNullable; + latestAttentionAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + runtime: z$1.ZodObject<{ + displayStatus: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + "host-reconnecting": "host-reconnecting"; + "waiting-for-host": "waiting-for-host"; + }>; + hostReconnectGraceExpiresAt: z$1.ZodNullable; + }, z$1.core.$strip>; + canSpawnChild: z$1.ZodBoolean; +}, z$1.core.$strip>; +type ThreadResponse = z$1.infer; +declare const threadGetQuerySchema: z$1.ZodObject<{ + include: z$1.ZodOptional; +}, z$1.core.$strip>; +type ThreadGetQuery = z$1.infer; +declare const threadWithIncludesResponseSchema: z$1.ZodObject<{ + id: z$1.ZodString; + projectId: z$1.ZodString; + environmentId: z$1.ZodNullable; + providerId: z$1.ZodString; + title: z$1.ZodNullable; + titleFallback: z$1.ZodNullable; + sectionId: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + }>; + parentThreadId: z$1.ZodNullable; + sourceThreadId: z$1.ZodNullable; + originKind: z$1.ZodNullable>; + childOrigin: z$1.ZodNullable>; + originPluginId: z$1.ZodNullable; + visibility: z$1.ZodEnum<{ + visible: "visible"; + hidden: "hidden"; + }>; + archivedAt: z$1.ZodNullable; + pinnedAt: z$1.ZodNullable; + deletedAt: z$1.ZodNullable; + lastReadAt: z$1.ZodNullable; + latestAttentionAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + runtime: z$1.ZodObject<{ + displayStatus: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + stopping: "stopping"; + idle: "idle"; + starting: "starting"; + active: "active"; + "host-reconnecting": "host-reconnecting"; + "waiting-for-host": "waiting-for-host"; + }>; + hostReconnectGraceExpiresAt: z$1.ZodNullable; + }, z$1.core.$strip>; + canSpawnChild: z$1.ZodBoolean; + environment: z$1.ZodOptional; + projectId: z$1.ZodString; + hostId: z$1.ZodString; + path: z$1.ZodNullable; + managed: z$1.ZodBoolean; + isGitRepo: z$1.ZodBoolean; + isWorktree: z$1.ZodBoolean; + workspaceProvisionType: z$1.ZodEnum<{ + personal: "personal"; + "managed-worktree": "managed-worktree"; + unmanaged: "unmanaged"; + }>; + branchName: z$1.ZodNullable; + baseBranch: z$1.ZodNullable; + defaultBranch: z$1.ZodNullable; + mergeBaseBranch: z$1.ZodNullable; + status: z$1.ZodEnum<{ + error: "error"; + provisioning: "provisioning"; + ready: "ready"; + retiring: "retiring"; + destroying: "destroying"; + destroyed: "destroyed"; + }>; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + }, z$1.core.$strip>>>; + host: z$1.ZodOptional; + status: z$1.ZodEnum<{ + disconnected: "disconnected"; + connected: "connected"; + }>; + lastSeenAt: z$1.ZodNullable; + lastRejectedProtocolVersion: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; + }, z$1.core.$strip>>>; +}, z$1.core.$strip>; +type ThreadWithIncludesResponse = z$1.infer; +declare const threadPendingInteractionsResponseSchema: z$1.ZodArray; + statusReason: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + expiresAt: z$1.ZodOptional>; + resolvedAt: z$1.ZodNullable; + turnId: z$1.ZodString; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodString; + providerRequestId: z$1.ZodString; + origin: z$1.ZodOptional; + providerId: z$1.ZodString; + providerThreadId: z$1.ZodString; + providerRequestId: z$1.ZodString; + }, z$1.core.$strip>>; + payload: z$1.ZodUnion; + subject: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + itemId: z$1.ZodString; + command: z$1.ZodString; + cwd: z$1.ZodNullable; + actions: z$1.ZodArray; + command: z$1.ZodString; + name: z$1.ZodString; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"listFiles">; + command: z$1.ZodString; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"search">; + command: z$1.ZodString; + query: z$1.ZodNullable; + path: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + type: z$1.ZodLiteral<"unknown">; + command: z$1.ZodString; + }, z$1.core.$strip>], "type">>; + sessionGrant: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"file_change">; + itemId: z$1.ZodString; + writeScope: z$1.ZodNullable; + sessionGrant: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"permission_grant">; + itemId: z$1.ZodString; + toolName: z$1.ZodNullable; + permissions: z$1.ZodObject<{ + network: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>; + }, z$1.core.$strip>], "kind">; + reason: z$1.ZodNullable; + availableDecisions: z$1.ZodArray>; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"user_question">; + questions: z$1.ZodArray; + multiSelect: z$1.ZodBoolean; + options: z$1.ZodOptional; + }, z$1.core.$strip>>>; + allowFreeText: z$1.ZodBoolean; + }, z$1.core.$strip>>; + }, z$1.core.$strip>]>; + resolution: z$1.ZodNullable; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"allow_for_session">; + grantedPermissions: z$1.ZodNullable; + }, z$1.core.$strip>>; + fileSystem: z$1.ZodNullable; + write: z$1.ZodArray; + }, z$1.core.$strip>>; + }, z$1.core.$strict>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + decision: z$1.ZodLiteral<"deny">; + }, z$1.core.$strip>], "decision">, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"user_answer">; + answers: z$1.ZodRecord; + freeText: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>]>>; +}, z$1.core.$strip>, z$1.ZodObject<{ + id: z$1.ZodString; + threadId: z$1.ZodString; + status: z$1.ZodEnum<{ + pending: "pending"; + interrupted: "interrupted"; + resolving: "resolving"; + resolved: "resolved"; + }>; + statusReason: z$1.ZodNullable; + createdAt: z$1.ZodNumber; + expiresAt: z$1.ZodOptional>; + resolvedAt: z$1.ZodNullable; + turnId: z$1.ZodNullable; + origin: z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + rendererId: z$1.ZodString; + }, z$1.core.$strip>; + payload: z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + title: z$1.ZodString; + data: z$1.ZodType>; + }, z$1.core.$strip>; + resolution: z$1.ZodNullable; + }, z$1.core.$strip>>; +}, z$1.core.$strip>]>>; +type ThreadPendingInteractionsResponse = z$1.infer; +declare const threadQueuedMessageListResponseSchema: z$1.ZodArray>; + type: z$1.ZodLiteral<"text">; + text: z$1.ZodString; + mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"thread">; + threadId: z$1.ZodString; + projectId: z$1.ZodOptional; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"project">; + projectId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"section">; + sectionId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"path">; + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + entryKind: z$1.ZodEnum<{ + file: "file"; + directory: "directory"; + }>; + path: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"command">; + trigger: z$1.ZodEnum<{ + "/": "/"; + }>; + name: z$1.ZodString; + source: z$1.ZodEnum<{ + command: "command"; + skill: "skill"; + }>; + origin: z$1.ZodEnum<{ + user: "user"; + project: "project"; + builtin: "builtin"; + }>; + label: z$1.ZodString; + argumentHint: z$1.ZodNullable; + }, z$1.core.$strip>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"plugin">; + pluginId: z$1.ZodString; + icon: z$1.ZodOptional>; + itemId: z$1.ZodString; + label: z$1.ZodString; + }, z$1.core.$strip>], "kind">>; + }, z$1.core.$strip>>>; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"image">; + url: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localImage">; + path: z$1.ZodString; + }, z$1.core.$strip>, z$1.ZodObject<{ + visibility: z$1.ZodOptional>; + type: z$1.ZodLiteral<"localFile">; + path: z$1.ZodString; + name: z$1.ZodOptional; + sizeBytes: z$1.ZodOptional; + mimeType: z$1.ZodOptional; + }, z$1.core.$strip>], "type">>; + model: z$1.ZodString; + reasoningLevel: z$1.ZodEnum<{ + none: "none"; + low: "low"; + medium: "medium"; + high: "high"; + xhigh: "xhigh"; + ultracode: "ultracode"; + max: "max"; + ultra: "ultra"; + }>; + permissionMode: z$1.ZodEnum<{ + "accept-edits": "accept-edits"; + auto: "auto"; + full: "full"; + }>; + serviceTier: z$1.ZodEnum<{ + default: "default"; + fast: "fast"; + }>; + groupWithNext: z$1.ZodBoolean; + createdAt: z$1.ZodNumber; + updatedAt: z$1.ZodNumber; +}, z$1.core.$strip>>; +type ThreadQueuedMessageListResponse = z$1.infer; +declare const threadChildSummaryResponseSchema: z$1.ZodObject<{ + nonDeletedChildCount: z$1.ZodNumber; +}, z$1.core.$strip>; +type ThreadChildSummaryResponse = z$1.infer; +declare const deleteThreadRequestSchema: z$1.ZodObject<{ + childThreadsConfirmed: z$1.ZodBoolean; +}, z$1.core.$strip>; +type DeleteThreadRequest = z$1.infer; +declare const updateThreadRequestSchema: z$1.ZodObject<{ + title: z$1.ZodOptional>; + sectionId: z$1.ZodOptional>; + parentThreadId: z$1.ZodOptional>; + model: z$1.ZodOptional>; + reasoningLevel: z$1.ZodOptional>>; + visibility: z$1.ZodOptional>; +}, z$1.core.$strip>; +type UpdateThreadRequest = z$1.infer; +declare const reorderPinnedThreadRequestSchema: z$1.ZodObject<{ + previousThreadId: z$1.ZodNullable; + nextThreadId: z$1.ZodNullable; +}, z$1.core.$strip>; +type ReorderPinnedThreadRequest = z$1.infer; +/** + * Requested placement for a thread opened in the app's split layout. Edge + * placements add panes through the eighth pane; at the cap they replace the + * focused pane. `replace` always replaces the focused pane. + */ +declare const threadOpenSplitSchema: z$1.ZodEnum<{ + right: "right"; + down: "down"; + left: "left"; + top: "top"; + replace: "replace"; +}>; +type ThreadOpenSplit = z$1.infer; +/** Optional secondary-panel file to open with a thread. */ +declare const threadOpenFileSchema: z$1.ZodObject<{ + source: z$1.ZodEnum<{ + workspace: "workspace"; + "thread-storage": "thread-storage"; + }>; + path: z$1.ZodString; + lineNumber: z$1.ZodNullable; +}, z$1.core.$strict>; +type ThreadOpenFile = z$1.infer; +/** Response for POST /threads/:id/open: how many connected clients received it. */ +declare const threadOpenResponseSchema: z$1.ZodObject<{ + delivered: z$1.ZodNumber; +}, z$1.core.$strip>; +type ThreadOpenResponse = z$1.infer; +/** Presentation action for one thread pane in each connected app window. */ +declare const threadPaneActionSchema: z$1.ZodEnum<{ + maximize: "maximize"; + restore: "restore"; + toggle: "toggle"; +}>; +type ThreadPaneAction = z$1.infer; +/** Number of connected app clients that received the pane action. */ +declare const threadPaneActionResponseSchema: z$1.ZodObject<{ + delivered: z$1.ZodNumber; +}, z$1.core.$strip>; +type ThreadPaneActionResponse = z$1.infer; +declare const threadArchiveAllResponseSchema: z$1.ZodObject<{ + ok: z$1.ZodLiteral; + archivedThreadIds: z$1.ZodArray; +}, z$1.core.$strip>; +type ThreadArchiveAllResponse = z$1.infer; +declare const threadListQuerySchema: z$1.ZodObject<{ + projectId: z$1.ZodOptional; + parentThreadId: z$1.ZodOptional; + sourceThreadId: z$1.ZodOptional; + archived: z$1.ZodOptional>; + sectionId: z$1.ZodOptional; + unsectioned: z$1.ZodOptional>; + hasParent: z$1.ZodOptional>; + originKind: z$1.ZodOptional>; + excludeSideChats: z$1.ZodOptional>; + childOrigin: z$1.ZodOptional>; + includeHidden: z$1.ZodOptional>; + limit: z$1.ZodOptional; + offset: z$1.ZodOptional; +}, z$1.core.$strip>; +type ThreadListQuery = z$1.infer; +declare const threadSearchQuerySchema: z$1.ZodObject<{ + query: z$1.ZodString; + limitPerGroup: z$1.ZodOptional; +}, z$1.core.$strip>; +type ThreadSearchQuery = z$1.infer; +declare const threadTimelineQuerySchema: z$1.ZodObject<{ + includeNestedRows: z$1.ZodOptional>; + segmentLimit: z$1.ZodOptional; + beforeAnchorSeq: z$1.ZodOptional; + beforeAnchorId: z$1.ZodOptional; + summaryOnly: z$1.ZodOptional>; + afterSequence: z$1.ZodOptional; +}, z$1.core.$strip>; +type ThreadTimelineQuery = z$1.infer; +declare const timelineTurnSummaryDetailsQuerySchema: z$1.ZodObject<{ + turnId: z$1.ZodString; + sourceSeqStart: z$1.ZodString; + sourceSeqEnd: z$1.ZodString; +}, z$1.core.$strip>; +type TimelineTurnSummaryDetailsQuery = z$1.infer; +declare const threadStorageFilesQuerySchema: z$1.ZodObject<{ + query: z$1.ZodOptional; + limit: z$1.ZodOptional; +}, z$1.core.$strip>; +type ThreadStorageFilesQuery = z$1.infer; +declare const threadStoragePathsQuerySchema: z$1.ZodObject<{ + query: z$1.ZodOptional; + limit: z$1.ZodOptional; + includeFiles: z$1.ZodEnum<{ + true: "true"; + false: "false"; + }>; + includeDirectories: z$1.ZodEnum<{ + true: "true"; + false: "false"; + }>; +}, z$1.core.$strip>; +type ThreadStoragePathsQuery = z$1.infer; +declare const timelineTurnSummaryDetailsResponseSchema: z$1.ZodObject<{ + rows: z$1.ZodArray>>; +}, z$1.core.$strip>; +type TimelineTurnSummaryDetailsResponse = z$1.infer; +declare const threadTimelineResponseSchema: z$1.ZodObject<{ + rows: z$1.ZodArray>>; + activePromptMode: z$1.ZodNullable; + providerId: z$1.ZodEnum<{ + codex: "codex"; + "claude-code": "claude-code"; + }>; + prompt: z$1.ZodString; + }, z$1.core.$strict>>; + activeThinking: z$1.ZodNullable>; + activeWorkflow: z$1.ZodNullable; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"workflow">; + itemId: z$1.ZodString; + taskType: z$1.ZodString; + workflowName: z$1.ZodNullable; + description: z$1.ZodString; + taskStatus: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + running: "running"; + paused: "paused"; + failed: "failed"; + killed: "killed"; + stopped: "stopped"; + }>; + workflow: z$1.ZodNullable; + }, z$1.core.$strip>>; + agents: z$1.ZodArray; + model: z$1.ZodString; + attempt: z$1.ZodNumber; + cached: z$1.ZodBoolean; + lastProgressAt: z$1.ZodNumber; + phaseIndex: z$1.ZodOptional; + phaseTitle: z$1.ZodOptional; + agentType: z$1.ZodOptional; + isolation: z$1.ZodOptional; + queuedAt: z$1.ZodOptional; + startedAt: z$1.ZodOptional; + lastToolName: z$1.ZodOptional; + lastToolSummary: z$1.ZodOptional; + promptPreview: z$1.ZodOptional; + resultPreview: z$1.ZodOptional; + error: z$1.ZodOptional; + tokens: z$1.ZodOptional; + toolCalls: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + usage: z$1.ZodNullable>; + summary: z$1.ZodNullable; + error: z$1.ZodNullable; + completedAt: z$1.ZodNullable; + }, z$1.core.$strip>>; + activeBackgroundCommands: z$1.ZodArray; + sourceSeqStart: z$1.ZodNumber; + sourceSeqEnd: z$1.ZodNumber; + startedAt: z$1.ZodNumber; + createdAt: z$1.ZodNumber; + kind: z$1.ZodLiteral<"work">; + status: z$1.ZodEnum<{ + error: "error"; + pending: "pending"; + completed: "completed"; + interrupted: "interrupted"; + }>; + workKind: z$1.ZodLiteral<"workflow">; + itemId: z$1.ZodString; + taskType: z$1.ZodString; + workflowName: z$1.ZodNullable; + description: z$1.ZodString; + taskStatus: z$1.ZodEnum<{ + pending: "pending"; + completed: "completed"; + running: "running"; + paused: "paused"; + failed: "failed"; + killed: "killed"; + stopped: "stopped"; + }>; + workflow: z$1.ZodNullable; + }, z$1.core.$strip>>; + agents: z$1.ZodArray; + model: z$1.ZodString; + attempt: z$1.ZodNumber; + cached: z$1.ZodBoolean; + lastProgressAt: z$1.ZodNumber; + phaseIndex: z$1.ZodOptional; + phaseTitle: z$1.ZodOptional; + agentType: z$1.ZodOptional; + isolation: z$1.ZodOptional; + queuedAt: z$1.ZodOptional; + startedAt: z$1.ZodOptional; + lastToolName: z$1.ZodOptional; + lastToolSummary: z$1.ZodOptional; + promptPreview: z$1.ZodOptional; + resultPreview: z$1.ZodOptional; + error: z$1.ZodOptional; + tokens: z$1.ZodOptional; + toolCalls: z$1.ZodOptional; + durationMs: z$1.ZodOptional; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + usage: z$1.ZodNullable>; + summary: z$1.ZodNullable; + error: z$1.ZodNullable; + completedAt: z$1.ZodNullable; + }, z$1.core.$strip>>; + pendingTodos: z$1.ZodNullable; + }, z$1.core.$strip>>; + }, z$1.core.$strip>>; + goal: z$1.ZodNullable; + tokenBudget: z$1.ZodNullable; + tokensUsed: z$1.ZodNumber; + timeUsedSeconds: z$1.ZodNumber; + }, z$1.core.$strip>>; + modelFallback: z$1.ZodNullable; + message: z$1.ZodString; + }, z$1.core.$strip>>; + contextWindowUsage: z$1.ZodOptional>; + timelinePage: z$1.ZodObject<{ + kind: z$1.ZodEnum<{ + latest: "latest"; + older: "older"; + }>; + segmentLimit: z$1.ZodNumber; + returnedSegmentCount: z$1.ZodNumber; + hasOlderRows: z$1.ZodBoolean; + olderCursor: z$1.ZodNullable>; + }, z$1.core.$strict>; + maxSeq: z$1.ZodNumber; + delta: z$1.ZodOptional>>; + rowOrder: z$1.ZodOptional>; + }, z$1.core.$strip>>; +}, z$1.core.$strip>; +type ThreadTimelineResponse = z$1.infer; +declare const threadConversationOutlineResponseSchema: z$1.ZodObject<{ + items: z$1.ZodArray; + preview: z$1.ZodString; + attachmentSummary: z$1.ZodNullable>; + }, z$1.core.$strict>>; + maxSeq: z$1.ZodNumber; +}, z$1.core.$strict>; +type ThreadConversationOutlineResponse = z$1.infer; +declare const threadStorageFileListResponseSchema: z$1.ZodObject<{ + files: z$1.ZodArray>; + truncated: z$1.ZodBoolean; + storageRootPath: z$1.ZodString; +}, z$1.core.$strip>; +type ThreadStorageFileListResponse = z$1.infer; +declare const threadStoragePathListResponseSchema: z$1.ZodObject<{ + paths: z$1.ZodArray; + path: z$1.ZodString; + name: z$1.ZodString; + score: z$1.ZodNumber; + positions: z$1.ZodArray; + }, z$1.core.$strip>>; + truncated: z$1.ZodBoolean; + storageRootPath: z$1.ZodString; +}, z$1.core.$strip>; +type ThreadStoragePathListResponse = z$1.infer; + +declare const threadTabsResponseSchema: z$1.ZodObject<{ + revision: z$1.ZodNumber; + tabs: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"git-diff">; + }, z$1.core.$strict>, z$1.ZodObject<{ + actionId: z$1.ZodString; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"plugin-panel">; + paramsJson: z$1.ZodNullable; + pluginId: z$1.ZodString; + title: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"workspace-file-preview">; + lineRange: z$1.ZodNullable>; + path: z$1.ZodString; + projectId: z$1.ZodNullable; + source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"working-tree">; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"head">; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"merge-base">; + ref: z$1.ZodString; + }, z$1.core.$strict>], "kind">; + statusLabel: z$1.ZodNullable>; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"host-file-preview">; + lineRange: z$1.ZodNullable>; + path: z$1.ZodString; + threadId: z$1.ZodNullable; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + isPinned: z$1.ZodBoolean; + kind: z$1.ZodLiteral<"thread-storage-file-preview">; + lineRange: z$1.ZodNullable>; + path: z$1.ZodString; + threadId: z$1.ZodNullable; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"browser">; + title: z$1.ZodNullable; + url: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"new-tab">; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"side-chat">; + sourceMessageText: z$1.ZodString; + sourceSeqEnd: z$1.ZodNullable; + threadId: z$1.ZodNullable; + title: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"terminal">; + terminalId: z$1.ZodString; + }, z$1.core.$strict>], "kind">>; +}, z$1.core.$strict>; +type ThreadTabsResponse = z$1.infer; +declare const updateThreadTabsRequestSchema: z$1.ZodObject<{ + expectedRevision: z$1.ZodNumber; + tabs: z$1.ZodArray; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"git-diff">; + }, z$1.core.$strict>, z$1.ZodObject<{ + actionId: z$1.ZodString; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"plugin-panel">; + paramsJson: z$1.ZodNullable; + pluginId: z$1.ZodString; + title: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"workspace-file-preview">; + lineRange: z$1.ZodNullable>; + path: z$1.ZodString; + projectId: z$1.ZodNullable; + source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{ + kind: z$1.ZodLiteral<"working-tree">; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"head">; + }, z$1.core.$strict>, z$1.ZodObject<{ + kind: z$1.ZodLiteral<"merge-base">; + ref: z$1.ZodString; + }, z$1.core.$strict>], "kind">; + statusLabel: z$1.ZodNullable>; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"host-file-preview">; + lineRange: z$1.ZodNullable>; + path: z$1.ZodString; + threadId: z$1.ZodNullable; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + isPinned: z$1.ZodBoolean; + kind: z$1.ZodLiteral<"thread-storage-file-preview">; + lineRange: z$1.ZodNullable>; + path: z$1.ZodString; + threadId: z$1.ZodNullable; + }, z$1.core.$strict>, z$1.ZodObject<{ + environmentId: z$1.ZodNullable; + id: z$1.ZodString; + kind: z$1.ZodLiteral<"browser">; + title: z$1.ZodNullable; + url: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"new-tab">; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"side-chat">; + sourceMessageText: z$1.ZodString; + sourceSeqEnd: z$1.ZodNullable; + threadId: z$1.ZodNullable; + title: z$1.ZodString; + }, z$1.core.$strict>, z$1.ZodObject<{ + id: z$1.ZodString; + kind: z$1.ZodLiteral<"terminal">; + terminalId: z$1.ZodString; + }, z$1.core.$strict>], "kind">>; +}, z$1.core.$strict>; +type UpdateThreadTabsRequest = z$1.infer; + +interface EnvironmentActionArgs { + environmentId: string; +} +interface EnvironmentGetArgs extends EnvironmentActionArgs { + signal?: AbortSignal; +} +type EnvironmentMergeBaseBranchUpdateValue = Exclude; +type EnvironmentNameUpdateValue = Exclude; +interface EnvironmentMergeBaseBranchUpdate { + mergeBaseBranch: EnvironmentMergeBaseBranchUpdateValue; + name?: EnvironmentNameUpdateValue; +} +interface EnvironmentNameUpdate { + mergeBaseBranch?: EnvironmentMergeBaseBranchUpdateValue; + name: EnvironmentNameUpdateValue; +} +type EnvironmentUpdateFields = EnvironmentMergeBaseBranchUpdate | EnvironmentNameUpdate; +type EnvironmentUpdateArgs = EnvironmentUpdateFields & { + environmentId: string; +}; +interface EnvironmentStatusArgs extends EnvironmentStatusQuery { + environmentId: string; + signal?: AbortSignal; +} +type EnvironmentDiffArgs = EnvironmentDiffQuery & { + environmentId: string; + signal?: AbortSignal; +}; +type EnvironmentDiffFileArgs = EnvironmentDiffFileQuery & { + environmentId: string; + signal?: AbortSignal; +}; +interface EnvironmentDiffBranchesArgs extends EnvironmentDiffBranchesQuery { + environmentId: string; + signal?: AbortSignal; +} +interface EnvironmentCommitArgs { + environmentId: string; +} +interface EnvironmentSquashMergeArgs { + environmentId: string; + mergeBaseBranch: string; +} +interface EnvironmentPullRequestMergeArgs { + environmentId: string; + method: PullRequestMergeMethod; +} +type EnvironmentDiffPatchArgs = EnvironmentDiffPatchRequest & { + environmentId: string; + signal?: AbortSignal; +}; +interface EnvironmentPathsArgs extends EnvironmentPathsQuery { + environmentId: string; + signal?: AbortSignal; +} +type EnvironmentArchiveThreadsResult = EnvironmentArchiveThreadsResponse; +type EnvironmentCommitResult = CommitActionResponse; +type EnvironmentDiffResult = EnvironmentDiffResponse; +type EnvironmentDiffBranchesResult = EnvironmentDiffBranchesResponse; +type EnvironmentDiffFileResult = EnvironmentDiffFileResponse; +type EnvironmentDiffFilesResult = EnvironmentDiffFilesResponse; +type EnvironmentDiffPatchResult = EnvironmentDiffPatchResponse; +type EnvironmentGetResult = Environment; +type EnvironmentMarkPullRequestDraftResult = PullRequestDraftActionResponse; +type EnvironmentMarkPullRequestReadyResult = PullRequestReadyActionResponse; +type EnvironmentMergePullRequestResult = PullRequestMergeActionResponse; +type EnvironmentPathsResult = WorkspacePathListResponse; +type EnvironmentPullRequestResult = EnvironmentPullRequestResponse; +type EnvironmentSquashMergeResult = SquashMergeActionResponse; +type EnvironmentStatusResult = EnvironmentStatusResponse; +type EnvironmentUpdateResult = Environment; +interface EnvironmentsArea { + archiveThreads(args: EnvironmentActionArgs): Promise; + commit(args: EnvironmentCommitArgs): Promise; + diff(args: EnvironmentDiffArgs): Promise; + diffBranches(args: EnvironmentDiffBranchesArgs): Promise; + diffFile(args: EnvironmentDiffFileArgs): Promise; + diffFiles(args: EnvironmentDiffArgs): Promise; + diffPatch(args: EnvironmentDiffPatchArgs): Promise; + get(args: EnvironmentGetArgs): Promise; + pullRequest(args: EnvironmentGetArgs): Promise; + markPullRequestDraft(args: EnvironmentActionArgs): Promise; + markPullRequestReady(args: EnvironmentActionArgs): Promise; + mergePullRequest(args: EnvironmentPullRequestMergeArgs): Promise; + paths(args: EnvironmentPathsArgs): Promise; + squashMerge(args: EnvironmentSquashMergeArgs): Promise; + status(args: EnvironmentStatusArgs): Promise; + update(args: EnvironmentUpdateArgs): Promise; +} + +/** + * Host file primitives. `hostId` may be omitted to target the server's + * primary (local) host. `rootPath`, when set, confines the target beneath + * that absolute root on the host (symlink-safe). + */ +interface FileReadArgs { + hostId?: string; + path: string; + rootPath?: string; + signal?: AbortSignal; +} +interface FileWriteArgs { + hostId?: string; + path: string; + rootPath?: string; + content: string; + /** Defaults to "utf8". */ + contentEncoding?: "utf8" | "base64"; + /** Defaults to false. */ + createParents?: boolean; + /** + * Optimistic-concurrency guard: omitted → unconditional write; a hash → + * write only when the current content hashes to it (use `read().sha256`); + * null → create-only. A failed guard resolves to the `conflict` outcome. + */ + expectedSha256?: string | null; + /** POSIX permission bits used when creating a file (for example 0o600). */ + mode?: number; +} +interface FileListArgs { + hostId?: string; + path: string; + query?: string; + limit?: number; + signal?: AbortSignal; +} +interface PathListArgs extends FileListArgs { + includeFiles: boolean; + includeDirectories: boolean; +} +interface FileMkdirArgs { + hostId?: string; + path: string; + rootPath?: string; + recursive?: boolean; +} +interface FileMoveArgs { + hostId?: string; + sourcePath: string; + destinationPath: string; + rootPath?: string; +} +interface FileRemoveArgs { + hostId?: string; + path: string; + rootPath?: string; + recursive?: boolean; +} +interface FilePreviewArgs { + hostId?: string; + rootPath: string; + signal?: AbortSignal; + ttlMs?: number; +} +type FileReadResult = HostFileReadResponse; +type FileWriteResult = HostFileWriteResponse; +type FileListResult = HostFileListResponse; +type PathListResult = HostPathListResponse; +type FileMkdirResult = HostMkdirResponse; +type FileMoveResult = HostMovePathResponse; +type FileRemoveResult = HostRemovePathResponse; +type FilePreviewResult = CreateFilePreviewResponse; +interface FilesArea { + read(args: FileReadArgs): Promise; + write(args: FileWriteArgs): Promise; + list(args: FileListArgs): Promise; + listPaths(args: PathListArgs): Promise; + mkdir(args: FileMkdirArgs): Promise; + move(args: FileMoveArgs): Promise; + remove(args: FileRemoveArgs): Promise; + createPreview(args: FilePreviewArgs): Promise; +} + +interface GuideRenderArgs { + chapter?: string; +} +interface GuideRenderResult { + chapter?: string; + content: string; +} +interface GuideArea { + render(args?: GuideRenderArgs): GuideRenderResult; +} + +interface HostGetArgs { + hostId: string; + signal?: AbortSignal; +} +interface HostDeleteArgs { + hostId: string; +} +interface HostUpdateArgs extends UpdateHostRequest { + hostId: string; +} +interface HostRetryUpdateArgs { + hostId: string; +} +interface HostDirectoryArgs extends HostDirectoryQuery { + hostId: string; + signal?: AbortSignal; +} +interface HostCloneDefaultPathArgs extends HostCloneDefaultPathQuery { + hostId: string; + signal?: AbortSignal; +} +interface HostPathsExistArgs extends HostPathsExistRequest { + hostId: string; + signal?: AbortSignal; +} +interface HostPickFolderArgs extends HostPickFolderRequest { + hostId: string; + signal?: AbortSignal; +} +interface HostProviderCliInstallArgs extends HostProviderCliInstallRequest { + hostId: string; +} +interface HostListArgs { + signal?: AbortSignal; +} +type HostCreateJoinCodeResult = CreateHostJoinCodeResponse; +type HostDeleteResult = { + ok: true; +}; +type HostDirectoryResult = HostDirectoryListing; +type HostGetResult = Host; +type HostCloneDefaultPathResult = HostCloneDefaultPathResponse; +type HostProviderCliInstallResult = HostProviderCliInstallEvent[]; +type HostListResult = Host[]; +type HostPathsExistResult = HostPathsExistResponse; +type HostPickFolderResult = HostPickFolderResponse; +type HostProviderCliStatusResult = HostProviderCliStatusResponse; +type HostRetryUpdateResult = HostRetryUpdateResponse; +type HostUpdateResult = Host; +interface HostsArea { + createJoinCode(): Promise; + delete(args: HostDeleteArgs): Promise; + directory(args: HostDirectoryArgs): Promise; + get(args: HostGetArgs): Promise; + cloneDefaultPath(args: HostCloneDefaultPathArgs): Promise; + installProviderCli(args: HostProviderCliInstallArgs): Promise; + list(args?: HostListArgs): Promise; + pathsExist(args: HostPathsExistArgs): Promise; + pickFolder(args: HostPickFolderArgs): Promise; + providerCliStatus(args: HostGetArgs): Promise; + retryUpdate(args: HostRetryUpdateArgs): Promise; + update(args: HostUpdateArgs): Promise; +} + +interface ProjectListArgs { + include?: ProjectListQuery["include"]; + /** Include the singleton personal project. Defaults to false for compatibility. */ + includePersonal?: boolean; + signal?: AbortSignal; +} +interface ProjectCreateArgs extends CreateProjectRequest { +} +interface ProjectGetArgs { + projectId: string; + signal?: AbortSignal; +} +interface ProjectUpdateArgs extends UpdateProjectRequest { + projectId: string; +} +interface ProjectDeleteArgs { + projectId: string; +} +interface ProjectReorderArgs extends ReorderProjectRequest { + projectId: string; +} +interface ProjectPromptHistoryArgs extends PromptHistoryQuery { + projectId: string; + signal?: AbortSignal; +} +/** Select one project workspace source, or omit both for the primary host. */ +type ProjectWorkspaceRoutingArgs = { + environmentId: string; + hostId?: never; +} | { + environmentId?: never; + hostId: string; +} | { + environmentId?: never; + hostId?: never; +}; +type ProjectFilesArgs = ProjectWorkspaceRoutingArgs & Omit & { + projectId: string; + signal?: AbortSignal; +}; +type ProjectPathsArgs = ProjectWorkspaceRoutingArgs & Omit & { + projectId: string; + signal?: AbortSignal; +}; +type ProjectCommandsArgs = ProjectWorkspaceRoutingArgs & Omit & { + projectId: string; + signal?: AbortSignal; +}; +type ProjectFileContentArgs = ProjectWorkspaceRoutingArgs & Omit & { + projectId: string; + signal?: AbortSignal; +}; +interface ProjectBranchesArgs extends ProjectBranchesQuery { + projectId: string; + signal?: AbortSignal; +} +interface ProjectDefaultExecutionOptionsArgs { + projectId: string; + signal?: AbortSignal; +} +interface ProjectAttachmentFileLike { + arrayBuffer(): Promise; + readonly name: string; + readonly type?: string; +} +interface ProjectAttachmentUploadArgsBase { + /** MIME override. Omit to use the File/Blob type, when available. */ + mimeType?: string; + projectId: string; +} +/** + * Upload bytes owned by this SDK client. A bare Blob/byte buffer needs an + * explicit filename; File-like values can supply their own name. + */ +type ProjectAttachmentUploadArgs = ProjectAttachmentUploadArgsBase & ({ + clientFile: ProjectAttachmentFileLike; + filename?: string; +} | { + clientFile: ArrayBuffer | Blob | Uint8Array; + filename: string; +}); +interface ProjectAttachmentReadArgs { + path: string; + projectId: string; + signal?: AbortSignal; +} +interface ProjectAttachmentCopyArgs extends CopyProjectAttachmentsRequest { + projectId: string; +} +type ProjectSourceAddArgs = CreateProjectSourceRequest & { + projectId: string; +}; +interface ProjectSourceUpdateArgs extends UpdateProjectSourceRequest { + projectId: string; + sourceId: string; +} +interface ProjectSourceDeleteArgs { + projectId: string; + sourceId: string; +} +type ProjectBranchesResult = ProjectBranchesResponse; +interface ProjectAttachmentReadResult { + bytes: Uint8Array; + mimeType: string; + sizeBytes: number; +} +type ProjectAttachmentUploadResult = UploadedPromptAttachment; +type ProjectCommandsResult = CommandListResponse; +type ProjectCreateResult = ProjectResponse; +type ProjectDefaultExecutionOptionsResult = ProjectExecutionDefaults | null; +type ProjectDeleteResult = { + ok: true; +}; +interface ProjectFileContentResult { + /** UTF-8 text or base64, as selected by `contentEncoding`. */ + content: string; + contentEncoding: "utf8" | "base64"; + mimeType: string; + sizeBytes: number; +} +type ProjectFilesResult = WorkspaceFileListResponse; +type ProjectGetResult = ProjectResponse; +type ProjectListResult = ProjectResponse[] | ProjectWithThreadsResponse[]; +type ProjectPathsResult = WorkspacePathListResponse; +type ProjectPromptHistoryResult = PromptHistoryResponse; +type ProjectReorderResult = ProjectResponse[]; +type ProjectSourceAddResult = ProjectSource; +type ProjectSourceDeleteResult = { + ok: true; +}; +type ProjectSourceUpdateResult = ProjectSource; +type ProjectUpdateResult = ProjectResponse; +interface ProjectSourcesArea { + add(args: ProjectSourceAddArgs): Promise; + delete(args: ProjectSourceDeleteArgs): Promise; + update(args: ProjectSourceUpdateArgs): Promise; +} +interface ProjectAttachmentsArea { + copy(args: ProjectAttachmentCopyArgs): Promise; + read(args: ProjectAttachmentReadArgs): Promise; + upload(args: ProjectAttachmentUploadArgs): Promise; +} +interface ProjectsArea { + attachments: ProjectAttachmentsArea; + branches(args: ProjectBranchesArgs): Promise; + commands(args: ProjectCommandsArgs): Promise; + create(args: ProjectCreateArgs): Promise; + defaultExecutionOptions(args: ProjectDefaultExecutionOptionsArgs): Promise; + delete(args: ProjectDeleteArgs): Promise; + fileContent(args: ProjectFileContentArgs): Promise; + files(args: ProjectFilesArgs): Promise; + get(args: ProjectGetArgs): Promise; + list(args?: ProjectListArgs): Promise; + paths(args: ProjectPathsArgs): Promise; + promptHistory(args: ProjectPromptHistoryArgs): Promise; + reorder(args: ProjectReorderArgs): Promise; + sources: ProjectSourcesArea; + update(args: ProjectUpdateArgs): Promise; +} + +/** Select exactly one provider-discovery host source, or omit both for primary. */ +type ProviderHostRoutingArgs = { + environmentId: string; + hostId?: never; +} | { + environmentId?: never; + hostId: string; +} | { + environmentId?: never; + hostId?: never; +}; +type ProviderListArgs = ProviderHostRoutingArgs & { + signal?: AbortSignal; +}; +type ProviderModelsArgs = ProviderHostRoutingArgs & { + providerId?: string; + signal?: AbortSignal; +}; +type ProviderListResult = ProviderInfo[]; +type ProviderModelsResult = SystemExecutionOptionsResponse; +interface ProvidersArea { + /** List providers on the environment host, explicit host, or primary host. */ + list(args?: ProviderListArgs): Promise; + /** List models on the environment host, explicit host, or primary host. */ + models(args?: ProviderModelsArgs): Promise; +} + +interface PluginIdArgs { + pluginId: string; +} +/** Install directly from a path:, git:, npm:, or builtin: source spec. */ +interface PluginInstallArgs { + source: string; +} +/** Install an entry from BB's official catalog. */ +interface PluginCatalogInstallArgs { + entryId: string; +} +interface PluginReloadArgs { + pluginId?: string; +} +interface PluginSettingsUpdateArgs extends PluginIdArgs { + values: Record; +} +interface PluginTokenArgs extends PluginIdArgs { + rotate?: boolean; +} +interface PluginCheckUpdatesArgs { + pluginId?: string; + signal?: AbortSignal; +} +interface PluginRpcArgs extends PluginIdArgs { + input?: JsonValue; + method: string; + outputSchema: z$1.ZodType; +} +interface PluginCatalogSearchArgs { + query: string; + signal?: AbortSignal; +} +interface PluginCatalogStatusArgs { + signal?: AbortSignal; +} +interface PluginGetSettingsArgs extends PluginIdArgs { + signal?: AbortSignal; +} +interface PluginGetSourceArgs extends PluginIdArgs { + signal?: AbortSignal; +} +interface PluginListArgs { + signal?: AbortSignal; +} +interface PluginListUpdateResultsArgs { + signal?: AbortSignal; +} +type PluginDisableResult = InstalledPlugin; +type PluginEnableResult = InstalledPlugin; +type PluginGetSettingsResult = PluginSettingsResponse; +type PluginInstallResult = InstalledPlugin; +type PluginListResult = PluginListResponse; +type PluginReloadResult = PluginReloadResponse; +type PluginRemoveResult = PluginRemoveResponse; +type PluginTokenResult = PluginTokenResponse; +type PluginUpdateSettingsResult = PluginSettingsResponse; +type PluginGetSourceResult = PluginSourceDetail; +type PluginCheckUpdatesResult = PluginUpdateCheckEntry[]; +type PluginApplyUpdateResult = PluginApplyUpdateResult$1; +type PluginCatalogStatusResult = PluginCatalogStatus; +type PluginCatalogSearchResult = PluginCatalogSearchResult$1[]; +interface PluginCatalogArea { + install(args: PluginCatalogInstallArgs): Promise; + search(args: PluginCatalogSearchArgs): Promise; + status(args?: PluginCatalogStatusArgs): Promise; +} +interface PluginsArea { + applyUpdate(args: PluginIdArgs): Promise; + callRpc(args: PluginRpcArgs): Promise; + checkUpdates(args?: PluginCheckUpdatesArgs): Promise; + catalog: PluginCatalogArea; + disable(args: PluginIdArgs): Promise; + enable(args: PluginIdArgs): Promise; + getSettings(args: PluginGetSettingsArgs): Promise; + getSource(args: PluginGetSourceArgs): Promise; + install(args: PluginInstallArgs): Promise; + list(args?: PluginListArgs): Promise; + listUpdateResults(args?: PluginListUpdateResultsArgs): Promise; + reload(args?: PluginReloadArgs): Promise; + remove(args: PluginIdArgs): Promise; + token(args: PluginTokenArgs): Promise; + updateSettings(args: PluginSettingsUpdateArgs): Promise; +} + +type BbRealtimeUnsubscribe = () => void; +type BbRealtimeEventName = "thread:changed" | "project:changed" | "environment:changed" | "host:changed" | "system:changed" | "system:config-changed" | "realtime:connection"; +type ThreadRealtimeEvent = Extract; +type ProjectRealtimeEvent = Extract; +type EnvironmentRealtimeEvent = Extract; +type HostRealtimeEvent = Extract; +type SystemRealtimeEvent = Extract; +type BbRealtimeConnectionState = "connecting" | "connected" | "disconnected"; +interface BbRealtimeConnectionEvent { + reconnectDelayMs: number | null; + reconnected: boolean; + state: BbRealtimeConnectionState; +} +/** + * Entity-changed events are delivered as one shared object to every matching + * listener; their payload types are readonly so a listener cannot mutate what + * the next listener receives. + */ +interface BbRealtimeEventMap { + "thread:changed": ThreadRealtimeEvent; + "project:changed": ProjectRealtimeEvent; + "environment:changed": EnvironmentRealtimeEvent; + "host:changed": HostRealtimeEvent; + "system:changed": SystemRealtimeEvent; + "system:config-changed": SystemRealtimeEvent; + "realtime:connection": BbRealtimeConnectionEvent; +} +type BbRealtimeCallback = (event: BbRealtimeEventMap[TEventName]) => void; +interface ThreadRealtimeSubscribeArgs { + callback: BbRealtimeCallback<"thread:changed">; + event: "thread:changed"; + threadId?: string; +} +interface ProjectRealtimeSubscribeArgs { + callback: BbRealtimeCallback<"project:changed">; + event: "project:changed"; + projectId?: string; +} +interface EnvironmentRealtimeSubscribeArgs { + callback: BbRealtimeCallback<"environment:changed">; + environmentId?: string; + event: "environment:changed"; +} +interface HostRealtimeSubscribeArgs { + callback: BbRealtimeCallback<"host:changed">; + event: "host:changed"; + hostId?: string; +} +interface SystemRealtimeSubscribeArgs { + callback: BbRealtimeCallback<"system:changed">; + event: "system:changed"; +} +interface SystemConfigRealtimeSubscribeArgs { + callback: BbRealtimeCallback<"system:config-changed">; + event: "system:config-changed"; +} +/** + * Connection listeners are pure observers — they never open or hold the + * socket. A listener registered while a socket already exists receives the + * latest connection event as a snapshot on the next microtask, so a status + * UI mounted after connect still learns the current state. + */ +interface RealtimeConnectionSubscribeArgs { + callback: BbRealtimeCallback<"realtime:connection">; + event: "realtime:connection"; +} +type BbRealtimeSubscribeArgsUnion = ThreadRealtimeSubscribeArgs | ProjectRealtimeSubscribeArgs | EnvironmentRealtimeSubscribeArgs | HostRealtimeSubscribeArgs | SystemRealtimeSubscribeArgs | SystemConfigRealtimeSubscribeArgs | RealtimeConnectionSubscribeArgs; +type BbRealtimeSubscribeArgs = Extract; +interface BbRealtime { + subscribe(args: BbRealtimeSubscribeArgs): BbRealtimeUnsubscribe; +} + +interface StatusGetArgs { + projectId?: string; + signal?: AbortSignal; + threadId?: string; +} +interface StatusThreadSummary { + environmentId: string | null; + id: string; + parentThreadId: string | null; + pinnedAt: number | null; + projectId: string; + status: ThreadStatus; + title: string | null; +} +type StatusProject = ProjectResponse; +type StatusChildThreads = ThreadListResponse; +interface StatusResult { + childThreads: StatusChildThreads | null; + pendingTodos: ThreadTimelinePendingTodos | null; + project: StatusProject | null; + thread: StatusThreadSummary | null; +} +interface StatusArea { + get(args?: StatusGetArgs): Promise; +} + +type ThemeGetResult = AppTheme; +type ThemeCatalogResult = ThemeCatalogResponse; +type ThemeSetInput = AppThemeSelection; +type ThemeSetResult = AppTheme; +interface ThemeCatalogArgs { + signal?: AbortSignal; +} +interface ThemeGetArgs { + signal?: AbortSignal; +} +interface ThemeArea { + /** The active app palette, resolved server-side (built-in id or custom CSS). */ + get(args?: ThemeGetArgs): Promise; + /** The custom-theme directory plus discovered themes and the active palette. */ + catalog(args?: ThemeCatalogArgs): Promise; + /** Set the complete app appearance selection in one request. */ + set(selection: ThemeSetInput): Promise; + /** + * Activate a palette by id while preserving the active favicon color. This + * compatibility shorthand reads the active appearance before writing the + * complete selection; prefer the object form when both values are known. + */ + set(themeId: string): Promise; +} + +interface SystemAttentionArgs { + signal?: AbortSignal; +} +interface SystemConfigArgs { + signal?: AbortSignal; +} +interface SystemExecutionOptionsArgs extends SystemExecutionOptionsQuery { + signal?: AbortSignal; +} +interface SystemUsageLimitsArgs extends SystemUsageLimitsQuery { + signal?: AbortSignal; +} +interface SystemVersionArgs { + force?: boolean; + signal?: AbortSignal; +} +interface SystemVoiceTranscriptionArgs { + file: Blob; + prompt?: string; + signal?: AbortSignal; +} +type SystemAttentionResult = SystemAttentionResponse; +type SystemConfigResult = SystemConfigResponse; +type SystemExecutionOptionsResult = SystemExecutionOptionsResponse; +type SystemReloadConfigResult = SystemConfigReloadResponse; +type SystemVoiceTranscriptionResult = SystemVoiceTranscriptionResponse; +type SystemUpdateExperimentsResult = Experiments; +type SystemUpdateGeneralSettingsResult = AppSettings; +type SystemUpdateKeyboardSettingsResult = AppKeybindingOverrides; +type SystemUsageLimitsResult = ProviderUsageResponse; +type SystemVersionResult = SystemVersionResponse; +interface SystemArea { + attention(args?: SystemAttentionArgs): Promise; + config(args?: SystemConfigArgs): Promise; + executionOptions(args?: SystemExecutionOptionsArgs): Promise; + reloadConfig(): Promise; + transcribeVoice(args: SystemVoiceTranscriptionArgs): Promise; + updateExperiments(args: Experiments): Promise; + updateGeneralSettings(args: AppSettings): Promise; + updateKeyboardSettings(args: AppKeybindingOverrides): Promise; + usageLimits(args?: SystemUsageLimitsArgs): Promise; + version(args?: SystemVersionArgs): Promise; +} + +interface TerminalThreadScope { + cwd?: never; + environmentId?: never; + hostId?: never; + kind: "thread"; + threadId: string; +} +interface TerminalEnvironmentScope { + environmentId: string; + cwd?: never; + hostId?: never; + kind: "environment"; + threadId?: never; +} +interface TerminalHostPathListScope { + /** Optional exact initial working-directory filter on the selected host. */ + cwd?: string; + environmentId?: never; + hostId: string; + kind: "host_path"; + threadId?: never; +} +interface TerminalHostPathCreateScope { + /** Null starts in the selected host's home directory. */ + cwd: string | null; + environmentId?: never; + hostId: string; + kind: "host_path"; + threadId?: never; +} +type TerminalListScope = TerminalThreadScope | TerminalEnvironmentScope | TerminalHostPathListScope; +type TerminalCreateScope = TerminalThreadScope | TerminalEnvironmentScope | TerminalHostPathCreateScope; +interface TerminalListArgs { + signal?: AbortSignal; + scope: TerminalListScope; +} +interface TerminalCreateArgs { + cols: number; + rows: number; + scope: TerminalCreateScope; + start?: CreateTerminalRequest["start"]; + title?: string; +} +interface TerminalTargetArgs { + terminalId: string; +} +interface TerminalGetArgs extends TerminalTargetArgs { + signal?: AbortSignal; +} +interface TerminalRenameArgs extends TerminalTargetArgs { + title: UpdateTerminalRequest["title"]; +} +interface TerminalCloseArgs extends TerminalTargetArgs { + mode: "force" | "if-clean"; +} +interface TerminalInputArgs extends TerminalTargetArgs { + dataBase64: TerminalInputRequest["dataBase64"]; +} +interface TerminalResizeArgs extends TerminalTargetArgs { + cols: TerminalResizeRequest["cols"]; + rows: TerminalResizeRequest["rows"]; +} +interface TerminalOutputArgs extends TerminalTargetArgs { + limitChunks?: TerminalOutputQuery["limitChunks"]; + signal?: AbortSignal; + sinceSeq?: TerminalOutputQuery["sinceSeq"]; + tailBytes?: TerminalOutputQuery["tailBytes"]; +} +type TerminalRestartArgs = TerminalTargetArgs; +type TerminalListResult = TerminalListResponse; +type TerminalCreateResult = TerminalSession; +type TerminalGetResult = TerminalSession; +type TerminalRenameResult = TerminalSession; +type TerminalCloseResult = TerminalSession; +type TerminalInputResult = TerminalSession; +type TerminalResizeResult = TerminalSession; +type TerminalOutputResult = TerminalOutputResponse; +type TerminalRestartResult = TerminalSession; +interface TerminalsArea { + close(args: TerminalCloseArgs): Promise; + create(args: TerminalCreateArgs): Promise; + get(args: TerminalGetArgs): Promise; + input(args: TerminalInputArgs): Promise; + list(args: TerminalListArgs): Promise; + output(args: TerminalOutputArgs): Promise; + rename(args: TerminalRenameArgs): Promise; + /** + * Replace a terminal with a shell at the same scope, size, and title. + * The original command is not replayed because terminal sessions do not + * persist launch commands. The replacement has a new terminal ID. + */ + restart(args: TerminalRestartArgs): Promise; + resize(args: TerminalResizeArgs): Promise; +} + +interface ThreadListArgs { + archived?: boolean; + excludeSideChats?: boolean; + sectionId?: string; + hasParent?: boolean; + includeHidden?: boolean; + limit?: number; + offset?: number; + originKind?: ThreadListQuery["originKind"]; + parentThreadId?: string; + projectId?: string; + signal?: AbortSignal; + sourceThreadId?: string; + unsectioned?: boolean; +} +interface ThreadSearchArgs extends ThreadSearchQuery { + signal?: AbortSignal; +} +interface ThreadGetArgs { + include?: ThreadGetQuery["include"]; + signal?: AbortSignal; + threadId: string; +} +type ThreadGetResult = ThreadResponse | ThreadWithIncludesResponse; +type ThreadListResult = ThreadListResponse; +type ThreadSearchResult = ThreadSearchResponse; +interface ThreadOutputResponse { + output: string | null; +} +type ThreadMutationResult = ThreadResponse; +type ThreadSpawnResult = ThreadResponse; +type ThreadForkResult = ThreadResponse; +type ThreadInteractionGetResult = PendingInteraction; +type ThreadInteractionListResult = ThreadPendingInteractionsResponse; +type ThreadInteractionResolveResult = PendingInteraction; +type ThreadInteractionRespondResult = PendingInteraction; +type ThreadInteractionCancelResult = PendingInteraction; +type ThreadEventsListResult = ThreadEventRow[]; +type ThreadEventWaitResult = ThreadEventRow | null; +type ThreadTimelineResult = ThreadTimelineResponse; +type ThreadArchiveResult = ThreadArchiveAllResponse; +type ThreadOpenResult = ThreadOpenResponse; +type ThreadPaneActionResult = ThreadPaneActionResponse; +type ThreadDeleteResult = { + ok: true; +}; +type ThreadSendResult = { + ok: true; +}; +type ThreadStopResult = { + ok: true; +}; +type ThreadBannerActionResult = { + ok: true; +}; +type ThreadUnarchiveResult = { + ok: true; +}; +type ThreadArchiveAllResult = ThreadArchiveAllResponse; +type ThreadReadStateResult = ThreadResponse; +type ThreadPinOrderResult = ThreadListResponse; +type ThreadPromptHistoryResult = PromptHistoryResponse; +type ThreadQueuedMessagesResult = ThreadQueuedMessageListResponse; +type ThreadQueuedMessageCreateResult = ThreadQueuedMessage; +type ThreadQueuedMessageUpdateResult = ThreadQueuedMessage; +type ThreadQueuedMessageDeleteResult = { + ok: true; +}; +type ThreadQueuedMessageReorderResult = ThreadQueuedMessageListResponse; +type ThreadQueuedMessageSendResult = SendQueuedMessageResponse; +type ThreadQueuedMessageGroupBoundaryResult = ThreadQueuedMessageListResponse; +type ThreadTabsResult = ThreadTabsResponse; +type ThreadTabsUpdateResult = ThreadTabsResponse; +type ThreadStorageFilesResult = ThreadStorageFileListResponse; +type ThreadStoragePathsResult = ThreadStoragePathListResponse; +type ThreadChildSummaryResult = ThreadChildSummaryResponse; +type ThreadDefaultExecutionOptionsResult = ResolvedThreadExecutionOptions | null; +type ThreadConversationOutlineResult = ThreadConversationOutlineResponse; +type ThreadTimelineTurnSummaryDetailsResult = TimelineTurnSummaryDetailsResponse; +interface ThreadSpawnBaseArgs extends Omit { + childOrigin?: CreateThreadRequest["childOrigin"]; + origin?: CreateThreadRequest["origin"]; + originKind?: CreateThreadRequest["originKind"]; + startedOnBehalfOf?: CreateThreadRequest["startedOnBehalfOf"]; +} +type ThreadSpawnArgs = ThreadSpawnBaseArgs & ({ + input: CreateThreadRequest["input"]; + prompt?: never; +} | { + input?: never; + prompt: string; +}); +interface ThreadForkArgs extends Omit { + origin?: ForkThreadRequest["origin"]; + visibility?: ForkThreadRequest["visibility"]; + workspace?: ForkThreadRequest["workspace"]; +} +interface ThreadUpdateArgs extends UpdateThreadRequest { + threadId: string; +} +interface ThreadDeleteArgs extends DeleteThreadRequest { + threadId: string; +} +interface ThreadSendArgs extends SendMessageRequest { + threadId: string; +} +interface ThreadActionArgs { + threadId: string; +} +interface ThreadStatusArgs extends ThreadActionArgs { + signal?: AbortSignal; +} +interface ThreadPromptHistoryArgs extends PromptHistoryQuery { + signal?: AbortSignal; + threadId: string; +} +interface ThreadPinOrderArgs extends ReorderPinnedThreadRequest { + threadId: string; +} +interface ThreadQueuedMessageArgs { + signal?: AbortSignal; + threadId: string; +} +interface ThreadQueuedMessageCreateArgs extends CreateQueuedMessageRequest { + threadId: string; +} +interface ThreadQueuedMessageUpdateArgs extends ThreadQueuedMessageTargetArgs, UpdateQueuedMessageRequest { +} +interface ThreadQueuedMessageTargetArgs { + queuedMessageId: string; + threadId: string; +} +interface ThreadQueuedMessageSendArgs extends ThreadQueuedMessageTargetArgs, SendQueuedMessageRequest { +} +interface ThreadQueuedMessageReorderArgs extends ThreadQueuedMessageTargetArgs, ReorderQueuedMessageRequest { +} +interface ThreadQueuedMessageGroupBoundaryArgs extends SetQueuedMessageGroupBoundaryRequest { + threadId: string; +} +interface ThreadStorageFilesArgs extends ThreadStorageFilesQuery { + signal?: AbortSignal; + threadId: string; +} +interface ThreadStoragePathsArgs extends ThreadStoragePathsQuery { + signal?: AbortSignal; + threadId: string; +} +interface ThreadTimelineTurnSummaryDetailsArgs extends TimelineTurnSummaryDetailsQuery { + signal?: AbortSignal; + threadId: string; +} +interface ThreadTabsUpdateArgs extends UpdateThreadTabsRequest { + threadId: string; +} +interface ThreadOpenArgs { + threadId: string; + split?: ThreadOpenSplit; + file: ThreadOpenFile | null; +} +interface ThreadPaneActionArgs { + action: ThreadPaneAction; + threadId: string; +} +interface ThreadEventsListArgs { + afterSeq?: string; + limit?: string; + signal?: AbortSignal; + threadId: string; +} +interface ThreadEventWaitArgs { + afterSeq?: string; + signal?: AbortSignal; + threadId: string; + type: string; + waitMs: string; +} +interface ThreadTimelineArgs extends ThreadTimelineQuery { + signal?: AbortSignal; + threadId: string; +} +interface ThreadOutputArgs { + signal?: AbortSignal; + threadId: string; +} +interface ThreadInteractionListArgs { + signal?: AbortSignal; + threadId: string; +} +interface ThreadInteractionTargetArgs { + interactionId: string; + threadId: string; +} +interface ThreadInteractionGetArgs extends ThreadInteractionTargetArgs { + signal?: AbortSignal; +} +interface ThreadInteractionResolveArgs extends ThreadInteractionTargetArgs { + resolution: PendingInteractionResolution; +} +interface ThreadInteractionRespondArgs extends ThreadInteractionTargetArgs { + value: JsonValue; +} +type ThreadWaitTarget = { + kind: "status"; + status: ThreadStatus; +} | { + kind: "event"; + eventType: string; +}; +interface ThreadWaitArgs { + event?: string; + pollIntervalMs?: number; + signal?: AbortSignal; + status?: ThreadStatus; + threadId: string; + timeoutMs?: number; +} +type ThreadWaitResult = { + event: NonNullable; + matched: true; + target: Extract; + threadId: string; +} | { + matched: true; + target: Extract; + thread: ThreadGetResult; + threadId: string; +}; +interface ThreadInteractionsArea { + cancel(args: ThreadInteractionTargetArgs): Promise; + get(args: ThreadInteractionGetArgs): Promise; + list(args: ThreadInteractionListArgs): Promise; + resolve(args: ThreadInteractionResolveArgs): Promise; + respond(args: ThreadInteractionRespondArgs): Promise; +} +interface ThreadEventsArea { + list(args: ThreadEventsListArgs): Promise; + wait(args: ThreadEventWaitArgs): Promise; +} +interface ThreadQueuedMessagesArea { + create(args: ThreadQueuedMessageCreateArgs): Promise; + delete(args: ThreadQueuedMessageTargetArgs): Promise; + list(args: ThreadQueuedMessageArgs): Promise; + reorder(args: ThreadQueuedMessageReorderArgs): Promise; + send(args: ThreadQueuedMessageSendArgs): Promise; + setGroupBoundary(args: ThreadQueuedMessageGroupBoundaryArgs): Promise; + update(args: ThreadQueuedMessageUpdateArgs): Promise; +} +interface ThreadTabsArea { + get(args: ThreadStatusArgs): Promise; + update(args: ThreadTabsUpdateArgs): Promise; +} +interface ThreadsArea { + archive(args: ThreadActionArgs): Promise; + archiveAll(args: ThreadActionArgs): Promise; + childSummary(args: ThreadStatusArgs): Promise; + cancelPlan(args: ThreadActionArgs): Promise; + clearGoal(args: ThreadActionArgs): Promise; + conversationOutline(args: ThreadStatusArgs): Promise; + defaultExecutionOptions(args: ThreadStatusArgs): Promise; + delete(args: ThreadDeleteArgs): Promise; + events: ThreadEventsArea; + fork(args: ThreadForkArgs): Promise; + get(args: ThreadGetArgs): Promise; + interactions: ThreadInteractionsArea; + list(args?: ThreadListArgs): Promise; + markRead(args: ThreadActionArgs): Promise; + markUnread(args: ThreadActionArgs): Promise; + open(args: ThreadOpenArgs): Promise; + paneAction(args: ThreadPaneActionArgs): Promise; + output(args: ThreadOutputArgs): Promise; + pin(args: ThreadActionArgs): Promise; + promptHistory(args: ThreadPromptHistoryArgs): Promise; + queuedMessages: ThreadQueuedMessagesArea; + reorderPinned(args: ThreadPinOrderArgs): Promise; + search(args: ThreadSearchArgs): Promise; + send(args: ThreadSendArgs): Promise; + spawn(args: ThreadSpawnArgs): Promise; + stop(args: ThreadActionArgs): Promise; + tabs: ThreadTabsArea; + timeline(args: ThreadTimelineArgs): Promise; + timelineTurnSummaryDetails(args: ThreadTimelineTurnSummaryDetailsArgs): Promise; + storageFiles(args: ThreadStorageFilesArgs): Promise; + storagePaths(args: ThreadStoragePathsArgs): Promise; + unarchive(args: ThreadActionArgs): Promise; + unpin(args: ThreadActionArgs): Promise; + update(args: ThreadUpdateArgs): Promise; + wait(args: ThreadWaitArgs): Promise; +} + +type ThreadSectionCreateResult = ThreadSectionResponse; +type ThreadSectionUpdateResult = ThreadSectionMutationResponse; +type ThreadSectionDeleteResult = ThreadSectionMutationResponse; +type ThreadSectionListResult = ThreadSectionResponse[]; +interface ThreadSectionListArgs { + signal?: AbortSignal; +} +interface ThreadSectionsArea { + create(args: CreateThreadSectionRequest): Promise; + delete(args: DeleteThreadSectionRequest): Promise; + list(args?: ThreadSectionListArgs): Promise; + update(args: UpdateThreadSectionRequest): Promise; +} + +interface BbSdk extends BbRealtime { + environments: EnvironmentsArea; + files: FilesArea; + guide: GuideArea; + hosts: HostsArea; + projects: ProjectsArea; + plugins: PluginsArea; + providers: ProvidersArea; + status: StatusArea; + system: SystemArea; + terminals: TerminalsArea; + theme: ThemeArea; + threadSections: ThreadSectionsArea; + threads: ThreadsArea; +} + +/** + * The backend plugin API contract — the `bb` object handed to a plugin's + * `server.ts` factory (`export default function plugin(bb: BbPluginApi)`). + * + * Types only: the implementation lives in the BB server + * (apps/server/src/services/plugins/plugin-api.ts), which imports these + * shapes so the contract and the implementation cannot drift. Plugin authors + * import them type-only (`import type { BbPluginApi } from + * "@bb/plugin-sdk"`); the import is erased when BB loads the file. + * + * Runtime classes stay host-side. NeedsConfigurationError in particular is + * matched by NAME, so plugin code needs no runtime import: + * `throw Object.assign(new Error(msg), { name: "NeedsConfigurationError" })`. + */ +interface PluginLogger { + debug(message: string): void; + info(message: string): void; + warn(message: string): void; + error(message: string): void; +} +/** + * Declarative settings descriptors (`bb.settings.define`). Deliberately plain + * data — not zod — so the host can render settings forms and the CLI can + * parse values without executing plugin code. + */ +type PluginSettingDescriptor = { + type: "string"; + label: string; + description?: string; + /** Stored in a 0600 file under /plugins//secrets/, never in the db or sent to the frontend. */ + secret?: true; + default?: string; +} | { + type: "boolean"; + label: string; + description?: string; + default?: boolean; +} | { + type: "select"; + label: string; + description?: string; + options: string[]; + default?: string; +} | { + type: "project"; + label: string; + description?: string; + default?: string; +}; +type PluginSettingDescriptors = Record; +type PluginSettingValue = string | boolean; +/** `default` present → non-optional value; absent → `T | undefined`. */ +type PluginSettingsValues> = { + [K in keyof Ds]: Ds[K] extends { + default: string | boolean; + } ? PluginSettingValueOf : PluginSettingValueOf | undefined; +}; +type PluginSettingValueOf = D extends { + type: "boolean"; +} ? boolean : string; +interface PluginSettingsHandle> { + /** Load-safe: callable inside the factory. */ + get(): Promise>; + /** Fires after values change through the settings route/CLI. */ + onChange(listener: (next: PluginSettingsValues, prev: PluginSettingsValues) => void): void; +} +interface PluginSettings { + define>(descriptors: Ds): PluginSettingsHandle; +} +interface PluginKvStorage { + get(key: string): Promise; + set(key: string, value: unknown): Promise; + delete(key: string): Promise; + list(prefix?: string): Promise; +} +interface PluginStorage { + /** Namespaced JSON key-value rows in bb.db; values ≤256KB each. */ + kv: PluginKvStorage; + /** + * Open (or reuse the path of) the plugin's own SQLite database at + * /plugins//data.db — the server's better-sqlite3, WAL mode, + * busy_timeout 5000. Handles are host-tracked and closed on + * dispose/reload; a closed handle throws on use. + */ + database(): Database.Database; + /** + * Ordered-statement migration helper: statement index = migration id in a + * `_bb_migrations` table; unapplied statements run in one transaction. + * Append-only — never reorder or edit shipped statements. + */ + migrate(db: Database.Database, statements: string[]): void; +} +/** + * Thread lifecycle events a plugin can observe (design §4.5). Observe-only: + * handlers run fire-and-forget after the transition is applied and can never + * block or veto it. `thread` is the same public DTO GET /threads/:id serves. + */ +interface PluginThreadEventPayloads { + /** Fired after a thread row is created. */ + "thread.created": { + thread: ThreadResponse; + }; + /** Fired when a thread transitions into `active`. */ + "thread.active": { + thread: ThreadResponse; + }; + /** Fired when a thread transitions into `idle`. `lastAssistantText` is + * assembled the same way GET /threads/:id/output is. */ + "thread.idle": { + thread: ThreadResponse; + lastAssistantText: string | null; + }; + /** Fired when a thread transitions into `error`. `error` is the latest + * system/error event message, when one exists. */ + "thread.failed": { + thread: ThreadResponse; + error: string | null; + }; + /** Fired after a thread is archived (including cascade archives). */ + "thread.archived": { + thread: ThreadResponse; + }; + /** Fired after a thread is soft-deleted. */ + "thread.deleted": { + thread: ThreadResponse; + }; +} +type PluginThreadEventName = keyof PluginThreadEventPayloads; +type PluginThreadEventHandler = (payload: PluginThreadEventPayloads[E]) => void | Promise; +type PluginHttpAuthMode = "local" | "token" | "none"; +type PluginHttpHandler = (context: Context) => Response | Promise; +interface PluginHttp { + /** + * Register an HTTP route, mounted at + * `/api/v1/plugins//http/`. Auth modes (default "local"): + * - "local": Origin/Host must be a local BB app origin; non-GET requires + * content-type application/json (forces a CORS preflight). + * - "token": requires the per-plugin token (`bb plugin token `) via + * the x-bb-plugin-token header or ?token=. + * - "none": no checks — only for signature-verified webhooks. + */ + route(method: string, path: string, handler: PluginHttpHandler, opts?: { + auth?: PluginHttpAuthMode; + }): void; +} +interface PluginRpc { + /** + * Register a Standard Schema-driven rpc contract and its inferred handlers, + * served at POST + * `/api/v1/plugins//rpc/` with "local" auth semantics. The + * host validates input before invocation and output before strict JSON + * serialization. The response is `{ ok: true, result }` or + * `{ ok: false, error: { code, message, issues? } }`. + */ + register(contract: Contract, handlers: PluginRpcHandlers): void; +} +interface PluginRealtime { + /** + * Broadcast an ephemeral `plugin-signal` WS message + * `{ pluginId, channel, payload }` to every connected client (V1 has no + * per-channel subscriptions). `payload` must be JSON-serializable; + * `undefined` is normalized to `null`. Nothing is persisted. + */ + publish(channel: string, payload: unknown): void; +} +interface PluginBackground { + /** + * Register a long-lived background service. `start` runs after the + * factory completes and should resolve when `signal` aborts + * (dispose/reload/disable/shutdown). A crash restarts it with capped + * exponential backoff; throwing NeedsConfigurationError marks the plugin + * `needs-configuration` and stops restarting until the next load. + */ + service(name: string, service: { + start(signal: AbortSignal): void | Promise; + }): void; + /** + * Register a cron schedule (5-field expression, server-local time). The + * durable row keyed (pluginId, name) is upserted at load; the periodic + * sweep claims due rows with a CAS on next_run_at, but only while this + * plugin is loaded. Failures land in last_status/last_error, visible in + * `bb plugin list`. + */ + schedule(name: string, cron: string, fn: () => void | Promise): void; +} +interface PluginCliCommandInfo { + name: string; + summary: string; + usage: string; +} +/** Context forwarded from the invoking CLI when known; all fields optional. */ +interface PluginCliContext { + cwd?: string; + threadId?: string; + projectId?: string; + /** Aborted when the invoking CLI HTTP request disconnects. */ + signal?: AbortSignal; +} +type PluginInteractionCancelReason = "user" | "request-aborted" | "thread-stopped" | "thread-deleted" | "plugin-disposed" | "server-restarted" | "timeout"; +type PluginInteractionResult = { + outcome: "submitted"; + value: JsonValue$1; +} | { + outcome: "cancelled"; + reason: PluginInteractionCancelReason; +}; +interface PluginInteractionRequest { + threadId: string; + rendererId: string; + title: string; + payload: JsonValue$1; + /** Defaults to ten minutes; capped at one hour. */ + timeoutMs?: number; +} +interface PluginCliResult { + exitCode: number; + stdout?: string; + stderr?: string; +} +/** + * Maximum combined UTF-8 bytes accepted from plugin CLI stdout and stderr. + * This is the shared source of truth for production and the testing harness. + */ +declare const PLUGIN_CLI_OUTPUT_MAX_BYTES: number; +interface PluginCliOutputLimitError { + code: "plugin_cli_output_too_large"; + message: string; + maxBytes: number; + stdoutBytes: number; + stderrBytes: number; + totalBytes: number; +} +/** Normalized host result returned by the plugin CLI HTTP/testing boundary. */ +interface PluginCliExecutionResult { + exitCode: number; + stdout: string; + stderr: string; + error?: PluginCliOutputLimitError; +} +interface PluginCliRegistration { + /** Top-level command name (`bb …`): lowercase [a-z0-9-]+, and not + * a core bb command (see RESERVED_BB_CLI_COMMANDS in the server). */ + name: string; + summary: string; + /** Subcommand metadata rendered in help and the plugin-commands skill + * without executing plugin code. Parsing argv is plugin-owned. */ + commands?: PluginCliCommandInfo[]; + run(argv: string[], ctx: PluginCliContext): PluginCliResult | Promise; +} +interface PluginCli { + /** + * Register this plugin's `bb` subcommand. One registration per factory + * execution; a repeated call is rejected. Core bb commands always win + * name collisions; reserved names are rejected at registration. + */ + register(registration: PluginCliRegistration): void; +} +/** Per-turn context handed to bb.agents context providers (design §4.4). */ +/** MCP-style content parts a native tool may return (design §4.4). */ +type PluginAgentToolContentPart = { + type: "text"; + text: string; +} | { + type: "image"; + data: string; + mimeType: string; +}; +type PluginAgentToolResult = string | { + content: PluginAgentToolContentPart[]; + isError?: boolean; +}; +/** Per-call context handed to a native tool's execute (design §4.4). */ +interface PluginAgentToolContext { + threadId: string; + projectId: string; + /** The tool-call request's abort signal (aborts if the daemon round-trip + * is torn down mid-call). */ + signal: AbortSignal; +} +interface PluginAgentToolRegistrationBase { + /** Tool name shown to the model: [a-zA-Z0-9_-]+, unique across plugins, + * and not a built-in dynamic tool (see RESERVED_AGENT_TOOL_NAMES in the + * server). */ + name: string; + description: string; + /** + * Optional usage snippet appended to the thread instructions whenever + * this tool is in the session's tool set (mirrors the built-in + * update_environment_directory guidance). Limited to 4096 characters. + */ + instructions?: string; +} +/** Stable, plain-data context resolved by the server for one agent session. */ +interface PluginAgentConfigurationContext { + thread: { + id: string; + title: string | null; + parentThreadId: string | null; + sourceThreadId: string | null; + }; + project: { + id: string; + kind: "standard" | "personal"; + name: string; + gitRemoteUrl: string | null; + }; + environment: { + id: string; + name: string | null; + path: string | null; + workspaceProvisionType: "unmanaged" | "managed-worktree" | "personal"; + branchName: string | null; + }; + host: { + id: string; + name: string; + }; + provider: { + id: string; + model: string; + }; + sideChat: boolean; + origin: { + kind: "fork" | "side-chat" | null; + pluginId: string | null; + }; +} +/** Object form of a {@link PluginAgentConfiguration} tools entry: selects a + * registered tool and overrides the parameter schema advertised to the + * provider for this resolution only. */ +interface PluginAgentToolSelection { + /** Name of a tool registered by this plugin via `registerTool`. */ + name: string; + /** JSON-schema object (root `type: "object"`, JSON-serializable, at most + * 128 KiB serialized) sent to the provider in place of the registered + * parameter schema. Execution-side validation still runs the registered + * parameters, so the override must only narrow what the registered schema + * already accepts. */ + parameters: Record; +} +/** Per-resolution selection returned by {@link PluginAgents.configure}. */ +interface PluginAgentConfiguration { + /** Tool names registered by this plugin, or {@link PluginAgentToolSelection} + * entries to also override a tool's advertised parameter schema for this + * resolution. Duplicate or unknown names, or an invalid override, reject + * this plugin's complete selection for the resolution. */ + tools: Array; + /** Skill frontmatter names from this plugin's manifest skill roots. + * Duplicate or unknown names reject this plugin's complete selection. */ + skills: string[]; + /** Optional dynamic instructions. Output is truncated to 4096 characters. */ + instructions?: string; +} +interface PluginAgents { + /** + * Select this plugin's statically registered tools and manifest skills for + * each thread/session resolution, with optional dynamic instructions. The + * callback is synchronous and runs at `thread.start` / `turn.submit`; it + * never rebuilds registrations. Exactly one callback may be registered per + * factory execution. A throw, malformed result, duplicate id, unknown id, + * or more than 256 tool/skill ids fails closed for this plugin only. + * + * Tools take effect when the provider session is next started or resumed; + * an already-running session is not hot-mutated. Instructions are resolved + * for the next turn. Skill changes follow BB's environment runtime policy: + * a busy runtime keeps its current catalog until a safe relaunch. Side-chat + * threads receive `sideChat: true`, and their returned tool, skill, and + * dynamic-instruction selections apply at the same boundaries. Independent + * side-chat safety policy (such as permission escalation) is unchanged. + */ + configure(provider: (context: PluginAgentConfigurationContext) => PluginAgentConfiguration): void; + /** + * Register a native dynamic tool (design §4.4). `parameters` is either a + * zod schema (validated per call; execute receives the parsed value) or a + * plain JSON-schema object (no validation; execute receives the raw + * arguments as `unknown`). Tool-set changes apply on the NEXT session + * start — a tool registered mid-session is not hot-added to running + * provider sessions. A second registration of the same name within this + * plugin is rejected; a name already registered by another plugin is + * rejected and surfaced as this plugin's status detail. + */ + registerTool(tool: PluginAgentToolRegistrationBase & { + parameters: Schema; + execute(params: z.output, ctx: PluginAgentToolContext): PluginAgentToolResult | Promise; + }): void; + registerTool(tool: PluginAgentToolRegistrationBase & { + /** Raw JSON-schema escape hatch; params arrive unvalidated. */ + parameters: Record; + execute(params: unknown, ctx: PluginAgentToolContext): PluginAgentToolResult | Promise; + }): void; + /** + * Contribute a dynamic section appended to thread instructions. The + * provider runs when a thread's runtime command config is resolved + * (thread.start / turn.submit); return null to contribute nothing for + * that resolution. Must be synchronous and fast — it sits on the + * thread-start path. Output longer than 4096 characters is truncated; a + * throwing provider is logged against the plugin and contributes nothing. + * A repeated registration within one factory execution is rejected. + * This legacy contribution is not applied to side-chat threads; use + * configure() when sideChat-aware dynamic instructions are required. + */ + contributeInstructions(provider: (ctx: { + threadId: string; + projectId: string; + }) => string | null): void; +} +interface PluginThreadActionContext { + threadId: string; + projectId: string; +} +interface PluginThreadActionToast { + kind: "success" | "error" | "info"; + message: string; +} +type PluginThreadActionResult = void | { + toast?: PluginThreadActionToast; +}; +interface PluginThreadActionRegistration { + /** Unique within this plugin: [a-zA-Z0-9_-]+ (becomes a URL segment). */ + id: string; + /** Button label rendered in the thread header. */ + title: string; + /** Optional icon name; the host falls back to a generic icon. */ + icon?: string; + /** Optional confirmation prompt the host shows before running. */ + confirm?: string; + /** + * Runs server-side when the user clicks the action. The host shows a + * pending state while in flight, the returned toast on completion, and an + * automatic error toast when this throws. + */ + run(ctx: PluginThreadActionContext): PluginThreadActionResult | Promise; +} +type PluginMentionTrigger = "@" | "#" | "$" | "!" | "~"; +/** Search context handed to a mention provider (design §4.9). `projectId`/ + * `threadId` are null when the composer has not committed one yet. */ +interface PluginMentionSearchContext { + trigger: PluginMentionTrigger; + query: string; + projectId: string | null; + threadId: string | null; +} +/** One row a mention provider returns from `search`. `id` is the provider's + * own item id — the host namespaces it before it reaches the wire. */ +interface PluginMentionItem { + id: string; + title: string; + subtitle?: string; + icon?: string; +} +interface PluginMentionProviderRegistration { + /** Unique within this plugin: [a-zA-Z0-9_-]+ (no ":" — the host composes + * wire item ids as ":"). */ + id: string; + /** Section label shown above this provider's rows in the mention menu. */ + label: string; + /** + * Composer trigger characters this provider should answer. Omit to use the + * default `@` mention trigger. Valid triggers are `@`, `#`, `$`, `!`, and `~`. + */ + triggers?: readonly PluginMentionTrigger[]; + /** + * Runs server-side as the user types after one of this provider's triggers + * in the composer. Each call is time-boxed (2s) and failure-isolated: a slow + * or throwing provider contributes an empty list — it can never break the + * mention menu. + */ + search(ctx: PluginMentionSearchContext): PluginMentionItem[] | Promise; + /** + * Resolves one picked item into agent context, called once per unique + * item at message send time. The returned `context` is attached to the + * message as an agent-visible (user-hidden) prompt input. Throwing blocks + * the send with a visible error. + */ + resolve(itemId: string): { + context: string; + } | Promise<{ + context: string; + }>; +} +interface PluginUi { + /** Block until the app submits or cancels a plugin-owned composer form. */ + requestInput(request: PluginInteractionRequest, options?: { + signal?: AbortSignal; + }): Promise; + /** + * Register a thread action rendered in the shipped app's thread header + * (design §4.9). Multiple actions per plugin; ids must be unique within + * the plugin. Invoked via POST /plugins/:id/actions/:actionId. + */ + registerThreadAction(action: PluginThreadActionRegistration): void; + /** + * Register a mention provider for the shipped app's composer (design §4.9). + * Providers default to the `@` trigger and may opt into `#`, `$`, `!`, or + * `~` with `triggers`. Items group under `label` in the mention menu; a + * picked item becomes a `{ kind: "plugin" }` mention resource whose context + * is resolved once at send time. Multiple providers per plugin; ids must be + * unique within the plugin. + */ + registerMentionProvider(provider: PluginMentionProviderRegistration): void; +} +interface PluginEvents { + /** + * Add a thread lifecycle listener. Multiple listeners for the same event are + * additive and run independently in registration order. + */ + on(event: E, handler: PluginThreadEventHandler): void; +} +interface PluginServerApi { + /** + * This BB server's own loopback base URL (e.g. "http://127.0.0.1:38886"), + * which serves the SPA + /api + /ws. For plugins that proxy or relay + * traffic back to the server itself (e.g. a tunnel). Bind-gated like + * `bb.sdk`: reading it before the server is listening throws, so prefer + * reading it from handlers, services, and timers. + */ + readonly loopbackBaseUrl: string; +} +interface PluginSharedPortTunnelIdentity { + /** Gate routing label assigned to this machine. */ + label: string; + /** Gate apex without a scheme, e.g. "getbb.app". */ + baseDomain: string; +} +interface PluginHosts { + /** + * Ensure this enrolled host has a gate label and return its read-only public + * identity. The daemon chooses the trusted gate and desired label; plugins + * cannot influence either credential-bearing destination. + */ + ensureSharedPortTunnel(hostId: string): Promise; + /** + * Replace this plugin's desired shared-loopback ports for one host. The + * server aggregates declarations, owns generations, and delivers the + * resulting set to that host's daemon. Tunnel identity is deliberately not + * accepted here: it is owned by the daemon's trusted enrollment. + */ + declareSharedPorts(hostId: string, ports: readonly number[]): void; +} +interface PluginStatusApi { + /** + * Mark this plugin `needs-configuration` (with a message shown in + * `bb plugin list` and the UI) instead of failing — e.g. a factory or + * service that finds no API key configured. Cleared on the next load; + * saving settings does not auto-reload in V1, so ask the user to + * `bb plugin reload ` after configuring. + */ + needsConfiguration(message: string): void; +} +/** + * The API object handed to a plugin's factory (design §4). Implemented by + * the BB server; this contract is what plugin `server.ts` files compile + * against. + */ +interface BbPluginApi { + /** The plugin's own id (namespaces storage, routes, commands). */ + readonly pluginId: string; + /** Leveled, plugin-scoped logger. */ + readonly log: PluginLogger; + /** Declarative settings (design §4.2). */ + readonly settings: PluginSettings; + /** Namespaced KV + per-plugin database (design §4.3). */ + readonly storage: PluginStorage; + /** HTTP routes under /api/v1/plugins//http/* (design §4.6). */ + readonly http: PluginHttp; + /** RPC methods under /api/v1/plugins//rpc/ (design §4.6). */ + readonly rpc: PluginRpc; + /** Ephemeral push to connected frontends (design §4.7). */ + readonly realtime: PluginRealtime; + /** Long-lived services + cron schedules (design §4.8). */ + readonly background: PluginBackground; + /** Agent-facing `bb` CLI subcommand (design §4.4). */ + readonly cli: PluginCli; + /** Per-turn agent context contributions (design §4.4). */ + readonly agents: PluginAgents; + /** Host-rendered UI contributions (design §4.9). */ + readonly ui: PluginUi; + /** Additive plugin lifecycle listeners (design §4.5). */ + readonly events: PluginEvents; + /** Plugin-reported status (needs-configuration). */ + readonly status: PluginStatusApi; + /** Read-only facts about the running server (loopback base URL). */ + readonly server: PluginServerApi; + /** Server-to-daemon host control-plane declarations. */ + readonly hosts: PluginHosts; + /** + * The full BB SDK, bound to this server over loopback (design §4.1). + * Bind-gated: reading this before the host binds the SDK throws. The real + * server binds it before loading plugins, so it is available from the + * moment factories run there — but isolated harnesses may not, so prefer + * using it from handlers, services, and timers for portability. + * `threads.spawn` defaults `origin` to "plugin" and `originPluginId` to + * this plugin's id so spawned threads are attributed automatically. + */ + readonly sdk: BbSdk; + /** + * Register cleanup to run on reload/disable/shutdown. Hooks run LIFO. + * The sanctioned place to clear timers and close connections. + */ + onDispose(hook: () => void | Promise): void; +} + +export { PLUGIN_CLI_OUTPUT_MAX_BYTES, defineRpcContract }; +export type { BbContext, BbNavigate, BbPluginApi, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, JsonValue$1 as JsonValue, MarkdownProps, PluginAgentConfiguration, PluginAgentConfigurationContext, PluginAgentToolContentPart, PluginAgentToolContext, PluginAgentToolRegistrationBase, PluginAgentToolResult, PluginAgentToolSelection, PluginAgents, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginBackground, PluginCli, PluginCliCommandInfo, PluginCliContext, PluginCliExecutionResult, PluginCliOutputLimitError, PluginCliRegistration, PluginCliResult, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginEvents, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginHosts, PluginHttp, PluginHttpAuthMode, PluginHttpHandler, PluginInteractionCancelReason, PluginInteractionRequest, PluginInteractionResult, PluginKvStorage, PluginLogger, PluginMentionItem, PluginMentionProviderRegistration, PluginMentionSearchContext, PluginMentionTrigger, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageActionThreadPanelOptions, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginRealtime, PluginRealtimeConnectionState, PluginRpc, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginServerApi, PluginSettingDescriptor, PluginSettingDescriptors, PluginSettingValue, PluginSettings, PluginSettingsHandle, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSettingsValues, PluginSharedPortTunnelIdentity, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginStatusApi, PluginStorage, PluginThreadActionContext, PluginThreadActionRegistration, PluginThreadActionResult, PluginThreadActionToast, PluginThreadEventHandler, PluginThreadEventName, PluginThreadEventPayloads, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, PluginUi, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps };