diff --git a/apps/app/.ladle/components.tsx b/apps/app/.ladle/components.tsx index c04459e497..234971a9b9 100644 --- a/apps/app/.ladle/components.tsx +++ b/apps/app/.ladle/components.tsx @@ -6,6 +6,7 @@ import { WorkerPoolContextProvider } from "@pierre/diffs/react"; import { Provider as JotaiProvider, createStore } from "jotai"; import { MemoryRouter } from "react-router-dom"; import { AppToaster } from "../src/components/AppToaster"; +import { RouteNavigationProvider } from "../src/components/ui/app-route-anchor"; import { TooltipProvider } from "@bb/shared-ui/tooltip"; import { setPreferredTheme } from "../src/hooks/useTheme"; import { @@ -57,24 +58,28 @@ export const Provider: GlobalProvider = ({ globalState, children }) => { return ( - - - - -
- {children} - -
-
-
-
-
+ {/* Sidebar rows, thread actions and the fork handler navigate through + useRouteNavigate, which throws at the click without this provider. */} + + + + + +
+ {children} + +
+
+
+
+
+
); }; diff --git a/apps/app/src/components/layout/AppLayout.tsx b/apps/app/src/components/layout/AppLayout.tsx index 2585da5cd7..1ec2329103 100644 --- a/apps/app/src/components/layout/AppLayout.tsx +++ b/apps/app/src/components/layout/AppLayout.tsx @@ -16,7 +16,10 @@ import { SidebarProvider, SidebarTrigger, } from "@/components/ui/sidebar.js"; -import { ThreadTitleMentionResourcesProvider } from "@/components/thread/ThreadTitleMentions"; +import { + ThreadTitleMentionResourcesProvider, + useSidebarThreadTitleMentionResources, +} from "@/components/thread/ThreadTitleMentions"; import { AppCommandShortcutHint } from "@/components/commands/AppCommandShortcutHint"; import { resolveAutomationBreadcrumbs, @@ -538,27 +541,9 @@ export function AppLayout({ children }: AppLayoutProps) { ...sidebarNavigation.personalProject.threads, ]; }, [sidebarNavigationQuery.data]); - const titleMentionResources = useMemo(() => { - const sectionNamesById = new Map(); - const projectNamesById = new Map(); - const threadById = new Map( - sidebarThreads.map((entry) => [entry.id, entry]), - ); - const navigation = sidebarNavigationQuery.data; - if (navigation) { - for (const section of navigation.sections) { - sectionNamesById.set(section.id, section.name); - } - for (const projectEntry of navigation.projects) { - projectNamesById.set(projectEntry.id, projectEntry.name); - } - projectNamesById.set( - navigation.personalProject.id, - navigation.personalProject.name, - ); - } - return { sectionNamesById, projectNamesById, threadById }; - }, [sidebarNavigationQuery.data, sidebarThreads]); + const titleMentionResources = useSidebarThreadTitleMentionResources( + sidebarNavigationQuery.data, + ); const threadDetailBootstrapQuery = useThreadDetailBootstrap(threadId ?? "", { enabled: isThreadView && Boolean(threadId), timelinePrefetch: isThreadView && Boolean(threadId), @@ -821,59 +806,59 @@ export function AppLayout({ children }: AppLayoutProps) { }, [documentTitle]); return ( - - - - - - - -
- {showHeader ? ( - - ) : null} -
- {children} -
-
-
- -
+ + + + + + + +
+ {showHeader ? ( + + ) : null} +
+ {children} +
+
+
+ +
{ + cleanup(); + vi.useRealTimers(); +}); + +describe("AnimatedBody", () => { + it("realizes the body on the first expand and retains it after collapse", () => { + const { rerender } = render( + + expensive body + , + ); + expect(screen.queryByText("expensive body")).toBeNull(); + + rerender( + + expensive body + , + ); + expect(screen.getByText("expensive body")).not.toBeNull(); + + rerender( + + expensive body + , + ); + // Retained: re-opening must be instant. + expect(screen.getByText("expensive body")).not.toBeNull(); + expect( + screen.getByRole("region", { hidden: true }).getAttribute("aria-hidden"), + ).toBe("true"); + }); +}); + +describe("prompt-stack card bodies", () => { + it("does not mount per-row live durations for a collapsed background-activity card", () => { + vi.useFakeTimers(); + const setInterval = vi.spyOn(globalThis, "setInterval"); + const startedAt = Date.now() - 5_000; + function Card() { + const [isExpanded, setIsExpanded] = useState(false); + return ( + + workflowRow({ + id: `wf_${index}`, + description: `Background agent ${index}`, + model: "haiku", + startedAt, + status: "pending", + taskStatus: "running", + taskType: "local_agent", + workflowName: null, + }), + )} + isExpanded={isExpanded} + onToggle={() => setIsExpanded((value) => !value)} + /> + ); + } + render(); + // Collapsed: the rows (and their live durations) are not in the DOM, so + // no timer runs for a card nobody opened. + expect(screen.queryByText("Background agent 2")).toBeNull(); + expect(setInterval).not.toHaveBeenCalled(); + + fireEvent.click(screen.getByRole("button", { expanded: false })); + expect(screen.getByText("Background agent 2")).not.toBeNull(); + // Three live durations mounted; they share one 1 Hz ticker. + expect(setInterval).toHaveBeenCalledTimes(1); + }); +}); diff --git a/apps/app/src/components/promptbox/banner/AnimatedBody.tsx b/apps/app/src/components/promptbox/banner/AnimatedBody.tsx new file mode 100644 index 0000000000..6b2b6ded12 --- /dev/null +++ b/apps/app/src/components/promptbox/banner/AnimatedBody.tsx @@ -0,0 +1,61 @@ +import { useState, type ReactNode } from "react"; +import { cn } from "@bb/shared-ui/lib/utils"; + +export interface AnimatedBodyProps { + id: string; + labelledBy: string; + isExpanded: boolean; + /** + * `reserve` keeps a transparent 1px top border while collapsed so the card + * height does not jump by a pixel on expand; `none` draws the border only + * while expanded (the prompt-stack cards' existing look). + */ + collapsedBorder: "reserve" | "none"; + children: ReactNode; +} + +/** + * Collapsible card body with the shared grid-rows expand animation. + * + * Realizes `children` only after the first expand, then retains them. A + * collapsed body still costs layout for every node inside it, and the bodies + * behind the prompt-stack cards (agent trees, changed-file lists, per-row + * live durations) are the expensive part; the DOM must not carry them before + * anyone opens the card. Retained after the first open so re-expanding is + * instant. + */ +export function AnimatedBody({ + id, + labelledBy, + isExpanded, + collapsedBorder, + children, +}: AnimatedBodyProps) { + const [hasRealizedBody, setHasRealizedBody] = useState(isExpanded); + if (isExpanded && !hasRealizedBody) { + setHasRealizedBody(true); + } + const isBodyRealized = hasRealizedBody || isExpanded; + + return ( +
+
+ {isBodyRealized ? children : null} +
+
+ ); +} diff --git a/apps/app/src/components/promptbox/banner/ThreadBackgroundCommandsCard.tsx b/apps/app/src/components/promptbox/banner/ThreadBackgroundCommandsCard.tsx index 3f07fde74e..2265124857 100644 --- a/apps/app/src/components/promptbox/banner/ThreadBackgroundCommandsCard.tsx +++ b/apps/app/src/components/promptbox/banner/ThreadBackgroundCommandsCard.tsx @@ -1,8 +1,9 @@ -import { useEffect, useState } from "react"; import { isBackgroundAgentTaskType } from "@bb/domain"; import type { TimelineWorkflowWorkRow } from "@bb/server-contract"; import { durationToCompactString } from "@bb/thread-view"; +import { AnimatedBody } from "@/components/promptbox/banner/AnimatedBody"; import { PromptStackCard } from "@/components/promptbox/banner/PromptStackCard"; +import { useSecondTick } from "@/hooks/useSecondTick"; import { Icon } from "@bb/shared-ui/icon"; import { useIsCompactViewport } from "@bb/shared-ui/hooks/use-compact-viewport"; import { @@ -89,14 +90,7 @@ function compactBackgroundActivityLabel( * workflow card's duration treatment. */ function BackgroundActivityDuration({ startedAt }: { startedAt: number }) { - const [elapsed, setElapsed] = useState(() => Date.now() - startedAt); - useEffect(() => { - setElapsed(Date.now() - startedAt); - const interval = window.setInterval(() => { - setElapsed(Date.now() - startedAt); - }, 1_000); - return () => window.clearInterval(interval); - }, [startedAt]); + const elapsed = useSecondTick() - startedAt; if (elapsed <= 1_000) { return null; } @@ -280,66 +274,58 @@ export function ThreadBackgroundCommandsCard({ )} {canExpand ? ( -
-
-
- {expandedRows.map((row) => { - const display = backgroundActivityDisplay(row); - const model = backgroundActivityModel(row); - return ( -
+ {expandedRows.map((row) => { + const display = backgroundActivityDisplay(row); + const model = backgroundActivityModel(row); + return ( +
+
- ); - })} -
+ ) : null} + + + +
+ ); + })}
-
+ ) : null} ); diff --git a/apps/app/src/components/promptbox/banner/ThreadPromptContextBanner.tsx b/apps/app/src/components/promptbox/banner/ThreadPromptContextBanner.tsx index c35abf7e71..0e23f53019 100644 --- a/apps/app/src/components/promptbox/banner/ThreadPromptContextBanner.tsx +++ b/apps/app/src/components/promptbox/banner/ThreadPromptContextBanner.tsx @@ -1,9 +1,4 @@ -import { - forwardRef, - useState, - type ButtonHTMLAttributes, - type ReactNode, -} from "react"; +import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from "react"; import { NavLink } from "react-router-dom"; import type { EnvironmentStatus, @@ -41,6 +36,7 @@ import { PULL_REQUEST_STATE_DISPLAY, } from "@/lib/pull-request-display"; import { PullRequestStatusPill } from "@/components/pull-request/PullRequestStatusPill"; +import { AnimatedBody } from "@/components/promptbox/banner/AnimatedBody"; import { DropdownMenu, DropdownMenuContent, @@ -662,46 +658,6 @@ function PullRequestBannerLink({ ); } -function AnimatedBody({ - id, - labelledBy, - isExpanded, - children, -}: { - id: string; - labelledBy: string; - isExpanded: boolean; - children: ReactNode; -}) { - // Realize the body only after the first expand, then retain it. A collapsed - // body still costs layout for every node inside it, and the changed-files - // list can be large, so the DOM must not carry it before anyone opens it. - const [hasRealizedBody, setHasRealizedBody] = useState(isExpanded); - if (isExpanded && !hasRealizedBody) { - setHasRealizedBody(true); - } - const isBodyRealized = hasRealizedBody || isExpanded; - - return ( -
-
- {isBodyRealized ? children : null} -
-
- ); -} - const CHILD_THREADS_HEADER_BUTTON_CLASS = "flex min-h-8 w-full min-w-0 cursor-pointer items-center gap-1.5 rounded-none px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-background/80"; @@ -797,6 +753,7 @@ function ActiveChildThreadsCard({ {parentThreadSection ? ( {showParentThread && parentThreadSection && !isParentThreadOnly ? ( -
-
- -
-
+ +
); } diff --git a/apps/app/src/components/promptbox/banner/ThreadWorkflowCard.tsx b/apps/app/src/components/promptbox/banner/ThreadWorkflowCard.tsx index 6be355adf9..e5b026f4ed 100644 --- a/apps/app/src/components/promptbox/banner/ThreadWorkflowCard.tsx +++ b/apps/app/src/components/promptbox/banner/ThreadWorkflowCard.tsx @@ -1,8 +1,9 @@ -import { useEffect, useState } from "react"; import { isSettledWorkflowAgentState } from "@bb/domain"; import type { TimelineWorkflowWorkRow } from "@bb/server-contract"; import { durationToCompactString } from "@bb/thread-view"; +import { AnimatedBody } from "@/components/promptbox/banner/AnimatedBody"; import { PromptStackCard } from "@/components/promptbox/banner/PromptStackCard"; +import { useSecondTick } from "@/hooks/useSecondTick"; import { WorkflowWorkRowBody } from "@/components/thread/timeline/WorkflowWorkRowBody"; import { activityIconClass, @@ -28,14 +29,7 @@ const WORKFLOW_HEADER_BUTTON_CLASS = activityRowClass( * sub-second flicker on entry. */ function WorkflowDuration({ startedAt }: { startedAt: number }) { - const [elapsed, setElapsed] = useState(() => Date.now() - startedAt); - useEffect(() => { - setElapsed(Date.now() - startedAt); - const interval = window.setInterval(() => { - setElapsed(Date.now() - startedAt); - }, 1_000); - return () => window.clearInterval(interval); - }, [startedAt]); + const elapsed = useSecondTick() - startedAt; if (elapsed <= 1_000) { return null; } @@ -148,22 +142,14 @@ export function ThreadWorkflowCard({ className="px-3 pb-2" /> ) : null} -
-
- -
-
+ +
); } diff --git a/apps/app/src/components/sidebar/ProjectList.tsx b/apps/app/src/components/sidebar/ProjectList.tsx index 07bdafc19f..deee8d8ddf 100644 --- a/apps/app/src/components/sidebar/ProjectList.tsx +++ b/apps/app/src/components/sidebar/ProjectList.tsx @@ -97,7 +97,7 @@ import { PinnedThreadTree, type PinnedThreadTreeProps, } from "./PinnedThreadTree"; -import { SidebarThreadTitleMentionResourcesProvider } from "./SidebarThreadTitleMentions"; +import { useThreadTitleMentionResources } from "@/components/thread/ThreadTitleMentions"; import { buildPinnedSidebarState } from "./pinnedSidebarThreads"; import { collapsedEnvironmentIdsAtom, @@ -177,11 +177,6 @@ interface ProjectListActionButtonsProps { interface ProjectListShellProps { children: ReactNode; - titleMentionResources?: { - sectionNamesById: ReadonlyMap; - projectNamesById: ReadonlyMap; - threadById: ReadonlyMap; - }; } interface ProjectListSectionIconButtonProps { @@ -937,23 +932,12 @@ export function ProjectListActionButtons({ ); } -export function ProjectListShell({ - children, - titleMentionResources, -}: ProjectListShellProps) { - const content = ( +export function ProjectListShell({ children }: ProjectListShellProps) { + return ( {children} ); - if (!titleMentionResources) { - return content; - } - return ( - - {content} - - ); } interface BuiltInSectionRenderState { @@ -1523,24 +1507,11 @@ function ProjectListComponent({ return sidebarThreads; }, [sidebarNavigation]); const draftThreadIds = usePromptDraftInputThreadIds(threads); - const projectNamesById = useMemo(() => { - const namesById = new Map(); - if (!sidebarNavigation) { - return namesById; - } - for (const project of sidebarNavigation.projects) { - namesById.set(project.id, project.name); - } - namesById.set(PERSONAL_PROJECT_ID, sidebarNavigation.personalProject.name); - return namesById; - }, [sidebarNavigation]); - const sectionNamesById = useMemo(() => { - const namesById = new Map(); - for (const section of sections) { - namesById.set(section.id, section.name); - } - return namesById; - }, [sections]); + // Provided once by AppLayout from the same sidebar payload (with value + // retention across refetches); building a second copy here re-rendered every + // row twice per sidebar update. + const titleMentionResources = useThreadTitleMentionResources(); + const { sectionNamesById, projectNamesById } = titleMentionResources; const threadById = useMemo(() => { const map = new Map(); for (const thread of threads) { @@ -1548,10 +1519,6 @@ function ProjectListComponent({ } return map; }, [threads]); - const titleMentionResources = useMemo( - () => ({ sectionNamesById, projectNamesById, threadById }), - [sectionNamesById, projectNamesById, threadById], - ); const projectsState = useConnectionAwareQueryState({ hasResolvedData: projects !== undefined, isFetching: sidebarNavigationQuery.isFetching, @@ -2014,7 +1981,7 @@ function ProjectListComponent({ if (threadSearch?.isActive) { return ( - + + ); } return ( - + ( diff --git a/apps/app/src/components/sidebar/ProjectRow.tsx b/apps/app/src/components/sidebar/ProjectRow.tsx index 014a1d9401..21f5fcc5c0 100644 --- a/apps/app/src/components/sidebar/ProjectRow.tsx +++ b/apps/app/src/components/sidebar/ProjectRow.tsx @@ -16,7 +16,7 @@ import { import { createPortal } from "react-dom"; import { PERSONAL_PROJECT_ID, type ThreadListEntry } from "@bb/domain"; import type { ProjectResponse } from "@bb/server-contract"; -import { NavLink, useNavigate } from "react-router-dom"; +import { NavLink } from "react-router-dom"; import { useCreateThreadInWorktree } from "@/hooks/useCreateThreadInWorktree"; import { usePromptDraftHasInput, @@ -72,6 +72,7 @@ import { getMutationErrorMessage } from "@/lib/mutation-errors"; import { getProjectSettingsRoutePath } from "@/lib/route-paths"; import { getThreadDisplayTitle } from "@/lib/thread-title"; import { appToast } from "@/components/ui/app-toast"; +import { useRouteNavigate } from "@/components/ui/app-route-anchor"; import { CollapsedThreadStatusGlyph, ThreadRow, @@ -754,7 +755,7 @@ function useArchiveEnvironmentThreadGroupAction({ selectedThreadId, threads, }: UseArchiveEnvironmentThreadGroupActionArgs): UseArchiveEnvironmentThreadGroupActionResult { - const navigate = useNavigate(); + const navigate = useRouteNavigate(); const archiveEnvironmentThreads = useArchiveEnvironmentThreads(); const { isPending: archiveThreadsIsPending, diff --git a/apps/app/src/components/sidebar/paneContentSplitIndicator.test.tsx b/apps/app/src/components/sidebar/paneContentSplitIndicator.test.tsx new file mode 100644 index 0000000000..ff6581ff5e --- /dev/null +++ b/apps/app/src/components/sidebar/paneContentSplitIndicator.test.tsx @@ -0,0 +1,90 @@ +// @vitest-environment jsdom + +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { act, renderHook } from "@testing-library/react"; +import { createStore, Provider } from "jotai"; +import type { ReactNode } from "react"; +import { splitLayoutAtom } from "@/lib/split-layout/atoms"; +import type { LayoutNode, PaneContent, SplitLayout } from "@/lib/split-layout"; +import { usePaneContentSplitIndicator } from "./paneContentSplitIndicator"; + +const { compactState } = vi.hoisted(() => ({ + compactState: { value: false }, +})); + +vi.mock("@bb/shared-ui/hooks/use-compact-viewport", () => ({ + useIsCompactViewport: () => compactState.value, +})); + +function content(threadId: string): PaneContent { + return { kind: "thread", projectId: "p1", threadId }; +} + +function pane(paneId: string, threadId: string): LayoutNode { + return { type: "pane", paneId, content: content(threadId) }; +} + +function twoPanes(focused: string): SplitLayout { + return { + root: { + type: "split", + dir: "row", + sizes: [0.5, 0.5], + children: [pane("pane-1", "t1"), pane("pane-2", "t2")], + }, + focusedPaneId: focused, + }; +} + +function renderIndicator(threadId: string) { + const store = createStore(); + store.set(splitLayoutAtom, twoPanes("pane-1")); + const wrapper = ({ children }: { children: ReactNode }) => ( + {children} + ); + let renders = 0; + const target = content(threadId); + const { result } = renderHook( + () => { + renders += 1; + return usePaneContentSplitIndicator(target, true); + }, + { wrapper }, + ); + return { store, result, renderCount: () => renders }; +} + +beforeEach(() => { + compactState.value = false; +}); + +describe("usePaneContentSplitIndicator", () => { + it("does not subscribe to the split layout on compact viewports", () => { + compactState.value = true; + const { store, result, renderCount } = renderIndicator("t1"); + expect(result.current.isOpenInSplit).toBe(false); + const settled = renderCount(); + + // Thread navigation on a phone still reconciles the layout atom; rows must + // not pay a render for a change they can never show. + act(() => { + store.set(splitLayoutAtom, twoPanes("pane-2")); + }); + expect(renderCount()).toBe(settled); + expect(result.current.isOpenInSplit).toBe(false); + }); + + it("follows the split layout on wide viewports", () => { + const { store, result } = renderIndicator("t1"); + expect(result.current.isOpenInSplit).toBe(true); + expect(result.current.miniMap?.find((slot) => slot.isMe)?.paneId).toBe( + "pane-1", + ); + act(() => { + store.set(splitLayoutAtom, twoPanes("pane-2")); + }); + expect(result.current.miniMap?.find((slot) => slot.isFocused)?.paneId).toBe( + "pane-2", + ); + }); +}); diff --git a/apps/app/src/components/sidebar/paneContentSplitIndicator.ts b/apps/app/src/components/sidebar/paneContentSplitIndicator.ts index f68f25d7e8..c1c082aa1f 100644 --- a/apps/app/src/components/sidebar/paneContentSplitIndicator.ts +++ b/apps/app/src/components/sidebar/paneContentSplitIndicator.ts @@ -1,5 +1,5 @@ import { useMemo } from "react"; -import { useAtomValue } from "jotai"; +import { atom, useAtomValue } from "jotai"; import { useIsCompactViewport } from "@bb/shared-ui/hooks/use-compact-viewport"; import { splitLayoutAtom } from "@/lib/split-layout/atoms"; import { @@ -33,6 +33,26 @@ const NO_INDICATOR: PaneContentSplitIndicator = { miniMap: null, }; +/** + * Subscribed instead of `splitLayoutAtom` when the indicator cannot show + * (compact viewport, or the caller disabled it). Every sidebar row calls these + * hooks; a live layout subscription there re-rendered every mounted row on + * each thread navigation on phones, where the layout still reconciles but the + * result is always {@link NO_INDICATOR}. + */ +const NULL_LAYOUT_ATOM = atom(null); + +function useSplitLayoutForIndicator(enabled: boolean): { + layout: SplitLayout | null; + isCompact: boolean; +} { + const isCompact = useIsCompactViewport(); + const layout = useAtomValue( + enabled && !isCompact ? splitLayoutAtom : NULL_LAYOUT_ATOM, + ); + return { layout, isCompact }; +} + export interface ThreadSplitIndicatorTarget { id: string; projectId: string; @@ -74,8 +94,7 @@ export function usePaneContentSplitIndicator( content: PaneContent, enabled: boolean, ): PaneContentSplitIndicator { - const layout = useAtomValue(splitLayoutAtom); - const isCompact = useIsCompactViewport(); + const { layout, isCompact } = useSplitLayoutForIndicator(enabled); return useMemo(() => { if ( @@ -103,8 +122,7 @@ export function useThreadGroupSplitIndicator( threads: readonly ThreadSplitIndicatorTarget[], enabled: boolean, ): PaneContentSplitIndicator { - const layout = useAtomValue(splitLayoutAtom); - const isCompact = useIsCompactViewport(); + const { layout, isCompact } = useSplitLayoutForIndicator(enabled); return useMemo(() => { if ( diff --git a/apps/app/src/components/sidebar/useThreadRowSplitDrag.test.tsx b/apps/app/src/components/sidebar/useThreadRowSplitDrag.test.tsx index 1086fb7345..6467484df0 100644 --- a/apps/app/src/components/sidebar/useThreadRowSplitDrag.test.tsx +++ b/apps/app/src/components/sidebar/useThreadRowSplitDrag.test.tsx @@ -7,6 +7,7 @@ import type { ReactNode } from "react"; import { splitLayoutAtom } from "@/lib/split-layout/atoms"; import { countPanes, findPaneByThread, listPanes } from "@/lib/split-layout"; import type { LayoutNode, PaneContent, SplitLayout } from "@/lib/split-layout"; +import { RouteNavigationProvider } from "@/components/ui/app-route-anchor"; import { useThreadRowSplitDrag } from "./useThreadRowSplitDrag"; const { navigateSpy, compactState, experimentState } = vi.hoisted(() => ({ @@ -70,7 +71,9 @@ function renderOpenInSplit(threadId: string, layout: SplitLayout | null) { const store = createStore(); store.set(splitLayoutAtom, layout); const wrapper = ({ children }: { children: ReactNode }) => ( - {children} + + {children} + ); const { result } = renderHook( () => useThreadRowSplitDrag({ projectId: "p1", threadId, title: "Thread" }), diff --git a/apps/app/src/components/sidebar/useThreadRowSplitDrag.ts b/apps/app/src/components/sidebar/useThreadRowSplitDrag.ts index ef2163d7a5..39914b979f 100644 --- a/apps/app/src/components/sidebar/useThreadRowSplitDrag.ts +++ b/apps/app/src/components/sidebar/useThreadRowSplitDrag.ts @@ -1,8 +1,8 @@ import { useCallback, type PointerEvent as ReactPointerEvent } from "react"; import { useStore } from "jotai"; -import { useNavigate } from "react-router-dom"; import { useIsCompactViewport } from "@bb/shared-ui/hooks/use-compact-viewport"; import { useThreadSplitsEnabled } from "@/hooks/useThreadSplitsEnabled"; +import { useRouteNavigate } from "@/components/ui/app-route-anchor"; import { getThreadRoutePath } from "@/lib/route-paths"; import { splitLayoutAtom } from "@/lib/split-layout/atoms"; import { @@ -60,7 +60,7 @@ export function useThreadRowSplitDrag({ openInSplit: () => void; } { const store = useStore(); - const navigate = useNavigate(); + const navigate = useRouteNavigate(); const isCompact = useIsCompactViewport(); const threadSplitsEnabled = useThreadSplitsEnabled(); diff --git a/apps/app/src/components/thread/ThreadActionsProvider.navigation.test.tsx b/apps/app/src/components/thread/ThreadActionsProvider.navigation.test.tsx new file mode 100644 index 0000000000..c66aa42fa0 --- /dev/null +++ b/apps/app/src/components/thread/ThreadActionsProvider.navigation.test.tsx @@ -0,0 +1,144 @@ +// @vitest-environment jsdom + +import { memo, type ReactNode } from "react"; +import { + act, + cleanup, + fireEvent, + render, + screen, +} from "@testing-library/react"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { MemoryRouter, useLocation, useNavigate } from "react-router-dom"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { + RouteNavigationProvider, + useRouteNavigate, +} from "@/components/ui/app-route-anchor"; +import { + ThreadActionsProvider, + useThreadActions, + type ThreadActionsContextValue, +} from "./ThreadActionsProvider"; + +vi.mock("@/components/dialogs/ThreadDeleteDialog", () => ({ + ThreadDeleteDialog: () => null, +})); + +vi.mock("@/components/dialogs/ThreadRenameDialog", () => ({ + ThreadRenameDialog: () => null, +})); + +vi.mock("@/hooks/mutations/thread-state-mutations", () => { + // Real mutation objects keep a stable `mutate`; the mock must too. + const mutationResult = { isPending: false, mutate: vi.fn() }; + const mutation = () => mutationResult; + return { + useArchiveThreadAndChildren: mutation, + useDeleteThread: mutation, + useMarkThreadRead: mutation, + useMarkThreadUnread: mutation, + usePinThread: mutation, + useUnarchiveThread: mutation, + useUnpinThread: mutation, + useUpdateThread: mutation, + }; +}); + +vi.mock("@/lib/sdk", () => ({ + sdk: { threads: { archiveAll: vi.fn(), childSummary: vi.fn() } }, +})); + +afterEach(() => { + cleanup(); +}); + +const consumerRenders: ThreadActionsContextValue[] = []; + +/** Stands in for a memoized sidebar ThreadRow: props never change. */ +const ActionsConsumer = memo(function ActionsConsumer() { + consumerRenders.push(useThreadActions()); + return null; +}); + +const routeNavigateIdentities: ReturnType[] = []; + +const RouteNavigateConsumer = memo(function RouteNavigateConsumer() { + routeNavigateIdentities.push(useRouteNavigate()); + return null; +}); + +/** Real router navigation, driven from a click so no test code renders. */ +function NavigationProbe() { + const navigate = useNavigate(); + const location = useLocation(); + return ( + <> + {location.pathname} + + + ); +} + +function navigateToT2(): void { + fireEvent.click(screen.getByRole("button", { name: "go to t2" })); +} + +function renderTree(children: ReactNode) { + const queryClient = new QueryClient(); + return render( + + + + + {children} + + + , + ); +} + +describe("ThreadActionsProvider across navigations", () => { + it("keeps the context value and memoized consumers stable when the route changes", () => { + consumerRenders.length = 0; + renderTree( + + + , + ); + expect(consumerRenders).toHaveLength(1); + + navigateToT2(); + expect(screen.getByTestId("pathname").textContent).toBe( + "/projects/p1/threads/t2", + ); + // Under BrowserRouter `useNavigate()` rebuilds per pathname; the provider + // must not fold that churn into its context value or every mounted + // sidebar ThreadRow (a `memo` consumer) re-renders per navigation. + expect(consumerRenders).toHaveLength(1); + }); +}); + +describe("useRouteNavigate", () => { + it("does not re-render its caller on navigation and navigates with options", () => { + routeNavigateIdentities.length = 0; + renderTree(); + expect(routeNavigateIdentities).toHaveLength(1); + + navigateToT2(); + expect(routeNavigateIdentities).toHaveLength(1); + + const navigate = routeNavigateIdentities[0]; + act(() => { + navigate?.("/projects/p1/threads/t3", { + replace: true, + state: { focusPrompt: true }, + }); + }); + expect(screen.getByTestId("pathname").textContent).toBe( + "/projects/p1/threads/t3", + ); + }); +}); diff --git a/apps/app/src/components/thread/ThreadActionsProvider.tsx b/apps/app/src/components/thread/ThreadActionsProvider.tsx index 87cca750d5..eada3d9fdb 100644 --- a/apps/app/src/components/thread/ThreadActionsProvider.tsx +++ b/apps/app/src/components/thread/ThreadActionsProvider.tsx @@ -8,7 +8,6 @@ import { type ReactNode, } from "react"; import { useSetAtom } from "jotai"; -import { useNavigate } from "react-router-dom"; import { appToast } from "@/components/ui/app-toast"; import { closePanesForThreadsAtom, @@ -47,6 +46,7 @@ import { destroyPersistedBrowserViewsForThread } from "@/components/secondary-pa import { getThreadReadToggleAction } from "@/components/sidebar/threadReadState"; import { getRootComposeRoutePath, getThreadRoutePath } from "@/lib/route-paths"; import { getDesktopBrowserApi } from "@/lib/bb-desktop"; +import { useRouteNavigate } from "@/components/ui/app-route-anchor"; export interface ThreadActionsContextValue { archiveThreadAndChildren: (thread: Thread) => void; @@ -96,7 +96,9 @@ const ARCHIVE_UNDO_TOAST_DURATION_MS = 10_000; export function ThreadActionsProvider({ children, }: ThreadActionsProviderProps) { - const navigate = useNavigate(); + // Stable across navigations: the context value below must not change per + // pathname, or every mounted sidebar ThreadRow re-renders on each route change. + const navigate = useRouteNavigate(); const { threadId: viewedThreadId } = useRouteState(); // Read the currently-viewed thread live inside async mutation callbacks: a // pane's stale-prune (deleted/archived thread) can move the URL between a diff --git a/apps/app/src/components/thread/ThreadTitleMentions.resources.test.ts b/apps/app/src/components/thread/ThreadTitleMentions.resources.test.ts new file mode 100644 index 0000000000..19eaaeccd8 --- /dev/null +++ b/apps/app/src/components/thread/ThreadTitleMentions.resources.test.ts @@ -0,0 +1,101 @@ +import { describe, expect, it } from "vitest"; +import { makeThreadListEntry } from "@/test/fixtures/thread-list-entries"; +import { + buildThreadTitleMentionResources, + EMPTY_TITLE_MENTION_RESOURCES, + type ThreadTitleMentionNavigationSource, +} from "./ThreadTitleMentions"; + +function navigation( + overrides: Partial<{ + sectionName: string; + projectName: string; + threadTitle: string | null; + updatedAt: number; + }> = {}, +): ThreadTitleMentionNavigationSource { + return { + sections: [{ id: "sec_1", name: overrides.sectionName ?? "Backlog" }], + projects: [ + { + id: "proj_app", + name: overrides.projectName ?? "App", + threads: [ + makeThreadListEntry({ + id: "thr_app", + projectId: "proj_app", + title: overrides.threadTitle ?? "Ship it", + updatedAt: overrides.updatedAt ?? 1, + }), + ], + }, + ], + personalProject: { + id: "personal", + name: "Personal", + threads: [makeThreadListEntry({ id: "thr_me", projectId: "personal" })], + }, + }; +} + +describe("buildThreadTitleMentionResources", () => { + it("returns the previous resources for a value-equal payload with new identity", () => { + const first = buildThreadTitleMentionResources( + navigation(), + EMPTY_TITLE_MENTION_RESOURCES, + ); + expect(first.threadById.get("thr_app")?.title).toBe("Ship it"); + + // A sidebar refetch after a turn boundary: fresh payload, same titles; only + // a status/updatedAt field moved. Every ThreadRow reads this context, so + // the object (and each map inside it) must keep identity. + const second = buildThreadTitleMentionResources( + navigation({ updatedAt: 2 }), + first, + ); + expect(second).toBe(first); + }); + + it("replaces only the map that changed and keeps unchanged thread entries", () => { + const first = buildThreadTitleMentionResources( + navigation(), + EMPTY_TITLE_MENTION_RESOURCES, + ); + const renamedProject = buildThreadTitleMentionResources( + navigation({ projectName: "Application" }), + first, + ); + expect(renamedProject).not.toBe(first); + expect(renamedProject.projectNamesById.get("proj_app")).toBe("Application"); + expect(renamedProject.sectionNamesById).toBe(first.sectionNamesById); + expect(renamedProject.threadById).toBe(first.threadById); + + const retitled = buildThreadTitleMentionResources( + navigation({ projectName: "Application", threadTitle: "Shipped" }), + renamedProject, + ); + expect(retitled.threadById).not.toBe(renamedProject.threadById); + expect(retitled.threadById.get("thr_app")?.title).toBe("Shipped"); + // The untouched personal thread keeps its entry object. + expect(retitled.threadById.get("thr_me")).toBe( + renamedProject.threadById.get("thr_me"), + ); + expect(retitled.projectNamesById).toBe(renamedProject.projectNamesById); + }); + + it("drops to the shared empty resources when the payload disappears", () => { + const first = buildThreadTitleMentionResources( + navigation(), + EMPTY_TITLE_MENTION_RESOURCES, + ); + expect(buildThreadTitleMentionResources(undefined, first)).toBe( + EMPTY_TITLE_MENTION_RESOURCES, + ); + expect( + buildThreadTitleMentionResources( + undefined, + EMPTY_TITLE_MENTION_RESOURCES, + ), + ).toBe(EMPTY_TITLE_MENTION_RESOURCES); + }); +}); diff --git a/apps/app/src/components/thread/ThreadTitleMentions.tsx b/apps/app/src/components/thread/ThreadTitleMentions.tsx index ed6e1abd99..ca0752935c 100644 --- a/apps/app/src/components/thread/ThreadTitleMentions.tsx +++ b/apps/app/src/components/thread/ThreadTitleMentions.tsx @@ -25,13 +25,19 @@ import { threadQueryKey } from "@/hooks/queries/query-keys"; import { sdk } from "@/lib/sdk"; import { getThreadDisplayTitle } from "@/lib/thread-title"; +/** The slice of a thread a title mention needs: its label and route. */ +export type ThreadTitleMentionThread = Pick< + ThreadListEntry, + "id" | "projectId" | "title" | "titleFallback" +>; + export interface ThreadTitleMentionResources { sectionNamesById: ReadonlyMap; projectNamesById: ReadonlyMap; - threadById: ReadonlyMap; + threadById: ReadonlyMap; } -const EMPTY_TITLE_MENTION_RESOURCES: ThreadTitleMentionResources = { +export const EMPTY_TITLE_MENTION_RESOURCES: ThreadTitleMentionResources = { sectionNamesById: new Map(), projectNamesById: new Map(), threadById: new Map(), @@ -40,6 +46,161 @@ const EMPTY_TITLE_MENTION_RESOURCES: ThreadTitleMentionResources = { const ThreadTitleMentionResourcesContext = createContext(EMPTY_TITLE_MENTION_RESOURCES); +/** The resources of the nearest {@link ThreadTitleMentionResourcesProvider}. */ +export function useThreadTitleMentionResources(): ThreadTitleMentionResources { + return useContext(ThreadTitleMentionResourcesContext); +} + +function areStringMapsEqual( + left: ReadonlyMap, + right: ReadonlyMap, +): boolean { + if (left.size !== right.size) return false; + for (const [key, value] of left) { + if (right.get(key) !== value) return false; + } + return true; +} + +function retainStringMap( + previous: ReadonlyMap, + next: ReadonlyMap, +): ReadonlyMap { + return areStringMapsEqual(previous, next) ? previous : next; +} + +function areThreadTitleMentionThreadsEqual( + left: ThreadTitleMentionThread, + right: ThreadTitleMentionThread, +): boolean { + return ( + left.id === right.id && + left.projectId === right.projectId && + left.title === right.title && + left.titleFallback === right.titleFallback + ); +} + +/** The part of the sidebar bootstrap payload title mentions read. */ +export interface ThreadTitleMentionNavigationSource { + sections: readonly { id: string; name: string }[]; + projects: readonly { + id: string; + name: string; + threads: readonly ThreadListEntry[]; + }[]; + personalProject: { + id: string; + name: string; + threads: readonly ThreadListEntry[]; + }; +} + +/** + * Build the sidebar-derived mention resources, reusing the previous maps and + * per-thread entries whenever their values are unchanged. Sidebar refetches + * land every turn boundary with a new payload identity, but titles, project + * names and section names rarely change; without retention every refetch + * gave the context a new value and re-rendered every ThreadRow, mention pill + * and markdown link that reads it. + */ +export function buildThreadTitleMentionResources( + navigation: ThreadTitleMentionNavigationSource | undefined, + previous: ThreadTitleMentionResources, +): ThreadTitleMentionResources { + if (navigation === undefined) { + return previous.threadById.size === 0 && + previous.projectNamesById.size === 0 && + previous.sectionNamesById.size === 0 + ? previous + : EMPTY_TITLE_MENTION_RESOURCES; + } + const sectionNamesById = new Map(); + for (const section of navigation.sections) { + sectionNamesById.set(section.id, section.name); + } + const projectNamesById = new Map(); + for (const project of navigation.projects) { + projectNamesById.set(project.id, project.name); + } + projectNamesById.set( + navigation.personalProject.id, + navigation.personalProject.name, + ); + const threadById = new Map(); + let threadsChanged = false; + const addThread = (thread: ThreadListEntry): void => { + const previousEntry = previous.threadById.get(thread.id); + if ( + previousEntry !== undefined && + areThreadTitleMentionThreadsEqual(previousEntry, thread) + ) { + threadById.set(thread.id, previousEntry); + return; + } + threadsChanged = true; + threadById.set(thread.id, { + id: thread.id, + projectId: thread.projectId, + title: thread.title, + titleFallback: thread.titleFallback, + }); + }; + for (const project of navigation.projects) { + for (const thread of project.threads) addThread(thread); + } + for (const thread of navigation.personalProject.threads) addThread(thread); + if (threadById.size !== previous.threadById.size) threadsChanged = true; + + const next: ThreadTitleMentionResources = { + sectionNamesById: retainStringMap( + previous.sectionNamesById, + sectionNamesById, + ), + projectNamesById: retainStringMap( + previous.projectNamesById, + projectNamesById, + ), + threadById: threadsChanged ? threadById : previous.threadById, + }; + return next.sectionNamesById === previous.sectionNamesById && + next.projectNamesById === previous.projectNamesById && + next.threadById === previous.threadById + ? previous + : next; +} + +/** + * Sidebar-derived mention resources with value retention (see + * {@link buildThreadTitleMentionResources}); the returned object only changes + * identity when a section name, project name or thread title/route changed. + */ +export function useSidebarThreadTitleMentionResources( + navigation: ThreadTitleMentionNavigationSource | undefined, +): ThreadTitleMentionResources { + // Render-time cache keyed on the payload identity. The previous resources + // are the input to the next build, and a state-based "adjust during render" + // would loop if a caller ever handed in a fresh payload object per render, + // so this deliberately reads and writes a ref during render (the hook is + // small; the compiler bailout is confined to it). + const cacheRef = useRef<{ + navigation: ThreadTitleMentionNavigationSource | undefined; + resources: ThreadTitleMentionResources; + } | null>(null); + /* eslint-disable react-hooks/refs -- render-time cache, see above */ + const cached = cacheRef.current; + if (cached !== null && cached.navigation === navigation) { + return cached.resources; + } + const resources = buildThreadTitleMentionResources( + navigation, + cached?.resources ?? EMPTY_TITLE_MENTION_RESOURCES, + ); + cacheRef.current = { navigation, resources }; + /* eslint-enable react-hooks/refs */ + return resources; +} + interface RawThreadMentionResolverContextValue { register: (threadId: string) => void; resourceById: ReadonlyMap; @@ -227,7 +388,7 @@ export interface ThreadTitleMentionResourcesProviderProps { children: ReactNode; sectionNamesById: ReadonlyMap; projectNamesById: ReadonlyMap; - threadById: ReadonlyMap; + threadById: ReadonlyMap; } export function ThreadTitleMentionResourcesProvider({ diff --git a/apps/app/src/components/thread/timeline/MessageActionBar.test.tsx b/apps/app/src/components/thread/timeline/MessageActionBar.test.tsx index 5384f9125b..dc051d7701 100644 --- a/apps/app/src/components/thread/timeline/MessageActionBar.test.tsx +++ b/apps/app/src/components/thread/timeline/MessageActionBar.test.tsx @@ -362,4 +362,42 @@ describe("MessageActionBar", () => { expect(onFork).toHaveBeenCalledTimes(1); }); + it("skips the desktop tooltip trees on touch phones", () => { + mockMobileCoarsePointer(); + render( + , + ); + + // Radix TooltipTrigger stamps `data-state` on its child; the mobile branch + // must render plain buttons (no tooltip tree per action). + const fork = screen.getByRole("button", { name: "Fork into new thread" }); + expect(fork.hasAttribute("data-state")).toBe(false); + expect( + screen + .getAllByRole("button") + .map((button) => button.getAttribute("aria-label")), + ).toEqual(["Copy message", "Add to chat", "Fork into new thread"]); + expect( + screen.queryByRole("button", { name: "Message actions" }), + ).toBeNull(); + }); + + it("mounts the tooltip bar on fine-pointer viewports", () => { + render( + , + ); + const fork = screen.getByRole("button", { name: "Fork into new thread" }); + expect(fork.getAttribute("data-state")).toBe("closed"); + }); }); diff --git a/apps/app/src/components/thread/timeline/MessageActionBar.tsx b/apps/app/src/components/thread/timeline/MessageActionBar.tsx index 68e087848e..1d9650cfdd 100644 --- a/apps/app/src/components/thread/timeline/MessageActionBar.tsx +++ b/apps/app/src/components/thread/timeline/MessageActionBar.tsx @@ -315,6 +315,29 @@ export function MessageActionBar({ return null; } + if (useMobileOverflowPopover) { + // Touch phones: no hover, so no tooltips. Mounting the desktop bar here + // would put five-plus hidden Radix tooltip trees per message into the + // timeline for nothing; render only the mobile surface. + return ( +
+ {mobileActionDisplay === "overflow" ? ( + + ) : ( + + )} +
+ ); + } + return (
))} {mobileActionDisplay === "overflow" ? ( - useMobileOverflowPopover ? ( - - ) : ( - - - - - + + + + + {overflowActions.map((action) => ( + + {action.plugin ? ( + + ) : ( + + ))} + + ) : null}
); } + +/** + * Inline (always visible) actions for touch phones: same buttons and classes as + * the desktop bar minus the tooltip trees, which have no hover to open on. + */ +function MobileInlineActions({ + actions, +}: { + actions: readonly MessageOverflowAction[]; +}) { + return actions.map((action) => + action.kind === "copy" ? ( + + ) : ( + + ), + ); +} diff --git a/apps/app/src/components/thread/timeline/ThreadTimelineRows.row-isolation.test.tsx b/apps/app/src/components/thread/timeline/ThreadTimelineRows.row-isolation.test.tsx new file mode 100644 index 0000000000..5b5abaaf49 --- /dev/null +++ b/apps/app/src/components/thread/timeline/ThreadTimelineRows.row-isolation.test.tsx @@ -0,0 +1,74 @@ +// @vitest-environment jsdom + +import { createElement, type ComponentProps } from "react"; +import { cleanup, render } from "@testing-library/react"; +import { MemoryRouter } from "react-router-dom"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { conversationRow } from "@/test/fixtures/thread-timeline-rows"; +import { ThreadTimelineRows } from "./ThreadTimelineRows"; + +const renderedMessageTexts = vi.hoisted(() => [] as string[]); + +// Wrap the message body so each render of a row's content is observable. The +// wrapper only re-renders when its parent hands it a new element, so the count +// measures whether `ConversationRowContent` bailed out. +vi.mock("./ConversationMessageContent.js", async (importOriginal) => { + const actual = + await importOriginal(); + const Actual = actual.ConversationMessageContent; + return { + ...actual, + ConversationMessageContent: (props: ComponentProps) => { + renderedMessageTexts.push(props.text); + return createElement(Actual, props); + }, + }; +}); + +function assistantRow(index: number) { + return conversationRow({ + id: `assistant_message_${index}`, + role: "assistant", + text: `Assistant answer number ${index}.`, + sourceSeqStart: 10 + index, + sourceSeqEnd: 10 + index, + threadId: "thr_main", + }); +} + +afterEach(() => { + cleanup(); + renderedMessageTexts.length = 0; +}); + +describe("ThreadTimelineRows row isolation", () => { + it("re-renders only the rows whose mobile action display flips when a message is appended", () => { + const queryClient = new QueryClient(); + const rows = Array.from({ length: 12 }, (_, index) => assistantRow(index)); + const renderTimeline = (timelineRows: typeof rows) => ( + + + + + + ); + const view = render(renderTimeline(rows)); + expect(renderedMessageTexts).toHaveLength(12); + renderedMessageTexts.length = 0; + + // A new assistant message moves the "latest actionable" id, which every + // row reads from context. Only the previous latest (inline -> overflow) + // and the new row may render; the other ten must bail out. + view.rerender(renderTimeline([...rows, assistantRow(12)])); + expect([...renderedMessageTexts].sort()).toEqual([ + "Assistant answer number 11.", + "Assistant answer number 12.", + ]); + }); +}); diff --git a/apps/app/src/components/thread/timeline/ThreadTimelineRows.tsx b/apps/app/src/components/thread/timeline/ThreadTimelineRows.tsx index f024f5ac14..3548ad65dc 100644 --- a/apps/app/src/components/thread/timeline/ThreadTimelineRows.tsx +++ b/apps/app/src/components/thread/timeline/ThreadTimelineRows.tsx @@ -406,6 +406,14 @@ interface ConversationRowProps { showAssistantMessageActions: boolean; } +interface ConversationRowContentProps extends ConversationRowProps { + /** + * Resolved by the outer {@link ConversationRow} from the latest-actionable + * message-id contexts so this body only re-renders when its own value flips. + */ + mobileActionDisplay: "inline" | "overflow"; +} + const TimelineRendererStaticContext = createContext(null); // Kept out of the static renderer context on purpose: the metadata map covers @@ -915,6 +923,11 @@ function buildRowConsumerMessageActions(args: { })); } +/** + * Thin context reader: the latest-actionable message ids change on every new + * message, which re-renders every mounted row. Only the row whose + * `mobileActionDisplay` flips gets a new element below; the rest bail out. + */ function ConversationRow({ row, showAssistantMessageActions, @@ -925,6 +938,47 @@ function ConversationRow({ const latestActionableUserMessageId = useContext( LatestActionableUserMessageIdContext, ); + const latestActionableMessageId = + row.role === "user" + ? latestActionableUserMessageId + : latestActionableAssistantMessageId; + return ( + + ); +} + +/** + * Host `
` the sent-message inline editor portals into. Separate component + * so the ref-callback read stays out of {@link ConversationRowContent}: React + * Compiler treats a value passed to `ref` as a ref object and refuses to + * memoize any component that reads other fields of it during render. + */ +function InlineMessageEditorHost({ + editor, +}: { + editor: ThreadTimelineInlineMessageEditor; +}) { + return ( +
+
+
+ ); +} + +const ConversationRowContent = memo(function ConversationRowContent({ + row, + showAssistantMessageActions, + mobileActionDisplay, +}: ConversationRowContentProps) { const { canSpawnChild, inlineMessageEditor, @@ -954,14 +1008,7 @@ function ConversationRow({ inlineMessageEditor !== undefined && inlineMessageEditor.messageId === row.id ) { - return ( -
-
-
- ); + return ; } // The narrow, stable message reference plugin actions receive — sourced // from row fields, never the row object itself. @@ -1034,9 +1081,7 @@ function ConversationRow({ originKind={originKind} initiator={row.initiator} mentions={row.mentions} - mobileActionDisplay={ - row.id === latestActionableUserMessageId ? "inline" : "overflow" - } + mobileActionDisplay={mobileActionDisplay} onAddToChat={onSelectionAddToChat} onEdit={onEdit} onOpenLink={onOpenLink} @@ -1102,9 +1147,7 @@ function ConversationRow({ resolveUserAttachmentImageSrc={resolveUserAttachmentImageSrc} role="assistant" showActions={showAssistantMessageActions} - mobileActionDisplay={ - row.id === latestActionableAssistantMessageId ? "inline" : "overflow" - } + mobileActionDisplay={mobileActionDisplay} sourceSeqEnd={row.sourceSeqEnd} sourceSeqStart={row.sourceSeqStart} text={row.text} @@ -1114,7 +1157,7 @@ function ConversationRow({ workspaceRootPath={workspaceRootPath} /> ); -} +}); function TimelineUnreadDivider({ autoScroll }: TimelineUnreadDividerProps) { const bottomAnchor = useBottomAnchoredScroll(); diff --git a/apps/app/src/components/ui/app-route-anchor.tsx b/apps/app/src/components/ui/app-route-anchor.tsx index 91db9feb3f..505c090f12 100644 --- a/apps/app/src/components/ui/app-route-anchor.tsx +++ b/apps/app/src/components/ui/app-route-anchor.tsx @@ -3,12 +3,14 @@ import { useCallback, useContext, useEffect, + useLayoutEffect, useMemo, + useRef, type ComponentPropsWithoutRef, type MouseEvent as ReactMouseEvent, type ReactNode, } from "react"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, type NavigateOptions } from "react-router-dom"; import { isRoutePath, resolveRouteHref } from "@/lib/route-paths"; import { getDesktopBrowserApi } from "@/lib/bb-desktop"; @@ -16,8 +18,10 @@ export interface RouteNavigationProviderProps { children: ReactNode; } -export interface RouteAnchorProps - extends Omit, "href"> { +export interface RouteAnchorProps extends Omit< + ComponentPropsWithoutRef<"a">, + "href" +> { href: string | undefined; } @@ -25,10 +29,43 @@ interface ShouldHandleRouteAnchorClickArgs { event: ReactMouseEvent; } -type RouteNavigate = (path: string) => void; +export interface RouteNavigateOptions { + replace?: boolean; + state?: NavigateOptions["state"]; +} + +/** Navigate to an absolute app route (`/projects/...`); see {@link useRouteNavigate}. */ +export type RouteNavigate = ( + path: string, + options?: RouteNavigateOptions, +) => void; const RouteNavigationContext = createContext(null); +/** + * A `navigate` whose identity never changes and whose caller does not + * subscribe to the router's location. + * + * Under `` react-router's `useNavigate()` reads `useLocation()` + * and rebuilds its function per pathname, so every component that calls it + * re-renders on every navigation and every callback listing it as a + * dependency is rebuilt. Sidebar rows, the thread-actions context and the fork + * handler only navigate to absolute app routes, so they read this one stable + * function from {@link RouteNavigationProvider} (mounted once at the app root, + * which holds the live `useNavigate()` in a ref) instead. Without a provider + * the returned function throws when called, so a misplaced consumer fails at + * the click, not silently. + */ +export function useRouteNavigate(): RouteNavigate { + return useContext(RouteNavigationContext) ?? navigateWithoutProvider; +} + +function navigateWithoutProvider(path: string): void { + throw new Error( + `useRouteNavigate: no above the caller (navigating to "${path}")`, + ); +} + function currentOrigin(): string | null { return typeof window === "undefined" ? null : window.location.origin; } @@ -55,12 +92,21 @@ export function RouteNavigationProvider({ children, }: RouteNavigationProviderProps) { const navigate = useNavigate(); - const navigateRoute = useCallback( - (path) => { - navigate(path); - }, - [navigate], - ); + // The live `navigate` changes per pathname; the context value must not, or + // every consumer would re-render per navigation (the thing this exists to + // avoid). Layout effect: the ref is current before any child effect or + // event handler can navigate after a commit. + const navigateRef = useRef(navigate); + useLayoutEffect(() => { + navigateRef.current = navigate; + }, [navigate]); + const navigateRoute = useCallback((path, options) => { + if (options === undefined) { + navigateRef.current(path); + return; + } + navigateRef.current(path, options); + }, []); useEffect(() => { const browserApi = getDesktopBrowserApi(); if (browserApi === null) { diff --git a/apps/app/src/components/ui/sidebar.test.tsx b/apps/app/src/components/ui/sidebar.test.tsx index ca48987e11..8d0a4be9ad 100644 --- a/apps/app/src/components/ui/sidebar.test.tsx +++ b/apps/app/src/components/ui/sidebar.test.tsx @@ -7,6 +7,7 @@ import { render, screen, } from "@testing-library/react"; +import { memo } from "react"; import { renderToString } from "react-dom/server"; import { afterEach, describe, expect, it, vi } from "vitest"; import { CompactViewportOverrideProvider } from "@bb/shared-ui/hooks/use-compact-viewport"; @@ -15,7 +16,9 @@ import { SidebarInset, SidebarProvider, SidebarTrigger, + useIsSidebarShowing, useOptionalIsSidebarShowing, + useSidebar, } from "./sidebar"; afterEach(() => { @@ -135,6 +138,70 @@ describe("useOptionalIsSidebarShowing", () => { }); }); +describe("useIsSidebarShowing", () => { + it("re-renders its reader only when the visible bit flips, not on every provider commit", () => { + vi.useFakeTimers(); + const showingRenders: boolean[] = []; + const ShowingReader = memo(function ShowingReader() { + const isShowing = useIsSidebarShowing(); + showingRenders.push(isShowing); + return {String(isShowing)}; + }); + function Controls() { + const { + openMobileSidebar, + closeMobileSidebar, + setSuppressMobileOpenAnimation, + } = useSidebar(); + return ( + <> + + + + + ); + } + render( + + + + + + , + ); + expect(screen.getByTestId("showing").textContent).toBe("false"); + const settled = showingRenders.length; + + // A provider commit that changes the full context object but not the + // visible bit (page header and retained secondary panel read only the bit). + fireEvent.click(screen.getByRole("button", { name: "suppress" })); + expect(showingRenders).toHaveLength(settled); + + fireEvent.click(screen.getByRole("button", { name: "open" })); + settleMobileToggle(); + expect(screen.getByTestId("showing").textContent).toBe("true"); + const afterOpen = showingRenders.length; + expect(afterOpen).toBe(settled + 1); + + // Close: the closing-flag commit must not reach the reader; only the + // deferred openMobile flip does. + fireEvent.click(screen.getByRole("button", { name: "close" })); + expect(showingRenders).toHaveLength(afterOpen); + settleMobileToggle(); + expect(screen.getByTestId("showing").textContent).toBe("false"); + expect(showingRenders).toHaveLength(afterOpen + 1); + }); +}); + describe("SidebarTrigger", () => { it("uses the shared sidebar icon on every viewport", () => { const markup = renderToString( diff --git a/apps/app/src/components/ui/sidebar.tsx b/apps/app/src/components/ui/sidebar.tsx index 62de2d826b..bab801da53 100644 --- a/apps/app/src/components/ui/sidebar.tsx +++ b/apps/app/src/components/ui/sidebar.tsx @@ -442,6 +442,16 @@ type SidebarContext = { const SidebarContext = React.createContext(null); +/** + * "Is the sidebar visible" as its own boolean context. The full + * {@link SidebarContext} value changes on every provider commit (the mobile + * close flips the closing flag, then four states), and its readers include + * the page header and the retained secondary panel, whose ~1000-line bodies + * only need this one bit. A boolean context re-renders them only when the + * bit flips. `null` outside a provider. + */ +const SidebarShowingContext = React.createContext(null); + const SidebarContentElementContext = React.createContext | null>(null); @@ -465,19 +475,18 @@ function useSidebar() { return context; } -function useIsSidebarShowing() { - const { state, isCompactViewport, openMobile } = useSidebar(); - return isCompactViewport ? openMobile : state === "expanded"; +function useIsSidebarShowing(): boolean { + const isShowing = React.useContext(SidebarShowingContext); + if (isShowing === null) { + throw new Error( + "useIsSidebarShowing must be used within a SidebarProvider.", + ); + } + return isShowing; } -function useOptionalIsSidebarShowing() { - const context = React.useContext(SidebarContext); - if (context === null) { - return null; - } - return context.isCompactViewport - ? context.openMobile - : context.state === "expanded"; +function useOptionalIsSidebarShowing(): boolean | null { + return React.useContext(SidebarShowingContext); } /** @@ -702,35 +711,39 @@ const SidebarProvider = React.forwardRef< ], ); + const isSidebarShowing = isCompactViewport ? openMobile : open; + return ( - {/* Match the agent message action bar's tooltip timing (300ms open + + {/* Match the agent message action bar's tooltip timing (300ms open delay + Radix's default skip window) so sidebar icon tooltips feel the same instead of flashing instantly on hover. disableHoverableContent dismisses the tooltip the moment the pointer leaves the trigger, so it never lingers/floats while the mouse moves on. */} - -
- {children} -
-
+ +
+ {children} +
+
+
); }, @@ -1079,9 +1092,8 @@ const SidebarMobilePanel = React.forwardRef< // assistive-technology activation leave the trigger focus-visible, so // keep the modal focus move for those paths. const shouldMoveFocus = - previouslyFocused?.matches( - '[data-sidebar="trigger"]:focus-visible', - ) ?? false; + previouslyFocused?.matches('[data-sidebar="trigger"]:focus-visible') ?? + false; if (shouldMoveFocus) { panelRef.current?.focus({ preventScroll: true }); } @@ -1129,7 +1141,9 @@ const SidebarMobilePanel = React.forwardRef< for (let step = 1; step <= stops.length; step += 1) { const nextIndex = activeIndex === -1 - ? (event.shiftKey ? stops.length - step : step - 1) + ? event.shiftKey + ? stops.length - step + : step - 1 : (((activeIndex + direction * step) % stops.length) + stops.length) % stops.length; @@ -1145,7 +1159,10 @@ const SidebarMobilePanel = React.forwardRef< return () => { window.removeEventListener("keydown", handleKeyDown); const active = document.activeElement; - if (active instanceof HTMLElement && panelRef.current?.contains(active)) { + if ( + active instanceof HTMLElement && + panelRef.current?.contains(active) + ) { active.blur(); if (shouldMoveFocus) { previouslyFocused?.focus({ preventScroll: true }); @@ -1228,7 +1245,8 @@ const SidebarMobilePanel = React.forwardRef< const nowMs = Date.now(); const elapsedMs = nowMs - session.lastTimeMs; if (elapsedMs > 0) { - session.velocityX = ((clientX - session.lastClientX) / elapsedMs) * 1000; + session.velocityX = + ((clientX - session.lastClientX) / elapsedMs) * 1000; session.lastClientX = clientX; session.lastTimeMs = nowMs; } @@ -1340,10 +1358,7 @@ const SidebarMobilePanel = React.forwardRef< const handleMove = (moveEvent: PointerEvent) => { const session = dragSessionRef.current; - if ( - session?.kind !== "pointer" || - moveEvent.pointerId !== session.id - ) { + if (session?.kind !== "pointer" || moveEvent.pointerId !== session.id) { return; } continuePanelDrag(moveEvent.clientX, moveEvent.clientY, moveEvent); @@ -1377,9 +1392,7 @@ const SidebarMobilePanel = React.forwardRef< removeDragListenersRef.current = removeListeners; }; - const handlePanelTouchStart = ( - event: React.TouchEvent, - ) => { + const handlePanelTouchStart = (event: React.TouchEvent) => { onTouchStart?.(event); if ( !open || diff --git a/apps/app/src/hooks/queries/child-thread-pending-interactions.hook.test.tsx b/apps/app/src/hooks/queries/child-thread-pending-interactions.hook.test.tsx new file mode 100644 index 0000000000..73cfb21ee7 --- /dev/null +++ b/apps/app/src/hooks/queries/child-thread-pending-interactions.hook.test.tsx @@ -0,0 +1,118 @@ +// @vitest-environment jsdom + +import type { ReactNode } from "react"; +import { cleanup, renderHook, waitFor } from "@testing-library/react"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import type { PendingInteraction } from "@bb/domain"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { + EMPTY_CHILD_THREAD_PENDING_ATTENTION, + useChildThreadPendingAttention, + type ChildThreadPendingAttentionSource, +} from "./child-thread-pending-interactions"; + +const mocks = vi.hoisted(() => ({ + list: vi.fn(), +})); + +vi.mock("@/lib/sdk", () => ({ + sdk: { threads: { interactions: { list: mocks.list } } }, +})); + +function makeApproval(id: string, createdAt: number): PendingInteraction { + return { + id, + threadId: "thr_child", + turnId: "turn_1", + providerId: "codex", + providerThreadId: "provider-thread", + providerRequestId: `request-${id}`, + origin: { + kind: "provider", + providerId: "codex", + providerThreadId: "provider-thread", + providerRequestId: `request-${id}`, + }, + status: "pending", + resolution: null, + statusReason: null, + createdAt, + resolvedAt: null, + payload: { + kind: "approval", + subject: { + kind: "command", + itemId: "item_cmd", + command: "ls", + cwd: "/tmp", + actions: [], + sessionGrant: null, + }, + reason: "Run a command", + availableDecisions: ["allow_once", "deny"], + }, + }; +} + +function renderAttention( + children: readonly ChildThreadPendingAttentionSource[], +) { + const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false } }, + }); + const wrapper = ({ children: node }: { children: ReactNode }) => ( + {node} + ); + return renderHook( + ({ items }: { items: readonly ChildThreadPendingAttentionSource[] }) => + useChildThreadPendingAttention(items), + { initialProps: { items: children }, wrapper }, + ); +} + +afterEach(() => { + cleanup(); + vi.clearAllMocks(); +}); + +describe("useChildThreadPendingAttention", () => { + it("returns the shared empty array when no child needs attention", () => { + const children = [ + { + id: "thr_working", + title: "Run tests", + href: "/threads/thr_working", + hasPendingInteraction: false, + }, + ]; + const { result, rerender } = renderAttention(children); + expect(result.current).toBe(EMPTY_CHILD_THREAD_PENDING_ATTENTION); + // ThreadDetailView re-renders constantly; the value it memoizes the prompt + // stack on must not change identity when nothing changed. + rerender({ items: children }); + expect(result.current).toBe(EMPTY_CHILD_THREAD_PENDING_ATTENTION); + expect(mocks.list).not.toHaveBeenCalled(); + }); + + it("keeps the same array across re-renders while the child interactions are unchanged", async () => { + mocks.list.mockResolvedValue([makeApproval("pi_1", 10)]); + const children = [ + { + id: "thr_blocked", + title: "Install tools", + href: "/threads/thr_blocked", + hasPendingInteraction: true, + }, + ]; + const { result, rerender } = renderAttention(children); + await waitFor(() => { + expect(result.current).toHaveLength(1); + }); + const settled = result.current; + expect(settled[0]?.interaction.id).toBe("pi_1"); + + rerender({ items: children }); + rerender({ items: children }); + expect(result.current).toBe(settled); + }); +}); diff --git a/apps/app/src/hooks/queries/child-thread-pending-interactions.ts b/apps/app/src/hooks/queries/child-thread-pending-interactions.ts index 743bd440cf..e99ff4fa3b 100644 --- a/apps/app/src/hooks/queries/child-thread-pending-interactions.ts +++ b/apps/app/src/hooks/queries/child-thread-pending-interactions.ts @@ -1,4 +1,4 @@ -import { useQueries } from "@tanstack/react-query"; +import { useQueries, type UseQueryResult } from "@tanstack/react-query"; import { useMemo } from "react"; import type { PendingInteraction } from "@bb/domain"; import { sdk } from "@/lib/sdk"; @@ -20,13 +20,21 @@ export interface ChildThreadPendingAttention { interaction: PendingInteraction; } +/** + * Shared "nothing pending" result. `ThreadDetailView` feeds the hook's return + * value into the prompt-area props (`promptStack`), which are memoized on it; + * a fresh empty array per render would invalidate them on every view render. + */ +export const EMPTY_CHILD_THREAD_PENDING_ATTENTION: readonly ChildThreadPendingAttention[] = + Object.freeze([]); + export function collectChildThreadPendingAttention( children: readonly ChildThreadPendingAttentionSource[], interactionsByThreadId: ReadonlyMap< string, readonly PendingInteraction[] | undefined >, -): ChildThreadPendingAttention[] { +): readonly ChildThreadPendingAttention[] { const items: ChildThreadPendingAttention[] = []; for (const child of children) { if (!child.hasPendingInteraction) { @@ -45,12 +53,31 @@ export function collectChildThreadPendingAttention( interaction, }); } - return items; + return items.length === 0 ? EMPTY_CHILD_THREAD_PENDING_ATTENTION : items; +} + +const EMPTY_INTERACTION_LISTS: readonly ( + | readonly PendingInteraction[] + | undefined +)[] = Object.freeze([]); + +/** + * Module-level so its identity is stable: TanStack only structurally shares + * a `useQueries` result across renders when `combine` keeps its reference, + * and it re-runs an inline one every render. Without it the hook returned a + * new array per render. + */ +function combinePendingInteractionLists( + results: UseQueryResult[], +): readonly (readonly PendingInteraction[] | undefined)[] { + return results.length === 0 + ? EMPTY_INTERACTION_LISTS + : results.map((result) => result.data); } export function useChildThreadPendingAttention( children: readonly ChildThreadPendingAttentionSource[], -): ChildThreadPendingAttention[] { +): readonly ChildThreadPendingAttention[] { // Thread-list realtime already flips `hasPendingInteraction`. Resolving // from the parent invalidates the interaction query. Do not subscribe to // each child detail stream. @@ -62,7 +89,7 @@ export function useChildThreadPendingAttention( [children], ); - const queries = useQueries({ + const interactionLists = useQueries({ queries: pendingChildIds.map((threadId) => ({ queryKey: threadPendingInteractionsQueryKey(threadId), queryFn: ({ signal }: { signal: AbortSignal }) => @@ -74,15 +101,16 @@ export function useChildThreadPendingAttention( refetchOnMount: true, ...REALTIME_OWNED_NO_FOCUS_QUERY_POLICY, })), + combine: combinePendingInteractionLists, }); const interactionsByThreadId = useMemo(() => { const next = new Map(); pendingChildIds.forEach((threadId, index) => { - next.set(threadId, queries[index]?.data); + next.set(threadId, interactionLists[index]); }); return next; - }, [pendingChildIds, queries]); + }, [pendingChildIds, interactionLists]); return useMemo( () => collectChildThreadPendingAttention(children, interactionsByThreadId), diff --git a/apps/app/src/hooks/useCreateThreadInWorktree.ts b/apps/app/src/hooks/useCreateThreadInWorktree.ts index 02967e5ee1..c5b3bd3607 100644 --- a/apps/app/src/hooks/useCreateThreadInWorktree.ts +++ b/apps/app/src/hooks/useCreateThreadInWorktree.ts @@ -1,5 +1,5 @@ import { useCallback } from "react"; -import { useNavigate } from "react-router-dom"; +import { useRouteNavigate } from "@/components/ui/app-route-anchor"; import { getRootComposeRoutePath } from "@/lib/route-paths"; import { useSetRootComposeProjectId } from "@/lib/root-compose-selection"; @@ -17,7 +17,7 @@ export function useCreateThreadInWorktree({ projectId, environmentId, }: UseCreateThreadInWorktreeArgs): () => void { - const navigate = useNavigate(); + const navigate = useRouteNavigate(); const setRootComposeProjectId = useSetRootComposeProjectId(); return useCallback(() => { setRootComposeProjectId(projectId); diff --git a/apps/app/src/hooks/useForkThreadFromMessage.test.tsx b/apps/app/src/hooks/useForkThreadFromMessage.test.tsx index c7ad96c86a..8310585c33 100644 --- a/apps/app/src/hooks/useForkThreadFromMessage.test.tsx +++ b/apps/app/src/hooks/useForkThreadFromMessage.test.tsx @@ -1,6 +1,7 @@ // @vitest-environment jsdom import { act, cleanup, renderHook } from "@testing-library/react"; +import type { ReactNode } from "react"; import type { Thread } from "@bb/domain"; import { afterEach, describe, expect, it, vi } from "vitest"; import { @@ -8,12 +9,31 @@ import { type ForkThreadCreateSeed, } from "@/lib/fork-thread-request"; import { getRootComposeRoutePath } from "@/lib/route-paths"; +import { RouteNavigationProvider } from "@/components/ui/app-route-anchor"; import { useForkThreadFromMessage } from "./useForkThreadFromMessage"; const mocks = vi.hoisted(() => ({ fetchQuery: vi.fn(), navigate: vi.fn(), setRootComposeProjectId: vi.fn(), + queryClient: { + fetchQuery: (...args: unknown[]) => mocks.fetchQuery(...args), + // findCachedProviderInfo scans cached execution-options responses for + // the source provider's fork capability. + getQueriesData: () => [ + [ + ["systemExecutionOptions"], + { + providers: [ + { + id: "codex", + capabilities: { supportsFork: true }, + }, + ], + }, + ], + ], + }, })); vi.mock("react-router-dom", async (importOriginal) => { @@ -28,24 +48,8 @@ vi.mock("@tanstack/react-query", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, - useQueryClient: () => ({ - fetchQuery: mocks.fetchQuery, - // findCachedProviderInfo scans cached execution-options responses for - // the source provider's fork capability. - getQueriesData: () => [ - [ - ["systemExecutionOptions"], - { - providers: [ - { - id: "codex", - capabilities: { supportsFork: true }, - }, - ], - }, - ], - ], - }), + // One stable client per test run, like the real provider hands out. + useQueryClient: () => mocks.queryClient, }; }); @@ -84,6 +88,10 @@ afterEach(() => { vi.clearAllMocks(); }); +function Wrapper({ children }: { children: ReactNode }) { + return {children}; +} + describe("useForkThreadFromMessage", () => { it("opens the root composer with the source thread display title in the fork seed", async () => { mocks.fetchQuery.mockResolvedValue({ @@ -93,10 +101,12 @@ describe("useForkThreadFromMessage", () => { serviceTier: "fast", }); - const { result } = renderHook(() => - useForkThreadFromMessage({ - sourceThread: makeThread(), - }), + const { result } = renderHook( + () => + useForkThreadFromMessage({ + sourceThread: makeThread(), + }), + { wrapper: Wrapper }, ); await act(async () => { @@ -130,4 +140,34 @@ describe("useForkThreadFromMessage", () => { sourceThreadTitle: "Fallback fork title", }); }); + it("keeps one handler identity across thread refetches and reads the latest thread", async () => { + mocks.fetchQuery.mockResolvedValue({ + model: "gpt-5", + permissionMode: "accept-edits", + reasoningLevel: "high", + serviceTier: "fast", + }); + const { result, rerender } = renderHook( + ({ sourceThread }: { sourceThread: Thread | null }) => + useForkThreadFromMessage({ sourceThread }), + { initialProps: { sourceThread: makeThread() }, wrapper: Wrapper }, + ); + const first = result.current; + + // A refetch hands the hook a new thread object (same id, new title): the + // handler feeds the timeline static context, so its identity must hold. + rerender({ sourceThread: makeThread({ title: "Renamed source" }) }); + expect(result.current).toBe(first); + + await act(async () => { + await first({ sourceSeqEnd: 3 }); + }); + const navigateState = mocks.navigate.mock.calls[0]?.[1]?.state as + | Record + | undefined; + const seed = navigateState?.[FORK_THREAD_CREATE_SEED_LOCATION_STATE_KEY] as + | ForkThreadCreateSeed + | undefined; + expect(seed?.sourceThreadTitle).toBe("Renamed source"); + }); }); diff --git a/apps/app/src/hooks/useForkThreadFromMessage.ts b/apps/app/src/hooks/useForkThreadFromMessage.ts index 85f65a979e..30c84c1ce2 100644 --- a/apps/app/src/hooks/useForkThreadFromMessage.ts +++ b/apps/app/src/hooks/useForkThreadFromMessage.ts @@ -1,5 +1,4 @@ -import { useCallback, useRef } from "react"; -import { useNavigate } from "react-router-dom"; +import { useCallback, useLayoutEffect, useRef } from "react"; import { useQueryClient } from "@tanstack/react-query"; import type { Thread } from "@bb/domain"; import { sdk } from "@/lib/sdk"; @@ -13,6 +12,7 @@ import { getThreadDisplayTitle } from "@/lib/thread-title"; import { useSetRootComposeProjectId } from "@/lib/root-compose-selection"; import { threadDefaultExecutionOptionsQueryKey } from "@/hooks/queries/query-keys"; import { findCachedProviderInfo } from "@/hooks/queries/system-queries"; +import { useRouteNavigate } from "@/components/ui/app-route-anchor"; export interface UseForkThreadFromMessageArgs { /** Source thread the fork branches from. Null until the thread loads. */ @@ -23,65 +23,79 @@ export interface ForkThreadFromMessageTarget { sourceSeqEnd: number; } +/** + * Returns a handler whose identity is stable for the lifetime of the caller. + * It reads the source thread from a ref at click time: the handler feeds the + * timeline's static context, so a new identity per thread-detail refetch + * would re-render every mounted message row. + */ export function useForkThreadFromMessage({ sourceThread, }: UseForkThreadFromMessageArgs): ( target: ForkThreadFromMessageTarget, ) => Promise { - const navigate = useNavigate(); + const navigate = useRouteNavigate(); const queryClient = useQueryClient(); const setRootComposeProjectId = useSetRootComposeProjectId(); const forkInFlightRef = useRef(false); + const sourceThreadRef = useRef(sourceThread); + useLayoutEffect(() => { + sourceThreadRef.current = sourceThread; + }, [sourceThread]); - return useCallback(async (target: ForkThreadFromMessageTarget) => { - if ( - sourceThread === null || - !isThreadForkable( - sourceThread, - findCachedProviderInfo(queryClient, sourceThread.providerId) - ?.capabilities.supportsFork ?? false, - ) || - forkInFlightRef.current - ) { - return; - } - - forkInFlightRef.current = true; - try { - const executionOptions = await queryClient.fetchQuery({ - queryKey: threadDefaultExecutionOptionsQueryKey(sourceThread.id), - queryFn: ({ signal }) => - sdk.threads.defaultExecutionOptions({ - signal, - threadId: sourceThread.id, - }), - }); - if (executionOptions === null || sourceThread.environmentId === null) { + return useCallback( + async (target: ForkThreadFromMessageTarget) => { + const source = sourceThreadRef.current; + if ( + source === null || + !isThreadForkable( + source, + findCachedProviderInfo(queryClient, source.providerId)?.capabilities + .supportsFork ?? false, + ) || + forkInFlightRef.current + ) { return; } - const seed: ForkThreadCreateSeed = { - environmentId: sourceThread.environmentId, - model: executionOptions.model, - permissionMode: executionOptions.permissionMode, - projectId: sourceThread.projectId, - providerId: sourceThread.providerId, - reasoningLevel: executionOptions.reasoningLevel, - serviceTier: executionOptions.serviceTier, - sourceSeqEnd: target.sourceSeqEnd, - sourceThreadId: sourceThread.id, - sourceThreadTitle: getThreadDisplayTitle(sourceThread), - }; - setRootComposeProjectId(sourceThread.projectId); - navigate(getRootComposeRoutePath(), { - state: { - focusPrompt: true, - reuseEnvironmentId: sourceThread.environmentId, - [FORK_THREAD_CREATE_SEED_LOCATION_STATE_KEY]: seed, - }, - }); - } finally { - forkInFlightRef.current = false; - } - }, [navigate, queryClient, setRootComposeProjectId, sourceThread]); + forkInFlightRef.current = true; + try { + const executionOptions = await queryClient.fetchQuery({ + queryKey: threadDefaultExecutionOptionsQueryKey(source.id), + queryFn: ({ signal }) => + sdk.threads.defaultExecutionOptions({ + signal, + threadId: source.id, + }), + }); + if (executionOptions === null || source.environmentId === null) { + return; + } + + const seed: ForkThreadCreateSeed = { + environmentId: source.environmentId, + model: executionOptions.model, + permissionMode: executionOptions.permissionMode, + projectId: source.projectId, + providerId: source.providerId, + reasoningLevel: executionOptions.reasoningLevel, + serviceTier: executionOptions.serviceTier, + sourceSeqEnd: target.sourceSeqEnd, + sourceThreadId: source.id, + sourceThreadTitle: getThreadDisplayTitle(source), + }; + setRootComposeProjectId(source.projectId); + navigate(getRootComposeRoutePath(), { + state: { + focusPrompt: true, + reuseEnvironmentId: source.environmentId, + [FORK_THREAD_CREATE_SEED_LOCATION_STATE_KEY]: seed, + }, + }); + } finally { + forkInFlightRef.current = false; + } + }, + [navigate, queryClient, setRootComposeProjectId], + ); } diff --git a/apps/app/src/hooks/useLatestRef.ts b/apps/app/src/hooks/useLatestRef.ts new file mode 100644 index 0000000000..3196208063 --- /dev/null +++ b/apps/app/src/hooks/useLatestRef.ts @@ -0,0 +1,22 @@ +import { useRef, type RefObject } from "react"; + +/** + * A ref that always holds the latest `value`, updated during render so event + * handlers, async continuations and child callbacks in the same commit read + * the current value without being re-created per render. + * + * Kept in its own hook on purpose: React Compiler refuses to memoize any + * function that writes a ref during render, and it also types the assigned + * value as a ref, so an inlined `ref.current = value` costs the whole calling + * component its memoization (this was one of the reasons + * `ThreadDetailPromptArea` compiled to nothing). Only the reads matter to the + * caller; do them outside render. + */ +export function useLatestRef(value: T): RefObject { + const ref = useRef(value); + // Deliberate render-time write: this hook exists to keep that write (and the + // compiler bailout it costs) out of the calling component. + // eslint-disable-next-line react-hooks/refs + ref.current = value; + return ref; +} diff --git a/apps/app/src/hooks/usePromptDraftStorage.test.tsx b/apps/app/src/hooks/usePromptDraftStorage.test.tsx index 8322aa909d..d120debed0 100644 --- a/apps/app/src/hooks/usePromptDraftStorage.test.tsx +++ b/apps/app/src/hooks/usePromptDraftStorage.test.tsx @@ -166,6 +166,59 @@ describe("usePromptDraftStorage", () => { expect([...result.current.inputThreadIds]).toEqual([]); }); + it("does not re-read storage or re-render the batch when a draft edit keeps presence", () => { + const projectId = "proj-batch-keystrokes"; + const threadRefs = Array.from({ length: 30 }, (_, index) => ({ + id: `thr-batch-${index}`, + projectId, + })); + const composer = getPromptDraftAccessor({ + kind: "thread", + projectId, + threadId: "thr-batch-3", + }); + let batchRenders = 0; + const { result, rerender } = renderHook(() => { + batchRenders += 1; + return usePromptDraftInputThreadIds(threadRefs); + }); + act(() => { + composer.setDraft({ text: "first", mentions: [], attachments: [] }); + }); + expect([...result.current]).toEqual(["thr-batch-3"]); + + const getItem = vi.spyOn(Storage.prototype, "getItem"); + const presenceReads = () => + getItem.mock.calls.filter(([key]) => String(key).includes(projectId)) + .length; + // The sidebar re-renders for unrelated reasons constantly; the presence + // snapshot must come from the cache, not 30 localStorage reads. + rerender(); + expect(presenceReads()).toBe(0); + + // A keystroke in an already-present draft: presence did not flip, so the + // batch subscriber is not notified (no sidebar render) and only the edited + // key is consulted. + const rendersBefore = batchRenders; + act(() => { + composer.setDraft({ + text: "first keystroke", + mentions: [], + attachments: [], + }); + }); + expect(presenceReads()).toBeLessThanOrEqual(1); + expect(batchRenders).toBe(rendersBefore); + + // Clearing flips presence: one notification, one render, one read. + act(() => { + composer.setDraft({ text: "", mentions: [], attachments: [] }); + }); + expect([...result.current]).toEqual([]); + expect(batchRenders).toBe(rendersBefore + 1); + getItem.mockRestore(); + }); + it("uses project-agnostic storage for new-thread prompt contents", () => { window.localStorage.setItem( LEGACY_PROJECT_DRAFT_KEY, diff --git a/apps/app/src/hooks/usePromptDraftStorage.ts b/apps/app/src/hooks/usePromptDraftStorage.ts index 09a7f0cf00..01dc987869 100644 --- a/apps/app/src/hooks/usePromptDraftStorage.ts +++ b/apps/app/src/hooks/usePromptDraftStorage.ts @@ -483,6 +483,67 @@ interface PromptDraftThreadSubscription { threadId: string; } +function getEmptyPresenceSnapshot(): string { + return ""; +} + +function readPromptDraftPresenceBit(storageKey: string): "0" | "1" { + return isPromptDraftEmpty(readPromptDraft(storageKey)) ? "0" : "1"; +} + +/** + * Presence bit-string store for one subscription set. `getSnapshot` runs on + * every render of the subscribing component (the sidebar), and a change to + * one draft notifies once per keystroke; reading localStorage for every + * sidebar thread on each of those was N `getItem` calls per keystroke and per + * sidebar render. The store caches the joined bits, re-reads only the key + * that changed, and stays silent when that key's presence did not flip. + */ +function createPromptDraftPresenceStore( + subscriptions: readonly PromptDraftThreadSubscription[], +): { + subscribe: (listener: () => void) => () => void; + getSnapshot: () => string; +} { + let bits: ("0" | "1")[] | null = null; + let snapshot: string | null = null; + const refresh = (): string => { + bits = subscriptions.map(({ storageKey }) => + readPromptDraftPresenceBit(storageKey), + ); + snapshot = bits.join(""); + return snapshot; + }; + return { + getSnapshot: () => snapshot ?? refresh(), + subscribe: (listener) => { + // A draft may have flipped between the render that computed `snapshot` + // and this subscription; drop the cache so the post-subscribe + // `getSnapshot` re-reads instead of returning the stale string. + snapshot = null; + bits = null; + const unsubscribe = subscriptions.map(({ storageKey }, index) => + subscribePromptDraft(storageKey, () => { + const bit = readPromptDraftPresenceBit(storageKey); + if (bits !== null && bits[index] === bit) return; + if (bits === null) { + refresh(); + } else { + bits[index] = bit; + snapshot = bits.join(""); + } + listener(); + }), + ); + return () => { + for (const stopListening of unsubscribe) { + stopListening(); + } + }; + }, + }; +} + /** * Subscribes to draft presence for a collection of threads without mounting a * hook per row. The primitive bit-string snapshot stays referentially stable @@ -509,30 +570,14 @@ export function usePromptDraftInputThreadIds( return next; }, [threads]); + const presenceStore = useMemo( + () => createPromptDraftPresenceStore(subscriptions), + [subscriptions], + ); const presenceSnapshot = useSyncExternalStore( - useCallback( - (listener) => { - const unsubscribe = subscriptions.map(({ storageKey }) => - subscribePromptDraft(storageKey, listener), - ); - return () => { - for (const stopListening of unsubscribe) { - stopListening(); - } - }; - }, - [subscriptions], - ), - useCallback( - () => - subscriptions - .map(({ storageKey }) => - isPromptDraftEmpty(readPromptDraft(storageKey)) ? "0" : "1", - ) - .join(""), - [subscriptions], - ), - () => "", + presenceStore.subscribe, + presenceStore.getSnapshot, + getEmptyPresenceSnapshot, ); return useMemo(() => { diff --git a/apps/app/src/hooks/useSecondTick.ts b/apps/app/src/hooks/useSecondTick.ts new file mode 100644 index 0000000000..e96c0b3fe0 --- /dev/null +++ b/apps/app/src/hooks/useSecondTick.ts @@ -0,0 +1,44 @@ +import { useSyncExternalStore } from "react"; + +/** + * One 1 Hz ticker shared by every live-duration label. Each label used to own + * a `setInterval` plus a state update; with several workflow/background rows + * mounted that is many timers firing at slightly different phases, each a + * separate render. One interval, one notification per second, and it stops + * when the last subscriber leaves. + */ +const listeners = new Set<() => void>(); +let lastTickMs = 0; +let intervalId: ReturnType | null = null; + +function tick(): void { + lastTickMs = Date.now(); + for (const listener of listeners) listener(); +} + +function subscribe(listener: () => void): () => void { + if (listeners.size === 0) { + lastTickMs = Date.now(); + intervalId = setInterval(tick, 1_000); + } + listeners.add(listener); + return () => { + listeners.delete(listener); + if (listeners.size === 0 && intervalId !== null) { + clearInterval(intervalId); + intervalId = null; + } + }; +} + +function getSnapshot(): number { + // Before the first subscription there is no ticker; read the clock once so + // the initial render is not a stale zero. + if (lastTickMs === 0) lastTickMs = Date.now(); + return lastTickMs; +} + +/** Current time in ms, refreshed once per second while any subscriber is mounted. */ +export function useSecondTick(): number { + return useSyncExternalStore(subscribe, getSnapshot, getSnapshot); +} diff --git a/apps/app/src/lib/plugin-frontend-load-order.test.ts b/apps/app/src/lib/plugin-frontend-load-order.test.ts index e6bf7daeff..f12f1c79f5 100644 --- a/apps/app/src/lib/plugin-frontend-load-order.test.ts +++ b/apps/app/src/lib/plugin-frontend-load-order.test.ts @@ -68,6 +68,7 @@ function makeDeps( removeRegistrations: vi.fn(), warn: vi.fn(), routePluginId: () => null, + beginSlotBatch: () => () => {}, ...overrides, }; } diff --git a/apps/app/src/lib/plugin-frontend-reload.test.ts b/apps/app/src/lib/plugin-frontend-reload.test.ts index e0823f5fce..bbdaefb61e 100644 --- a/apps/app/src/lib/plugin-frontend-reload.test.ts +++ b/apps/app/src/lib/plugin-frontend-reload.test.ts @@ -86,6 +86,7 @@ function makeDeps(initial: PluginFrontendCandidate[] = []) { resetCrashedSlots: vi.fn(), setRegistrations: vi.fn(), removeRegistrations: vi.fn(), + beginSlotBatch: () => () => {}, warn: vi.fn(), routePluginId: () => null, mountTimeoutMs: undefined as number | undefined, @@ -154,6 +155,7 @@ describe("reconcilePluginFrontends", () => { resetCrashedSlots: vi.fn(), setRegistrations: setPluginSlotRegistrations, removeRegistrations: removePluginSlotRegistrations, + beginSlotBatch: () => () => {}, warn: vi.fn(), routePluginId: () => null, }; diff --git a/apps/app/src/lib/plugin-frontend.ts b/apps/app/src/lib/plugin-frontend.ts index c99be26254..0b1e2a2653 100644 --- a/apps/app/src/lib/plugin-frontend.ts +++ b/apps/app/src/lib/plugin-frontend.ts @@ -51,6 +51,7 @@ import { createGatedPierreDiffsReact } from "./plugin-pierre-diffs-react"; import { getPluginPanelRoutePluginId } from "./route-paths"; import { pluginSdkAppImplementation } from "./plugin-sdk-app-impl"; import { + beginPluginSlotBatch, removePluginSlotRegistrations, setPluginSlotRegistrations, type PluginRegistrationSet, @@ -492,6 +493,11 @@ export interface PluginFrontendReconcileDeps { registrations: PluginRegistrationSet, ) => void; removeRegistrations: (pluginId: string) => void; + /** + * Hold slot-store notifications while a reconcile run activates several + * plugins; returns the closer. Production binds `beginPluginSlotBatch`. + */ + beginSlotBatch: () => () => void; warn: (message: string) => void; /** * The plugin whose panel is the current route (`/plugins/:pluginId/...`), @@ -778,6 +784,23 @@ export async function reconcilePluginFrontends( state.diagnostics.delete(pluginId); deps.diagnosticsChanged?.(); } + // One notification burst per run instead of one per plugin: every + // `usePluginSlots` reader (timeline static context, markdown directive + // registry, composer customizations, ...) would otherwise re-render once + // per bundle as they resolve. + const closeSlotBatch = deps.beginSlotBatch(); + try { + await reconcileCandidates(candidates, state, deps); + } finally { + closeSlotBatch(); + } +} + +async function reconcileCandidates( + candidates: readonly PluginFrontendCandidate[], + state: PluginFrontendReconcileState, + deps: PluginFrontendReconcileDeps, +): Promise { // Bounded, ordered loading: every bundle is a separate parse/eval on the // main thread and, on a phone, they used to all land during the window in // which the route chunk itself was still arriving. Three at a time keeps @@ -1027,6 +1050,13 @@ function publishBrowserDiagnostics(): void { for (const listener of browserDiagnosticsListeners) listener(); } +/** + * Longest a reconcile run holds slot notifications: bundles that resolve + * within this window flush together; a slow bundle cannot keep the others' + * UI off screen past it. + */ +const PLUGIN_SLOT_BATCH_MAX_HOLD_MS = 150; + const browserReconcileDeps: PluginFrontendReconcileDeps = { fetchCandidates: fetchFrontendCandidates, importModule: (url) => import(/* @vite-ignore */ url), @@ -1040,6 +1070,8 @@ const browserReconcileDeps: PluginFrontendReconcileDeps = { resetCrashedSlots: resetCrashedPluginSlots, setRegistrations: setPluginSlotRegistrations, removeRegistrations: removePluginSlotRegistrations, + beginSlotBatch: () => + beginPluginSlotBatch({ maxHoldMs: PLUGIN_SLOT_BATCH_MAX_HOLD_MS }), warn: (message) => console.warn(message), diagnosticsChanged: publishBrowserDiagnostics, }; diff --git a/apps/app/src/lib/plugin-sidebar-hooks.test.tsx b/apps/app/src/lib/plugin-sidebar-hooks.test.tsx new file mode 100644 index 0000000000..78356c8b43 --- /dev/null +++ b/apps/app/src/lib/plugin-sidebar-hooks.test.tsx @@ -0,0 +1,91 @@ +// @vitest-environment jsdom + +import { cleanup, renderHook } from "@testing-library/react"; +import { PERSONAL_PROJECT_ID, type ThreadListEntry } from "@bb/domain"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { makeThreadListEntry } from "@/test/fixtures/thread-list-entries"; +import { useSidebarThreads } from "./plugin-sidebar-hooks"; + +const state = vi.hoisted(() => ({ + data: undefined as + | { + sections: never[]; + projects: { id: string; name: string; threads: ThreadListEntry[] }[]; + personalProject: { + id: string; + name: string; + threads: ThreadListEntry[]; + }; + } + | undefined, +})); + +vi.mock("@/hooks/queries/sidebar-navigation-query", () => ({ + useSidebarNavigation: () => ({ data: state.data, isError: false }), +})); + +vi.mock("@/hooks/queries/host-queries", () => { + // Stable like the real query result; a fresh array per render would rebuild + // the host-name map and (correctly) invalidate every cached DTO. + const hosts: never[] = []; + return { useHosts: () => ({ data: hosts }) }; +}); + +function payload(threads: ThreadListEntry[]) { + return { + sections: [], + projects: [{ id: "proj_app", name: "App", threads }], + personalProject: { id: PERSONAL_PROJECT_ID, name: "Personal", threads: [] }, + }; +} + +afterEach(() => { + cleanup(); + state.data = undefined; +}); + +describe("useSidebarThreads", () => { + it("keeps DTO identity for entries that did not change across a sidebar update", () => { + const stable = makeThreadListEntry({ id: "thr_stable", title: "Stable" }); + const changing = makeThreadListEntry({ id: "thr_changing", title: "One" }); + state.data = payload([stable, changing]); + const { result, rerender } = renderHook(() => useSidebarThreads()); + const before = result.current.threads; + expect(before.map((thread) => thread.id)).toEqual([ + "thr_stable", + "thr_changing", + ]); + + // React Query structurally shares the payload: a refetch that touched + // one thread keeps the other entry objects. Plugin rows memoized on their + // thread DTO must get the same object back for the untouched thread. + state.data = payload([ + stable, + makeThreadListEntry({ id: "thr_changing", title: "Two" }), + ]); + rerender(); + const after = result.current.threads; + expect(after).not.toBe(before); + expect(after[0]).toBe(before[0]); + expect(after[1]).not.toBe(before[1]); + expect(after[1]?.title).toBe("Two"); + }); + + it("shares DTO identity between two consumers of the same payload", () => { + const stable = makeThreadListEntry({ id: "thr_stable", title: "Stable" }); + state.data = payload([stable]); + const first = renderHook(() => useSidebarThreads()); + const second = renderHook(() => useSidebarThreads()); + // Two plugin lists mounted at once (or one list plus the built-in + // sidebar's plugin surfaces): each derives the host-name map from the + // same hosts payload, so they must not evict each other's cached DTOs. + expect(second.result.current.threads[0]).toBe( + first.result.current.threads[0], + ); + const before = first.result.current.threads[0]; + first.rerender(); + second.rerender(); + expect(first.result.current.threads[0]).toBe(before); + expect(second.result.current.threads[0]).toBe(before); + }); +}); diff --git a/apps/app/src/lib/plugin-sidebar-hooks.ts b/apps/app/src/lib/plugin-sidebar-hooks.ts index e9ed333427..07d2f714ed 100644 --- a/apps/app/src/lib/plugin-sidebar-hooks.ts +++ b/apps/app/src/lib/plugin-sidebar-hooks.ts @@ -1,7 +1,10 @@ import { useCallback, useMemo } from "react"; import { useStore } from "jotai"; -import { useNavigate } from "react-router-dom"; -import { PERSONAL_PROJECT_ID, type ThreadListEntry } from "@bb/domain"; +import { + PERSONAL_PROJECT_ID, + type Host, + type ThreadListEntry, +} from "@bb/domain"; import { useIsCompactViewport } from "@bb/shared-ui/hooks/use-compact-viewport"; import type { PluginSidebarProject, @@ -19,6 +22,7 @@ import { useHosts } from "@/hooks/queries/host-queries"; import { useSidebarNavigation } from "@/hooks/queries/sidebar-navigation-query"; import { useUpdateThread } from "@/hooks/mutations/thread-state-mutations"; import { useThreadSplitsEnabled } from "@/hooks/useThreadSplitsEnabled"; +import { useRouteNavigate } from "@/components/ui/app-route-anchor"; import { toPluginSidebarThread } from "./plugin-sidebar-threads"; import { useSetRootComposeProjectId } from "./root-compose-selection"; import { openThreadInSplit } from "./split-layout/openThreadInSplit"; @@ -31,6 +35,54 @@ import { const EMPTY_THREADS: readonly PluginSidebarThread[] = []; const EMPTY_PROJECTS: readonly PluginSidebarProject[] = []; const EMPTY_ENTRIES: ReadonlyMap = new Map(); +const EMPTY_HOST_NAMES: ReadonlyMap = new Map(); + +/** + * Host-name map per hosts payload. Module-level (not `useMemo`) so every + * `useSidebarThreads` caller derives the same map object from the same React + * Query result; a per-hook map would give two plugin lists two keys and make + * them evict each other's entries from {@link pluginSidebarThreadByEntry}. + */ +const hostNamesByHosts = new WeakMap< + readonly Host[], + ReadonlyMap +>(); + +function hostNamesFor( + hosts: readonly Host[] | undefined, +): ReadonlyMap { + if (hosts === undefined) return EMPTY_HOST_NAMES; + const cached = hostNamesByHosts.get(hosts); + if (cached !== undefined) return cached; + const names = new Map(hosts.map((host) => [host.id, host.name] as const)); + hostNamesByHosts.set(hosts, names); + return names; +} + +/** + * Per-entry DTO memo. React Query structurally shares the sidebar payload, so + * an unchanged `ThreadListEntry` keeps its identity across refetches; mapping + * it again produced a fresh DTO per thread per sidebar update, which defeats + * `memo`/compiler bailouts in every plugin row. The DTO also depends on the + * host-name map, so a cached DTO is reused only for the same map instance. + */ +const pluginSidebarThreadByEntry = new WeakMap< + ThreadListEntry, + { hostNamesById: ReadonlyMap; thread: PluginSidebarThread } +>(); + +function toPluginSidebarThreadCached( + entry: ThreadListEntry, + hostNamesById: ReadonlyMap, +): PluginSidebarThread { + const cached = pluginSidebarThreadByEntry.get(entry); + if (cached !== undefined && cached.hostNamesById === hostNamesById) { + return cached.thread; + } + const thread = toPluginSidebarThread(entry, hostNamesById); + pluginSidebarThreadByEntry.set(entry, { hostNamesById, thread }); + return thread; +} /** * The sidebar's live thread view for plugin surfaces. @@ -49,10 +101,7 @@ export function useSidebarThreads(): PluginSidebarThreadsState { // The sidebar already subscribes to host updates; this reads the same // cached list so a row can print a machine name instead of a host id. const { data: hosts } = useHosts(); - const hostNamesById = useMemo( - () => new Map((hosts ?? []).map((host) => [host.id, host.name] as const)), - [hosts], - ); + const hostNamesById = hostNamesFor(hosts); return useMemo(() => { if (data === undefined) { @@ -69,7 +118,7 @@ export function useSidebarThreads(): PluginSidebarThreadsState { status: "ready", threads: allProjects.flatMap((project) => project.threads.map((thread) => - toPluginSidebarThread(thread, hostNamesById), + toPluginSidebarThreadCached(thread, hostNamesById), ), ), projects: allProjects.map((project) => ({ @@ -111,7 +160,7 @@ export function useSidebarThreadEntry( * dead threads. */ export function useSidebarThreadActions(): PluginSidebarThreadActions { - const navigate = useNavigate(); + const navigate = useRouteNavigate(); const store = useStore(); const isCompact = useIsCompactViewport(); const threadSplitsEnabled = useThreadSplitsEnabled(); diff --git a/apps/app/src/lib/plugin-slots.test.ts b/apps/app/src/lib/plugin-slots.test.ts index eb8c6c4594..a2a7c33fb9 100644 --- a/apps/app/src/lib/plugin-slots.test.ts +++ b/apps/app/src/lib/plugin-slots.test.ts @@ -5,6 +5,7 @@ import type { PluginNavPanelProps, } from "@get-bb/plugin-sdk"; import { + beginPluginSlotBatch, getPluginSlotSnapshot, removePluginSlotRegistrations, resetPluginSlotStoreForTest, @@ -242,3 +243,134 @@ describe("plugin slot store", () => { expect(snapshot.messageDirectives).toHaveLength(0); }); }); + +describe("plugin slot store structural sharing", () => { + it("keeps the messageActions array identity when a navPanels-only plugin registers", () => { + setPluginSlotRegistrations( + "actions", + registrationSet({ + messageActions: [{ id: "copy", title: "copy", run: () => {} }], + }), + ); + const before = getPluginSlotSnapshot(); + + setPluginSlotRegistrations( + "board", + registrationSet({ + navPanels: [ + { + id: "board", + title: "Board", + icon: "columns", + path: "board", + component: PanelComponent, + }, + ], + }), + ); + const after = getPluginSlotSnapshot(); + + expect(after).not.toBe(before); + expect(after.navPanels).toHaveLength(1); + // Kinds the new plugin did not touch keep their arrays, so consumers keyed + // on `messageActions`/`messageDirectives` (timeline static context, + // markdown directive registry) do not re-render or re-parse. + expect(after.messageActions).toBe(before.messageActions); + expect(after.messageDirectives).toBe(before.messageDirectives); + expect(after.composerCustomizations).toBe(before.composerCustomizations); + // Slot objects of untouched plugins keep identity too. + expect(after.messageActions[0]).toBe(before.messageActions[0]); + }); + + it("does not notify when a registration changes nothing visible", () => { + const listener = vi.fn(); + const unsubscribe = subscribePluginSlots(listener); + const before = getPluginSlotSnapshot(); + setPluginSlotRegistrations("empty", registrationSet()); + expect(getPluginSlotSnapshot()).toBe(before); + expect(listener).not.toHaveBeenCalled(); + unsubscribe(); + }); + + it("re-registering a plugin replaces only its own kinds' arrays", () => { + setPluginSlotRegistrations( + "a", + registrationSet({ + messageActions: [{ id: "a-copy", title: "a-copy", run: () => {} }], + }), + ); + setPluginSlotRegistrations( + "b", + registrationSet({ + messageDirectives: [{ id: "b-vis", component: DirectiveComponent }], + }), + ); + const before = getPluginSlotSnapshot(); + setPluginSlotRegistrations( + "b", + registrationSet({ + messageDirectives: [{ id: "b-chart", component: DirectiveComponent }], + }), + ); + const after = getPluginSlotSnapshot(); + expect(after.messageDirectives.map((d) => d.id)).toEqual(["b-chart"]); + expect(after.messageDirectives[0]?.generation).toBe(2); + expect(after.messageActions).toBe(before.messageActions); + }); +}); + +describe("plugin slot batches", () => { + it("holds notifications until the batch closes and then notifies once", () => { + const listener = vi.fn(); + const unsubscribe = subscribePluginSlots(listener); + const close = beginPluginSlotBatch({ maxHoldMs: 10_000 }); + setPluginSlotRegistrations( + "a", + registrationSet({ + messageActions: [{ id: "a", title: "a", run: () => {} }], + }), + ); + setPluginSlotRegistrations( + "b", + registrationSet({ + messageActions: [{ id: "b", title: "b", run: () => {} }], + }), + ); + expect(listener).not.toHaveBeenCalled(); + // Reads inside the batch see the current registrations. + expect(getPluginSlotSnapshot().messageActions.map((a) => a.id)).toEqual([ + "a", + "b", + ]); + close(); + expect(listener).toHaveBeenCalledTimes(1); + close(); + expect(listener).toHaveBeenCalledTimes(1); + unsubscribe(); + }); + + it("flushes on the hold timer so a slow plugin cannot starve the others", () => { + vi.useFakeTimers(); + try { + const listener = vi.fn(); + const unsubscribe = subscribePluginSlots(listener); + const close = beginPluginSlotBatch({ maxHoldMs: 100 }); + setPluginSlotRegistrations( + "fast", + registrationSet({ + messageActions: [{ id: "fast", title: "fast", run: () => {} }], + }), + ); + vi.advanceTimersByTime(99); + expect(listener).not.toHaveBeenCalled(); + vi.advanceTimersByTime(1); + expect(listener).toHaveBeenCalledTimes(1); + // Nothing new since the flush: closing does not notify again. + close(); + expect(listener).toHaveBeenCalledTimes(1); + unsubscribe(); + } finally { + vi.useRealTimers(); + } + }); +}); diff --git a/apps/app/src/lib/plugin-slots.ts b/apps/app/src/lib/plugin-slots.ts index 3cc062be24..897d11e76d 100644 --- a/apps/app/src/lib/plugin-slots.ts +++ b/apps/app/src/lib/plugin-slots.ts @@ -128,97 +128,105 @@ const generationByPluginId = new Map(); const listeners = new Set<() => void>(); let snapshot: PluginSlotSnapshot = EMPTY_PLUGIN_SLOT_SNAPSHOT; -function buildSnapshot(): PluginSlotSnapshot { - const pluginIds = [...registrationsByPluginId.keys()].sort(); - const next: { - homepageSections: PluginHomepageSectionSlot[]; - settingsSections: PluginSettingsSectionSlot[]; - navPanels: PluginNavPanelSlot[]; - threadPanelActions: PluginThreadPanelActionSlot[]; - newThreadPanelActions: PluginNewThreadPanelActionSlot[]; - composerCustomizations: PluginComposerCustomizationSlot[]; - pendingInteractions: PluginPendingInteractionSlot[]; - sidebarFooterActions: PluginSidebarFooterActionSlot[]; - threadLists: PluginThreadListSlot[]; - threadHeaderActions: PluginThreadHeaderActionSlot[]; - fileOpeners: PluginFileOpenerSlot[]; - messageDirectives: PluginMessageDirectiveSlot[]; - messageActions: PluginMessageActionSlot[]; - providerIcons: PluginProviderIconSlot[]; - } = { - homepageSections: [], - settingsSections: [], - navPanels: [], - threadPanelActions: [], - newThreadPanelActions: [], - composerCustomizations: [], - pendingInteractions: [], - sidebarFooterActions: [], - threadLists: [], - threadHeaderActions: [], - fileOpeners: [], - messageDirectives: [], - messageActions: [], - providerIcons: [], +type SlotKind = keyof PluginSlotSnapshot; + +const SLOT_KINDS: readonly SlotKind[] = [ + "homepageSections", + "settingsSections", + "navPanels", + "threadPanelActions", + "newThreadPanelActions", + "composerCustomizations", + "pendingInteractions", + "sidebarFooterActions", + "threadLists", + "threadHeaderActions", + "fileOpeners", + "messageDirectives", + "messageActions", + "providerIcons", +]; + +/** + * One plugin's registrations flattened into slot objects (`pluginId` + + * `generation` baked in). Built once per `setPluginSlotRegistrations` call, so + * slot objects keep their identity across later snapshot rebuilds. That is + * what lets {@link buildSnapshot} hand back the previous per-kind array when + * a different plugin's registrations change: consumers keyed on one kind + * (`messageDirectives` -> markdown directive registry, `messageActions` -> + * timeline static context) only re-render when their own kind changed. + */ +type FlattenedPluginSlots = { + readonly [K in SlotKind]: PluginSlotSnapshot[K]; +}; + +const flattenedByPluginId = new Map(); + +function flattenRegistrations( + pluginId: string, + generation: number, + set: PluginRegistrationSet, +): FlattenedPluginSlots { + const stamp = ( + registrations: readonly T[] | undefined, + ): readonly (T & PluginSlotBase)[] => + (registrations ?? []).map((registration) => ({ + ...registration, + pluginId, + generation, + })); + return { + homepageSections: stamp(set.homepageSections), + settingsSections: stamp(set.settingsSections), + navPanels: stamp(set.navPanels), + threadPanelActions: stamp(set.threadPanelActions), + newThreadPanelActions: stamp(set.newThreadPanelActions), + composerCustomizations: stamp(set.composerCustomizations), + pendingInteractions: stamp(set.pendingInteractions), + sidebarFooterActions: stamp(set.sidebarFooterActions), + threadLists: stamp(set.threadLists), + threadHeaderActions: stamp(set.threadHeaderActions), + fileOpeners: stamp(set.fileOpeners), + messageDirectives: stamp(set.messageDirectives), + messageActions: stamp(set.messageActions), + providerIcons: stamp(set.providerIcons), }; +} + +function sameSlotSequence( + previous: readonly unknown[], + next: readonly unknown[], +): boolean { + if (previous.length !== next.length) return false; + for (let index = 0; index < previous.length; index += 1) { + if (previous[index] !== next[index]) return false; + } + return true; +} + +function collectKind( + kind: K, + pluginIds: readonly string[], +): PluginSlotSnapshot[K][number][] { + const collected: PluginSlotSnapshot[K][number][] = []; for (const pluginId of pluginIds) { - const set = registrationsByPluginId.get(pluginId); - if (set === undefined) continue; - const generation = generationByPluginId.get(pluginId) ?? 0; - for (const registration of set.homepageSections) { - next.homepageSections.push({ ...registration, pluginId, generation }); - } - for (const registration of set.settingsSections) { - next.settingsSections.push({ ...registration, pluginId, generation }); - } - for (const registration of set.navPanels) { - next.navPanels.push({ ...registration, pluginId, generation }); - } - for (const registration of set.threadPanelActions) { - next.threadPanelActions.push({ ...registration, pluginId, generation }); - } - for (const registration of set.newThreadPanelActions ?? []) { - next.newThreadPanelActions.push({ - ...registration, - pluginId, - generation, - }); - } - for (const registration of set.composerCustomizations ?? []) { - next.composerCustomizations.push({ - ...registration, - pluginId, - generation, - }); - } - for (const registration of set.pendingInteractions ?? []) { - next.pendingInteractions.push({ ...registration, pluginId, generation }); - } - for (const registration of set.sidebarFooterActions) { - next.sidebarFooterActions.push({ - ...registration, - pluginId, - generation, - }); - } - for (const registration of set.threadLists ?? []) { - next.threadLists.push({ ...registration, pluginId, generation }); - } - for (const registration of set.threadHeaderActions ?? []) { - next.threadHeaderActions.push({ ...registration, pluginId, generation }); - } - for (const registration of set.fileOpeners) { - next.fileOpeners.push({ ...registration, pluginId, generation }); - } - for (const registration of set.messageDirectives) { - next.messageDirectives.push({ ...registration, pluginId, generation }); - } - for (const registration of set.messageActions ?? []) { - next.messageActions.push({ ...registration, pluginId, generation }); - } - for (const registration of set.providerIcons ?? []) { - const claimed = next.providerIcons.find( - (slot) => slot.providerId === registration.providerId, + const flattened = flattenedByPluginId.get(pluginId); + if (flattened === undefined) continue; + for (const slot of flattened[kind]) collected.push(slot); + } + return collected; +} + +function collectProviderIcons( + pluginIds: readonly string[], +): PluginProviderIconSlot[] { + const collected: PluginProviderIconSlot[] = []; + for (const pluginId of pluginIds) { + const flattened = flattenedByPluginId.get(pluginId); + if (flattened === undefined) continue; + for (const slot of flattened.providerIcons) { + const claimed = collected.find( + (existing) => existing.providerId === slot.providerId, ); if (claimed !== undefined) { // Provider ids are a shared namespace: nothing stops a second plugin @@ -226,30 +234,125 @@ function buildSnapshot(): PluginSlotSnapshot { // sorted order, so keeping the first claim makes the winner stable // across reloads instead of depending on load timing. console.warn( - `plugin ${pluginId}: provider icon for "${registration.providerId}" ignored — already registered by plugin ${claimed.pluginId}`, + `plugin ${pluginId}: provider icon for "${slot.providerId}" ignored — already registered by plugin ${claimed.pluginId}`, ); continue; } - next.providerIcons.push({ ...registration, pluginId, generation }); + collected.push(slot); } } - return next; + return collected; } -function emitChange(): void { - snapshot = buildSnapshot(); +/** + * Rebuild the flattened snapshot with per-kind structural sharing: a kind + * whose slot sequence equals the previous snapshot's keeps the previous + * array, and a rebuild that changes no kind returns the previous snapshot + * object so `useSyncExternalStore` readers bail out entirely. + */ +function buildSnapshot(previous: PluginSlotSnapshot): PluginSlotSnapshot { + const pluginIds = [...registrationsByPluginId.keys()].sort(); + const next: { -readonly [K in SlotKind]: PluginSlotSnapshot[K] } = { + ...previous, + }; + let changed = false; + for (const kind of SLOT_KINDS) { + const collected = + kind === "providerIcons" + ? collectProviderIcons(pluginIds) + : collectKind(kind, pluginIds); + if (sameSlotSequence(previous[kind], collected)) continue; + changed = true; + // `collected` came from `collectKind(kind)`, so it has the element type + // of `next[kind]`; the loop variable erases that correlation for TS. + Object.assign(next, { [kind]: collected }); + } + return changed ? next : previous; +} + +/** + * Open batches hold listener notifications so a burst of registrations (every + * plugin bundle resolving during boot, a multi-plugin reload) turns into a + * few flushes instead of one app-wide re-render per plugin. Reads stay + * consistent while a batch is open: the snapshot is rebuilt lazily on the + * next `getPluginSlotSnapshot`. Batches nest (depth count). + */ +let openBatchDepth = 0; +let batchMaxHoldMs = 0; +/** Registrations changed since `snapshot` was last built. */ +let snapshotStale = false; +/** `snapshot` changed since listeners were last notified. */ +let notifyPending = false; +let batchFlushTimer: ReturnType | null = null; + +function rebuildIfStale(): void { + if (!snapshotStale) return; + snapshotStale = false; + const previous = snapshot; + snapshot = buildSnapshot(previous); + if (snapshot !== previous) notifyPending = true; +} + +function flushChange(): void { + if (batchFlushTimer !== null) { + clearTimeout(batchFlushTimer); + batchFlushTimer = null; + } + rebuildIfStale(); + if (!notifyPending) return; + notifyPending = false; for (const listener of listeners) listener(); } +function emitChange(): void { + snapshotStale = true; + if (openBatchDepth === 0) { + flushChange(); + return; + } + if (batchFlushTimer !== null) return; + // Bound the hold: a slow plugin bundle must not keep every other plugin's + // UI off screen for the whole batch. + batchFlushTimer = setTimeout(() => { + batchFlushTimer = null; + flushChange(); + }, batchMaxHoldMs); +} + +/** + * Hold notifications until the returned closer runs, or until `maxHoldMs` + * passes since the first held change (whichever comes first, repeatedly). + * The closer is idempotent. + */ +export function beginPluginSlotBatch(options: { + maxHoldMs: number; +}): () => void { + openBatchDepth += 1; + batchMaxHoldMs = + openBatchDepth === 1 + ? options.maxHoldMs + : Math.min(batchMaxHoldMs, options.maxHoldMs); + let closed = false; + return () => { + if (closed) return; + closed = true; + // Never below zero: a test reset can zero the depth under an open batch. + openBatchDepth = Math.max(0, openBatchDepth - 1); + if (openBatchDepth === 0) flushChange(); + }; +} + /** Replace one plugin's registrations wholesale (P3.4 reload reuses this). */ export function setPluginSlotRegistrations( pluginId: string, registrations: PluginRegistrationSet, ): void { registrationsByPluginId.set(pluginId, registrations); - generationByPluginId.set( + const generation = (generationByPluginId.get(pluginId) ?? 0) + 1; + generationByPluginId.set(pluginId, generation); + flattenedByPluginId.set( pluginId, - (generationByPluginId.get(pluginId) ?? 0) + 1, + flattenRegistrations(pluginId, generation, registrations), ); emitChange(); } @@ -257,6 +360,7 @@ export function setPluginSlotRegistrations( /** Drop one plugin's registrations (uninstall/disable/failed re-interpret). */ export function removePluginSlotRegistrations(pluginId: string): void { if (!registrationsByPluginId.delete(pluginId)) return; + flattenedByPluginId.delete(pluginId); emitChange(); } @@ -268,6 +372,9 @@ export function subscribePluginSlots(listener: () => void): () => void { } export function getPluginSlotSnapshot(): PluginSlotSnapshot { + // A read inside an open batch must not observe stale registrations: the + // batch defers the notification, not the data. + rebuildIfStale(); return snapshot; } @@ -280,5 +387,7 @@ export function usePluginSlots(): PluginSlotSnapshot { export function resetPluginSlotStoreForTest(): void { registrationsByPluginId.clear(); generationByPluginId.clear(); + flattenedByPluginId.clear(); + openBatchDepth = 0; emitChange(); } diff --git a/apps/app/src/lib/split-layout/openThreadInSplit.ts b/apps/app/src/lib/split-layout/openThreadInSplit.ts index 01ff2cfa4d..d2d894e0f6 100644 --- a/apps/app/src/lib/split-layout/openThreadInSplit.ts +++ b/apps/app/src/lib/split-layout/openThreadInSplit.ts @@ -1,4 +1,3 @@ -import type { useNavigate } from "react-router-dom"; import { getThreadRoutePath } from "@/lib/route-paths"; import { decideThreadDrop } from "@/lib/split-drag"; import { splitLayoutAtom } from "./atoms"; @@ -20,7 +19,7 @@ interface SplitLayoutStore { export interface OpenThreadInSplitArgs { store: SplitLayoutStore; - navigate: ReturnType; + navigate: (route: string, options?: { replace?: boolean }) => void; projectId: string; threadId: string; /** Splits are off on compact viewports. */ diff --git a/apps/app/src/views/thread-detail/ThreadDetailPromptArea.tsx b/apps/app/src/views/thread-detail/ThreadDetailPromptArea.tsx index f2a9d82d15..df67f90eeb 100644 --- a/apps/app/src/views/thread-detail/ThreadDetailPromptArea.tsx +++ b/apps/app/src/views/thread-detail/ThreadDetailPromptArea.tsx @@ -1,4 +1,11 @@ -import { useCallback, useMemo, useRef, useState } from "react"; +import { + useCallback, + useLayoutEffect, + useMemo, + useRef, + useState, + type RefObject, +} from "react"; import { createPortal } from "react-dom"; import { NavLink, useNavigate } from "react-router-dom"; import type { IconName } from "@bb/shared-ui/icon"; @@ -60,6 +67,7 @@ import { import { ThreadEnvironmentSummary } from "@/components/promptbox/ThreadEnvironmentSummary"; import type { WorkspaceCheckoutDisplay } from "@/lib/workspace-checkout-display"; import { useComposerTextEffects } from "@/lib/composer-text-effects"; +import { useLatestRef } from "@/hooks/useLatestRef"; import { useEscapeToHide } from "@/hooks/useEscapeToHide"; import { useThreadCreationOptions } from "@/hooks/useThreadCreationOptions"; import { useProjectDisplayName } from "@/hooks/queries/sidebar-navigation-query"; @@ -308,6 +316,89 @@ function buildInlineDraftComposer(options: InlineDraftComposerOptions) { ); } +type InlineQueuedMessageEditSession = Pick< + InlineQueuedMessageEditState, + "editSessionId" | "queuedMessageId" +>; + +function isInlineQueuedMessageEditSession( + current: InlineQueuedMessageEditState | null, + session: InlineQueuedMessageEditSession, +): current is InlineQueuedMessageEditState { + return ( + current?.editSessionId === session.editSessionId && + current.queuedMessageId === session.queuedMessageId + ); +} + +/** Plugin composer-host accessors for the queued-message inline editor (see below). */ +function readInlineQueuedMessageDraft( + editStateRef: RefObject, + session: InlineQueuedMessageEditSession, + fallback: PromptDraftState, +): PromptDraftState { + const current = editStateRef.current; + return isInlineQueuedMessageEditSession(current, session) + ? current.draft + : fallback; +} + +function writeInlineQueuedMessageDraft( + editStateRef: RefObject, + session: InlineQueuedMessageEditSession, + draft: PromptDraftState, + commit: (next: InlineQueuedMessageEditState) => void, +): void { + const current = editStateRef.current; + if (isInlineQueuedMessageEditSession(current, session)) { + commit({ ...current, draft }); + } +} + +/** + * Plugin composer-host accessors for the sent-message inline editor. Module + * level on purpose: inlined closures that return `ref.current.draft` in one + * branch and the render-time `draft` in another make React Compiler type the + * whole edit object as a ref value and bail out of the component. + */ +function readSentMessageEditDraft( + sentMessageEditRef: RefObject, + operationId: string, + fallback: PromptDraftState, +): PromptDraftState { + const current = sentMessageEditRef.current; + return current?.operationId === operationId ? current.draft : fallback; +} + +function writeSentMessageEditDraft( + sentMessageEditRef: RefObject, + operationId: string, + nextDraft: PromptDraftState, +): void { + const current = sentMessageEditRef.current; + if (current?.operationId === operationId) { + current.updateDraft(() => nextDraft); + } +} + +/** + * Flip the "sending" flag around a task. Kept outside the component: React + * Compiler bails out of any function containing `try`/`finally`, and one such + * block inside `ThreadDetailPromptArea` left the whole ~1600-line body + * unmemoized. + */ +async function runWhileFollowUpShortcutSending( + setSending: (sending: boolean) => void, + task: () => Promise, +): Promise { + setSending(true); + try { + await task(); + } finally { + setSending(false); + } +} + export function ThreadDetailPromptArea({ activeBackgroundAgentCount, canUseGitUi, @@ -372,8 +463,8 @@ export function ThreadDetailPromptArea({ const { data: queuedMessages = [] } = useThreadQueuedMessages(thread.id, { enabled: true, }); - const queuedMessagesRef = useRef([]); - queuedMessagesRef.current = queuedMessages; + const queuedMessagesRef = + useLatestRef(queuedMessages); const [bottomPluginFocusNonce, setBottomPluginFocusNonce] = useState(0); const [editFocusNonce, setEditFocusNonce] = useState(0); const focusBottomPluginComposer = useCallback(() => { @@ -382,8 +473,7 @@ export function ThreadDetailPromptArea({ const focusInlinePluginComposer = useCallback(() => { setEditFocusNonce((nonce) => nonce + 1); }, []); - const sentMessageEditRef = useRef(sentMessageEdit); - sentMessageEditRef.current = sentMessageEdit; + const sentMessageEditRef = useLatestRef(sentMessageEdit); const clearInlineAttachmentErrorRef = useRef<() => void>(() => {}); const { inlineEditingQueuedMessage, @@ -481,7 +571,12 @@ export function ThreadDetailPromptArea({ } : null, }); - clearInlineAttachmentErrorRef.current = () => setInlineAttachmentError(null); + // Read only from the queued-message edit handler (never during render), so + // a layout-effect write is current by the time it can run. + useLayoutEffect(() => { + clearInlineAttachmentErrorRef.current = () => + setInlineAttachmentError(null); + }, [setInlineAttachmentError]); const promptTextEffects = useComposerTextEffects(promptDraft.storageKey); const queuedComposerTextEffects = useComposerTextEffects( inlineEditingQueuedMessage @@ -840,24 +935,25 @@ export function ThreadDetailPromptArea({ } if (shortcutRequest.kind === "draft") { - setIsFollowUpShortcutSending(true); promptDraft.clearIfCurrentMatches(submittedDraft); setBottomAttachmentError(null); - - try { - await sendMessage.mutateAsync(shortcutRequest.request); - } catch (nextError) { - promptDraft.restoreIfEmpty(submittedDraft); - appToast.error( - getMutationErrorMessage({ - error: nextError, - fallbackMessage: "Failed to send message", - lifecycleOperation: "send_message", - }), - ); - } finally { - setIsFollowUpShortcutSending(false); - } + await runWhileFollowUpShortcutSending( + setIsFollowUpShortcutSending, + async () => { + try { + await sendMessage.mutateAsync(shortcutRequest.request); + } catch (nextError) { + promptDraft.restoreIfEmpty(submittedDraft); + appToast.error( + getMutationErrorMessage({ + error: nextError, + fallbackMessage: "Failed to send message", + lifecycleOperation: "send_message", + }), + ); + } + }, + ); return; } @@ -866,20 +962,21 @@ export function ThreadDetailPromptArea({ return; } - setIsFollowUpShortcutSending(true); - try { - await sendQueuedMessageById({ - guard: "current-head", - messageId: queuedMessageId, - }); - } finally { - setIsFollowUpShortcutSending(false); - } + await runWhileFollowUpShortcutSending( + setIsFollowUpShortcutSending, + async () => { + await sendQueuedMessageById({ + guard: "current-head", + messageId: queuedMessageId, + }); + }, + ); }, [ canSubmitModifierShortcut, currentPromptDraft, currentPromptDraftInput, promptDraft, + queuedMessagesRef, sendMessage, sendQueuedMessageById, setBottomAttachmentError, @@ -1225,11 +1322,7 @@ export function ThreadDetailPromptArea({ editSessionId, queuedMessageId, } = inlineEditingQueuedMessage; - const isCurrentSession = ( - current: InlineQueuedMessageEditState | null, - ): current is InlineQueuedMessageEditState => - current?.editSessionId === editSessionId && - current.queuedMessageId === queuedMessageId; + const session = { editSessionId, queuedMessageId }; const pluginComposerHost: PluginComposerHost = { scope: { kind: "queued-message", @@ -1238,16 +1331,19 @@ export function ThreadDetailPromptArea({ }, textEffectKey: `queued-message:${thread.id}:${queuedMessageId}:${editSessionId}`, draft: activeComposerDraft, - getCurrent: () => { - const current = inlineEditingQueuedMessageRef.current; - return isCurrentSession(current) ? current.draft : initialDraft; - }, - setDraft: (draft) => { - const current = inlineEditingQueuedMessageRef.current; - if (isCurrentSession(current)) { - commitInlineQueuedMessage({ ...current, draft }); - } - }, + getCurrent: () => + readInlineQueuedMessageDraft( + inlineEditingQueuedMessageRef, + session, + initialDraft, + ), + setDraft: (draft) => + writeInlineQueuedMessageDraft( + inlineEditingQueuedMessageRef, + session, + draft, + commitInlineQueuedMessage, + ), focus: focusInlinePluginComposer, }; const inlineEditor: QueuedMessageInlineEditor = { @@ -1369,18 +1465,14 @@ export function ThreadDetailPromptArea({ scope: { kind: "thread", threadId: thread.id }, textEffectKey: `sent-message:${thread.id}:${operationId}`, draft, - getCurrent: () => { - const current = sentMessageEditRef.current; - return current?.operationId === operationId - ? current.draft - : draft; - }, - setDraft: (nextDraft) => { - const current = sentMessageEditRef.current; - if (current?.operationId === operationId) { - current.updateDraft(() => nextDraft); - } - }, + getCurrent: () => + readSentMessageEditDraft(sentMessageEditRef, operationId, draft), + setDraft: (nextDraft) => + writeSentMessageEditDraft( + sentMessageEditRef, + operationId, + nextDraft, + ), focus: focusInlinePluginComposer, }, promptActions, @@ -1412,6 +1504,7 @@ export function ThreadDetailPromptArea({ sentMessageAttachmentError, sentMessageComposerTextEffects, sentMessageEdit, + sentMessageEditRef, sentMessageEditSubmitMode, thread.id, typeaheadConfig, diff --git a/docs/api_to_audit.md b/docs/api_to_audit.md index 7f66a36f65..694fc734aa 100644 --- a/docs/api_to_audit.md +++ b/docs/api_to_audit.md @@ -578,7 +578,15 @@ reimplementing it, and `indicatorLabel` carries the matching accessible string. child threads and running threads that `isUnreadDoneThread` excludes by design. Confirm that is the more useful primitive for a replaced list. 4. **Scale.** Confirm one array of every thread is right at ten thousand - threads, versus a paged or windowed read. + threads, versus a paged or windowed read. Today the host memoizes each + thread DTO per unchanged `ThreadListEntry` (React Query structurally shares + the payload), so a refetch that changes one thread hands plugins the same + objects for every other thread and a `memo`/compiler-memoized row bails + out; the array itself is new whenever the payload changes. Plugin lists + are still expected to window their rows (the built-in sidebar does): the + host does not cap the array, and mounting one row per thread on a phone is + the plugin's cost. Decide whether that expectation should be enforced by + the contract (paged/windowed read) before stabilizing. 5. **Draft indicators.** `indicator` never reports "draft" or "working-draft", because an unsubmitted draft is per-composer client state the host reads per row. An idle unread thread holding a draft therefore reads as diff --git a/packages/plugin-sdk/bundled-types/bb-plugin-sdk-app.d.ts b/packages/plugin-sdk/bundled-types/bb-plugin-sdk-app.d.ts index 3e95d3078e..c15e87483f 100644 --- a/packages/plugin-sdk/bundled-types/bb-plugin-sdk-app.d.ts +++ b/packages/plugin-sdk/bundled-types/bb-plugin-sdk-app.d.ts @@ -1553,6 +1553,13 @@ interface PluginSdkApp { * The sidebar's live thread view (see {@link PluginSidebarThreadsState}). * Reads the host's own cache and realtime subscriptions, so it costs no * extra request and updates exactly when the built-in sidebar does. + * + * `threads` is one array of every visible thread and is not capped. Thread + * objects keep their identity across updates while the underlying entry is + * unchanged, so a memoized row re-renders only when its own thread changed; + * the array itself is new on every update. Window your rows (render only + * what is on screen) as the built-in sidebar does — a list that mounts one + * row per thread is slow on phones with many threads. * Experimental: see docs/api_to_audit.md. */ experimental_useSidebarThreads(): PluginSidebarThreadsState; diff --git a/packages/plugin-sdk/bundled-types/bb-plugin-sdk.d.ts b/packages/plugin-sdk/bundled-types/bb-plugin-sdk.d.ts index 6560a28b03..e9ad727718 100644 --- a/packages/plugin-sdk/bundled-types/bb-plugin-sdk.d.ts +++ b/packages/plugin-sdk/bundled-types/bb-plugin-sdk.d.ts @@ -12272,6 +12272,13 @@ interface PluginSdkApp { * The sidebar's live thread view (see {@link PluginSidebarThreadsState}). * Reads the host's own cache and realtime subscriptions, so it costs no * extra request and updates exactly when the built-in sidebar does. + * + * `threads` is one array of every visible thread and is not capped. Thread + * objects keep their identity across updates while the underlying entry is + * unchanged, so a memoized row re-renders only when its own thread changed; + * the array itself is new on every update. Window your rows (render only + * what is on screen) as the built-in sidebar does — a list that mounts one + * row per thread is slow on phones with many threads. * Experimental: see docs/api_to_audit.md. */ experimental_useSidebarThreads(): PluginSidebarThreadsState; diff --git a/packages/plugin-sdk/src/app-contract.ts b/packages/plugin-sdk/src/app-contract.ts index fa7c9e6a92..9b82efe875 100644 --- a/packages/plugin-sdk/src/app-contract.ts +++ b/packages/plugin-sdk/src/app-contract.ts @@ -763,8 +763,7 @@ export interface ThreadChatMessageReference { * action opening its own tab is already the target, so it passes the bare * {@link PluginPanelActionOpenOptions} instead. */ -export interface PluginTargetedPanelActionOpenOptions - extends PluginPanelActionOpenOptions { +export interface PluginTargetedPanelActionOpenOptions extends PluginPanelActionOpenOptions { /** A `threadPanelAction` id registered by this same plugin. */ actionId: string; } @@ -1472,6 +1471,13 @@ export interface PluginSdkApp { * The sidebar's live thread view (see {@link PluginSidebarThreadsState}). * Reads the host's own cache and realtime subscriptions, so it costs no * extra request and updates exactly when the built-in sidebar does. + * + * `threads` is one array of every visible thread and is not capped. Thread + * objects keep their identity across updates while the underlying entry is + * unchanged, so a memoized row re-renders only when its own thread changed; + * the array itself is new on every update. Window your rows (render only + * what is on screen) as the built-in sidebar does — a list that mounts one + * row per thread is slow on phones with many threads. * Experimental: see docs/api_to_audit.md. */ experimental_useSidebarThreads(): PluginSidebarThreadsState; diff --git a/packages/templates/src/generated/plugin-sdk-dts.generated.ts b/packages/templates/src/generated/plugin-sdk-dts.generated.ts index 3d85774139..3bf6c203f4 100644 --- a/packages/templates/src/generated/plugin-sdk-dts.generated.ts +++ b/packages/templates/src/generated/plugin-sdk-dts.generated.ts @@ -2,6 +2,6 @@ // Generated by packages/templates/scripts/generate-templates.mjs from // @get-bb/plugin-sdk/bundled-types. Do not edit directly. -export const PLUGIN_SDK_DTS = "// Portable type declarations for `@get-bb/plugin-sdk`. Unpublished BB\n// workspace contracts are flattened; public subpaths may reuse the\n// package root without requiring any other @bb/* package.\n//\n// Confused by the API, or need a symbol that isn't here? Clone the BB repo\n// and read the real source: https://github.com/get-bb/bb\n\nimport * as react from 'react';\nimport { ComponentType, ReactNode } from 'react';\nimport * as z from 'zod';\nimport { z as z$1 } from 'zod';\nimport Database from 'better-sqlite3';\nimport { Context } from 'hono';\n\n/**\n * App-wide server-backed preferences.\n * Client-local settings stay in the frontend localStorage helpers instead.\n */\ndeclare const appSettingsSchema: z$1.ZodObject<{\n claudeCodeMemoryEnabled: z$1.ZodBoolean;\n claudeCodeSubagentsDisabled: z$1.ZodBoolean;\n claudeCodeWorkflowsDisabled: z$1.ZodBoolean;\n codexMemoryEnabled: z$1.ZodBoolean;\n codexSubagentsDisabled: z$1.ZodBoolean;\n onboardingCompletedAt: z$1.ZodNullable;\n showKeyboardHints: z$1.ZodBoolean;\n showUnhandledProviderEvents: z$1.ZodBoolean;\n steerActiveThreadOnEnter: z$1.ZodBoolean;\n}, z$1.core.$strict>;\ntype AppSettings = z$1.infer;\n\ndeclare const appKeybindingOverridesSchema: z$1.ZodArray;\n shortcut: z$1.ZodNullable>;\n}, z$1.core.$strict>>;\ntype AppKeybindingOverrides = z$1.infer;\n\ninterface JsonObject {\n [key: string]: JsonValue$1;\n}\ntype JsonValue$1 = string | number | boolean | null | JsonValue$1[] | JsonObject;\n\ndeclare const appThemeSchema: z$1.ZodObject<{\n customCss: z$1.ZodNullable;\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n resolvedCodeTheme: z$1.ZodDefault>>;\n light: z$1.ZodString;\n }, z$1.core.$strict>>;\n themeId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype AppTheme = z$1.infer;\n/**\n * The complete appearance selection a client sends when changing the palette\n * and/or favicon tint. The server validates `themeId` (built-in id or an\n * existing custom theme) and resolves the CSS from disk for custom themes.\n * Callers changing only one facet must carry the other facet forward explicitly.\n */\ndeclare const appThemeSelectionSchema: z$1.ZodObject<{\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n themeId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype AppThemeSelection = z$1.infer;\n\ndeclare const changedMessageSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"thread\">;\n id: z$1.ZodOptional;\n metadata: z$1.ZodOptional;\n eventTypes: z$1.ZodOptional>>>>;\n hasPendingInteraction: z$1.ZodOptional;\n projectId: z$1.ZodOptional;\n }, z$1.core.$strict>>;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"project\">;\n id: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"environment\">;\n id: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"host\">;\n id: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"system\">;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>], \"entity\">;\ntype ChangedMessage = z$1.infer;\n\ndeclare const environmentSchema: z$1.ZodObject<{\n baseBranch: z$1.ZodNullable;\n branchName: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n defaultBranch: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n isGitRepo: z$1.ZodBoolean;\n isWorktree: z$1.ZodBoolean;\n managed: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodNullable;\n name: z$1.ZodNullable;\n path: z$1.ZodNullable;\n projectId: z$1.ZodString;\n status: z$1.ZodEnum<{\n destroyed: \"destroyed\";\n destroying: \"destroying\";\n error: \"error\";\n provisioning: \"provisioning\";\n ready: \"ready\";\n retiring: \"retiring\";\n }>;\n updatedAt: z$1.ZodNumber;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n}, z$1.core.$strip>;\ntype Environment = z$1.infer;\n\ndeclare const experimentsSchema: z$1.ZodRecord, z$1.ZodBoolean>;\ntype Experiments = z$1.infer;\n\ndeclare const hostSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n lastRejectedProtocolVersion: z$1.ZodNullable;\n lastSeenAt: z$1.ZodNullable;\n maxPermissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n name: z$1.ZodString;\n status: z$1.ZodEnum<{\n connected: \"connected\";\n disconnected: \"disconnected\";\n }>;\n type: z$1.ZodEnum<{\n persistent: \"persistent\";\n }>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype Host = z$1.infer;\n\ndeclare const pendingInteractionResolutionSchema: z$1.ZodUnion;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n}, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin_submitted\">;\n}, z$1.core.$strip>]>;\ntype PendingInteractionResolution = z$1.infer;\ndeclare const providerPendingInteractionSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n expiresAt: z$1.ZodOptional>;\n id: z$1.ZodString;\n origin: z$1.ZodOptional;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>>;\n payload: z$1.ZodUnion>;\n kind: z$1.ZodLiteral<\"approval\">;\n reason: z$1.ZodNullable;\n subject: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n actions: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"listFiles\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n command: z$1.ZodString;\n cwd: z$1.ZodNullable;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"command\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"file_change\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n writeScope: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"permission_grant\">;\n permissions: z$1.ZodObject<{\n fileSystem: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plan\">;\n plan: z$1.ZodString;\n planFilePath: z$1.ZodNullable;\n }, z$1.core.$strip>], \"kind\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"user_question\">;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>]>;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n resolution: z$1.ZodNullable;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>]>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype ProviderPendingInteraction = z$1.infer;\ndeclare const pluginPendingInteractionSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n expiresAt: z$1.ZodOptional>;\n id: z$1.ZodString;\n origin: z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin\">;\n pluginId: z$1.ZodString;\n rendererId: z$1.ZodString;\n }, z$1.core.$strip>;\n payload: z$1.ZodObject<{\n data: z$1.ZodType>;\n kind: z$1.ZodLiteral<\"plugin\">;\n title: z$1.ZodString;\n }, z$1.core.$strip>;\n resolution: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype PluginPendingInteraction = z$1.infer;\ntype PendingInteraction = ProviderPendingInteraction | PluginPendingInteraction;\n\ndeclare const projectSourceSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n path: z$1.ZodString;\n projectId: z$1.ZodString;\n type: z$1.ZodLiteral<\"local_path\">;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ProjectSource = z$1.infer;\n\ndeclare const reasoningLevelSchema: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n}>;\ntype ReasoningLevel = z$1.infer;\ndeclare const serviceTierSchema: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n}>;\ntype ServiceTier = z$1.infer;\ndeclare const permissionModeSchema: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n}>;\ntype PermissionMode = z$1.infer;\ndeclare const promptInputSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>], \"type\">;\ntype PromptInput = z$1.infer;\ndeclare const resolvedThreadExecutionOptionsSchema: z$1.ZodObject<{\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n seq: z$1.ZodOptional;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n source: z$1.ZodEnum<{\n \"client/thread/start\": \"client/thread/start\";\n \"client/turn/requested\": \"client/turn/requested\";\n \"client/turn/start\": \"client/turn/start\";\n }>;\n}, z$1.core.$strip>;\ntype ResolvedThreadExecutionOptions = z$1.infer;\ndeclare const projectExecutionDefaultsSchema: z$1.ZodObject<{\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n providerId: z$1.ZodString;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n}, z$1.core.$strip>;\ntype ProjectExecutionDefaults = z$1.infer;\n\n/** All thread events — provider-originated or system-originated. */\ndeclare const threadEventSchema: z$1.ZodPipe;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/identity\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n error: z$1.ZodOptional>;\n providerCheckpointId: z$1.ZodOptional;\n providerThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n clientRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/input/accepted\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n threadName: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/name/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/compacted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/context/cleared\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n objective: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n status: z$1.ZodEnum<{\n active: \"active\";\n budgetLimited: \"budgetLimited\";\n complete: \"complete\";\n paused: \"paused\";\n }>;\n threadId: z$1.ZodString;\n timeUsedSeconds: z$1.ZodNumber;\n tokenBudget: z$1.ZodNullable;\n tokensUsed: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"thread/goal/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/goal/cleared\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n clientRequestId: z$1.ZodOptional;\n content: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localFile\">;\n }, z$1.core.$strip>], \"type\">>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"userMessage\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"agentMessage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n aggregatedOutput: z$1.ZodOptional;\n approvalStatus: z$1.ZodNullable>;\n command: z$1.ZodString;\n cwd: z$1.ZodString;\n durationMs: z$1.ZodOptional;\n exitCode: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"commandExecution\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalStatus: z$1.ZodNullable>;\n changes: z$1.ZodArray;\n kind: z$1.ZodEnum<{\n add: \"add\";\n delete: \"delete\";\n update: \"update\";\n }>;\n movePath: z$1.ZodOptional;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n type: z$1.ZodLiteral<\"fileChange\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n queries: z$1.ZodArray;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webSearch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n pattern: z$1.ZodNullable;\n prompt: z$1.ZodNullable;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webFetch\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"imageView\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n arguments: z$1.ZodOptional>;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n result: z$1.ZodOptional;\n server: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusLabels: z$1.ZodOptional>;\n tool: z$1.ZodString;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"toolCall\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n content: z$1.ZodArray;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n summary: z$1.ZodArray;\n type: z$1.ZodLiteral<\"reasoning\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"contextCompaction\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>], \"type\">;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n clientRequestId: z$1.ZodOptional;\n content: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localFile\">;\n }, z$1.core.$strip>], \"type\">>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"userMessage\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"agentMessage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n aggregatedOutput: z$1.ZodOptional;\n approvalStatus: z$1.ZodNullable>;\n command: z$1.ZodString;\n cwd: z$1.ZodString;\n durationMs: z$1.ZodOptional;\n exitCode: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"commandExecution\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalStatus: z$1.ZodNullable>;\n changes: z$1.ZodArray;\n kind: z$1.ZodEnum<{\n add: \"add\";\n delete: \"delete\";\n update: \"update\";\n }>;\n movePath: z$1.ZodOptional;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n type: z$1.ZodLiteral<\"fileChange\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n queries: z$1.ZodArray;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webSearch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n pattern: z$1.ZodNullable;\n prompt: z$1.ZodNullable;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webFetch\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"imageView\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n arguments: z$1.ZodOptional>;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n result: z$1.ZodOptional;\n server: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusLabels: z$1.ZodOptional>;\n tool: z$1.ZodString;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"toolCall\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n content: z$1.ZodArray;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n summary: z$1.ZodArray;\n type: z$1.ZodLiteral<\"reasoning\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"contextCompaction\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>], \"type\">;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/agentMessage/delta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n reset: z$1.ZodOptional;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/commandExecution/outputDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/fileChange/outputDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/reasoning/summaryTextDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/reasoning/textDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/plan/delta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n message: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/mcpToolCall/progress\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n message: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/toolCall/progress\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/backgroundTask/progress\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/backgroundTask/completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n tokenUsage: z$1.ZodObject<{\n last: z$1.ZodObject<{\n cachedInputTokens: z$1.ZodNumber;\n inputTokens: z$1.ZodNumber;\n outputTokens: z$1.ZodNumber;\n reasoningOutputTokens: z$1.ZodNumber;\n totalTokens: z$1.ZodNumber;\n }, z$1.core.$strip>;\n modelContextWindow: z$1.ZodNullable;\n total: z$1.ZodObject<{\n cachedInputTokens: z$1.ZodNumber;\n inputTokens: z$1.ZodNumber;\n outputTokens: z$1.ZodNumber;\n reasoningOutputTokens: z$1.ZodNumber;\n totalTokens: z$1.ZodNumber;\n }, z$1.core.$strip>;\n }, z$1.core.$strip>;\n type: z$1.ZodLiteral<\"thread/tokenUsage/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n contextWindowUsage: z$1.ZodObject<{\n estimated: z$1.ZodBoolean;\n modelContextWindow: z$1.ZodNullable;\n usedTokens: z$1.ZodNullable;\n }, z$1.core.$strip>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/contextWindowUsage/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n explanation: z$1.ZodOptional;\n plan: z$1.ZodArray>;\n step: z$1.ZodString;\n }, z$1.core.$strip>>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/plan/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n diff: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/diff/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n detail: z$1.ZodOptional;\n errorInfo: z$1.ZodOptional;\n httpStatusCode: z$1.ZodNullable;\n providerCode: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n message: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/error\">;\n willRetry: z$1.ZodOptional;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n rateLimits: z$1.ZodObject<{\n kind: z$1.ZodEnum<{\n \"spend-control\": \"spend-control\";\n \"subscription-window\": \"subscription-window\";\n credits: \"credits\";\n unknown: \"unknown\";\n }>;\n overageReason: z$1.ZodNullable;\n overageStatus: z$1.ZodNullable>;\n providerId: z$1.ZodString;\n reachedReason: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n allowed: \"allowed\";\n blocked: \"blocked\";\n unknown: \"unknown\";\n warning: \"warning\";\n }>;\n windows: z$1.ZodArray;\n providerKey: z$1.ZodNullable;\n resetsAtMs: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n allowed: \"allowed\";\n blocked: \"blocked\";\n unknown: \"unknown\";\n warning: \"warning\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/rateLimits/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n category: z$1.ZodEnum<{\n \"compaction-skipped\": \"compaction-skipped\";\n config: \"config\";\n deprecation: \"deprecation\";\n general: \"general\";\n }>;\n details: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n summary: z$1.ZodOptional;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/warning\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n fallbackModel: z$1.ZodString;\n message: z$1.ZodString;\n originalModel: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n reason: z$1.ZodEnum<{\n provider: \"provider\";\n refusal: \"refusal\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/modelFallback\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n parentToolCallId: z$1.ZodOptional;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n rawEvent: z$1.ZodObject<{\n id: z$1.ZodOptional>;\n jsonrpc: z$1.ZodLiteral<\"2.0\">;\n method: z$1.ZodString;\n params: z$1.ZodOptional>>;\n }, z$1.core.$strip>;\n rawType: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/unhandled\">;\n}, z$1.core.$strip>], \"type\">, z$1.ZodObject<{\n scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n}, z$1.core.$strip>>, z$1.ZodIntersection;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n request: z$1.ZodObject<{\n method: z$1.ZodEnum<{\n \"thread/start\": \"thread/start\";\n \"turn/start\": \"turn/start\";\n }>;\n params: z$1.ZodRecord;\n }, z$1.core.$strip>;\n source: z$1.ZodEnum<{\n spawn: \"spawn\";\n tell: \"tell\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/thread/start\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n continuationOfRequestId: z$1.ZodOptional;\n direction: z$1.ZodLiteral<\"outbound\">;\n execution: z$1.ZodObject<{\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n \"workspace-write\": \"workspace-write\";\n auto: \"auto\";\n full: \"full\";\n readonly: \"readonly\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n seq: z$1.ZodOptional;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n source: z$1.ZodEnum<{\n \"client/thread/start\": \"client/thread/start\";\n \"client/turn/requested\": \"client/turn/requested\";\n \"client/turn/start\": \"client/turn/start\";\n }>;\n }, z$1.core.$strip>;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n inputGroups: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>>;\n request: z$1.ZodObject<{\n method: z$1.ZodEnum<{\n \"thread/start\": \"thread/start\";\n \"turn/start\": \"turn/start\";\n }>;\n params: z$1.ZodRecord;\n }, z$1.core.$strip>;\n requestId: z$1.ZodString;\n senderThreadId: z$1.ZodNullable;\n source: z$1.ZodEnum<{\n spawn: \"spawn\";\n tell: \"tell\";\n }>;\n systemMessageKind: z$1.ZodOptional>;\n systemMessageSubject: z$1.ZodOptional;\n threadId: z$1.ZodString;\n threadName: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n count: z$1.ZodNumber;\n kind: z$1.ZodLiteral<\"thread-batch\">;\n }, z$1.core.$strip>], \"kind\">>>;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread-start\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"new-turn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"auto\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"steer\">;\n }, z$1.core.$strip>], \"kind\">;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/turn/requested\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n reason: z$1.ZodString;\n requestId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/turn/rejected\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n direction: z$1.ZodLiteral<\"outbound\">;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n request: z$1.ZodObject<{\n method: z$1.ZodEnum<{\n \"thread/start\": \"thread/start\";\n \"turn/start\": \"turn/start\";\n }>;\n params: z$1.ZodRecord;\n }, z$1.core.$strip>;\n source: z$1.ZodEnum<{\n spawn: \"spawn\";\n tell: \"tell\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/turn/start\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n code: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n message: z$1.ZodString;\n reconnectAttempt: z$1.ZodOptional;\n reconnectTotal: z$1.ZodOptional;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/error\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n text: z$1.ZodString;\n threadId: z$1.ZodString;\n toolCallId: z$1.ZodOptional;\n turnId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"system/manager/user_message\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n reason: z$1.ZodEnum<{\n \"host-daemon-restarted\": \"host-daemon-restarted\";\n \"manual-stop\": \"manual-stop\";\n \"provider-turn-idle\": \"provider-turn-idle\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/thread/interrupted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n metadata: z$1.ZodOptional>>>;\n operation: z$1.ZodString;\n operationId: z$1.ZodString;\n status: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/operation\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n interactionId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n resolution: z$1.ZodDefault;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">>>;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodDefault>;\n subject: z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"permission_grant\">;\n permissions: z$1.ZodObject<{\n fileSystem: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/permissionGrant/lifecycle\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n interactionId: z$1.ZodString;\n payload: z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"user_question\">;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n resolution: z$1.ZodDefault;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>>>;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodDefault>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/userQuestion/lifecycle\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n entries: z$1.ZodArray>;\n startedAt: z$1.ZodOptional;\n status: z$1.ZodOptional>;\n text: z$1.ZodString;\n type: z$1.ZodEnum<{\n output: \"output\";\n step: \"step\";\n }>;\n }, z$1.core.$strip>>;\n environmentId: z$1.ZodString;\n provisioningId: z$1.ZodString;\n status: z$1.ZodEnum<{\n active: \"active\";\n cancelled: \"cancelled\";\n completed: \"completed\";\n failed: \"failed\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/thread-provisioning\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n activeTurnId: z$1.ZodString;\n activeTurnStartedAt: z$1.ZodNumber;\n elapsedMs: z$1.ZodNumber;\n firedAt: z$1.ZodNumber;\n lastActivityEventAt: z$1.ZodNumber;\n lastActivityEventSequence: z$1.ZodNumber;\n lastActivityEventType: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodNullable;\n reason: z$1.ZodLiteral<\"provider-turn-idle\">;\n threadId: z$1.ZodString;\n thresholdMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"system/provider-turn-watchdog\">;\n}, z$1.core.$strip>]>, z$1.ZodObject<{\n scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n}, z$1.core.$strip>>]>>;\ntype ThreadEvent = z$1.infer;\ntype ThreadEventType = ThreadEvent[\"type\"];\n\n/**\n * How completely a provider can clone one of its sessions — the single\n * vocabulary shared by the provider declaration\n * (`bb.agents.experimental_registerProvider`), the server→daemon\n * `bridgeLaunch`, and the bridge's `initialize` handshake.\n *\n * - `\"none\"`: sessions cannot be cloned at all.\n * - `\"tip\"`: only the current end of a session can be cloned (ACP\n * `session/fork`), so thread fork works but edit-past-message rewind\n * cannot.\n * - `\"checkpoint\"`: a session can be recreated at an earlier point, which is\n * what edit-past-message rewind needs.\n *\n * The values are ordered least to most capable: a declaration is a ceiling\n * the handshake may narrow but never widen.\n */\ndeclare const PROVIDER_FORK_VALUES: readonly [\"none\", \"tip\", \"checkpoint\"];\ntype ProviderFork = (typeof PROVIDER_FORK_VALUES)[number];\n\ndeclare const providerInfoSchema: z$1.ZodObject<{\n available: z$1.ZodBoolean;\n capabilities: z$1.ZodObject<{\n permissionModes: z$1.ZodArray>;\n supportsFork: z$1.ZodBoolean;\n supportsNativeUserQuestion: z$1.ZodBoolean;\n supportsServiceTier: z$1.ZodBoolean;\n supportsSessionRewind: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n composerActions: z$1.ZodArray;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"goal\">;\n }, z$1.core.$strip>], \"kind\">>;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n logoUrl: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ProviderInfo = z$1.infer;\n\ndeclare const threadEventScopeSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>], \"kind\">;\ntype ThreadEventScope = z$1.infer;\n\ntype ThreadEventByType = {\n [TType in ThreadEventType]: Extract;\n};\ntype ThreadEventForType = ThreadEventByType[TType];\ntype StoredThreadEventDataFromEvent = Omit;\ninterface ThreadEventRowBase {\n id: string;\n scope: ThreadEventScope;\n threadId: string;\n seq: number;\n createdAt: number;\n}\ntype ThreadEventRowFromEvent = ThreadEventRowBase & {\n type: TEvent[\"type\"];\n data: StoredThreadEventDataFromEvent;\n};\ntype ThreadEventRowOfType = ThreadEventRowFromEvent>;\ntype ThreadEventRow = {\n [TType in ThreadEventType]: ThreadEventRowOfType;\n}[ThreadEventType];\n\ndeclare const threadStatusSchema: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n}>;\ntype ThreadStatus = z$1.infer;\n\ndeclare const threadTimelinePendingTodosSchema: z$1.ZodObject<{\n items: z$1.ZodArray;\n text: z$1.ZodString;\n }, z$1.core.$strip>>;\n sourceSeq: z$1.ZodNumber;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadTimelinePendingTodos = z$1.infer;\n\ndeclare const threadQueuedMessageSchema: z$1.ZodObject<{\n content: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n createdAt: z$1.ZodNumber;\n groupWithNext: z$1.ZodBoolean;\n id: z$1.ZodString;\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadQueuedMessage = z$1.infer;\n\ndeclare const createThreadEnvironmentArgsSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"reuse\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host\">;\n workspace: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branch: z$1.ZodOptional;\n name: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new\">;\n }, z$1.core.$strict>], \"kind\">>;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"unmanaged\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n baseBranch: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"named\">;\n name: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"default\">;\n }, z$1.core.$strip>], \"kind\">;\n type: z$1.ZodLiteral<\"managed-worktree\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"personal\">;\n }, z$1.core.$strip>], \"type\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"project-default\">;\n}, z$1.core.$strip>], \"type\">;\ntype CreateThreadEnvironmentArgs = z$1.infer;\ndeclare const workspaceFileListResponseSchema: z$1.ZodObject<{\n files: z$1.ZodArray>;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype WorkspaceFileListResponse = z$1.infer;\ndeclare const workspacePathListResponseSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n positions: z$1.ZodArray;\n score: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype WorkspacePathListResponse = z$1.infer;\n\ndeclare const createProjectSourceRequestSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n hostId: z$1.ZodString;\n path: z$1.ZodPipe>;\n type: z$1.ZodLiteral<\"local_path\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n hostId: z$1.ZodString;\n remoteUrl: z$1.ZodOptional;\n targetPath: z$1.ZodOptional>>;\n type: z$1.ZodLiteral<\"clone\">;\n}, z$1.core.$strict>], \"type\">;\ntype CreateProjectSourceRequest = z$1.infer;\ndeclare const createProjectRequestSchema: z$1.ZodObject<{\n name: z$1.ZodString;\n source: z$1.ZodObject<{\n hostId: z$1.ZodString;\n path: z$1.ZodPipe>;\n type: z$1.ZodLiteral<\"local_path\">;\n }, z$1.core.$strict>;\n}, z$1.core.$strip>;\ntype CreateProjectRequest = z$1.infer;\ndeclare const threadSectionSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n name: z$1.ZodString;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype ThreadSectionResponse = z$1.infer;\ndeclare const createThreadSectionRequestSchema: z$1.ZodObject<{\n name: z$1.ZodString;\n}, z$1.core.$strict>;\ntype CreateThreadSectionRequest = z$1.infer;\ndeclare const updateThreadSectionRequestSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n name: z$1.ZodString;\n}, z$1.core.$strict>;\ntype UpdateThreadSectionRequest = z$1.infer;\ndeclare const deleteThreadSectionRequestSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n}, z$1.core.$strict>;\ntype DeleteThreadSectionRequest = z$1.infer;\ndeclare const threadSectionMutationResponseSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n name: z$1.ZodString;\n updatedThreadCount: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype ThreadSectionMutationResponse = z$1.infer;\ndeclare const reorderProjectRequestSchema: z$1.ZodObject<{\n nextProjectId: z$1.ZodNullable;\n previousProjectId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ReorderProjectRequest = z$1.infer;\ndeclare const projectListQuerySchema: z$1.ZodObject<{\n include: z$1.ZodOptional;\n includePersonal: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ProjectListQuery = z$1.infer;\ndeclare const projectFilesQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n limit: z$1.ZodOptional>;\n query: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ProjectFilesQuery = z$1.infer;\ndeclare const projectPathsQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n includeDirectories: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n includeFiles: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n limit: z$1.ZodOptional>;\n query: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ProjectPathsQuery = z$1.infer;\ndeclare const projectFileContentQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n path: z$1.ZodString;\n}, z$1.core.$strip>;\ntype ProjectFileContentQuery = z$1.infer;\ndeclare const projectBranchesQuerySchema: z$1.ZodObject<{\n hostId: z$1.ZodString;\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n selectedBranch: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ProjectBranchesQuery = z$1.infer;\ndeclare const projectBranchesResponseSchema: z$1.ZodObject<{\n branches: z$1.ZodArray;\n branchesTruncated: z$1.ZodBoolean;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n defaultBranch: z$1.ZodNullable;\n defaultBranchRelation: z$1.ZodNullable>;\n defaultWorktreeBaseBranch: z$1.ZodNullable;\n hasUncommittedChanges: z$1.ZodBoolean;\n operation: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"none\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"merge\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"rebase\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"cherry-pick\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"revert\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n originDefaultBranch: z$1.ZodNullable;\n remoteBranches: z$1.ZodArray;\n remoteBranchesTruncated: z$1.ZodBoolean;\n selectedBranch: z$1.ZodNullable;\n name: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype ProjectBranchesResponse = z$1.infer;\ndeclare const promptHistoryQuerySchema: z$1.ZodObject<{\n limit: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype PromptHistoryQuery = z$1.infer;\ndeclare const promptHistoryResponseSchema: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n}, z$1.core.$strip>>;\ntype PromptHistoryResponse = z$1.infer;\ndeclare const updateProjectRequestSchema: z$1.ZodObject<{\n name: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype UpdateProjectRequest = z$1.infer;\ndeclare const updateProjectSourceRequestSchema: z$1.ZodObject<{\n isDefault: z$1.ZodOptional>;\n path: z$1.ZodOptional>>;\n type: z$1.ZodLiteral<\"local_path\">;\n}, z$1.core.$strict>;\ntype UpdateProjectSourceRequest = z$1.infer;\ndeclare const commandListResponseSchema: z$1.ZodObject<{\n commands: z$1.ZodArray;\n description: z$1.ZodNullable;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n pluginId: z$1.ZodOptional;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype CommandListResponse = z$1.infer;\n/** Query for the complete command catalog available to a project and provider. */\ndeclare const projectCommandsQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n provider: z$1.ZodString;\n}, z$1.core.$strict>;\ntype ProjectCommandsQuery = z$1.infer;\ndeclare const skillListResponseSchema: z$1.ZodObject<{\n skills: z$1.ZodArray;\n filePath: z$1.ZodString;\n id: z$1.ZodString;\n manageable: z$1.ZodBoolean;\n name: z$1.ZodString;\n pluginId: z$1.ZodNullable;\n provider: z$1.ZodNullable;\n registrySkillId: z$1.ZodNullable;\n scope: z$1.ZodEnum<{\n \"bb-builtin\": \"bb-builtin\";\n \"bb-project\": \"bb-project\";\n \"bb-user\": \"bb-user\";\n \"provider-project\": \"provider-project\";\n \"provider-user\": \"provider-user\";\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n plugin: \"plugin\";\n }>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype SkillListResponse = z$1.infer;\ndeclare const skillContentResponseSchema: z$1.ZodObject<{\n content: z$1.ZodString;\n revision: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SkillContentResponse = z$1.infer;\ndeclare const skillFilesResponseSchema: z$1.ZodObject<{\n files: z$1.ZodArray;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype SkillFilesResponse = z$1.infer;\ndeclare const projectResponseSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n gitRemoteUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n personal: \"personal\";\n standard: \"standard\";\n }>;\n name: z$1.ZodString;\n sources: z$1.ZodArray;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ProjectResponse = z$1.infer;\ndeclare const projectWithThreadsResponseSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n defaultExecutionOptions: z$1.ZodNullable;\n providerId: z$1.ZodString;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n }, z$1.core.$strip>>;\n gitRemoteUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n personal: \"personal\";\n standard: \"standard\";\n }>;\n name: z$1.ZodString;\n sources: z$1.ZodArray;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n threads: z$1.ZodArray;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n }, z$1.core.$strip>>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ProjectWithThreadsResponse = z$1.infer;\ndeclare const uploadedPromptAttachmentSchema: z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodString;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n type: z$1.ZodEnum<{\n localFile: \"localFile\";\n localImage: \"localImage\";\n }>;\n}, z$1.core.$strip>;\ntype UploadedPromptAttachment = z$1.infer;\ndeclare const copyProjectAttachmentsRequestSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n sourceProjectId: z$1.ZodString;\n}, z$1.core.$strict>;\ntype CopyProjectAttachmentsRequest = z$1.infer;\n\ndeclare const registrySkillSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n installUrl: z$1.ZodNullable;\n installs: z$1.ZodNumber;\n name: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n stars: z$1.ZodNullable;\n summary: z$1.ZodNullable;\n topic: z$1.ZodNullable;\n url: z$1.ZodString;\n}, z$1.core.$strip>;\ntype RegistrySkill = z$1.infer;\ndeclare const registrySkillsPageSchema: z$1.ZodObject<{\n pagination: z$1.ZodObject<{\n hasMore: z$1.ZodBoolean;\n page: z$1.ZodNumber;\n perPage: z$1.ZodNumber;\n total: z$1.ZodNumber;\n }, z$1.core.$strip>;\n ranking: z$1.ZodEnum<{\n \"all-time\": \"all-time\";\n trending: \"trending\";\n }>;\n skills: z$1.ZodArray;\n installs: z$1.ZodNumber;\n name: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n stars: z$1.ZodNullable;\n summary: z$1.ZodNullable;\n topic: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype RegistrySkillsPage = z$1.infer;\ndeclare const registryRepositoryStarsSchema: z$1.ZodObject<{\n stars: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype RegistryRepositoryStars = z$1.infer;\ndeclare const registrySkillDetailSchema: z$1.ZodObject<{\n files: z$1.ZodNullable>>;\n hash: z$1.ZodNullable;\n id: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n}, z$1.core.$strip>;\ntype RegistrySkillDetail = z$1.infer;\n/**\n * Entries that could not be resolved (dead detail page, malformed id) are\n * omitted rather than failing the batch: each entry is independent upstream,\n * and callers already treat a missing entry as \"unknown\" per card.\n */\ndeclare const registrySkillEntriesResponseSchema: z$1.ZodObject<{\n entries: z$1.ZodArray;\n installs: z$1.ZodNumber;\n name: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n stars: z$1.ZodNullable;\n summary: z$1.ZodNullable;\n topic: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype RegistrySkillEntriesResponse = z$1.infer;\ndeclare const registrySkillInstallResponseSchema: z$1.ZodObject<{\n filePath: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype RegistrySkillInstallResponse = z$1.infer;\n\ndeclare const updateEnvironmentRequestSchema: z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodOptional>;\n name: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype UpdateEnvironmentRequest = z$1.infer;\n/**\n * Query for searching paths in an environment's workspace. Unlike the\n * project-scoped variant this needs no `environmentId` — the environment is\n * the route param — and is project-agnostic, so it works for projectless\n * (personal) environments too.\n */\ndeclare const environmentPathsQuerySchema: z$1.ZodObject<{\n includeDirectories: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n includeFiles: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype EnvironmentPathsQuery = z$1.infer;\ndeclare const environmentDiffBranchesQuerySchema: z$1.ZodObject<{\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n selectedBranch: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype EnvironmentDiffBranchesQuery = z$1.infer;\ndeclare const environmentDiffBranchesResponseSchema: z$1.ZodObject<{\n branches: z$1.ZodArray;\n branchesTruncated: z$1.ZodBoolean;\n remoteBranches: z$1.ZodArray;\n remoteBranchesTruncated: z$1.ZodBoolean;\n selectedBranch: z$1.ZodNullable;\n name: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype EnvironmentDiffBranchesResponse = z$1.infer;\ndeclare const environmentStatusQuerySchema: z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype EnvironmentStatusQuery = z$1.infer;\ndeclare const environmentDiffQuerySchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n target: z$1.ZodLiteral<\"uncommitted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodPipe;\n target: z$1.ZodLiteral<\"branch_committed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodPipe;\n target: z$1.ZodLiteral<\"all\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n target: z$1.ZodLiteral<\"commit\">;\n}, z$1.core.$strip>], \"target\">;\ntype EnvironmentDiffQuery = z$1.infer;\n/**\n * Query for fetching a single file's contents at one side of a diff target.\n * Used by the diff card to reparse the card's patch with full old/new contents\n * so `@pierre/diffs` can render expand-context buttons between hunks.\n *\n * For `branch_committed` / `all`, callers pass the resolved merge-base SHA\n * (`mergeBaseRef`, surfaced by `workspace.diff`) rather than the branch name\n * — the diff itself was computed against that SHA, so reading the old side\n * from the same SHA keeps the file content aligned with the hunk line\n * numbers. Reading from the branch tip is wrong whenever the branch has\n * moved past the merge-base since the file existed there.\n */\ndeclare const environmentDiffFileQuerySchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n path: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"uncommitted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseRef: z$1.ZodString;\n path: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"branch_committed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseRef: z$1.ZodString;\n path: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"all\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n sha: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"commit\">;\n}, z$1.core.$strip>], \"target\">;\ntype EnvironmentDiffFileQuery = z$1.infer;\ndeclare const environmentDiffFileResponseSchema: z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n mimeType: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype EnvironmentDiffFileResponse = z$1.infer;\ndeclare const environmentArchiveThreadsResponseSchema: z$1.ZodObject<{\n archivedThreadIds: z$1.ZodArray;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype EnvironmentArchiveThreadsResponse = z$1.infer;\ndeclare const pullRequestMergeMethodSchema: z$1.ZodEnum<{\n merge: \"merge\";\n rebase: \"rebase\";\n squash: \"squash\";\n}>;\ntype PullRequestMergeMethod = z$1.infer;\ndeclare const commitActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"commit\">;\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype CommitActionResponse = z$1.infer;\ndeclare const squashMergeActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"squash_merge\">;\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n merged: z$1.ZodBoolean;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype SquashMergeActionResponse = z$1.infer;\ndeclare const pullRequestReadyActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"pull_request_ready\">;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PullRequestReadyActionResponse = z$1.infer;\ndeclare const pullRequestMergeActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"pull_request_merge\">;\n message: z$1.ZodString;\n method: z$1.ZodEnum<{\n merge: \"merge\";\n rebase: \"rebase\";\n squash: \"squash\";\n }>;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PullRequestMergeActionResponse = z$1.infer;\ndeclare const pullRequestDraftActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"pull_request_draft\">;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PullRequestDraftActionResponse = z$1.infer;\ndeclare const environmentStatusResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n workspace: z$1.ZodObject<{\n branch: z$1.ZodObject<{\n currentBranch: z$1.ZodNullable;\n defaultBranch: z$1.ZodString;\n }, z$1.core.$strip>;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n mergeBase: z$1.ZodNullable;\n behindCount: z$1.ZodNumber;\n commits: z$1.ZodArray>;\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasCommittedUnmergedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodString;\n }, z$1.core.$strip>>;\n workingTree: z$1.ZodObject<{\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasUncommittedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n state: z$1.ZodEnum<{\n clean: \"clean\";\n committed_unmerged: \"committed_unmerged\";\n dirty_and_committed_unmerged: \"dirty_and_committed_unmerged\";\n dirty_uncommitted: \"dirty_uncommitted\";\n untracked: \"untracked\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strip>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\n/**\n * Structured pull-request lookup outcome. \"absent\" is a real answer — the\n * host checked and the branch has no PR (non-git environments resolve to\n * \"absent\" without a daemon call). \"unavailable\" means the lookup itself\n * failed (gh missing, not authenticated, timeout, unreachable workspace), so\n * callers must not render it as \"no PR exists\".\n */\ndeclare const environmentPullRequestResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n pullRequest: z$1.ZodObject<{\n attention: z$1.ZodEnum<{\n blocked: \"blocked\";\n changes_requested: \"changes_requested\";\n checks_failed: \"checks_failed\";\n checks_pending: \"checks_pending\";\n closed: \"closed\";\n conflicts: \"conflicts\";\n draft: \"draft\";\n merged: \"merged\";\n none: \"none\";\n ready_to_merge: \"ready_to_merge\";\n review_requested: \"review_requested\";\n }>;\n baseRefName: z$1.ZodString;\n checks: z$1.ZodObject<{\n failedCount: z$1.ZodNumber;\n passedCount: z$1.ZodNumber;\n pendingCount: z$1.ZodNumber;\n state: z$1.ZodEnum<{\n failing: \"failing\";\n no_checks: \"no_checks\";\n passing: \"passing\";\n pending: \"pending\";\n unknown: \"unknown\";\n }>;\n totalCount: z$1.ZodNumber;\n }, z$1.core.$strict>;\n headRefName: z$1.ZodString;\n mergeability: z$1.ZodObject<{\n mergeStateStatus: z$1.ZodNullable>;\n mergeable: z$1.ZodNullable>;\n state: z$1.ZodEnum<{\n blocked: \"blocked\";\n conflicts: \"conflicts\";\n draft: \"draft\";\n mergeable: \"mergeable\";\n unknown: \"unknown\";\n }>;\n }, z$1.core.$strict>;\n number: z$1.ZodNumber;\n review: z$1.ZodObject<{\n reviewRequestCount: z$1.ZodNumber;\n state: z$1.ZodEnum<{\n approved: \"approved\";\n changes_requested: \"changes_requested\";\n none: \"none\";\n review_requested: \"review_requested\";\n review_required: \"review_required\";\n }>;\n }, z$1.core.$strict>;\n state: z$1.ZodEnum<{\n closed: \"closed\";\n draft: \"draft\";\n merged: \"merged\";\n open: \"open\";\n }>;\n title: z$1.ZodString;\n updatedAt: z$1.ZodString;\n url: z$1.ZodString;\n }, z$1.core.$strict>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"absent\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentPullRequestResponse = z$1.infer;\ndeclare const environmentDiffResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n diff: z$1.ZodObject<{\n diff: z$1.ZodString;\n files: z$1.ZodString;\n mergeBaseRef: z$1.ZodNullable;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n outcome: z$1.ZodLiteral<\"available\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentDiffResponse = z$1.infer;\ndeclare const environmentDiffFilesResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n files: z$1.ZodArray;\n deletions: z$1.ZodNumber;\n loadMode: z$1.ZodEnum<{\n auto: \"auto\";\n on_demand: \"on_demand\";\n too_large: \"too_large\";\n }>;\n origin: z$1.ZodEnum<{\n tracked: \"tracked\";\n untracked: \"untracked\";\n }>;\n path: z$1.ZodString;\n previousPath: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n initialPatches: z$1.ZodArray>;\n mergeBaseRef: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"available\">;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentDiffFilesResponse = z$1.infer;\ndeclare const environmentDiffPatchResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n patches: z$1.ZodArray>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentDiffPatchResponse = z$1.infer;\n/**\n * Body for `POST /diff/patch`: the diff target plus the list of new paths whose\n * patches the client wants. A POST (not GET) because the repeated `paths` array\n * cannot survive flat query parsing. The client supplies only new paths; the\n * server re-derives each file's rename/copy pairing (`previousPath`) from its\n * own TOC.\n */\ndeclare const environmentDiffPatchRequestSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n}, z$1.core.$strict>;\ntype EnvironmentDiffPatchRequest = z$1.infer;\ntype EnvironmentStatusResponse = z$1.infer;\n\ndeclare const providerUsageResponseSchema: z$1.ZodObject<{\n claudeCode: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n codex: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n cursor: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n}, z$1.core.$strip>;\ntype ProviderUsageResponse = z$1.infer;\ndeclare const discoverReposResultSchema: z$1.ZodObject<{\n repos: z$1.ZodArray;\n lastActivityAt: z$1.ZodString;\n name: z$1.ZodString;\n originUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>>;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strict>;\ntype DiscoverReposResult = z$1.infer;\ntype HostDaemonCommandTransport = \"onlineRpc\" | \"settled\";\ntype HostDaemonCommandEnvironmentLane = \"read\" | \"write\";\ntype HostDaemonFlushEventsBeforeResult = boolean | \"when-initiated\";\ninterface HostDaemonCommandDescriptor {\n type: Type;\n schema: Schema;\n resultSchema: ResultSchema;\n transport: Transport;\n retryable: Retryable;\n flushEventsBeforeResult: HostDaemonFlushEventsBeforeResult;\n envLane: HostDaemonCommandEnvironmentLane | null;\n}\ndeclare const hostDaemonCommandRegistry: {\n \"thread.rewind.discard\": HostDaemonCommandDescriptor<\"thread.rewind.discard\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n leaseId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.rewind.discard\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"thread.rewind.prepare\": HostDaemonCommandDescriptor<\"thread.rewind.prepare\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n environmentId: z$1.ZodString;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n leaseId: z$1.ZodString;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n retainThroughProviderCheckpoint: z$1.ZodString;\n sourceProviderThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.rewind.prepare\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"thread.start\": HostDaemonCommandDescriptor<\"thread.start\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n environmentId: z$1.ZodString;\n fork: z$1.ZodOptional>;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n inputGroups: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n requestId: z$1.ZodString;\n threadId: z$1.ZodString;\n threadStoragePath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"thread.start\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"turn.submit\": HostDaemonCommandDescriptor<\"turn.submit\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n inputGroups: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>>;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n requestId: z$1.ZodString;\n resumeContext: z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n mode: z$1.ZodLiteral<\"start\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n mode: z$1.ZodLiteral<\"auto\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n mode: z$1.ZodLiteral<\"steer\">;\n }, z$1.core.$strip>], \"mode\">;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn.submit\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n appliedAs: z$1.ZodEnum<{\n \"new-turn\": \"new-turn\";\n steer: \"steer\";\n }>;\n }, z$1.core.$strip>, \"settled\", false>;\n \"thread.stop\": HostDaemonCommandDescriptor<\"thread.stop\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n intent: z$1.ZodEnum<{\n interrupt: \"interrupt\";\n release: \"release\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.stop\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n providerCheckpointId: z$1.ZodNullable;\n }, z$1.core.$strict>, \"settled\", false>;\n \"thread.goal.clear\": HostDaemonCommandDescriptor<\"thread.goal.clear\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n resumeContext: z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.goal.clear\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cleared: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"settled\", false>;\n \"thread.plan.cancel\": HostDaemonCommandDescriptor<\"thread.plan.cancel\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n expectedTurnId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.plan.cancel\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cancelled: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"settled\", false>;\n \"thread.rename\": HostDaemonCommandDescriptor<\"thread.rename\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.rename\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"thread.archive\": HostDaemonCommandDescriptor<\"thread.archive\", z$1.ZodObject<{\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.archive\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"thread.unarchive\": HostDaemonCommandDescriptor<\"thread.unarchive\", z$1.ZodObject<{\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.unarchive\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"interactive.resolve\": HostDaemonCommandDescriptor<\"interactive.resolve\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n interactionId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n resolution: z$1.ZodUnion;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin_submitted\">;\n }, z$1.core.$strip>]>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"interactive.resolve\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"codex.inference.complete\": HostDaemonCommandDescriptor<\"codex.inference.complete\", z$1.ZodObject<{\n model: z$1.ZodString;\n outputSchema: z$1.ZodType>;\n prompt: z$1.ZodString;\n reasoningEffort: z$1.ZodLiteral<\"none\">;\n timeoutMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"codex.inference.complete\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n model: z$1.ZodString;\n value: z$1.ZodType>;\n }, z$1.core.$strip>, \"settled\", false>;\n \"codex.voice.transcribe\": HostDaemonCommandDescriptor<\"codex.voice.transcribe\", z$1.ZodObject<{\n audioBase64: z$1.ZodString;\n filename: z$1.ZodString;\n mimeType: z$1.ZodString;\n model: z$1.ZodString;\n prompt: z$1.ZodNullable;\n timeoutMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"codex.voice.transcribe\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n model: z$1.ZodString;\n text: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"environment.provision\": HostDaemonCommandDescriptor<\"environment.provision\", z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n checkout: z$1.ZodOptional;\n name: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new\">;\n name: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n environmentId: z$1.ZodString;\n initiator: z$1.ZodNullable>;\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision\">;\n workspaceProvisionType: z$1.ZodLiteral<\"unmanaged\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodNullable;\n branchName: z$1.ZodString;\n environmentId: z$1.ZodString;\n initiator: z$1.ZodNullable>;\n setupTimeoutMs: z$1.ZodNumber;\n sourcePath: z$1.ZodString;\n targetPath: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision\">;\n workspaceProvisionType: z$1.ZodLiteral<\"managed-worktree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n initiator: z$1.ZodNullable>;\n targetPath: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision\">;\n workspaceProvisionType: z$1.ZodLiteral<\"personal\">;\n }, z$1.core.$strict>], \"workspaceProvisionType\">, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n defaultBranch: z$1.ZodNullable;\n isGitRepo: z$1.ZodBoolean;\n isWorktree: z$1.ZodBoolean;\n path: z$1.ZodString;\n transcript: z$1.ZodArray>;\n startedAt: z$1.ZodOptional;\n status: z$1.ZodOptional>;\n text: z$1.ZodString;\n type: z$1.ZodEnum<{\n output: \"output\";\n step: \"step\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"settled\", false>;\n \"project.clone\": HostDaemonCommandDescriptor<\"project.clone\", z$1.ZodObject<{\n projectSlug: z$1.ZodString;\n remoteUrl: z$1.ZodString;\n targetPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"project.clone\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n gitRemoteUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>, \"settled\", false>;\n \"environment.provision.cancel\": HostDaemonCommandDescriptor<\"environment.provision.cancel\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision.cancel\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n aborted: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"settled\", false>;\n \"environment.destroy\": HostDaemonCommandDescriptor<\"environment.destroy\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.destroy\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"workspace.commit\": HostDaemonCommandDescriptor<\"workspace.commit\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n message: z$1.ZodString;\n type: z$1.ZodLiteral<\"workspace.commit\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"workspace.squash_merge\": HostDaemonCommandDescriptor<\"workspace.squash_merge\", z$1.ZodObject<{\n commitMessage: z$1.ZodString;\n environmentId: z$1.ZodString;\n targetBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"workspace.squash_merge\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n merged: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"settled\", false>;\n \"workspace.pull_request_action\": HostDaemonCommandDescriptor<\"workspace.pull_request_action\", z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n environmentId: z$1.ZodString;\n operation: z$1.ZodLiteral<\"ready\">;\n type: z$1.ZodLiteral<\"workspace.pull_request_action\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n operation: z$1.ZodLiteral<\"draft\">;\n type: z$1.ZodLiteral<\"workspace.pull_request_action\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n method: z$1.ZodEnum<{\n merge: \"merge\";\n rebase: \"rebase\";\n squash: \"squash\";\n }>;\n operation: z$1.ZodLiteral<\"merge\">;\n type: z$1.ZodLiteral<\"workspace.pull_request_action\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>], \"operation\">, z$1.ZodObject<{}, z$1.core.$strict>, \"settled\", false>;\n \"host.list_files\": HostDaemonCommandDescriptor<\"host.list_files\", z$1.ZodObject<{\n limit: z$1.ZodNumber;\n path: z$1.ZodString;\n query: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.list_files\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n files: z$1.ZodArray>;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.list_paths\": HostDaemonCommandDescriptor<\"host.list_paths\", z$1.ZodObject<{\n includeDirectories: z$1.ZodBoolean;\n includeFiles: z$1.ZodBoolean;\n limit: z$1.ZodNumber;\n path: z$1.ZodString;\n query: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.list_paths\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n paths: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n positions: z$1.ZodArray;\n score: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.mkdir\": HostDaemonCommandDescriptor<\"host.mkdir\", z$1.ZodObject<{\n path: z$1.ZodString;\n recursive: z$1.ZodBoolean;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.mkdir\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.move_path\": HostDaemonCommandDescriptor<\"host.move_path\", z$1.ZodObject<{\n destinationPath: z$1.ZodString;\n rootPath: z$1.ZodOptional;\n sourcePath: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.move_path\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.remove_path\": HostDaemonCommandDescriptor<\"host.remove_path\", z$1.ZodObject<{\n path: z$1.ZodString;\n recursive: z$1.ZodBoolean;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.remove_path\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.browse_directory\": HostDaemonCommandDescriptor<\"host.browse_directory\", z$1.ZodObject<{\n path: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.browse_directory\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n directory: z$1.ZodString;\n entries: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n parent: z$1.ZodNullable;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.paths_exist\": HostDaemonCommandDescriptor<\"host.paths_exist\", z$1.ZodObject<{\n paths: z$1.ZodPipe, z$1.ZodTransform>;\n type: z$1.ZodLiteral<\"host.paths_exist\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n existence: z$1.ZodRecord;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"project.inspect\": HostDaemonCommandDescriptor<\"project.inspect\", z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"project.inspect\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n gitRemoteUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"project.clone_default_path\": HostDaemonCommandDescriptor<\"project.clone_default_path\", z$1.ZodObject<{\n projectSlug: z$1.ZodString;\n type: z$1.ZodLiteral<\"project.clone_default_path\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n path: z$1.ZodString;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"host.pick_folder\": HostDaemonCommandDescriptor<\"host.pick_folder\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"host.pick_folder\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n path: z$1.ZodNullable;\n }, z$1.core.$strip>, \"onlineRpc\", false>;\n \"plugin.host.call\": HostDaemonCommandDescriptor<\"plugin.host.call\", z$1.ZodObject<{\n artifact: z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n }, z$1.core.$strict>;\n callId: z$1.ZodString;\n generation: z$1.ZodString;\n input: z$1.ZodType>;\n method: z$1.ZodString;\n pluginId: z$1.ZodString;\n timeoutMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"plugin.host.call\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n output: z$1.ZodType>;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"plugin.host.cancel\": HostDaemonCommandDescriptor<\"plugin.host.cancel\", z$1.ZodObject<{\n callId: z$1.ZodString;\n generation: z$1.ZodString;\n pluginId: z$1.ZodString;\n type: z$1.ZodLiteral<\"plugin.host.cancel\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cancelled: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"plugin.host.dispose\": HostDaemonCommandDescriptor<\"plugin.host.dispose\", z$1.ZodObject<{\n generation: z$1.ZodString;\n pluginId: z$1.ZodString;\n type: z$1.ZodLiteral<\"plugin.host.dispose\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n disposed: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"connect-tunnel.ensure-identity\": HostDaemonCommandDescriptor<\"connect-tunnel.ensure-identity\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"connect-tunnel.ensure-identity\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseDomain: z$1.ZodString;\n label: z$1.ZodString;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"host.list_commands\": HostDaemonCommandDescriptor<\"host.list_commands\", z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n providerId: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.list_commands\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n commands: z$1.ZodArray;\n description: z$1.ZodNullable;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.list_skills\": HostDaemonCommandDescriptor<\"host.list_skills\", z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n providerId: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.list_skills\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n skills: z$1.ZodArray;\n filePath: z$1.ZodString;\n id: z$1.ZodString;\n linked: z$1.ZodBoolean;\n name: z$1.ZodString;\n rootKind: z$1.ZodEnum<{\n \"bb-builtin\": \"bb-builtin\";\n \"bb-data-dir\": \"bb-data-dir\";\n \"bb-project\": \"bb-project\";\n \"provider-project\": \"provider-project\";\n \"provider-user\": \"provider-user\";\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n plugin: \"plugin\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.delete_skill\": HostDaemonCommandDescriptor<\"host.delete_skill\", z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n name: z$1.ZodString;\n rootPath: z$1.ZodNullable;\n scope: z$1.ZodEnum<{\n \"bb-project\": \"bb-project\";\n \"bb-user\": \"bb-user\";\n \"provider-project\": \"provider-project\";\n \"provider-user\": \"provider-user\";\n }>;\n type: z$1.ZodLiteral<\"host.delete_skill\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n deletedPath: z$1.ZodString;\n }, z$1.core.$strip>, \"onlineRpc\", false>;\n \"host.write_skill\": HostDaemonCommandDescriptor<\"host.write_skill\", z$1.ZodObject<{\n content: z$1.ZodString;\n cwd: z$1.ZodNullable;\n expectedSha256: z$1.ZodString;\n name: z$1.ZodString;\n scope: z$1.ZodEnum<{\n \"bb-project\": \"bb-project\";\n \"bb-user\": \"bb-user\";\n }>;\n type: z$1.ZodLiteral<\"host.write_skill\">;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n filePath: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"written\">;\n sha256: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n currentSha256: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"conflict\">;\n }, z$1.core.$strip>], \"outcome\">, \"onlineRpc\", false>;\n \"host.install_global_skills\": HostDaemonCommandDescriptor<\"host.install_global_skills\", z$1.ZodObject<{\n skills: z$1.ZodArray>;\n type: z$1.ZodLiteral<\"host.install_global_skills\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n installations: z$1.ZodArray>;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.global_skills_status\": HostDaemonCommandDescriptor<\"host.global_skills_status\", z$1.ZodObject<{\n names: z$1.ZodArray;\n type: z$1.ZodLiteral<\"host.global_skills_status\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n entries: z$1.ZodArray;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"host.list_branches\": HostDaemonCommandDescriptor<\"host.list_branches\", z$1.ZodObject<{\n limit: z$1.ZodNumber;\n path: z$1.ZodString;\n query: z$1.ZodOptional;\n selectedBranch: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.list_branches\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branches: z$1.ZodArray;\n branchesTruncated: z$1.ZodBoolean;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n defaultBranch: z$1.ZodNullable;\n defaultBranchRelation: z$1.ZodNullable>;\n hasUncommittedChanges: z$1.ZodBoolean;\n operation: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"none\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"merge\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"rebase\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"cherry-pick\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"revert\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n originDefaultBranch: z$1.ZodNullable;\n remoteBranches: z$1.ZodArray;\n remoteBranchesTruncated: z$1.ZodBoolean;\n selectedBranch: z$1.ZodNullable;\n name: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.file_metadata\": HostDaemonCommandDescriptor<\"host.file_metadata\", z$1.ZodObject<{\n path: z$1.ZodString;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.file_metadata\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n modifiedAtMs: z$1.ZodNumber;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.read_file\": HostDaemonCommandDescriptor<\"host.read_file\", z$1.ZodObject<{\n path: z$1.ZodString;\n ref: z$1.ZodOptional;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.read_file\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n mimeType: z$1.ZodOptional;\n modifiedAtMs: z$1.ZodOptional;\n path: z$1.ZodString;\n sha256: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.read_file_relative\": HostDaemonCommandDescriptor<\"host.read_file_relative\", z$1.ZodObject<{\n dotfiles: z$1.ZodEnum<{\n allow: \"allow\";\n deny: \"deny\";\n }>;\n path: z$1.ZodString;\n rootPath: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.read_file_relative\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n mimeType: z$1.ZodOptional;\n modifiedAtMs: z$1.ZodOptional;\n path: z$1.ZodString;\n sha256: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.write_file\": HostDaemonCommandDescriptor<\"host.write_file\", z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n createParents: z$1.ZodBoolean;\n expectedSha256: z$1.ZodOptional>;\n mode: z$1.ZodOptional;\n path: z$1.ZodString;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.write_file\">;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"written\">;\n sha256: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strict>, z$1.ZodObject<{\n currentSha256: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"conflict\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", false>;\n \"provider.list_models\": HostDaemonCommandDescriptor<\"provider.list_models\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n cwd: z$1.ZodOptional;\n providerId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider.list_models\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n models: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n selectedOnlyModels: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"known_acp_agents.status\": HostDaemonCommandDescriptor<\"known_acp_agents.status\", z$1.ZodObject<{\n agents: z$1.ZodArray>;\n type: z$1.ZodLiteral<\"known_acp_agents.status\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n agents: z$1.ZodArray;\n id: z$1.ZodString;\n installed: z$1.ZodBoolean;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"provider.usage\": HostDaemonCommandDescriptor<\"provider.usage\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"provider.usage\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n claudeCode: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n codex: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n cursor: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"workspace.discover_repos\": HostDaemonCommandDescriptor<\"workspace.discover_repos\", z$1.ZodObject<{\n limit: z$1.ZodNumber;\n maxDepth: z$1.ZodNumber;\n sinceDays: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"workspace.discover_repos\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n repos: z$1.ZodArray;\n lastActivityAt: z$1.ZodString;\n name: z$1.ZodString;\n originUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>>;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"provider_cli.status\": HostDaemonCommandDescriptor<\"provider_cli.status\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"provider_cli.status\">;\n }, z$1.core.$strict>, z$1.ZodRecord, z$1.ZodObject<{\n currentVersion: z$1.ZodNullable;\n displayName: z$1.ZodString;\n executableName: z$1.ZodString;\n executablePath: z$1.ZodNullable;\n installAction: z$1.ZodNullable;\n kind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n label: z$1.ZodEnum<{\n Install: \"Install\";\n Update: \"Update\";\n }>;\n }, z$1.core.$strip>>;\n installSource: z$1.ZodEnum<{\n external: \"external\";\n notInstalled: \"notInstalled\";\n npmGlobal: \"npmGlobal\";\n }>;\n installed: z$1.ZodBoolean;\n latestVersion: z$1.ZodNullable;\n minimumSupportedVersion: z$1.ZodNullable;\n needsUpdate: z$1.ZodBoolean;\n npmGlobalPackageVersion: z$1.ZodNullable;\n npmPackageName: z$1.ZodNullable;\n versionUnsupported: z$1.ZodBoolean;\n }, z$1.core.$strip>>, \"onlineRpc\", true>;\n \"provider_cli.install\": HostDaemonCommandDescriptor<\"provider_cli.install\", z$1.ZodObject<{\n actionKind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"provider_cli.install\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n events: z$1.ZodArray;\n type: z$1.ZodLiteral<\"started\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n stream: z$1.ZodEnum<{\n stderr: \"stderr\";\n stdout: \"stdout\";\n }>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"output\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n exitCode: z$1.ZodNullable;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n signal: z$1.ZodNullable;\n success: z$1.ZodBoolean;\n type: z$1.ZodLiteral<\"completed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"type\">>;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"workspace.status\": HostDaemonCommandDescriptor<\"workspace.status\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxUntrackedLineStatBytes: z$1.ZodNumber;\n maxUntrackedLineStatFiles: z$1.ZodNumber;\n mergeBaseBranch: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"workspace.status\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n workspaceStatus: z$1.ZodObject<{\n branch: z$1.ZodObject<{\n currentBranch: z$1.ZodNullable;\n defaultBranch: z$1.ZodString;\n }, z$1.core.$strip>;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n mergeBase: z$1.ZodNullable;\n behindCount: z$1.ZodNumber;\n commits: z$1.ZodArray>;\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasCommittedUnmergedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodString;\n }, z$1.core.$strip>>;\n workingTree: z$1.ZodObject<{\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasUncommittedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n state: z$1.ZodEnum<{\n clean: \"clean\";\n committed_unmerged: \"committed_unmerged\";\n dirty_and_committed_unmerged: \"dirty_and_committed_unmerged\";\n dirty_uncommitted: \"dirty_uncommitted\";\n untracked: \"untracked\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.diff\": HostDaemonCommandDescriptor<\"workspace.diff\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxDiffBytes: z$1.ZodNumber;\n maxFileListBytes: z$1.ZodNumber;\n maxUntrackedFiles: z$1.ZodNumber;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n type: z$1.ZodLiteral<\"workspace.diff\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n diff: z$1.ZodObject<{\n diff: z$1.ZodString;\n files: z$1.ZodString;\n mergeBaseRef: z$1.ZodNullable;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n outcome: z$1.ZodLiteral<\"available\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.diffFiles\": HostDaemonCommandDescriptor<\"workspace.diffFiles\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxFiles: z$1.ZodNumber;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n type: z$1.ZodLiteral<\"workspace.diffFiles\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n files: z$1.ZodArray;\n path: z$1.ZodString;\n previousPath: z$1.ZodNullable;\n statusLetter: z$1.ZodEnum<{\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n T: \"T\";\n }>;\n }, z$1.core.$strip>>;\n mergeBaseRef: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"available\">;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.diffPatch\": HostDaemonCommandDescriptor<\"workspace.diffPatch\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxBytesPerFile: z$1.ZodNumber;\n paths: z$1.ZodArray;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n type: z$1.ZodLiteral<\"workspace.diffPatch\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n patches: z$1.ZodArray>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.pull_request\": HostDaemonCommandDescriptor<\"workspace.pull_request\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"workspace.pull_request\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n pullRequest: z$1.ZodObject<{\n baseRefName: z$1.ZodString;\n checks: z$1.ZodArray>;\n name: z$1.ZodString;\n startedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n in_progress: \"in_progress\";\n queued: \"queued\";\n unknown: \"unknown\";\n }>;\n url: z$1.ZodNullable;\n }, z$1.core.$strict>>;\n headRefName: z$1.ZodString;\n isDraft: z$1.ZodBoolean;\n mergeStateStatus: z$1.ZodNullable>;\n mergeable: z$1.ZodNullable>;\n number: z$1.ZodNumber;\n reviewDecision: z$1.ZodNullable>;\n reviewRequestCount: z$1.ZodNumber;\n state: z$1.ZodEnum<{\n CLOSED: \"CLOSED\";\n MERGED: \"MERGED\";\n OPEN: \"OPEN\";\n }>;\n title: z$1.ZodString;\n updatedAt: z$1.ZodString;\n url: z$1.ZodString;\n }, z$1.core.$strict>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"absent\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n};\ntype HostDaemonCommandRegistry = typeof hostDaemonCommandRegistry;\ntype AnyHostDaemonCommandDescriptor = HostDaemonCommandRegistry[keyof HostDaemonCommandRegistry];\ntype HostDaemonCommandDescriptorForTransport = Extract;\ntype HostDaemonResultSchemaMapForTransport = {\n [Descriptor in HostDaemonCommandDescriptorForTransport as Descriptor[\"type\"]]: Descriptor[\"resultSchema\"];\n};\ntype HostDaemonOnlineRpcResultSchemaMap = HostDaemonResultSchemaMapForTransport<\"onlineRpc\">;\ntype HostDaemonOnlineRpcResultByType = {\n [K in keyof HostDaemonOnlineRpcResultSchemaMap]: z$1.infer;\n};\n\ndeclare const pickFolderResponseSchema: z$1.ZodObject<{\n path: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype PickFolderResponse = z$1.infer;\ndeclare const pathsExistRequestSchema: z$1.ZodObject<{\n paths: z$1.ZodPipe, z$1.ZodTransform>;\n}, z$1.core.$strip>;\ntype PathsExistRequest = z$1.infer;\ndeclare const pathsExistResponseSchema: z$1.ZodObject<{\n existence: z$1.ZodRecord;\n}, z$1.core.$strip>;\ntype PathsExistResponse = z$1.infer;\ndeclare const providerCliStatusResponseSchema: z$1.ZodRecord, z$1.ZodObject<{\n currentVersion: z$1.ZodNullable;\n displayName: z$1.ZodString;\n executableName: z$1.ZodString;\n executablePath: z$1.ZodNullable;\n installAction: z$1.ZodNullable;\n kind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n label: z$1.ZodEnum<{\n Install: \"Install\";\n Update: \"Update\";\n }>;\n }, z$1.core.$strip>>;\n installSource: z$1.ZodEnum<{\n external: \"external\";\n notInstalled: \"notInstalled\";\n npmGlobal: \"npmGlobal\";\n }>;\n installed: z$1.ZodBoolean;\n latestVersion: z$1.ZodNullable;\n minimumSupportedVersion: z$1.ZodNullable;\n needsUpdate: z$1.ZodBoolean;\n npmGlobalPackageVersion: z$1.ZodNullable;\n npmPackageName: z$1.ZodNullable;\n versionUnsupported: z$1.ZodBoolean;\n}, z$1.core.$strip>>;\ntype ProviderCliStatusResponse = z$1.infer;\ndeclare const providerCliInstallRequestSchema: z$1.ZodObject<{\n actionKind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n}, z$1.core.$strip>;\ntype ProviderCliInstallRequest = z$1.infer;\ndeclare const providerCliInstallEventSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n command: z$1.ZodString;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n stream: z$1.ZodEnum<{\n stderr: \"stderr\";\n stdout: \"stdout\";\n }>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"output\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n exitCode: z$1.ZodNullable;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n signal: z$1.ZodNullable;\n success: z$1.ZodBoolean;\n type: z$1.ZodLiteral<\"completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"error\">;\n}, z$1.core.$strip>], \"type\">;\ntype ProviderCliInstallEvent = z$1.infer;\n\ninterface CreateFilePreviewResponse {\n baseUrl: string;\n expiresAtMs: number;\n}\ntype HostFileReadResponse = HostDaemonOnlineRpcResultByType[\"host.read_file\"];\ntype HostFileWriteResponse = HostDaemonOnlineRpcResultByType[\"host.write_file\"];\ntype HostFileListResponse = HostDaemonOnlineRpcResultByType[\"host.list_files\"];\ntype HostPathListResponse = HostDaemonOnlineRpcResultByType[\"host.list_paths\"];\ntype HostMkdirResponse = HostDaemonOnlineRpcResultByType[\"host.mkdir\"];\ntype HostMovePathResponse = HostDaemonOnlineRpcResultByType[\"host.move_path\"];\ntype HostRemovePathResponse = HostDaemonOnlineRpcResultByType[\"host.remove_path\"];\n\n/**\n * Query for `GET /hosts/:id/directory`, the interactive path browser's\n * single-level directory read. `path` is an absolute directory on the host;\n * omitting it lists the host's home directory (the daemon resolves it, since a\n * remote caller cannot know the host's home).\n */\ndeclare const hostDirectoryQuerySchema: z$1.ZodObject<{\n path: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype HostDirectoryQuery = z$1.infer;\ndeclare const hostDirectoryListingSchema: z$1.ZodObject<{\n directory: z$1.ZodString;\n entries: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n parent: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype HostDirectoryListing = z$1.infer;\n/** Project name is sent so the daemon can derive its host-local checkout path. */\ndeclare const hostCloneDefaultPathQuerySchema: z$1.ZodObject<{\n projectId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype HostCloneDefaultPathQuery = z$1.infer;\ndeclare const hostCloneDefaultPathResponseSchema: z$1.ZodObject<{\n path: z$1.ZodString;\n}, z$1.core.$strict>;\ntype HostCloneDefaultPathResponse = z$1.infer;\ndeclare const createHostJoinCodeResponseSchema: z$1.ZodObject<{\n expiresAt: z$1.ZodNumber;\n hostId: z$1.ZodString;\n joinCode: z$1.ZodString;\n}, z$1.core.$strip>;\ntype CreateHostJoinCodeResponse = z$1.infer;\ndeclare const updateHostRequestSchema: z$1.ZodObject<{\n name: z$1.ZodString;\n}, z$1.core.$strict>;\ntype UpdateHostRequest = z$1.infer;\ndeclare const hostRetryUpdateResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n}, z$1.core.$strict>;\ntype HostRetryUpdateResponse = z$1.infer;\ntype HostPathsExistRequest = PathsExistRequest;\ntype HostPathsExistResponse = PathsExistResponse;\ndeclare const hostPickFolderRequestSchema: z$1.ZodObject<{\n clientHostId: z$1.ZodString;\n}, z$1.core.$strict>;\ntype HostPickFolderRequest = z$1.infer;\ntype HostPickFolderResponse = PickFolderResponse;\ntype HostProviderCliStatusResponse = ProviderCliStatusResponse;\ntype HostProviderCliInstallRequest = ProviderCliInstallRequest;\ntype HostProviderCliInstallEvent = ProviderCliInstallEvent;\n\ndeclare const pluginUpdateCheckEntrySchema: z$1.ZodObject<{\n blocked: z$1.ZodOptional;\n version: z$1.ZodString;\n }, z$1.core.$strip>>;\n candidate: z$1.ZodOptional>;\n detail: z$1.ZodOptional;\n devMode: z$1.ZodOptional>;\n id: z$1.ZodString;\n installed: z$1.ZodObject<{\n display: z$1.ZodString;\n version: z$1.ZodString;\n }, z$1.core.$strip>;\n outcome: z$1.ZodEnum<{\n \"update-available\": \"update-available\";\n current: \"current\";\n incompatible: \"incompatible\";\n pinned: \"pinned\";\n unavailable: \"unavailable\";\n }>;\n}, z$1.core.$strip>;\ntype PluginUpdateCheckEntry = z$1.infer;\ndeclare const pluginApplyUpdateResultSchema: z$1.ZodObject<{\n applied: z$1.ZodBoolean;\n detail: z$1.ZodOptional;\n from: z$1.ZodObject<{\n display: z$1.ZodString;\n version: z$1.ZodString;\n }, z$1.core.$strip>;\n outcome: z$1.ZodEnum<{\n \"rolled-back\": \"rolled-back\";\n current: \"current\";\n updated: \"updated\";\n }>;\n to: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype PluginApplyUpdateResult$1 = z$1.infer;\ndeclare const pluginSourceDetailSchema: z$1.ZodObject<{\n engines: z$1.ZodObject<{\n bb: z$1.ZodOptional;\n bbPluginSdk: z$1.ZodOptional;\n }, z$1.core.$strip>;\n history: z$1.ZodArray>;\n installedAt: z$1.ZodOptional;\n integrity: z$1.ZodOptional;\n range: z$1.ZodOptional;\n registry: z$1.ZodOptional;\n requested: z$1.ZodString;\n resolved: z$1.ZodString;\n resolvedTag: z$1.ZodOptional;\n subdirectory: z$1.ZodOptional;\n tagPrefix: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype PluginSourceDetail = z$1.infer;\ndeclare const installedPluginSchema: z$1.ZodObject<{\n app: z$1.ZodObject<{\n bundle: z$1.ZodNullable;\n hash: z$1.ZodString;\n jsBytes: z$1.ZodNumber;\n jsUrl: z$1.ZodString;\n sdkMajor: z$1.ZodNumber;\n sdkVersion: z$1.ZodString;\n }, z$1.core.$strip>>;\n hasApp: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n capabilities: z$1.ZodDefault;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n \"agent-tool\": \"agent-tool\";\n \"thread-integration\": \"thread-integration\";\n skill: \"skill\";\n theme: \"theme\";\n }>;\n label: z$1.ZodString;\n }, z$1.core.$strip>>>;\n catalogEntryId: z$1.ZodOptional;\n catalogMarketplaceName: z$1.ZodOptional;\n cliCommand: z$1.ZodNullable>;\n description: z$1.ZodNullable;\n enabled: z$1.ZodBoolean;\n handlerStats: z$1.ZodObject<{\n count: z$1.ZodNumber;\n errorCount: z$1.ZodNumber;\n maxMs: z$1.ZodNumber;\n totalMs: z$1.ZodNumber;\n }, z$1.core.$strip>;\n hasSettings: z$1.ZodBoolean;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n isOrphanedBuiltin: z$1.ZodBoolean;\n logoDarkUrl: z$1.ZodNullable;\n logoUrl: z$1.ZodNullable;\n name: z$1.ZodNullable;\n provenance: z$1.ZodEnum<{\n builtin: \"builtin\";\n catalog: \"catalog\";\n direct: \"direct\";\n }>;\n publisherLabel: z$1.ZodDefault>;\n rootDir: z$1.ZodString;\n schedules: z$1.ZodArray;\n lastRunAt: z$1.ZodNullable;\n lastStatus: z$1.ZodNullable>;\n name: z$1.ZodString;\n nextRunAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n services: z$1.ZodArray;\n }, z$1.core.$strip>>;\n source: z$1.ZodString;\n sourceDisplay: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"needs-configuration\": \"needs-configuration\";\n degraded: \"degraded\";\n disabled: \"disabled\";\n error: \"error\";\n incompatible: \"incompatible\";\n missing: \"missing\";\n running: \"running\";\n }>;\n statusDetail: z$1.ZodNullable;\n updateState: z$1.ZodObject<{\n availableVersion: z$1.ZodOptional;\n blockedReasons: z$1.ZodOptional>;\n blockedVersion: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n lastCheckAt: z$1.ZodOptional;\n lastFailure: z$1.ZodOptional>;\n outcome: z$1.ZodOptional>;\n }, z$1.core.$strip>;\n version: z$1.ZodString;\n}, z$1.core.$strip>;\ntype InstalledPlugin = z$1.infer;\ndeclare const pluginListResponseSchema: z$1.ZodObject<{\n plugins: z$1.ZodArray;\n hash: z$1.ZodString;\n jsBytes: z$1.ZodNumber;\n jsUrl: z$1.ZodString;\n sdkMajor: z$1.ZodNumber;\n sdkVersion: z$1.ZodString;\n }, z$1.core.$strip>>;\n hasApp: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n capabilities: z$1.ZodDefault;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n \"agent-tool\": \"agent-tool\";\n \"thread-integration\": \"thread-integration\";\n skill: \"skill\";\n theme: \"theme\";\n }>;\n label: z$1.ZodString;\n }, z$1.core.$strip>>>;\n catalogEntryId: z$1.ZodOptional;\n catalogMarketplaceName: z$1.ZodOptional;\n cliCommand: z$1.ZodNullable>;\n description: z$1.ZodNullable;\n enabled: z$1.ZodBoolean;\n handlerStats: z$1.ZodObject<{\n count: z$1.ZodNumber;\n errorCount: z$1.ZodNumber;\n maxMs: z$1.ZodNumber;\n totalMs: z$1.ZodNumber;\n }, z$1.core.$strip>;\n hasSettings: z$1.ZodBoolean;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n isOrphanedBuiltin: z$1.ZodBoolean;\n logoDarkUrl: z$1.ZodNullable;\n logoUrl: z$1.ZodNullable;\n name: z$1.ZodNullable;\n provenance: z$1.ZodEnum<{\n builtin: \"builtin\";\n catalog: \"catalog\";\n direct: \"direct\";\n }>;\n publisherLabel: z$1.ZodDefault>;\n rootDir: z$1.ZodString;\n schedules: z$1.ZodArray;\n lastRunAt: z$1.ZodNullable;\n lastStatus: z$1.ZodNullable>;\n name: z$1.ZodString;\n nextRunAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n services: z$1.ZodArray;\n }, z$1.core.$strip>>;\n source: z$1.ZodString;\n sourceDisplay: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"needs-configuration\": \"needs-configuration\";\n degraded: \"degraded\";\n disabled: \"disabled\";\n error: \"error\";\n incompatible: \"incompatible\";\n missing: \"missing\";\n running: \"running\";\n }>;\n statusDetail: z$1.ZodNullable;\n updateState: z$1.ZodObject<{\n availableVersion: z$1.ZodOptional;\n blockedReasons: z$1.ZodOptional>;\n blockedVersion: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n lastCheckAt: z$1.ZodOptional;\n lastFailure: z$1.ZodOptional>;\n outcome: z$1.ZodOptional>;\n }, z$1.core.$strip>;\n version: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype PluginListResponse = z$1.infer;\ndeclare const pluginReloadResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n plugins: z$1.ZodArray;\n hash: z$1.ZodString;\n jsBytes: z$1.ZodNumber;\n jsUrl: z$1.ZodString;\n sdkMajor: z$1.ZodNumber;\n sdkVersion: z$1.ZodString;\n }, z$1.core.$strip>>;\n hasApp: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n capabilities: z$1.ZodDefault;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n \"agent-tool\": \"agent-tool\";\n \"thread-integration\": \"thread-integration\";\n skill: \"skill\";\n theme: \"theme\";\n }>;\n label: z$1.ZodString;\n }, z$1.core.$strip>>>;\n catalogEntryId: z$1.ZodOptional;\n catalogMarketplaceName: z$1.ZodOptional;\n cliCommand: z$1.ZodNullable>;\n description: z$1.ZodNullable;\n enabled: z$1.ZodBoolean;\n handlerStats: z$1.ZodObject<{\n count: z$1.ZodNumber;\n errorCount: z$1.ZodNumber;\n maxMs: z$1.ZodNumber;\n totalMs: z$1.ZodNumber;\n }, z$1.core.$strip>;\n hasSettings: z$1.ZodBoolean;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n isOrphanedBuiltin: z$1.ZodBoolean;\n logoDarkUrl: z$1.ZodNullable;\n logoUrl: z$1.ZodNullable;\n name: z$1.ZodNullable;\n provenance: z$1.ZodEnum<{\n builtin: \"builtin\";\n catalog: \"catalog\";\n direct: \"direct\";\n }>;\n publisherLabel: z$1.ZodDefault>;\n rootDir: z$1.ZodString;\n schedules: z$1.ZodArray;\n lastRunAt: z$1.ZodNullable;\n lastStatus: z$1.ZodNullable>;\n name: z$1.ZodString;\n nextRunAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n services: z$1.ZodArray;\n }, z$1.core.$strip>>;\n source: z$1.ZodString;\n sourceDisplay: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"needs-configuration\": \"needs-configuration\";\n degraded: \"degraded\";\n disabled: \"disabled\";\n error: \"error\";\n incompatible: \"incompatible\";\n missing: \"missing\";\n running: \"running\";\n }>;\n statusDetail: z$1.ZodNullable;\n updateState: z$1.ZodObject<{\n availableVersion: z$1.ZodOptional;\n blockedReasons: z$1.ZodOptional>;\n blockedVersion: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n lastCheckAt: z$1.ZodOptional;\n lastFailure: z$1.ZodOptional>;\n outcome: z$1.ZodOptional>;\n }, z$1.core.$strip>;\n version: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype PluginReloadResponse = z$1.infer;\ndeclare const pluginRemoveResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PluginRemoveResponse = z$1.infer;\ndeclare const pluginSettingsResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n schema: z$1.ZodRecord;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n secret: z$1.ZodOptional>;\n type: z$1.ZodLiteral<\"string\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n default: z$1.ZodOptional;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n type: z$1.ZodLiteral<\"boolean\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n default: z$1.ZodOptional;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n options: z$1.ZodArray;\n type: z$1.ZodLiteral<\"select\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n default: z$1.ZodOptional;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n type: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>], \"type\">>;\n values: z$1.ZodRecord>>;\n}, z$1.core.$strip>;\ntype PluginSettingsResponse = z$1.infer;\ndeclare const pluginTokenResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n token: z$1.ZodString;\n}, z$1.core.$strip>;\ntype PluginTokenResponse = z$1.infer;\ndeclare const pluginCatalogStatusSchema: z$1.ZodObject<{\n includedPluginCount: z$1.ZodNumber;\n optionalPluginCount: z$1.ZodNumber;\n pluginCount: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype PluginCatalogStatus = z$1.infer;\ndeclare const pluginCatalogSearchResultSchema: z$1.ZodObject<{\n author: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n category: z$1.ZodString;\n compatible: z$1.ZodBoolean;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n entryId: z$1.ZodString;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n incompatibleReason: z$1.ZodNullable;\n installed: z$1.ZodBoolean;\n marketplace: z$1.ZodString;\n marketplaceDisplayName: z$1.ZodString;\n official: z$1.ZodBoolean;\n pluginId: z$1.ZodString;\n publisherKey: z$1.ZodString;\n publisherLabel: z$1.ZodString;\n source: z$1.ZodString;\n}, z$1.core.$strip>;\ntype PluginCatalogSearchResult$1 = z$1.infer;\n/**\n * The true source an install will run against, resolved before anything runs.\n * Both kinds report the exact artifact they resolve to right now — a commit\n * for git, a version and its integrity for npm — so a range or tag install is\n * confirmed against the exact code it will fetch.\n */\ndeclare const pluginCatalogResolvedSourceSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"npm\">;\n package: z$1.ZodString;\n range: z$1.ZodOptional;\n registry: z$1.ZodOptional;\n resolvedIntegrity: z$1.ZodOptional;\n resolvedVersion: z$1.ZodOptional;\n tag: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n}, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"git\">;\n range: z$1.ZodOptional;\n ref: z$1.ZodOptional;\n resolvedCommit: z$1.ZodOptional;\n resolvedTag: z$1.ZodOptional;\n subdir: z$1.ZodOptional;\n tagPrefix: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n url: z$1.ZodString;\n}, z$1.core.$strict>], \"kind\">;\ntype PluginCatalogResolvedSource = z$1.infer;\n/**\n * What `POST /plugin-catalog/install` would do with the same arguments, shown\n * to the user before anything runs. `bundled` entries install from the copy\n * inside the app; `marketplace` entries install from their listed source.\n */\ndeclare const pluginCatalogInstallPlanSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n compatible: z$1.ZodBoolean;\n displayName: z$1.ZodString;\n entryId: z$1.ZodString;\n incompatibleReason: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"bundled\">;\n pluginId: z$1.ZodString;\n source: z$1.ZodString;\n}, z$1.core.$strip>, z$1.ZodObject<{\n author: z$1.ZodObject<{\n name: z$1.ZodString;\n url: z$1.ZodNullable;\n }, z$1.core.$strip>;\n compatible: z$1.ZodBoolean;\n displayName: z$1.ZodString;\n entryId: z$1.ZodString;\n incompatibleReason: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"marketplace\">;\n marketplace: z$1.ZodString;\n marketplaceDisplayName: z$1.ZodString;\n official: z$1.ZodBoolean;\n pluginId: z$1.ZodString;\n resolvedSource: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"npm\">;\n package: z$1.ZodString;\n range: z$1.ZodOptional;\n registry: z$1.ZodOptional;\n resolvedIntegrity: z$1.ZodOptional;\n resolvedVersion: z$1.ZodOptional;\n tag: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"git\">;\n range: z$1.ZodOptional;\n ref: z$1.ZodOptional;\n resolvedCommit: z$1.ZodOptional;\n resolvedTag: z$1.ZodOptional;\n subdir: z$1.ZodOptional;\n tagPrefix: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n url: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n source: z$1.ZodString;\n}, z$1.core.$strip>], \"kind\">;\ntype PluginCatalogInstallPlan = z$1.infer;\ndeclare const pluginMarketplaceSchema: z$1.ZodObject<{\n description: z$1.ZodNullable;\n displayName: z$1.ZodString;\n entryCount: z$1.ZodNumber;\n lastAttemptAt: z$1.ZodNullable;\n lastError: z$1.ZodNullable;\n lastRefreshAt: z$1.ZodNullable;\n name: z$1.ZodString;\n official: z$1.ZodBoolean;\n resolvedCommit: z$1.ZodNullable;\n source: z$1.ZodString;\n sourceKind: z$1.ZodEnum<{\n git: \"git\";\n https: \"https\";\n path: \"path\";\n }>;\n}, z$1.core.$strip>;\ntype PluginMarketplace = z$1.infer;\ndeclare const pluginMarketplaceRefreshResultSchema: z$1.ZodObject<{\n error: z$1.ZodNullable;\n marketplace: z$1.ZodObject<{\n description: z$1.ZodNullable;\n displayName: z$1.ZodString;\n entryCount: z$1.ZodNumber;\n lastAttemptAt: z$1.ZodNullable;\n lastError: z$1.ZodNullable;\n lastRefreshAt: z$1.ZodNullable;\n name: z$1.ZodString;\n official: z$1.ZodBoolean;\n resolvedCommit: z$1.ZodNullable;\n source: z$1.ZodString;\n sourceKind: z$1.ZodEnum<{\n git: \"git\";\n https: \"https\";\n path: \"path\";\n }>;\n }, z$1.core.$strip>;\n name: z$1.ZodString;\n ok: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype PluginMarketplaceRefreshResult$1 = z$1.infer;\n\ndeclare const systemExecutionOptionsResponseSchema: z$1.ZodObject<{\n modelLoadError: z$1.ZodNullable;\n providerId: z$1.ZodString;\n }, z$1.core.$strip>>;\n models: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n permissionCeiling: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n providers: z$1.ZodArray>;\n supportsFork: z$1.ZodBoolean;\n supportsNativeUserQuestion: z$1.ZodBoolean;\n supportsServiceTier: z$1.ZodBoolean;\n supportsSessionRewind: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n composerActions: z$1.ZodArray;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"goal\">;\n }, z$1.core.$strip>], \"kind\">>;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n logoUrl: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n selectedOnlyModels: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype SystemExecutionOptionsResponse = z$1.infer;\n/**\n * Routes provider discovery through an environment's host or an explicit\n * host. Omitting both preserves the primary-host fallback.\n */\ndeclare const systemProvidersQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional;\n hostId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemProvidersQuery = z$1.infer;\ndeclare const systemExecutionOptionsQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional;\n hostId: z$1.ZodOptional;\n providerId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemExecutionOptionsQuery = z$1.infer;\n/** Omission preserves the existing behavior of reading the primary machine. */\ndeclare const systemUsageLimitsQuerySchema: z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemUsageLimitsQuery = z$1.infer;\ndeclare const systemVoiceTranscriptionResponseSchema: z$1.ZodObject<{\n text: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SystemVoiceTranscriptionResponse = z$1.infer;\ndeclare const onboardingAgentOverviewSchema: z$1.ZodObject<{\n agents: z$1.ZodArray;\n canInstall: z$1.ZodBoolean;\n displayName: z$1.ZodString;\n loginCommand: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n providerId: z$1.ZodString;\n status: z$1.ZodEnum<{\n connected: \"connected\";\n expired: \"expired\";\n not_installed: \"not_installed\";\n unauthenticated: \"unauthenticated\";\n }>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype OnboardingAgentOverview = z$1.infer;\n/** Omission reads the primary machine, matching the usage-limits route. */\ndeclare const systemOnboardingReposQuerySchema: z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemOnboardingReposQuery = z$1.infer;\n/**\n * Onboarding funnel events, reported by the app and forwarded to the server's\n * anonymous telemetry. Categorical or counts only — never paths, project names,\n * or account emails.\n */\ndeclare const onboardingTelemetryEventSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n agentState: z$1.ZodEnum<{\n connected: \"connected\";\n none: \"none\";\n signed_out: \"signed_out\";\n }>;\n detectedAgentCount: z$1.ZodNumber;\n name: z$1.ZodLiteral<\"onboarding_started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n name: z$1.ZodLiteral<\"onboarding_step_completed\">;\n step: z$1.ZodEnum<{\n agents: \"agents\";\n projects: \"projects\";\n }>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n name: z$1.ZodLiteral<\"onboarding_step_skipped\">;\n step: z$1.ZodEnum<{\n agents: \"agents\";\n projects: \"projects\";\n }>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n agentState: z$1.ZodEnum<{\n connected: \"connected\";\n none: \"none\";\n signed_out: \"signed_out\";\n }>;\n durationMs: z$1.ZodNumber;\n name: z$1.ZodLiteral<\"onboarding_completed\">;\n projectsAdded: z$1.ZodNumber;\n}, z$1.core.$strip>, z$1.ZodObject<{\n name: z$1.ZodLiteral<\"onboarding_dismissed\">;\n step: z$1.ZodEnum<{\n agents: \"agents\";\n projects: \"projects\";\n }>;\n}, z$1.core.$strip>], \"name\">;\ntype OnboardingTelemetryEvent = z$1.infer;\ndeclare const systemConfigResponseSchema: z$1.ZodObject<{\n appearance: z$1.ZodObject<{\n customCss: z$1.ZodNullable;\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n resolvedCodeTheme: z$1.ZodDefault>>;\n light: z$1.ZodString;\n }, z$1.core.$strict>>;\n themeId: z$1.ZodString;\n }, z$1.core.$strip>;\n customThemes: z$1.ZodArray;\n dataDir: z$1.ZodString;\n defaultKeybindings: z$1.ZodArray;\n desktopOnly: z$1.ZodBoolean;\n shortcut: z$1.ZodNullable>;\n when: z$1.ZodObject<{\n all: z$1.ZodArray>;\n none: z$1.ZodArray>;\n }, z$1.core.$strict>;\n }, z$1.core.$strict>>;\n experiments: z$1.ZodRecord, z$1.ZodBoolean>;\n featureFlags: z$1.ZodObject<{\n placeholder: z$1.ZodBoolean;\n timelineWindowEventBudget: z$1.ZodNumber;\n }, z$1.core.$strip>;\n generalSettings: z$1.ZodObject<{\n claudeCodeMemoryEnabled: z$1.ZodBoolean;\n claudeCodeSubagentsDisabled: z$1.ZodBoolean;\n claudeCodeWorkflowsDisabled: z$1.ZodBoolean;\n codexMemoryEnabled: z$1.ZodBoolean;\n codexSubagentsDisabled: z$1.ZodBoolean;\n onboardingCompletedAt: z$1.ZodNullable;\n showKeyboardHints: z$1.ZodBoolean;\n showUnhandledProviderEvents: z$1.ZodBoolean;\n steerActiveThreadOnEnter: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n hostDaemonPort: z$1.ZodNullable;\n keybindingOverrides: z$1.ZodArray;\n shortcut: z$1.ZodNullable>;\n }, z$1.core.$strict>>;\n keybindings: z$1.ZodArray;\n desktopOnly: z$1.ZodBoolean;\n shortcut: z$1.ZodObject<{\n alt: z$1.ZodBoolean;\n control: z$1.ZodBoolean;\n key: z$1.ZodString;\n meta: z$1.ZodBoolean;\n mod: z$1.ZodBoolean;\n shift: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n when: z$1.ZodObject<{\n all: z$1.ZodArray>;\n none: z$1.ZodArray>;\n }, z$1.core.$strict>;\n }, z$1.core.$strict>>;\n pluginThemes: z$1.ZodArray;\n id: z$1.ZodString;\n name: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>>;\n primaryHostId: z$1.ZodNullable;\n primaryHostPlatform: z$1.ZodNullable>;\n serverUrl: z$1.ZodString;\n voiceTranscriptionEnabled: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype SystemConfigResponse = z$1.infer;\ndeclare const systemAttentionResponseSchema: z$1.ZodObject<{\n hasAttention: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype SystemAttentionResponse = z$1.infer;\n/**\n * Theme catalog: the on-disk custom-theme directory plus the discovered custom\n * themes and the active palette. Drives `bb theme list` / `bb theme dir`.\n */\ndeclare const themeCatalogResponseSchema: z$1.ZodObject<{\n active: z$1.ZodObject<{\n customCss: z$1.ZodNullable;\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n resolvedCodeTheme: z$1.ZodDefault>>;\n light: z$1.ZodString;\n }, z$1.core.$strict>>;\n themeId: z$1.ZodString;\n }, z$1.core.$strip>;\n custom: z$1.ZodArray;\n dir: z$1.ZodString;\n plugins: z$1.ZodArray;\n id: z$1.ZodString;\n name: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype ThemeCatalogResponse = z$1.infer;\ndeclare const systemVersionResponseSchema: z$1.ZodObject<{\n currentVersion: z$1.ZodString;\n isDevelopment: z$1.ZodBoolean;\n latestVersion: z$1.ZodNullable;\n source: z$1.ZodLiteral<\"npm\">;\n updateAvailable: z$1.ZodBoolean;\n upgradeCommand: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SystemVersionResponse = z$1.infer;\ndeclare const systemConfigReloadResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ndeclare const systemCliSkillsStatusResponseSchema: z$1.ZodObject<{\n machines: z$1.ZodArray;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype SystemCliSkillsStatusResponse = z$1.infer;\n/** The machines to copy the built-in bb CLI skills onto. */\ndeclare const systemInstallCliSkillsRequestSchema: z$1.ZodObject<{\n hostIds: z$1.ZodArray;\n}, z$1.core.$strip>;\ntype SystemInstallCliSkillsRequest = z$1.infer;\n/**\n * One entry per requested machine. A machine that is offline or otherwise\n * refuses the install fails on its own without taking the others down, so the\n * caller can report exactly which machines got the skills.\n */\ndeclare const systemInstallCliSkillsResponseSchema: z$1.ZodObject<{\n results: z$1.ZodArray>;\n ok: z$1.ZodLiteral;\n }, z$1.core.$strip>, z$1.ZodObject<{\n errorMessage: z$1.ZodString;\n hostId: z$1.ZodString;\n hostName: z$1.ZodString;\n ok: z$1.ZodLiteral;\n }, z$1.core.$strip>], \"ok\">>;\n}, z$1.core.$strip>;\ntype SystemInstallCliSkillsResponse = z$1.infer;\ntype SystemConfigReloadResponse = z$1.infer;\n\ndeclare const terminalSessionSchema: z$1.ZodObject<{\n closeReason: z$1.ZodNullable>;\n cols: z$1.ZodNumber;\n createdAt: z$1.ZodNumber;\n environmentId: z$1.ZodNullable;\n exitCode: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n initialCwd: z$1.ZodString;\n lastUserInputAt: z$1.ZodNullable;\n rows: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n disconnected: \"disconnected\";\n exited: \"exited\";\n running: \"running\";\n starting: \"starting\";\n }>;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype TerminalSession = z$1.infer;\ndeclare const terminalListResponseSchema: z$1.ZodObject<{\n sessions: z$1.ZodArray>;\n cols: z$1.ZodNumber;\n createdAt: z$1.ZodNumber;\n environmentId: z$1.ZodNullable;\n exitCode: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n initialCwd: z$1.ZodString;\n lastUserInputAt: z$1.ZodNullable;\n rows: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n disconnected: \"disconnected\";\n exited: \"exited\";\n running: \"running\";\n starting: \"starting\";\n }>;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype TerminalListResponse = z$1.infer;\ndeclare const createTerminalRequestSchema: z$1.ZodObject<{\n cols: z$1.ZodNumber;\n rows: z$1.ZodNumber;\n start: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodObject<{\n command: z$1.ZodString;\n mode: z$1.ZodLiteral<\"command\">;\n }, z$1.core.$strict>], \"mode\">>;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"environment\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n hostId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host_path\">;\n }, z$1.core.$strict>], \"kind\">;\n title: z$1.ZodOptional;\n}, z$1.core.$strict>;\ntype CreateTerminalRequest = z$1.infer;\ndeclare const updateTerminalRequestSchema: z$1.ZodObject<{\n title: z$1.ZodString;\n}, z$1.core.$strict>;\ntype UpdateTerminalRequest = z$1.infer;\ndeclare const terminalInputRequestSchema: z$1.ZodObject<{\n dataBase64: z$1.ZodString;\n}, z$1.core.$strict>;\ntype TerminalInputRequest = z$1.infer;\ndeclare const terminalResizeRequestSchema: z$1.ZodObject<{\n cols: z$1.ZodNumber;\n rows: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype TerminalResizeRequest = z$1.infer;\ndeclare const terminalOutputQuerySchema: z$1.ZodObject<{\n limitChunks: z$1.ZodOptional>;\n sinceSeq: z$1.ZodOptional>;\n tailBytes: z$1.ZodOptional>;\n}, z$1.core.$strict>;\ntype TerminalOutputQuery = z$1.infer;\ndeclare const terminalOutputResponseSchema: z$1.ZodObject<{\n chunks: z$1.ZodArray>;\n nextSeq: z$1.ZodNumber;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strict>;\ntype TerminalOutputResponse = z$1.infer;\n\ndeclare const timelineRowStatusSchema: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n}>;\ntype TimelineRowStatus = z$1.infer;\ndeclare const timelineRowBaseSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype TimelineRowBase = z$1.infer;\ndeclare const timelineConversationRowSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n attachments: z$1.ZodNullable;\n localFilePaths: z$1.ZodArray;\n localFiles: z$1.ZodNumber;\n localImagePaths: z$1.ZodArray;\n localImages: z$1.ZodNumber;\n webImages: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n kind: z$1.ZodLiteral<\"conversation\">;\n mentions: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n role: z$1.ZodLiteral<\"user\">;\n senderThreadId: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n systemMessageKind: z$1.ZodEnum<{\n \"child-completed\": \"child-completed\";\n \"child-failed\": \"child-failed\";\n \"child-interrupted\": \"child-interrupted\";\n \"child-needs-attention\": \"child-needs-attention\";\n \"child-outcome-batch\": \"child-outcome-batch\";\n \"ownership-assigned\": \"ownership-assigned\";\n \"ownership-removed\": \"ownership-removed\";\n unlabeled: \"unlabeled\";\n }>;\n systemMessageSubject: z$1.ZodNullable;\n threadId: z$1.ZodString;\n threadName: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n count: z$1.ZodNumber;\n kind: z$1.ZodLiteral<\"thread-batch\">;\n }, z$1.core.$strip>], \"kind\">>;\n text: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n turnRequest: z$1.ZodObject<{\n isGrouped: z$1.ZodBoolean;\n kind: z$1.ZodEnum<{\n message: \"message\";\n steer: \"steer\";\n }>;\n status: z$1.ZodEnum<{\n accepted: \"accepted\";\n pending: \"pending\";\n rejected: \"rejected\";\n }>;\n }, z$1.core.$strip>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n attachments: z$1.ZodNullable;\n localFilePaths: z$1.ZodArray;\n localFiles: z$1.ZodNumber;\n localImagePaths: z$1.ZodArray;\n localImages: z$1.ZodNumber;\n webImages: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"conversation\">;\n role: z$1.ZodLiteral<\"assistant\">;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n text: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n turnRequest: z$1.ZodNull;\n}, z$1.core.$strip>], \"role\">;\ntype TimelineConversationRow = z$1.infer;\ndeclare const timelineSystemRowSchema: z$1.ZodUnion;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"system\">;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodNullable>;\n systemKind: z$1.ZodEnum<{\n debug: \"debug\";\n error: \"error\";\n reconnect: \"reconnect\";\n }>;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n detail: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"system\">;\n operationKind: z$1.ZodEnum<{\n \"context-clear\": \"context-clear\";\n \"provider-unhandled\": \"provider-unhandled\";\n \"thread-interrupted\": \"thread-interrupted\";\n \"thread-provisioning\": \"thread-provisioning\";\n compaction: \"compaction\";\n deprecation: \"deprecation\";\n generic: \"generic\";\n warning: \"warning\";\n }>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodNullable>;\n systemKind: z$1.ZodLiteral<\"operation\">;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>, z$1.ZodObject<{\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n detail: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"system\">;\n operationKind: z$1.ZodLiteral<\"parent-change\">;\n parentChange: z$1.ZodObject<{\n action: z$1.ZodEnum<{\n assign: \"assign\";\n release: \"release\";\n transfer: \"transfer\";\n }>;\n nextParentThreadId: z$1.ZodNullable;\n nextParentThreadTitle: z$1.ZodNullable;\n previousParentThreadId: z$1.ZodNullable;\n previousParentThreadTitle: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n systemKind: z$1.ZodLiteral<\"operation\">;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>], \"operationKind\">]>;\ntype TimelineSystemRow = z$1.infer;\ninterface TimelineWorkRowBase extends TimelineRowBase {\n kind: \"work\";\n status: TimelineRowStatus;\n}\ndeclare const timelineCommandWorkRowSchema: z$1.ZodObject<{\n activityIntents: z$1.ZodArray;\n type: z$1.ZodLiteral<\"read\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"list_files\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n approvalStatus: z$1.ZodNullable>;\n callId: z$1.ZodString;\n command: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n cwd: z$1.ZodNullable;\n exitCode: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n output: z$1.ZodString;\n outputPreview: z$1.ZodOptional>;\n source: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"command\">;\n}, z$1.core.$strip>;\ntype TimelineCommandWorkRow = z$1.infer;\ndeclare const timelineToolWorkRowSchema: z$1.ZodObject<{\n activityIntents: z$1.ZodArray;\n type: z$1.ZodLiteral<\"read\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"list_files\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n approvalStatus: z$1.ZodNullable>;\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n output: z$1.ZodString;\n outputPreview: z$1.ZodOptional>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusLabels: z$1.ZodOptional>;\n threadId: z$1.ZodString;\n toolArgs: z$1.ZodNullable>>>;\n toolName: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"tool\">;\n}, z$1.core.$strip>;\ntype TimelineToolWorkRow = z$1.infer;\ndeclare const timelineFileChangeWorkRowSchema: z$1.ZodObject<{\n approvalStatus: z$1.ZodNullable>;\n callId: z$1.ZodString;\n change: z$1.ZodObject<{\n diff: z$1.ZodNullable;\n diffStats: z$1.ZodObject<{\n added: z$1.ZodNumber;\n removed: z$1.ZodNumber;\n }, z$1.core.$strip>;\n kind: z$1.ZodNullable;\n movePath: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strip>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n stderr: z$1.ZodNullable;\n stdout: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"file-change\">;\n}, z$1.core.$strip>;\ntype TimelineFileChangeWorkRow = z$1.infer;\ndeclare const timelineWebSearchWorkRowSchema: z$1.ZodObject<{\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n queries: z$1.ZodArray;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"web-search\">;\n}, z$1.core.$strip>;\ntype TimelineWebSearchWorkRow = z$1.infer;\ndeclare const timelineWebFetchWorkRowSchema: z$1.ZodObject<{\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n pattern: z$1.ZodNullable;\n prompt: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n url: z$1.ZodString;\n workKind: z$1.ZodLiteral<\"web-fetch\">;\n}, z$1.core.$strip>;\ntype TimelineWebFetchWorkRow = z$1.infer;\ndeclare const timelineImageViewWorkRowSchema: z$1.ZodObject<{\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n path: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"image-view\">;\n}, z$1.core.$strip>;\ntype TimelineImageViewWorkRow = z$1.infer;\ndeclare const timelineApprovalWorkRowSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalKind: z$1.ZodLiteral<\"file-edit\">;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n interactionId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n lifecycle: z$1.ZodEnum<{\n denied: \"denied\";\n waiting: \"waiting\";\n }>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n target: z$1.ZodObject<{\n itemId: z$1.ZodString;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"approval\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n approvalKind: z$1.ZodLiteral<\"permission-grant\">;\n createdAt: z$1.ZodNumber;\n grantScope: z$1.ZodNullable>;\n id: z$1.ZodString;\n interactionId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n lifecycle: z$1.ZodEnum<{\n denied: \"denied\";\n granted: \"granted\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolving: \"resolving\";\n }>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusReason: z$1.ZodNullable;\n target: z$1.ZodObject<{\n itemId: z$1.ZodString;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"approval\">;\n}, z$1.core.$strip>], \"approvalKind\">;\ntype TimelineApprovalWorkRow = z$1.infer;\ndeclare const timelineQuestionWorkRowSchema: z$1.ZodObject<{\n answers: z$1.ZodNullable;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n interactionId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n lifecycle: z$1.ZodEnum<{\n answered: \"answered\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolving: \"resolving\";\n }>;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"question\">;\n}, z$1.core.$strip>;\ntype TimelineQuestionWorkRow = z$1.infer;\ninterface TimelineDelegationWorkRow extends TimelineWorkRowBase {\n workKind: \"delegation\";\n callId: string;\n toolName: string;\n subagentType: string | null;\n description: string | null;\n output: string;\n completedAt: number | null;\n childRows: TimelineRow[];\n}\n/**\n * A provider background task — a dynamic workflow (Claude Code Workflow tool)\n * or a backgrounded shell command (Bash run_in_background), discriminated by\n * `taskType`. The row outlives its spawning turn: progress and terminal state\n * arrive via thread-scoped events folded into this single row. `workflow` is\n * the merged phase/agent tree, present only for workflows; null for shell\n * commands and for workflows the provider reported no progress records for\n * (degraded rendering falls back to description + summary). `model` is the\n * spawning delegation's requested model for background agents; null for\n * commands, workflows, legacy events, and providers that do not expose it.\n */\ndeclare const timelineWorkflowWorkRowSchema: z$1.ZodObject<{\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n description: z$1.ZodString;\n error: z$1.ZodNullable;\n id: z$1.ZodString;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n model: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodNullable;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n usage: z$1.ZodNullable>;\n workKind: z$1.ZodLiteral<\"workflow\">;\n workflow: z$1.ZodNullable;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype TimelineWorkflowWorkRow = z$1.infer;\ntype TimelineWorkRow = TimelineCommandWorkRow | TimelineToolWorkRow | TimelineFileChangeWorkRow | TimelineWebSearchWorkRow | TimelineWebFetchWorkRow | TimelineImageViewWorkRow | TimelineApprovalWorkRow | TimelineQuestionWorkRow | TimelineDelegationWorkRow | TimelineWorkflowWorkRow;\ninterface TimelineTurnRow extends TimelineRowBase {\n kind: \"turn\";\n turnId: string;\n status: TimelineRowStatus;\n summaryCount: number;\n completedAt: number | null;\n children: TimelineRow[] | null;\n}\ntype TimelineSourceRow = TimelineConversationRow | TimelineWorkRow | TimelineSystemRow;\ntype TimelineRow = TimelineSourceRow | TimelineTurnRow;\n\ndeclare const createExecutionInputSourcesSchema: z$1.ZodObject<{\n model: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n providerId: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strict>;\ntype CreateExecutionInputSources = z$1.infer;\ndeclare const createThreadRequestSchema: z$1.ZodObject<{\n environment: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"reuse\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host\">;\n workspace: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branch: z$1.ZodOptional;\n name: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new\">;\n }, z$1.core.$strict>], \"kind\">>;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"unmanaged\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n baseBranch: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"named\">;\n name: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"default\">;\n }, z$1.core.$strip>], \"kind\">;\n type: z$1.ZodLiteral<\"managed-worktree\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"personal\">;\n }, z$1.core.$strip>], \"type\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"project-default\">;\n }, z$1.core.$strip>], \"type\">;\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n providerId: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n model: z$1.ZodOptional;\n origin: z$1.ZodEnum<{\n app: \"app\";\n cli: \"cli\";\n plugin: \"plugin\";\n sdk: \"sdk\";\n }>;\n originKind: z$1.ZodDefault>>;\n originPluginId: z$1.ZodOptional;\n parentThreadId: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n projectId: z$1.ZodString;\n providerId: z$1.ZodOptional;\n reasoningLevel: z$1.ZodOptional>;\n sectionId: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n sourceSeqEnd: z$1.ZodOptional;\n sourceThreadId: z$1.ZodOptional;\n startedOnBehalfOf: z$1.ZodDefault;\n senderThreadId: z$1.ZodString;\n }, z$1.core.$strip>>>;\n title: z$1.ZodOptional;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype CreateThreadRequest = z$1.infer;\ndeclare const forkThreadRequestSchema: z$1.ZodObject<{\n agentContextSeed: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">, z$1.ZodObject<{\n visibility: z$1.ZodLiteral<\"agent-only\">;\n }, z$1.core.$strip>>>>;\n input: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>;\n origin: z$1.ZodDefault>;\n originPluginId: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n sourceSeqEnd: z$1.ZodOptional;\n sourceThreadId: z$1.ZodString;\n title: z$1.ZodOptional;\n visibility: z$1.ZodDefault>;\n workspace: z$1.ZodDefault>;\n}, z$1.core.$strip>;\ntype ForkThreadRequest = z$1.infer;\ndeclare const sendMessageRequestSchema: z$1.ZodObject<{\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n mode: z$1.ZodEnum<{\n \"queue-if-active\": \"queue-if-active\";\n \"steer-if-active\": \"steer-if-active\";\n auto: \"auto\";\n start: \"start\";\n steer: \"steer\";\n }>;\n model: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n reasoningLevel: z$1.ZodOptional>;\n senderThreadId: z$1.ZodOptional;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype SendMessageRequest = z$1.infer;\ndeclare const editMessageRequestSchema: z$1.ZodObject<{\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n expectedRequestSequence: z$1.ZodOptional;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n model: z$1.ZodOptional;\n operationId: z$1.ZodString;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n reasoningLevel: z$1.ZodOptional>;\n senderThreadId: z$1.ZodOptional;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strict>;\ntype EditMessageRequest = z$1.infer;\ndeclare const editMessageResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n operationId: z$1.ZodString;\n requestSequence: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype EditMessageResponse = z$1.infer;\ndeclare const createQueuedMessageRequestSchema: z$1.ZodObject<{\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n model: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n reasoningLevel: z$1.ZodOptional>;\n senderThreadId: z$1.ZodOptional;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype CreateQueuedMessageRequest = z$1.infer;\ndeclare const updateQueuedMessageRequestSchema: z$1.ZodObject<{\n expectedUpdatedAt: z$1.ZodNumber;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n}, z$1.core.$strip>;\ntype UpdateQueuedMessageRequest = z$1.infer;\ndeclare const sendQueuedMessageRequestSchema: z$1.ZodObject<{\n mode: z$1.ZodEnum<{\n auto: \"auto\";\n steer: \"steer\";\n }>;\n}, z$1.core.$strip>;\ntype SendQueuedMessageRequest = z$1.infer;\ndeclare const reorderQueuedMessageRequestSchema: z$1.ZodObject<{\n groupBoundaryQueuedMessageId: z$1.ZodOptional;\n nextQueuedMessageId: z$1.ZodNullable;\n previousQueuedMessageId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ReorderQueuedMessageRequest = z$1.infer;\ndeclare const setQueuedMessageGroupBoundaryRequestSchema: z$1.ZodObject<{\n expectedGroupedPrefixQueuedMessageIds: z$1.ZodArray;\n groupBoundaryQueuedMessageId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SetQueuedMessageGroupBoundaryRequest = z$1.infer;\ndeclare const sendQueuedMessageResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n queuedMessage: z$1.ZodObject<{\n content: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n createdAt: z$1.ZodNumber;\n groupWithNext: z$1.ZodBoolean;\n id: z$1.ZodString;\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>;\n}, z$1.core.$strip>;\ntype SendQueuedMessageResponse = z$1.infer;\ndeclare const threadListResponseSchema: z$1.ZodArray;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n}, z$1.core.$strip>>;\ntype ThreadListResponse = z$1.infer;\ndeclare const resolveThreadMentionsRequestSchema: z$1.ZodObject<{\n threadIds: z$1.ZodArray;\n}, z$1.core.$strict>;\ntype ResolveThreadMentionsRequest = z$1.infer;\ndeclare const resolveThreadMentionsResponseSchema: z$1.ZodArray>;\ntype ResolveThreadMentionsResponse = z$1.infer;\ndeclare const threadSearchResponseSchema: z$1.ZodObject<{\n active: z$1.ZodObject<{\n results: z$1.ZodArray>;\n sourceKind: z$1.ZodEnum<{\n assistant_message: \"assistant_message\";\n system_message: \"system_message\";\n title: \"title\";\n title_fallback: \"title_fallback\";\n user_message: \"user_message\";\n }>;\n sourceSeq: z$1.ZodNullable;\n text: z$1.ZodString;\n }, z$1.core.$strict>>;\n thread: z$1.ZodObject<{\n activity: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n activeBackgroundCommandCount: z$1.ZodNumber;\n activeGoalCount: z$1.ZodNumber;\n activePlanModeCount: z$1.ZodNumber;\n activeWorkflowCount: z$1.ZodNumber;\n }, z$1.core.$strip>;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>>;\n total: z$1.ZodNumber;\n }, z$1.core.$strict>;\n archived: z$1.ZodObject<{\n results: z$1.ZodArray>;\n sourceKind: z$1.ZodEnum<{\n assistant_message: \"assistant_message\";\n system_message: \"system_message\";\n title: \"title\";\n title_fallback: \"title_fallback\";\n user_message: \"user_message\";\n }>;\n sourceSeq: z$1.ZodNullable;\n text: z$1.ZodString;\n }, z$1.core.$strict>>;\n thread: z$1.ZodObject<{\n activity: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n activeBackgroundCommandCount: z$1.ZodNumber;\n activeGoalCount: z$1.ZodNumber;\n activePlanModeCount: z$1.ZodNumber;\n activeWorkflowCount: z$1.ZodNumber;\n }, z$1.core.$strip>;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>>;\n total: z$1.ZodNumber;\n }, z$1.core.$strict>;\n}, z$1.core.$strict>;\ntype ThreadSearchResponse = z$1.infer;\ndeclare const threadResponseSchema: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n archivedAt: z$1.ZodNullable;\n canSpawnChild: z$1.ZodBoolean;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n}, z$1.core.$strip>;\ntype ThreadResponse = z$1.infer;\ndeclare const threadGetQuerySchema: z$1.ZodObject<{\n include: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ThreadGetQuery = z$1.infer;\ndeclare const threadWithIncludesResponseSchema: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n archivedAt: z$1.ZodNullable;\n canSpawnChild: z$1.ZodBoolean;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environment: z$1.ZodOptional;\n branchName: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n defaultBranch: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n isGitRepo: z$1.ZodBoolean;\n isWorktree: z$1.ZodBoolean;\n managed: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodNullable;\n name: z$1.ZodNullable;\n path: z$1.ZodNullable;\n projectId: z$1.ZodString;\n status: z$1.ZodEnum<{\n destroyed: \"destroyed\";\n destroying: \"destroying\";\n error: \"error\";\n provisioning: \"provisioning\";\n ready: \"ready\";\n retiring: \"retiring\";\n }>;\n updatedAt: z$1.ZodNumber;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>>>;\n environmentId: z$1.ZodNullable;\n host: z$1.ZodOptional;\n lastSeenAt: z$1.ZodNullable;\n maxPermissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n name: z$1.ZodString;\n status: z$1.ZodEnum<{\n connected: \"connected\";\n disconnected: \"disconnected\";\n }>;\n type: z$1.ZodEnum<{\n persistent: \"persistent\";\n }>;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n}, z$1.core.$strip>;\ntype ThreadWithIncludesResponse = z$1.infer;\ndeclare const threadPendingInteractionsResponseSchema: z$1.ZodArray>;\n id: z$1.ZodString;\n origin: z$1.ZodOptional;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>>;\n payload: z$1.ZodUnion>;\n kind: z$1.ZodLiteral<\"approval\">;\n reason: z$1.ZodNullable;\n subject: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n actions: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"listFiles\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n command: z$1.ZodString;\n cwd: z$1.ZodNullable;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"command\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"file_change\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n writeScope: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"permission_grant\">;\n permissions: z$1.ZodObject<{\n fileSystem: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plan\">;\n plan: z$1.ZodString;\n planFilePath: z$1.ZodNullable;\n }, z$1.core.$strip>], \"kind\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"user_question\">;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>]>;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n resolution: z$1.ZodNullable;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>]>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>, z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n expiresAt: z$1.ZodOptional>;\n id: z$1.ZodString;\n origin: z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin\">;\n pluginId: z$1.ZodString;\n rendererId: z$1.ZodString;\n }, z$1.core.$strip>;\n payload: z$1.ZodObject<{\n data: z$1.ZodType>;\n kind: z$1.ZodLiteral<\"plugin\">;\n title: z$1.ZodString;\n }, z$1.core.$strip>;\n resolution: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>]>>;\ntype ThreadPendingInteractionsResponse = z$1.infer;\ndeclare const threadQueuedMessageListResponseSchema: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n createdAt: z$1.ZodNumber;\n groupWithNext: z$1.ZodBoolean;\n id: z$1.ZodString;\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>>;\ntype ThreadQueuedMessageListResponse = z$1.infer;\ndeclare const threadChildSummaryResponseSchema: z$1.ZodObject<{\n nonDeletedChildCount: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadChildSummaryResponse = z$1.infer;\ndeclare const deleteThreadRequestSchema: z$1.ZodObject<{\n childThreadsConfirmed: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype DeleteThreadRequest = z$1.infer;\ndeclare const updateThreadRequestSchema: z$1.ZodObject<{\n model: z$1.ZodOptional>;\n parentThreadId: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>>;\n sectionId: z$1.ZodOptional>;\n title: z$1.ZodOptional>;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype UpdateThreadRequest = z$1.infer;\ndeclare const reorderPinnedThreadRequestSchema: z$1.ZodObject<{\n nextThreadId: z$1.ZodNullable;\n previousThreadId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ReorderPinnedThreadRequest = z$1.infer;\n/**\n * Requested placement for a thread opened in the app's split layout. Edge\n * placements add panes through the eighth pane; at the cap they replace the\n * focused pane. `replace` always replaces the focused pane.\n */\ndeclare const threadOpenSplitSchema: z$1.ZodEnum<{\n down: \"down\";\n left: \"left\";\n replace: \"replace\";\n right: \"right\";\n top: \"top\";\n}>;\ntype ThreadOpenSplit = z$1.infer;\n/** Optional secondary-panel file to open with a thread. */\ndeclare const threadOpenFileSchema: z$1.ZodObject<{\n lineNumber: z$1.ZodNullable;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n}, z$1.core.$strict>;\ntype ThreadOpenFile = z$1.infer;\n/** Response for POST /threads/:id/open: how many connected clients received it. */\ndeclare const threadOpenResponseSchema: z$1.ZodObject<{\n delivered: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadOpenResponse = z$1.infer;\n/** Presentation action for one thread pane in each connected app window. */\ndeclare const threadPaneActionSchema: z$1.ZodEnum<{\n \"clear-spotlight\": \"clear-spotlight\";\n maximize: \"maximize\";\n restore: \"restore\";\n spotlight: \"spotlight\";\n toggle: \"toggle\";\n}>;\ntype ThreadPaneAction = z$1.infer;\n/** Number of connected app clients that received the pane action. */\ndeclare const threadPaneActionResponseSchema: z$1.ZodObject<{\n delivered: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadPaneActionResponse = z$1.infer;\ndeclare const threadArchiveAllResponseSchema: z$1.ZodObject<{\n archivedThreadIds: z$1.ZodArray;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype ThreadArchiveAllResponse = z$1.infer;\ndeclare const threadListQuerySchema: z$1.ZodObject<{\n archived: z$1.ZodOptional>;\n hasParent: z$1.ZodOptional>;\n includeHidden: z$1.ZodOptional>;\n limit: z$1.ZodOptional;\n offset: z$1.ZodOptional;\n originKind: z$1.ZodOptional>;\n originPluginId: z$1.ZodOptional;\n parentThreadId: z$1.ZodOptional;\n projectId: z$1.ZodOptional;\n sectionId: z$1.ZodOptional;\n sourceThreadId: z$1.ZodOptional;\n unsectioned: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ThreadListQuery = z$1.infer;\ndeclare const threadSearchQuerySchema: z$1.ZodObject<{\n limitPerGroup: z$1.ZodOptional;\n query: z$1.ZodString;\n}, z$1.core.$strip>;\ntype ThreadSearchQuery = z$1.infer;\ndeclare const threadTimelineQuerySchema: z$1.ZodObject<{\n afterSequence: z$1.ZodOptional;\n beforeAnchorId: z$1.ZodOptional;\n beforeAnchorSeq: z$1.ZodOptional;\n includeNestedRows: z$1.ZodOptional>;\n segmentLimit: z$1.ZodOptional;\n summaryOnly: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ThreadTimelineQuery = z$1.infer;\ndeclare const timelineTurnSummaryDetailsQuerySchema: z$1.ZodObject<{\n sourceSeqEnd: z$1.ZodString;\n sourceSeqStart: z$1.ZodString;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype TimelineTurnSummaryDetailsQuery = z$1.infer;\ndeclare const threadStorageFilesQuerySchema: z$1.ZodObject<{\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ThreadStorageFilesQuery = z$1.infer;\ndeclare const threadStoragePathsQuerySchema: z$1.ZodObject<{\n includeDirectories: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n includeFiles: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ThreadStoragePathsQuery = z$1.infer;\ndeclare const timelineTurnSummaryDetailsResponseSchema: z$1.ZodObject<{\n rows: z$1.ZodArray>>;\n}, z$1.core.$strip>;\ntype TimelineTurnSummaryDetailsResponse = z$1.infer;\ndeclare const threadTimelineResponseSchema: z$1.ZodObject<{\n activeBackgroundCommands: z$1.ZodArray;\n createdAt: z$1.ZodNumber;\n description: z$1.ZodString;\n error: z$1.ZodNullable;\n id: z$1.ZodString;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n model: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodNullable;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n usage: z$1.ZodNullable>;\n workKind: z$1.ZodLiteral<\"workflow\">;\n workflow: z$1.ZodNullable;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n activePromptMode: z$1.ZodNullable;\n prompt: z$1.ZodString;\n providerId: z$1.ZodString;\n }, z$1.core.$strict>>;\n activeThinking: z$1.ZodNullable>;\n activeWorkflows: z$1.ZodArray;\n createdAt: z$1.ZodNumber;\n description: z$1.ZodString;\n error: z$1.ZodNullable;\n id: z$1.ZodString;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n model: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodNullable;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n usage: z$1.ZodNullable>;\n workKind: z$1.ZodLiteral<\"workflow\">;\n workflow: z$1.ZodNullable;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n contextWindowUsage: z$1.ZodOptional>;\n delta: z$1.ZodOptional>;\n upsertRows: z$1.ZodArray>>;\n }, z$1.core.$strip>>;\n goal: z$1.ZodNullable;\n timeUsedSeconds: z$1.ZodNumber;\n tokenBudget: z$1.ZodNullable;\n tokensUsed: z$1.ZodNumber;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n maxSeq: z$1.ZodNumber;\n modelFallback: z$1.ZodNullable;\n sourceSeq: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n pendingTodos: z$1.ZodNullable;\n text: z$1.ZodString;\n }, z$1.core.$strip>>;\n sourceSeq: z$1.ZodNumber;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n rows: z$1.ZodArray>>;\n timelinePage: z$1.ZodObject<{\n hasOlderRows: z$1.ZodBoolean;\n kind: z$1.ZodEnum<{\n latest: \"latest\";\n older: \"older\";\n }>;\n olderCursor: z$1.ZodNullable>;\n returnedSegmentCount: z$1.ZodNumber;\n segmentLimit: z$1.ZodNumber;\n }, z$1.core.$strict>;\n}, z$1.core.$strip>;\ntype ThreadTimelineResponse = z$1.infer;\ndeclare const threadConversationOutlineResponseSchema: z$1.ZodObject<{\n items: z$1.ZodArray>;\n id: z$1.ZodString;\n preview: z$1.ZodString;\n role: z$1.ZodEnum<{\n assistant: \"assistant\";\n user: \"user\";\n }>;\n }, z$1.core.$strict>>;\n maxSeq: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype ThreadConversationOutlineResponse = z$1.infer;\ndeclare const threadStorageFileListResponseSchema: z$1.ZodObject<{\n files: z$1.ZodArray>;\n storageRootPath: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype ThreadStorageFileListResponse = z$1.infer;\ndeclare const threadStoragePathListResponseSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n positions: z$1.ZodArray;\n score: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n storageRootPath: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype ThreadStoragePathListResponse = z$1.infer;\n\ndeclare const threadTabsResponseSchema: z$1.ZodObject<{\n revision: z$1.ZodNumber;\n tabs: z$1.ZodArray;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"git-diff\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n actionId: z$1.ZodString;\n fileOpenerOwner: z$1.ZodOptional;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n projectId: z$1.ZodNullable;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin-panel\">;\n paramsJson: z$1.ZodNullable;\n pluginId: z$1.ZodString;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n projectId: z$1.ZodNullable;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n isPinned: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"browser\">;\n title: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new-tab\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"side-chat\">;\n sourceMessageText: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNullable;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"terminal\">;\n target: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"environment\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n hostId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host_path\">;\n }, z$1.core.$strict>], \"kind\">>;\n terminalId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n}, z$1.core.$strict>;\ntype ThreadTabsResponse = z$1.infer;\ndeclare const updateThreadTabsRequestSchema: z$1.ZodObject<{\n expectedRevision: z$1.ZodNumber;\n tabs: z$1.ZodArray;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"git-diff\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n actionId: z$1.ZodString;\n fileOpenerOwner: z$1.ZodOptional;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n projectId: z$1.ZodNullable;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin-panel\">;\n paramsJson: z$1.ZodNullable;\n pluginId: z$1.ZodString;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n projectId: z$1.ZodNullable;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n isPinned: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"browser\">;\n title: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new-tab\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"side-chat\">;\n sourceMessageText: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNullable;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"terminal\">;\n target: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"environment\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n hostId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host_path\">;\n }, z$1.core.$strict>], \"kind\">>;\n terminalId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n}, z$1.core.$strict>;\ntype UpdateThreadTabsRequest = z$1.infer;\n\n/**\n * A value that survives a JSON round trip without coercion or data loss.\n *\n * Host boundaries still validate values at runtime because TypeScript cannot\n * exclude non-finite numbers and plugin bundles can bypass static types.\n */\ntype JsonValue = string | number | boolean | null | JsonValue[] | {\n [key: string]: JsonValue;\n};\n\n/** A JSON-safe path segment reported by a Standard Schema validation issue. */\ntype PluginRpcIssuePathSegment = string | number;\n/** Validator-neutral validation detail carried by an RPC error envelope. */\ninterface PluginRpcValidationIssue {\n message: string;\n path?: PluginRpcIssuePathSegment[];\n}\n/** Stable wire error categories for plugin RPC. */\ntype PluginRpcErrorCode = \"handler_error\" | \"invalid_input\" | \"invalid_json\" | \"invalid_output\" | \"non_json_result\" | \"unknown_method\";\n/** Structured RPC failure returned as `{ ok: false, error }`. */\ninterface PluginRpcError {\n code: PluginRpcErrorCode;\n message: string;\n issues?: PluginRpcValidationIssue[];\n}\n/**\n * The validator-neutral subset of Standard Schema v1 used by plugin RPC.\n * Zod 4 schemas implement this interface directly; other validators can do\n * the same without becoming part of BB's public protocol.\n */\ninterface StandardSchemaV1 {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardSchemaV1Result | Promise>;\n readonly types?: {\n readonly input: Input;\n readonly output: Output;\n };\n };\n}\ntype StandardSchemaV1Result = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: readonly StandardSchemaV1Issue[];\n};\ninterface StandardSchemaV1Issue {\n readonly message: string;\n readonly path?: PropertyKey | readonly (PropertyKey | {\n readonly key: PropertyKey;\n })[];\n}\ntype StandardSchemaV1InferInput = NonNullable[\"input\"];\ntype StandardSchemaV1InferOutput = NonNullable[\"output\"];\ninterface PluginRpcMethodContract {\n readonly input: InputSchema;\n readonly output: OutputSchema;\n}\ntype PluginRpcContract = Readonly>;\n/** Define a shared RPC contract while preserving exact method/schema types. */\ndeclare function defineRpcContract(contract: Contract): Contract;\ntype PluginRpcHandlers = {\n [Method in keyof Contract]: (input: StandardSchemaV1InferOutput) => StandardSchemaV1InferInput | Promise>;\n};\ntype PluginRpcCallInput = StandardSchemaV1InferInput;\ntype PluginRpcCallArgs = null extends PluginRpcCallInput ? [input?: PluginRpcCallInput] : [input: PluginRpcCallInput];\ntype PluginRpcResult = StandardSchemaV1InferOutput;\n\n/**\n * The `@get-bb/plugin-sdk/app` contract (plugin design §5.2) — pure types with no\n * side effects. The BB app imports these to keep its real implementation in\n * sync (`satisfies PluginSdkApp`). Plugin authors import the same shapes through\n * `@get-bb/plugin-sdk/app`.\n *\n * Per-slot props are versioned contracts: additive-only within an SDK major.\n */\n/** Props passed to a `homepageSection` component. */\ninterface PluginHomepageSectionProps {\n /** Project in view on the compose surface; null when none is selected. */\n projectId: string | null;\n}\n/**\n * Props passed to a `settingsSection` component.\n *\n * Deliberately empty in V1; versioned additive like the other slot props.\n */\ninterface PluginSettingsSectionProps {\n}\n/** Props passed to a `navPanel` component (it owns its whole route). */\ninterface PluginNavPanelProps {\n /**\n * The route remainder after the panel root, \"\" at the root. The panel's\n * route is `/plugins///*`, so a deep link like\n * `/plugins/notes/notes/work/ideas.md` renders the panel with\n * `subPath: \"work/ideas.md\"`. Navigate within the panel via\n * `useBbNavigate().toPluginPanel(path, { subPath })` — browser\n * back/forward then walks panel-internal history.\n */\n subPath: string;\n}\n/**\n * Props passed to a panel tab opened by a `threadPanelAction`.\n *\n * This slot is rendered only for an existing thread. Use\n * `experimental_newThreadPanelAction` for the root New thread screen.\n */\ninterface PluginThreadPanelProps {\n threadId: string;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\n/** Props passed to a panel tab opened by `experimental_newThreadPanelAction`. */\ninterface PluginNewThreadPanelProps {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\ninterface PluginPendingInteractionView {\n id: string;\n threadId: string;\n title: string;\n payload: JsonValue;\n createdAt: number;\n expiresAt: number | null;\n}\ninterface PluginPendingInteractionProps {\n interaction: PluginPendingInteractionView;\n submit(value: JsonValue): Promise;\n cancel(): Promise;\n}\n/**\n * Props for a `sidebarFooterAction` — host-rendered (no plugin component).\n * Deliberately empty; the registration's `run` carries the behavior.\n */\ninterface PluginSidebarFooterActionProps {\n}\n/**\n * Props passed to an `experimental_threadList` component — the sidebar's\n * scrolling thread area, replaced wholesale by one plugin.\n */\ninterface PluginThreadListProps {\n /** The thread the route currently shows; null on non-thread routes. */\n activeThreadId: string | null;\n /** The project the route currently shows; null when none is selected. */\n activeProjectId: string | null;\n /** True on phone-width viewports and coarse pointers. */\n isCompactViewport: boolean;\n /**\n * Call after the user opens a thread. It closes the mobile sidebar drawer,\n * and it clears the host search field on every viewport. Always call it, or\n * the sidebar stays in search mode after the thread opens.\n */\n onNavigate: () => void;\n /**\n * The host search field's current text, or \"\" when the field is closed.\n * The host owns that field, so a plugin list filters by this rather than\n * shipping a second search box.\n */\n searchQuery: string;\n /**\n * BB's thread list, bound to this sidebar instance. Render it to delegate\n * conditionally without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Props passed to an `experimental_threadHeaderAction` component, rendered in\n * the thread header's action row.\n */\ninterface PluginThreadHeaderActionProps {\n /**\n * The thread this header belongs to. Never null: the slot is not rendered\n * on the compose screen or other non-thread routes. A split layout renders\n * one header per pane, so the component mounts once per visible thread,\n * each with its own id — keep per-thread state in the component, never in a\n * module-level singleton.\n */\n threadId: string;\n projectId: string;\n /**\n * True on phone-width viewports and coarse pointers. Collapse to an\n * icon-sized control when it is true — the row is short.\n */\n isCompactViewport: boolean;\n}\n/**\n * Where a file being opened by a `fileOpener` lives. `path` semantics follow\n * the source: workspace paths are relative to the environment's worktree,\n * thread-storage paths are relative to the thread's storage root, host paths\n * are absolute on the thread's host.\n */\ninterface PluginFileOpenerSource {\n kind: \"host\" | \"thread-storage\" | \"workspace\";\n threadId: string | null;\n environmentId: string | null;\n projectId: string | null;\n}\n/** Props passed to a `fileOpener` component (rendered as a panel file tab). */\ninterface PluginFileOpenerProps {\n path: string;\n source: PluginFileOpenerSource;\n /**\n * BB's file preview, bound to this file. Render it to delegate conditionally\n * without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Message context passed to a `messageDirective` component — the assistant\n * (or nested agent) message that contained the directive.\n */\ninterface PluginMessageDirectiveMessage {\n id: string;\n threadId: string;\n turnId: string | null;\n projectId: string | null;\n}\n/**\n * Open a worktree-relative file in the host's workspace file viewer. Returns\n * true when the host accepted the path; false when the path is invalid or the\n * viewer declined it.\n */\ntype PluginMessageDirectiveOpenWorkspaceFile = (path: string) => boolean;\n/**\n * Props passed to a `messageDirective` component. Attributes are untrusted\n * strings parsed from the directive; the plugin validates its own fields.\n */\ninterface PluginMessageDirectiveProps {\n /** Parsed, untrusted directive attributes (e.g. `{ file: \"demo.html\" }`). */\n attributes: Readonly>;\n /** Original directive source text (useful for diagnostics / crash fallback). */\n source: string;\n message: PluginMessageDirectiveMessage;\n /**\n * Opens a worktree-relative file in the host's workspace file viewer. Null\n * when the message surface has no workspace viewer available.\n */\n openWorkspaceFile: PluginMessageDirectiveOpenWorkspaceFile | null;\n}\ninterface PluginHomepageSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n component: ComponentType;\n}\ninterface PluginSettingsSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Optional host-rendered section heading. */\n title?: string;\n /**\n * Optional one-line host-rendered subheading under `title`, in the built-in\n * SettingsSection idiom (ignored when `title` is absent).\n */\n description?: string;\n component: ComponentType;\n}\ninterface PluginNavPanelRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /** URL segment under `/plugins//`; letters, digits, `-`, `_`. */\n path: string;\n component: ComponentType;\n /**\n * Ordered, non-closable tabs shown in this page's host-owned right panel.\n * BB owns selection and persistence and always includes its native Browser\n * and Terminal tools beside them. Components mount only while their tab is\n * active and the panel is open, and receive the same `subPath` as the page\n * component.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_fixedTabs?: readonly {\n /** Unique within this nav panel; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n component: ComponentType;\n /** `flush` lets the component own padding and scrolling. */\n layout?: \"flush\" | \"padded\";\n }[];\n /**\n * Optional presentational component rendered at the trailing edge of this\n * panel's sidebar row. It receives no props so it can own a narrow live\n * value through the ordinary SDK hooks without coupling that state to the\n * host sidebar. The host does not mount it on compact viewports and clips it\n * to a small, single-line box on wider viewports. It shares the trailing\n * action column, fading out for the host's options button on hover or focus;\n * do not render controls or rely on unbounded content here.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_sidebarAccessory?: ComponentType;\n /**\n * Optional component rendered on the right side of the shared title bar\n * (e.g. a sync button or a count). Contained separately from the body: a\n * throwing headerContent is hidden without breaking the title bar.\n */\n headerContent?: ComponentType;\n}\n/**\n * What a plugin action passes when it asks the host to open one of its panel\n * tabs. Shared by every `openPanel` entry point so a plugin registering more\n * than one kind of action can write a single open routine;\n * `PluginTargetedPanelActionOpenOptions` adds the `actionId` a caller\n * outside a panel action must pass to name the panel it wants.\n */\ninterface PluginPanelActionOpenOptions {\n /** Tab label. Default: the action's `title`. */\n title?: string;\n /**\n * Persisted with the tab and handed to the component as its `params` prop.\n * Must be a JSON value; anything else is a declined open.\n */\n params?: JsonValue;\n}\n/**\n * Context handed to a `threadPanelAction`'s `run`.\n *\n * The action is thread-only and is never offered on the root New thread\n * screen, so `threadId` is always present.\n */\ninterface PluginThreadPanelActionContext {\n /** The thread whose panel launcher invoked the action. */\n threadId: string;\n /**\n * Open a tab in the thread's side panel rendering this action's\n * `component`. `title` labels the tab (default: the action's `title`);\n * `params` must be JSON-serializable — it is persisted with the tab and\n * reaches the component as its `params` prop. Opening with params\n * identical to an already-open tab of this action focuses that tab\n * (updating its title) instead of duplicating it. May be called more than\n * once (different params ⇒ multiple tabs) or not at all.\n *\n * Returns true when the host accepted the open; false when it declined —\n * from this launcher, only a `params` that is not a JSON value. The true /\n * false contract is shared with `messageAction`'s `openPanel` and\n * `useBbNavigate().openThreadPanel` (which decline for more reasons) so one\n * open routine can serve every action kind. A decline is never thrown: the\n * host logs it and reports it here.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\ninterface PluginThreadPanelActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /**\n * Icon hint (BB icon name) used when the plugin ships no logo; the\n * launcher row and opened tabs prefer the plugin's logo.\n */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /**\n * How the host frames the tab content. \"padded\" (default) wraps the\n * component in the panel's scroll container with standard padding —\n * right for document-like content. \"flush\" gives the component the full\n * tab area (no padding, definite height, no host scrolling) — right for\n * app-like content that manages its own layout, such as\n * `ThreadChat`.\n */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action: call your RPC methods, show a\n * toast, and/or open panel tabs via `context.openPanel`. Omitted =\n * immediately open a panel tab with defaults. Errors (sync or async) are\n * contained and logged; they never break the launcher.\n */\n run?(context: PluginThreadPanelActionContext): void | Promise;\n}\n/** Context handed to an `experimental_newThreadPanelAction`'s `run`. */\ninterface PluginNewThreadPanelActionContext {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * Open a tab in the root New thread screen's side panel rendering this\n * action's `component`. The title, params, deduplication, return value, and\n * error semantics match `threadPanelAction`.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\n/** Registration for the root New thread screen's panel Actions list. */\ninterface PluginNewThreadPanelActionRegistration {\n /** Unique within this slot for the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /** Icon hint (BB icon name) used when the plugin ships no logo. */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /** Host framing; matches `threadPanelAction`. */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action. Omitted = immediately open a\n * panel tab with defaults. Errors are contained and logged.\n */\n run?(context: PluginNewThreadPanelActionContext): void | Promise;\n}\ninterface PluginPendingInteractionRegistration {\n /** Matches `rendererId` passed to `bb.ui.requestInput`. */\n id: string;\n component: ComponentType;\n}\n/** Context handed to a `sidebarFooterAction`'s `run`. */\ninterface PluginSidebarFooterActionContext {\n /**\n * Navigate to this plugin's detail page in Tools, where declarative settings\n * and `settingsSection` slots render.\n */\n openSettings(): void;\n}\n/**\n * An icon button in the app sidebar footer (next to Settings / bug report).\n * Host-rendered for consistent chrome — plugins supply icon, label, and\n * `run` behavior only.\n */\ninterface PluginSidebarFooterActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip and accessible label for the icon button. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /**\n * Runs when the user activates the action (e.g. call `openSettings()`,\n * open a panel via other surfaces, toast). Errors (sync or async) are\n * contained and logged; they never break the sidebar.\n */\n run(context: PluginSidebarFooterActionContext): void | Promise;\n}\n/**\n * The one status bb would paint for a thread, already resolved through the\n * host's precedence (attention before work; plan and goal before the generic\n * spinner). Draw your own glyph for it — the SDK ships no status component.\n *\n * Treat an unrecognized value as \"none\": bb adds kinds over time, and an\n * older plugin must degrade to drawing nothing rather than throwing.\n *\n * \"draft\" and \"working-draft\" are never reported here: an unsubmitted composer\n * draft is per-client state the host reads per row, which an array-wide view\n * cannot. A thread holding a draft reports whatever it would report without\n * one.\n */\ntype PluginSidebarThreadIndicator = \"background-agent\" | \"background-command\" | \"draft\" | \"goal\" | \"none\" | \"plan-mode\" | \"runtime\" | \"unread-error\" | \"unread-success\" | \"waiting-for-input\" | \"workflow\" | \"working-draft\";\n/**\n * How a thread's environment presents its workspace: a worktree bb manages,\n * a worktree the user manages, or anything else (a plain checkout).\n */\ntype PluginSidebarWorkspaceKind = \"managed-worktree\" | \"other\" | \"unmanaged-worktree\";\n/** Live work counts on a thread. All zero means nothing is running. */\ninterface PluginSidebarThreadActivity {\n workflows: number;\n backgroundAgents: number;\n backgroundCommands: number;\n planMode: number;\n goals: number;\n}\n/**\n * One thread in the sidebar's live view.\n *\n * A deliberate copy of the fields a sidebar needs — not a re-export of the\n * host's internal thread row type, which changes whenever the app needs a\n * field. Timestamps are epoch milliseconds.\n */\ninterface PluginSidebarThread {\n id: string;\n projectId: string;\n /** Null while a thread is still unnamed; pair with `titleFallback`. */\n title: string | null;\n titleFallback: string | null;\n /** The thread this one was forked from or spawned under; null at the root. */\n parentThreadId: string | null;\n sectionId: string | null;\n /** How this thread came to exist under its parent; null for root threads. */\n originKind: \"fork\" | null;\n /** The plugin that spawned it, or null for non-plugin origins. */\n originPluginId: string | null;\n /** The agent provider this thread runs on, e.g. \"codex\", \"claude-code\". */\n providerId: string;\n /** The agent is blocked on the user: an approval or a question. */\n hasPendingInteraction: boolean;\n activity: PluginSidebarThreadActivity;\n indicator: PluginSidebarThreadIndicator;\n /**\n * The host's accessible label for `indicator`, e.g. \"Thread needs user\n * input\"; null when the indicator is \"none\". Use it for `aria-label` so\n * screen-reader text stays consistent across sidebars.\n */\n indicatorLabel: string | null;\n isUnread: boolean;\n isPinned: boolean;\n isArchived: boolean;\n environment: {\n id: string | null;\n name: string | null;\n branchName: string | null;\n workspaceDisplayKind: PluginSidebarWorkspaceKind;\n } | null;\n /**\n * The machine this thread's work runs on, with the name resolved for you.\n * Null when the thread has no environment yet, or when its host is not in\n * the known-hosts list. Useful where a thread has no branch to show — a\n * personal-project thread has a machine but no worktree.\n */\n host: {\n id: string;\n name: string;\n } | null;\n createdAt: number;\n updatedAt: number;\n lastReadAt: number | null;\n latestAttentionAt: number;\n}\n/**\n * The pull request for a thread's branch, narrowed to what a sidebar row\n * needs. `attention` is bb's rolled-up \"does this need you\" signal, so a row\n * can colour a badge without reading checks, review, and mergeability itself.\n */\ninterface PluginSidebarPullRequest {\n number: number;\n title: string;\n url: string;\n state: \"closed\" | \"draft\" | \"merged\" | \"open\";\n attention: \"blocked\" | \"changes_requested\" | \"checks_failed\" | \"checks_pending\" | \"closed\" | \"conflicts\" | \"draft\" | \"merged\" | \"none\" | \"ready_to_merge\" | \"review_requested\";\n}\ninterface PluginSidebarThreadPullRequestState {\n /** True while the first lookup for this thread's environment is in flight. */\n isLoading: boolean;\n /**\n * The pull request, or null when the branch has none, the thread has no\n * environment, or the lookup could not run (a git-host hiccup). A row should\n * treat null as \"nothing to show\", never as an error.\n */\n pullRequest: PluginSidebarPullRequest | null;\n}\n/** One project in the sidebar's live view. */\ninterface PluginSidebarProject {\n id: string;\n name: string;\n /** True for the implicit personal project. */\n isPersonal: boolean;\n}\ninterface PluginSidebarThreadsState {\n status: \"error\" | \"loading\" | \"ready\";\n threads: readonly PluginSidebarThread[];\n projects: readonly PluginSidebarProject[];\n}\n/**\n * Act on threads from a plugin surface. Every method routes to the host's own\n * flow, so optimistic updates, toasts, dialogs, pane closing, and route repair\n * behave exactly as they do in the built-in sidebar. Unknown thread ids are\n * ignored by `open` and rejected by the rest.\n */\ninterface PluginSidebarThreadActions {\n /**\n * Navigate to a thread. `split: true` applies bb's split placement rules —\n * a right split by default, focus when the thread is already open, replace\n * at the pane cap — and falls back to plain navigation where splits are off.\n */\n open(threadId: string, options?: {\n split?: boolean;\n }): void;\n /**\n * Go to the new-thread screen. Passing `projectId` also makes that project\n * the composer's selection, so the thread is created where you asked.\n */\n openNewThread(options?: {\n projectId?: string;\n focusPrompt?: boolean;\n }): void;\n setPinned(threadId: string, pinned: boolean): Promise;\n setRead(threadId: string, read: boolean): Promise;\n /** Silent rename — no dialog. For inline editing in your own row. */\n rename(threadId: string, title: string): Promise;\n /** Archives the thread AND its children, closing any panes showing them. */\n archive(threadId: string): void;\n /**\n * Opens bb's delete confirmation, which counts child threads first. Deletion\n * is destructive and recursive, so the host owns the confirmation: there is\n * deliberately no silent `delete`.\n */\n requestDelete(threadId: string): void;\n}\n/**\n * Render a plugin component in the thread header's action row.\n *\n * The frontend sibling of the backend `bb.ui.registerThreadAction`, which\n * renders a host-owned button and runs server-side. Use that one for \"do a\n * thing\"; use this one when the control must draw live state.\n *\n * The host places it at the left end of the action row, before the workspace\n * button, git actions, the panel toggle, maximize, and close. That row is a\n * 48px chrome row with 28px controls: render one inline control that fits, and\n * put anything taller in a portalled popover.\n */\ninterface PluginThreadHeaderActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Names the region the host wraps around your component (a labelled group).\n * It does NOT label your control: an icon-only button still needs its own\n * accessible name.\n */\n title: string;\n component: ComponentType;\n}\n/** One pane's place in the split layout, as fractions of the split area. */\ninterface PluginSidebarSplitPane {\n paneId: string;\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n /** This pane holds the thread the row represents. */\n isMe: boolean;\n isFocused: boolean;\n}\n/**\n * Drag-to-split support for one row, plus where that thread currently sits in\n * the split layout.\n */\ninterface PluginSidebarThreadSplit {\n /**\n * Spread onto the row's interactive element. Carries the pointer handler\n * that starts a split drag; empty when splits are unavailable, so spreading\n * it is always safe.\n *\n * The host owns every rule: the gesture engages only once the pointer leaves\n * the sidebar toward the main area (so a list with its own drag-to-reorder\n * keeps working), an edge drop splits, a center drop replaces, an\n * already-open thread focuses its pane, and the pane cap coerces a split\n * into a replace.\n */\n splitProps: {\n onPointerDown?: (event: react.PointerEvent) => void;\n };\n /**\n * False on compact viewports, when the user disabled splits, and for an\n * unknown thread id. Gate any \"open in split\" affordance you draw on it.\n */\n isAvailable: boolean;\n /**\n * Where this thread sits in the split layout, or null when it is not open in\n * one (including single-pane layouts). Draw a mini-map, a tint, or nothing.\n */\n layout: {\n panes: readonly PluginSidebarSplitPane[];\n } | null;\n}\n/**\n * Replace the sidebar's thread list with a plugin component.\n *\n * Unlike every other slot, this one is EXCLUSIVE: two lists cannot share one\n * scroll area. Registering activates the replacement while the plugin is\n * enabled. If multiple plugins register one, the first in deterministic slot\n * order is active by default; removing it reveals the next. The user can pin\n * BB's list or a specific provider under Settings → Appearance. A plugin can\n * also use its own setting and render `experimental_Original` conditionally.\n * An absent or crashing replacement falls back to BB's list rather than\n * leaving the user with no sidebar.\n *\n * The plugin gets the scrolling list and nothing else. The New-thread button,\n * the search field, the plugin nav rows, and the footer stay host-rendered in\n * every sidebar — they are shared surfaces (other plugins live in two of\n * them), and a replaced list must not be able to remove them.\n */\ninterface PluginThreadListRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label shown in Settings → Appearance and capability details. */\n title: string;\n /** Optional one-line description shown with the provider choice. */\n description?: string;\n component: ComponentType;\n}\n/**\n * Register this plugin as a viewer/editor for file extensions. By default,\n * matching files render the first applicable opener in deterministic slot\n * order. The user can pin BB's preview or a specific opener per extension\n * under Settings → Files. The file tab's \"Open with\" menu can override that\n * choice for one open. A plugin can also use its own setting and render\n * `experimental_Original` conditionally. Applies to working-tree, host, and\n * thread-storage files — never to git-ref snapshots (diff views always use\n * BB's preview).\n */\ninterface PluginFileOpenerRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label in the \"Open with\" menu (e.g. \"Notes editor\"). */\n title: string;\n /** Lowercase extensions without the dot (e.g. [\"md\", \"mdx\"]). */\n extensions: readonly string[];\n component: ComponentType;\n}\n/**\n * Register a leaf message directive rendered inside assistant (and nested\n * agent) message Markdown. `id` is the directive name: `inline-vis` matches\n * `::inline-vis{file=\"demo.html\"}`.\n */\ninterface PluginMessageDirectiveRegistration {\n /**\n * The directive name. Lowercase kebab-case beginning with a letter.\n */\n id: string;\n component: ComponentType;\n}\n/**\n * A narrow, stable reference to one rendered chat message — NOT an internal\n * timeline row. `sourceSeqEnd` is the last source event sequence the message\n * covers, the anchor the server accepts for provider-history forks.\n */\ninterface ThreadChatMessageReference {\n id: string;\n threadId: string;\n role: \"assistant\" | \"user\";\n /** Visible text of the message. */\n text: string;\n sourceSeqEnd: number;\n}\n/**\n * What a caller that is *not* itself a panel action passes to open one — a\n * `messageAction`'s `run`, or any component via `useBbNavigate()`. A panel\n * action opening its own tab is already the target, so it passes the bare\n * {@link PluginPanelActionOpenOptions} instead.\n */\ninterface PluginTargetedPanelActionOpenOptions extends PluginPanelActionOpenOptions {\n /** A `threadPanelAction` id registered by this same plugin. */\n actionId: string;\n}\n/** Context handed to a `messageAction`'s `run`. */\ninterface PluginMessageActionContext {\n /** The thread whose timeline surfaced the action. */\n threadId: string;\n message: ThreadChatMessageReference;\n /**\n * Present only when the action was invoked from the text-selection menu;\n * the exact text the user highlighted inside `message`.\n */\n selectedText?: string;\n /**\n * Open one of this plugin's `threadPanelAction` components in the current\n * thread's side panel — the registration-callback equivalent of\n * `useBbNavigate().openThreadPanel`.\n *\n * Returns true when the host accepted the open; false when it declined —\n * `params` was not a JSON value, the action id names no `threadPanelAction`\n * of this plugin, or the surface has no side panel (only the main thread\n * view does; a `ThreadChat` embedded in a plugin panel does not). A decline\n * is never thrown: the host logs it and reports it here.\n */\n openPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * An action on chat messages: an icon button in the per-message action bar\n * (user and assistant messages) and an entry in the assistant-message\n * text-selection menu. Host-rendered chrome — the plugin supplies title,\n * icon hint, and `run` behavior only.\n */\ninterface PluginMessageActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(context: PluginMessageActionContext): void | Promise;\n}\n/**\n * Supply the inline React mark bb draws for one agent provider.\n *\n * A manifest `branding.icon` (or a provider's `logoUrl`) is fetched and drawn\n * through ``, a separate document where `currentColor` resolves to black\n * — invisible on dark themes and unreachable from app CSS. A component is\n * rendered inline, so it inherits the app's theme colors and the host's sizing\n * classes. Register a static color logo as a file and a theme-aware mark here.\n *\n * The host passes only `className` (sizing plus the provider's color class);\n * the component must render an inline SVG (or other inline markup) and must\n * not fetch. One registration per provider id per plugin; when two plugins\n * claim the same provider id the host keeps the first by plugin id and warns.\n */\ninterface PluginProviderIconRegistration {\n /**\n * The provider this mark is for — the id bb knows the provider by (the\n * provider declaration's id, e.g. `codex` or `acp-cursor`), not the plugin\n * id. Letters, digits, `-`, `_`.\n */\n providerId: string;\n /** Inline, theme-aware mark. Receives the host's sizing/color className. */\n icon: ComponentType<{\n className?: string;\n }>;\n}\ninterface PluginAppSlots {\n homepageSection(registration: PluginHomepageSectionRegistration): void;\n settingsSection(registration: PluginSettingsSectionRegistration): void;\n navPanel(registration: PluginNavPanelRegistration): void;\n /**\n * Add an action to an existing thread's panel launcher. This slot is\n * thread-only; use `experimental_newThreadPanelAction` for root compose.\n */\n threadPanelAction(registration: PluginThreadPanelActionRegistration): void;\n /**\n * Add an action to the root New thread screen's panel launcher (see\n * {@link PluginNewThreadPanelActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_newThreadPanelAction(registration: PluginNewThreadPanelActionRegistration): void;\n pendingInteraction(registration: PluginPendingInteractionRegistration): void;\n sidebarFooterAction(registration: PluginSidebarFooterActionRegistration): void;\n /**\n * Replace the sidebar's thread list (see\n * {@link PluginThreadListRegistration}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_threadList(registration: PluginThreadListRegistration): void;\n /**\n * Render a component in the thread header's action row (see\n * {@link PluginThreadHeaderActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_threadHeaderAction(registration: PluginThreadHeaderActionRegistration): void;\n fileOpener(registration: PluginFileOpenerRegistration): void;\n messageDirective(registration: PluginMessageDirectiveRegistration): void;\n messageAction(registration: PluginMessageActionRegistration): void;\n /**\n * Draw one agent provider's icon with an inline React component instead of\n * its ``-rendered logo file (see\n * {@link PluginProviderIconRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_providerIcon(registration: PluginProviderIconRegistration): void;\n}\ninterface PluginAppComposer {\n customize(registration: ComposerCustomization): void;\n}\n/** Stable lifecycle values for one content-script instance in one bb client. */\ninterface PluginContentScriptContext {\n /** The id of the plugin that owns this script. */\n readonly pluginId: string;\n /** Monotonic per-client generation, starting at 1. */\n readonly generation: number;\n /** Aborted before cleanup begins on replacement, deactivation, or teardown. */\n readonly signal: AbortSignal;\n /**\n * Persistently decorate any thread row for this plugin generation.\n *\n * The status is owned by the frontend generation and therefore survives\n * route changes. Passing `null` clears the plugin's status for that thread.\n * The host clears every remaining status when the frontend generation\n * deactivates.\n *\n * Optional so bundles can feature-detect support while this experimental\n * surface rolls out across 0.x clients.\n */\n readonly experimental_setThreadRowStatus?: (threadId: string, status: PluginComposerThreadRowStatus | null) => void;\n}\n/** Cleanup returned by a frontend content script. */\ntype PluginContentScriptDisposer = () => void | Promise;\n/**\n * Trusted same-origin JavaScript/TypeScript mounted once per active frontend\n * generation in each bb app window or browser tab.\n */\ninterface PluginContentScriptRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Install behavior into the bb app shell. The host awaits a returned\n * promise, contains failures, and calls the returned disposer exactly once.\n */\n mount(context: PluginContentScriptContext): void | PluginContentScriptDisposer | Promise;\n}\n/** Lifecycle surface for trusted frontend content scripts. */\ninterface PluginAppContentScripts {\n register(registration: PluginContentScriptRegistration): void;\n}\ninterface PluginAppBuilder {\n slots: PluginAppSlots;\n composer: PluginAppComposer;\n contentScripts: PluginAppContentScripts;\n}\ntype PluginAppSetup = (app: PluginAppBuilder) => void;\n/**\n * The opaque product of `definePluginApp` — a plugin's `app.tsx` default\n * export. The host re-runs `setup` against a fresh collector on every\n * (re)interpretation, replacing that plugin's registrations wholesale.\n */\ninterface PluginAppDefinition {\n /** Brand the host checks before interpreting a bundle's default export. */\n readonly __bbPluginApp: true;\n readonly setup: PluginAppSetup;\n}\ninterface PluginRpcClient {\n /**\n * Invoke one of the plugin's `bb.rpc` methods (POST\n * /api/v1/plugins/<id>/rpc/<method>). Resolves with the method's\n * inferred output; rejects with an `Error` carrying the server's message,\n * stable `code`, and validation `issues` when present.\n */\n call>(method: Method, ...args: PluginRpcCallArgs): Promise>;\n}\ninterface PluginSettingsState {\n /**\n * Effective non-secret setting values (secret settings are excluded —\n * read them server-side). Undefined while loading or unavailable.\n */\n values: Record | undefined;\n isLoading: boolean;\n}\n/** State of the app's shared realtime connection to the bb server. */\ntype PluginRealtimeConnectionState = \"connected\" | \"connecting\" | \"reconnecting\";\n/** Where `useComposer()` writes. */\ntype PluginComposerScope = {\n kind: \"thread\";\n threadId: string;\n} | {\n kind: \"queued-message\";\n threadId: string;\n queuedMessageId: string;\n} | {\n kind: \"side-chat\";\n projectId: string;\n parentThreadId: string;\n tabId: string;\n childThreadId: string | null;\n} | {\n kind: \"new-thread\";\n /** Root compose's effective selected project; null only while unresolved. */\n projectId: string | null;\n};\n/** One plugin-owned composer customization registration. */\ninterface ComposerCustomization {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Composer kinds where this customization is active; omit for all kinds. */\n scopes?: readonly PluginComposerScope[\"kind\"][];\n actions?: readonly {\n id: string;\n component: ComponentType;\n }[];\n banners?: readonly {\n id: string;\n /** Host chrome around the banner. Defaults to `\"card\"`. */\n chrome?: \"bare\" | \"card\";\n component: ComponentType;\n }[];\n plusMenu?: readonly ComposerPlusMenuItem[];\n richText?: ComposerRichTextSpec;\n}\n/** Host-rendered menu row in the composer's `+` menu. */\ninterface ComposerPlusMenuItem {\n id: string;\n label: string;\n /** BB icon name; unknown names fall back to the generic plugin icon. */\n icon?: string;\n /** Accessible description for the host-rendered row. */\n description?: string;\n disabled?: boolean | ((view: ComposerView) => boolean);\n run(context: {\n composer: PluginComposerApi;\n view: ComposerView;\n }): void | Promise;\n}\n/** Reactive read-side of the composer a plugin surface is mounted in. */\ninterface ComposerView {\n scope: PluginComposerScope;\n layout: \"compact\" | \"expanded\" | \"zen\";\n draft: {\n text: string;\n isEmpty: boolean;\n attachmentCount: number;\n };\n run: {\n isRunning: boolean;\n isSubmitting: boolean;\n };\n}\ninterface ComposerRichTextSpec {\n /** Content-derived paint: match ranges receive `className`; text is never mutated. */\n effects?: readonly {\n id: string;\n /** Plain-text offsets into the current structured draft. */\n match(text: string): readonly {\n from: number;\n to: number;\n }[];\n className: string;\n }[];\n /** Debounced, read-only observation of the structured draft. */\n onDraftChange?(draft: ComposerStructuredDraft, view: ComposerView): void;\n}\ninterface ComposerStructuredDraft {\n text: string;\n mentions: readonly {\n from: number;\n to: number;\n provider: string;\n id: string;\n label: string;\n }[];\n}\n/** Host-rendered paint applied to the editable composer text. */\ninterface PluginComposerTextEffect {\n className: string;\n}\n/** Host-rendered status that temporarily replaces a thread's draft glyph. */\ninterface PluginComposerThreadRowStatus {\n /** BB icon-name hint; unknown names fall back to the generic plugin icon. */\n icon: string;\n /** Accessible label for the status glyph. */\n label: string;\n /**\n * Semantic host treatment for the status glyph. `running` automatically\n * shimmers; terminal `success` and `error` tones are static. Defaults to the\n * neutral tone.\n */\n tone?: \"default\" | \"error\" | \"running\" | \"success\";\n}\n/** An @-mention pill bound to one of the calling plugin's mention providers. */\ninterface PluginComposerMention {\n /** Mention provider id registered by THIS plugin via `bb.ui.registerMentionProvider`. */\n provider: string;\n /** Item id your provider's `resolve` will receive at send time. */\n id: string;\n /** Pill text shown in the composer. */\n label: string;\n}\n/**\n * Programmatic access to the chat composer draft — the same shared draft the\n * built-in \"Add to chat\" affordances (file preview, diff, terminal selections)\n * write to. While a queued message is being edited, writes land in that\n * message's inline editor. In a side chat, writes land in the visible side-chat\n * draft. Otherwise, inside a thread context writes land in that thread's draft;\n * anywhere else (nav panel, homepage section) they seed the new-thread composer\n * draft, which persists until the user sends or clears it.\n */\ninterface PluginComposerApi {\n scope: PluginComposerScope;\n /** Current plain text for this composer scope. */\n readonly text: string;\n /**\n * Replace the draft's plain text. Attachments are preserved. Inline mentions\n * outside the changed range are preserved and rebased; mentions overlapped\n * by the replacement are removed because their text representation changed.\n */\n setText(next: string): void;\n /**\n * Replace the draft's plain text from the latest committed value. Uses the\n * same structured-state reconciliation as `setText`.\n */\n updateText(updater: (current: string) => string): void;\n /** Clear plain text without clearing independently attached files. */\n clear(): void;\n /**\n * Apply a host-rendered effect to this composer's editable text, or clear it.\n * Effects are scoped to the calling plugin and automatically clear when the\n * slot unmounts or its composer scope changes.\n */\n setTextEffect(effect: PluginComposerTextEffect | null): void;\n /**\n * Lock or unlock editing for this composer. Locks are scoped to the calling\n * plugin and automatically release when the slot unmounts or its composer\n * scope changes.\n */\n setInputLock(locked: boolean): void;\n /**\n * Append text to the draft as a `> ` blockquote block and focus the\n * composer. Blank text is a no-op. This is the \"reference this selection\n * in chat\" primitive.\n */\n addQuote(text: string): void;\n /**\n * Insert an @-mention pill that resolves through this plugin's mention\n * provider at send time — the durable way to reference an entity whose\n * content should be fetched fresh when the message is sent.\n */\n insertMention(mention: PluginComposerMention): void;\n /** Focus the composer caret at the end of the draft. */\n focus(): void;\n}\n/**\n * A consumer-supplied action on the messages of one `ThreadChat` instance,\n * rendered in the embedded timeline's per-message action bar alongside the\n * native and slot-registered actions. Unlike the `messageAction` slot this is\n * scoped to the rendering component, not registered globally.\n */\ninterface ThreadChatMessageAction {\n /** Unique within this ThreadChat instance; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Message roles the action applies to. Omitted = both user and assistant\n * messages.\n */\n roles?: readonly (\"assistant\" | \"user\")[];\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(message: ThreadChatMessageReference): void | Promise;\n}\n/**\n * Props of the host-owned `ThreadChat` component — one thread's chat\n * (timeline, and for the composer variants the full send/queue/draft\n * engine), rendered by the BB app inside a plugin slot. This is the\n * deliberate exception to the no-host-components rule (§5.5): a stable\n * product capability, not a UI kit. Versioned additive like slot props;\n * internal timeline rows, query hooks, and prompt-box configuration are\n * deliberately not exposed.\n */\ninterface ThreadChatProps {\n threadId: string;\n /**\n * \"full\" (default) is the page presentation (centered reading width);\n * \"compact\" is the side-panel presentation; \"timeline\" renders the\n * transcript without a composer.\n */\n variant?: \"compact\" | \"full\" | \"timeline\";\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the composer (ignored by `variant: \"timeline\"`). */\n focusRequest?: number;\n /**\n * Who controls the permission mode sends run with. \"inherit\" (default)\n * pins every send to the thread's own resolved default and renders the\n * picker as a dimmed label — a plugin surface can never widen it.\n * \"editable\" gives this chat its own picker, so the user can raise or\n * lower permissions for this thread independently of the thread it was\n * forked from. Ignored by `variant: \"timeline\"` (no composer).\n */\n permissionPolicy?: \"editable\" | \"inherit\";\n className?: string;\n /** Rendered above the conversation, scrolling with it. */\n leadingContent?: ReactNode;\n /**\n * Actions rendered in this instance's per-message action bar (see\n * {@link ThreadChatMessageAction}).\n */\n messageActions?: readonly ThreadChatMessageAction[];\n}\n/**\n * Every selection the composer resolved, JSON-serializable so a plugin can\n * forward it to its own backend rpc verbatim and hand it straight to\n * `bb.sdk.threads.spawn`.\n *\n * The split is deliberate: the composer owns *user selections*, the plugin\n * owns *filing and attribution*. `bb.sdk.threads.spawn` auto-fills\n * `origin: \"plugin\"` and `originPluginId`, so a thread created this way stays\n * attributed to the plugin — which it would not be if the component created\n * the thread itself. The plugin adds `sectionId`, `parentThreadId`, `title`,\n * and `visibility` to the request on its own; they are deliberately not\n * composer props.\n */\ninterface NewThreadRequest {\n /**\n * The selected project id. Choosing \"Don't work in a project\" submits BB's\n * personal-project id (not `null`) together with a `personal` workspace\n * environment. Forward those fields unchanged to `threads.spawn`; if the\n * plugin needs project metadata, request it from the plugin backend with\n * `bb.sdk.projects.list({ includePersonal: true })`.\n */\n projectId: string;\n providerId: string;\n model: string;\n reasoningLevel: ReasoningLevel;\n permissionMode: PermissionMode;\n /** Omitted when the selected provider has no service tiers. */\n serviceTier?: ServiceTier;\n /**\n * Per-field provenance (caller-explicit vs. default) for the execution\n * options above, forwarded to `spawn` so the server records what the user\n * actually chose.\n */\n executionInputSources: CreateExecutionInputSources;\n environment: CreateThreadEnvironmentArgs;\n input: PromptInput[];\n}\n/**\n * Props of the host-owned `experimental_NewThreadComposer` component — bb's\n * full new-thread compose surface (prompt editor with @-mentions and expand,\n * attachments, provider/model/reasoning picker, voice, submit, and the row\n * beneath with project, environment, branch-from, and permission mode),\n * rendered by the BB app inside a plugin slot.\n *\n * It is the create-side counterpart to `ThreadChat`: same deliberate\n * exception to the no-host-components rule (§5.5), same additive versioning.\n */\ninterface NewThreadComposerProps {\n /**\n * Seeds the project picker. The user can change it, including choosing\n * \"Don't work in a project\"; see {@link NewThreadRequest.projectId} for the\n * submitted projectless shape.\n */\n defaultProjectId?: string;\n /**\n * Seeds the provider picker. Like every `default*` prop this is a SEED, not\n * a controlled value: the composer stays uncontrolled, the user can change\n * it, and when omitted the composer falls back to the project's remembered\n * execution defaults exactly as before. When provided it takes precedence\n * over those project defaults.\n *\n * Re-seeding: the `default*` props are value-compared each render. When any\n * of them changes after mount, the composer re-seeds EVERY execution and\n * environment selection from the new props — including selections the user\n * had already touched — so switching between two saved records in the same\n * mounted composer reloads that record's values (the same rule\n * `defaultProjectId` already follows).\n *\n * Every seeded field is reported as caller-explicit in the submitted\n * request's `executionInputSources`. That is what makes the seed survive\n * `threads.spawn`: the server drops a requested `providerId`/`model` that\n * carries no provenance source and re-derives it from the project's stored\n * defaults, which would silently undo the seed.\n */\n defaultProviderId?: string;\n /** Seeds the model picker. Same seed semantics as {@link defaultProviderId}. */\n defaultModel?: string;\n /**\n * Seeds the reasoning-level picker. Same seed semantics as\n * {@link defaultProviderId}. If the seeded model does not support this\n * level, the composer reconciles to the closest supported one.\n */\n defaultReasoningLevel?: ReasoningLevel;\n /**\n * Seeds the service-tier picker. Same seed semantics as\n * {@link defaultProviderId}. Ignored (and omitted from the submitted\n * request) when the selected provider has no service tiers.\n */\n defaultServiceTier?: ServiceTier;\n /** Seeds the permission-mode picker. Same seed semantics as {@link defaultProviderId}. */\n defaultPermissionMode?: PermissionMode;\n /**\n * Seeds the environment and branch pickers from a previously submitted\n * `NewThreadRequest.environment`. Same seed semantics as\n * {@link defaultProviderId}: a seed the user can change, taking precedence\n * over the composer's own environment default when provided.\n *\n * Round trip: feeding a submitted request's `environment` back in and\n * resubmitting untouched reproduces an equivalent environment, with these\n * documented limits — the composer cannot represent every args variant:\n *\n * - `{ type: \"project-default\" }` seeds nothing; the composer resolves its\n * own default and submits that concrete environment instead.\n * - A `host` environment whose host no longer exists (or whose project has\n * no source on it) falls back to the composer's default host, exactly as\n * the primary compose surface would.\n * - A `reuse` environment whose worktree no longer has unarchived threads\n * falls back the same way.\n * - An `unmanaged` workspace's `path` has no composer control; the seeded\n * selection submits `path: null` (the host's configured checkout). The\n * composer itself never produces a non-null `path`, so real round trips\n * are unaffected.\n * - A `managed-worktree` with `baseBranch: { kind: \"default\" }` leaves the\n * branch picker on its default, which may resolve to a named base branch\n * when the project configures a dedicated worktree base — the same branch\n * the original `default` submission would have created from.\n */\n defaultEnvironment?: CreateThreadEnvironmentArgs;\n /** Seeds the draft, only while the draft is still empty. */\n initialPrompt?: string;\n placeholder?: string;\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the editor. */\n focusRequest?: number;\n className?: string;\n /**\n * Where the draft persists. Drafts survive reloads and are shared by every\n * composer using the same key; defaults to a key scoped to this plugin.\n */\n draftKey?: string;\n /**\n * Fires on submit with every selection resolved. The draft clears when this\n * resolves and is KEPT if it throws, so a failed create never loses what the\n * user typed.\n */\n onSubmit: (request: NewThreadRequest) => void | Promise;\n}\n/**\n * Props of the host-owned `Markdown` component — bb's chat message renderer\n * (the same typography, spacing, and code styling as timeline messages).\n * Use it wherever plugin UI quotes or previews message content so it reads\n * like the rest of the chat. Like `ThreadChat`, this is a stable product\n * capability, not a UI kit; renderer internals stay private.\n */\ninterface MarkdownProps {\n /** Markdown source, rendered exactly like a chat message body. */\n content: string;\n className?: string;\n}\n/** Current app selection, derived from the route. */\ninterface BbContext {\n projectId: string | null;\n threadId: string | null;\n}\ninterface BbNavigate {\n toThread(threadId: string): void;\n toProject(projectId: string): void;\n /**\n * Navigate to one of this plugin's own nav panels by its `path`.\n * `subPath` targets a location inside the panel (the component's\n * `subPath` prop); `replace` swaps the current history entry instead of\n * pushing — use it for redirects so back does not bounce.\n */\n toPluginPanel(path: string, options?: {\n subPath?: string;\n replace?: boolean;\n }): void;\n /**\n * Navigate to the root compose surface (the new-thread screen). Pass\n * `initialPrompt` to seed the composer draft and `focusPrompt` to focus the\n * composer on arrival — the pairing behind \"Create via chat\" style entry\n * points that drop the user into chat with a prefilled prompt.\n */\n toCompose(options?: {\n initialPrompt?: string;\n focusPrompt?: boolean;\n }): void;\n /**\n * Open one of this plugin's registered thread-panel actions in the current\n * thread surface. Returns false when the surface has no thread side panel or\n * the action is unavailable.\n */\n openThreadPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * Everything `@get-bb/plugin-sdk/app` resolves to at runtime. The BB app builds\n * the real implementation and `satisfies` this interface; `bb plugin build`\n * shims the specifier to that object on `globalThis.__bbPluginRuntime`.\n */\ninterface PluginSdkApp {\n definePluginApp(setup: PluginAppSetup): PluginAppDefinition;\n useRpc(): PluginRpcClient;\n useRealtime(channel: string, handler: (payload: unknown) => void): void;\n /**\n * Observe the same shared connection that delivers `useRealtime` signals.\n * Use a subsequent transition to `connected` to reconcile server state that\n * may have changed while ephemeral signals could not be delivered. The first\n * connection can transition from `connecting` and is not a reconnection.\n */\n useRealtimeConnectionState(): PluginRealtimeConnectionState;\n useSettings(): PluginSettingsState;\n useBbContext(): BbContext;\n useBbNavigate(): BbNavigate;\n useComposer(): PluginComposerApi;\n /**\n * The sidebar's live thread view (see {@link PluginSidebarThreadsState}).\n * Reads the host's own cache and realtime subscriptions, so it costs no\n * extra request and updates exactly when the built-in sidebar does.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreads(): PluginSidebarThreadsState;\n /**\n * Thread actions bound to the host's mutations (see\n * {@link PluginSidebarThreadActions}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_useSidebarThreadActions(): PluginSidebarThreadActions;\n /**\n * The pull request for one thread's branch (see\n * {@link PluginSidebarThreadPullRequestState}).\n *\n * Per row and opt-in, because it costs a git-host lookup: it is NOT on the\n * thread payload every sidebar loads. Threads sharing an environment share\n * one query, and the host owns the polling and staleness rules — an open PR\n * with pending checks refreshes, a merged one does not.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadPullRequest(threadId: string): PluginSidebarThreadPullRequestState;\n /**\n * Per-row drag-to-split support (see {@link PluginSidebarThreadSplit}).\n * Call it once per rendered row, like the built-in sidebar does.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadSplit(threadId: string): PluginSidebarThreadSplit;\n /**\n * The host-owned chat component (see {@link ThreadChatProps}). Together\n * with `Markdown`, the only components the SDK ships — everything else\n * stays vendored per §5.5.\n */\n ThreadChat: ComponentType;\n /**\n * The host-owned chat-message markdown renderer (see\n * {@link MarkdownProps}).\n */\n Markdown: ComponentType;\n /**\n * The host-owned new-thread compose surface (see\n * {@link NewThreadComposerProps}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_NewThreadComposer: ComponentType;\n useComposerView(): ComposerView;\n}\n\ninterface EnvironmentActionArgs {\n environmentId: string;\n}\ninterface EnvironmentGetArgs extends EnvironmentActionArgs {\n signal?: AbortSignal;\n}\ntype EnvironmentMergeBaseBranchUpdateValue = Exclude;\ntype EnvironmentNameUpdateValue = Exclude;\ninterface EnvironmentMergeBaseBranchUpdate {\n mergeBaseBranch: EnvironmentMergeBaseBranchUpdateValue;\n name?: EnvironmentNameUpdateValue;\n}\ninterface EnvironmentNameUpdate {\n mergeBaseBranch?: EnvironmentMergeBaseBranchUpdateValue;\n name: EnvironmentNameUpdateValue;\n}\ntype EnvironmentUpdateFields = EnvironmentMergeBaseBranchUpdate | EnvironmentNameUpdate;\ntype EnvironmentUpdateArgs = EnvironmentUpdateFields & {\n environmentId: string;\n};\ninterface EnvironmentStatusArgs extends EnvironmentStatusQuery {\n environmentId: string;\n signal?: AbortSignal;\n}\ntype EnvironmentDiffArgs = EnvironmentDiffQuery & {\n environmentId: string;\n signal?: AbortSignal;\n};\ntype EnvironmentDiffFileArgs = EnvironmentDiffFileQuery & {\n environmentId: string;\n signal?: AbortSignal;\n};\ninterface EnvironmentDiffBranchesArgs extends EnvironmentDiffBranchesQuery {\n environmentId: string;\n signal?: AbortSignal;\n}\ninterface EnvironmentCommitArgs {\n environmentId: string;\n}\ninterface EnvironmentSquashMergeArgs {\n environmentId: string;\n mergeBaseBranch: string;\n}\ninterface EnvironmentPullRequestMergeArgs {\n environmentId: string;\n method: PullRequestMergeMethod;\n}\ntype EnvironmentDiffPatchArgs = EnvironmentDiffPatchRequest & {\n environmentId: string;\n signal?: AbortSignal;\n};\ninterface EnvironmentPathsArgs extends EnvironmentPathsQuery {\n environmentId: string;\n signal?: AbortSignal;\n}\ntype EnvironmentArchiveThreadsResult = EnvironmentArchiveThreadsResponse;\ntype EnvironmentCommitResult = CommitActionResponse;\ntype EnvironmentDiffResult = EnvironmentDiffResponse;\ntype EnvironmentDiffBranchesResult = EnvironmentDiffBranchesResponse;\ntype EnvironmentDiffFileResult = EnvironmentDiffFileResponse;\ntype EnvironmentDiffFilesResult = EnvironmentDiffFilesResponse;\ntype EnvironmentDiffPatchResult = EnvironmentDiffPatchResponse;\ntype EnvironmentGetResult = Environment;\ntype EnvironmentMarkPullRequestDraftResult = PullRequestDraftActionResponse;\ntype EnvironmentMarkPullRequestReadyResult = PullRequestReadyActionResponse;\ntype EnvironmentMergePullRequestResult = PullRequestMergeActionResponse;\ntype EnvironmentPathsResult = WorkspacePathListResponse;\ntype EnvironmentPullRequestResult = EnvironmentPullRequestResponse;\ntype EnvironmentSquashMergeResult = SquashMergeActionResponse;\ntype EnvironmentStatusResult = EnvironmentStatusResponse;\ntype EnvironmentUpdateResult = Environment;\ninterface EnvironmentsArea {\n archiveThreads(args: EnvironmentActionArgs): Promise;\n commit(args: EnvironmentCommitArgs): Promise;\n diff(args: EnvironmentDiffArgs): Promise;\n diffBranches(args: EnvironmentDiffBranchesArgs): Promise;\n diffFile(args: EnvironmentDiffFileArgs): Promise;\n diffFiles(args: EnvironmentDiffArgs): Promise;\n diffPatch(args: EnvironmentDiffPatchArgs): Promise;\n get(args: EnvironmentGetArgs): Promise;\n pullRequest(args: EnvironmentGetArgs): Promise;\n markPullRequestDraft(args: EnvironmentActionArgs): Promise;\n markPullRequestReady(args: EnvironmentActionArgs): Promise;\n mergePullRequest(args: EnvironmentPullRequestMergeArgs): Promise;\n paths(args: EnvironmentPathsArgs): Promise;\n squashMerge(args: EnvironmentSquashMergeArgs): Promise;\n status(args: EnvironmentStatusArgs): Promise;\n update(args: EnvironmentUpdateArgs): Promise;\n}\n\n/**\n * Host file primitives. `hostId` may be omitted to target the server's\n * primary (local) host. `rootPath`, when set, confines the target beneath\n * that absolute root on the host (symlink-safe).\n */\ninterface FileReadArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n signal?: AbortSignal;\n}\ninterface FileWriteArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n content: string;\n /** Defaults to \"utf8\". */\n contentEncoding?: \"base64\" | \"utf8\";\n /** Defaults to false. */\n createParents?: boolean;\n /**\n * Optimistic-concurrency guard: omitted → unconditional write; a hash →\n * write only when the current content hashes to it (use `read().sha256`);\n * null → create-only. A failed guard resolves to the `conflict` outcome.\n */\n expectedSha256?: string | null;\n /** POSIX permission bits used when creating a file (for example 0o600). */\n mode?: number;\n}\ninterface FileListArgs {\n hostId?: string;\n path: string;\n query?: string;\n limit?: number;\n signal?: AbortSignal;\n}\ninterface PathListArgs extends FileListArgs {\n includeFiles: boolean;\n includeDirectories: boolean;\n}\ninterface FileMkdirArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n recursive?: boolean;\n}\ninterface FileMoveArgs {\n hostId?: string;\n sourcePath: string;\n destinationPath: string;\n rootPath?: string;\n}\ninterface FileRemoveArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n recursive?: boolean;\n}\ninterface FilePreviewArgs {\n hostId?: string;\n rootPath: string;\n signal?: AbortSignal;\n ttlMs?: number;\n}\ntype FileReadResult = HostFileReadResponse;\ntype FileWriteResult = HostFileWriteResponse;\ntype FileListResult = HostFileListResponse;\ntype PathListResult = HostPathListResponse;\ntype FileMkdirResult = HostMkdirResponse;\ntype FileMoveResult = HostMovePathResponse;\ntype FileRemoveResult = HostRemovePathResponse;\ntype FilePreviewResult = CreateFilePreviewResponse;\ninterface FilesArea {\n read(args: FileReadArgs): Promise;\n write(args: FileWriteArgs): Promise;\n list(args: FileListArgs): Promise;\n listPaths(args: PathListArgs): Promise;\n mkdir(args: FileMkdirArgs): Promise;\n move(args: FileMoveArgs): Promise;\n remove(args: FileRemoveArgs): Promise;\n createPreview(args: FilePreviewArgs): Promise;\n}\n\ninterface GuideRenderArgs {\n chapter?: string;\n}\ninterface GuideRenderResult {\n chapter?: string;\n content: string;\n}\ninterface GuideArea {\n render(args?: GuideRenderArgs): GuideRenderResult;\n}\n\ninterface HostGetArgs {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostDeleteArgs {\n hostId: string;\n}\ninterface HostUpdateArgs extends UpdateHostRequest {\n hostId: string;\n}\ninterface HostRetryUpdateArgs {\n hostId: string;\n}\ninterface HostDirectoryArgs extends HostDirectoryQuery {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostCloneDefaultPathArgs extends HostCloneDefaultPathQuery {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostPathsExistArgs extends HostPathsExistRequest {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostPickFolderArgs extends HostPickFolderRequest {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostProviderCliInstallArgs extends HostProviderCliInstallRequest {\n hostId: string;\n}\ninterface HostListArgs {\n signal?: AbortSignal;\n}\ntype HostCreateJoinCodeResult = CreateHostJoinCodeResponse;\ntype HostDeleteResult = {\n ok: true;\n};\ntype HostDirectoryResult = HostDirectoryListing;\ntype HostGetResult = Host;\ntype HostCloneDefaultPathResult = HostCloneDefaultPathResponse;\ntype HostProviderCliInstallResult = HostProviderCliInstallEvent[];\ntype HostListResult = Host[];\ntype HostPathsExistResult = HostPathsExistResponse;\ntype HostPickFolderResult = HostPickFolderResponse;\ntype HostProviderCliStatusResult = HostProviderCliStatusResponse;\ntype HostRetryUpdateResult = HostRetryUpdateResponse;\ntype HostUpdateResult = Host;\ninterface HostsArea {\n createJoinCode(): Promise;\n delete(args: HostDeleteArgs): Promise;\n directory(args: HostDirectoryArgs): Promise;\n get(args: HostGetArgs): Promise;\n cloneDefaultPath(args: HostCloneDefaultPathArgs): Promise;\n installProviderCli(args: HostProviderCliInstallArgs): Promise;\n list(args?: HostListArgs): Promise;\n pathsExist(args: HostPathsExistArgs): Promise;\n pickFolder(args: HostPickFolderArgs): Promise;\n providerCliStatus(args: HostGetArgs): Promise;\n retryUpdate(args: HostRetryUpdateArgs): Promise;\n update(args: HostUpdateArgs): Promise;\n}\n\ninterface ProjectListArgs {\n include?: ProjectListQuery[\"include\"];\n /** Include the singleton personal project. Defaults to false for compatibility. */\n includePersonal?: boolean;\n signal?: AbortSignal;\n}\ninterface ProjectCreateArgs extends CreateProjectRequest {\n}\ninterface ProjectGetArgs {\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectUpdateArgs extends UpdateProjectRequest {\n projectId: string;\n}\ninterface ProjectDeleteArgs {\n projectId: string;\n}\ninterface ProjectReorderArgs extends ReorderProjectRequest {\n projectId: string;\n}\ninterface ProjectPromptHistoryArgs extends PromptHistoryQuery {\n projectId: string;\n signal?: AbortSignal;\n}\n/** Select one project workspace source, or omit both for the primary host. */\ntype ProjectWorkspaceRoutingArgs = {\n environmentId: string;\n hostId?: never;\n} | {\n environmentId?: never;\n hostId: string;\n} | {\n environmentId?: never;\n hostId?: never;\n};\ntype ProjectFilesArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ntype ProjectPathsArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ntype ProjectCommandsArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ntype ProjectFileContentArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ninterface ProjectBranchesArgs extends ProjectBranchesQuery {\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectDefaultExecutionOptionsArgs {\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectAttachmentFileLike {\n arrayBuffer(): Promise;\n readonly name: string;\n readonly type?: string;\n}\ninterface ProjectAttachmentUploadArgsBase {\n /** MIME override. Omit to use the File/Blob type, when available. */\n mimeType?: string;\n projectId: string;\n}\n/**\n * Upload bytes owned by this SDK client. A bare Blob/byte buffer needs an\n * explicit filename; File-like values can supply their own name.\n */\ntype ProjectAttachmentUploadArgs = ProjectAttachmentUploadArgsBase & ({\n clientFile: ProjectAttachmentFileLike;\n filename?: string;\n} | {\n clientFile: ArrayBuffer | Blob | Uint8Array;\n filename: string;\n});\ninterface ProjectAttachmentReadArgs {\n path: string;\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectAttachmentCopyArgs extends CopyProjectAttachmentsRequest {\n projectId: string;\n}\ntype ProjectSourceAddArgs = CreateProjectSourceRequest & {\n projectId: string;\n};\ninterface ProjectSourceUpdateArgs extends UpdateProjectSourceRequest {\n projectId: string;\n sourceId: string;\n}\ninterface ProjectSourceDeleteArgs {\n projectId: string;\n sourceId: string;\n}\ntype ProjectBranchesResult = ProjectBranchesResponse;\ninterface ProjectAttachmentReadResult {\n bytes: Uint8Array;\n mimeType: string;\n sizeBytes: number;\n}\ntype ProjectAttachmentUploadResult = UploadedPromptAttachment;\ntype ProjectCommandsResult = CommandListResponse;\ntype ProjectCreateResult = ProjectResponse;\ntype ProjectDefaultExecutionOptionsResult = ProjectExecutionDefaults | null;\ntype ProjectDeleteResult = {\n ok: true;\n};\ninterface ProjectFileContentResult {\n /** UTF-8 text or base64, as selected by `contentEncoding`. */\n content: string;\n contentEncoding: \"base64\" | \"utf8\";\n mimeType: string;\n sizeBytes: number;\n}\ntype ProjectFilesResult = WorkspaceFileListResponse;\ntype ProjectGetResult = ProjectResponse;\ntype ProjectListResult = ProjectResponse[] | ProjectWithThreadsResponse[];\ntype ProjectPathsResult = WorkspacePathListResponse;\ntype ProjectPromptHistoryResult = PromptHistoryResponse;\ntype ProjectReorderResult = ProjectResponse[];\ntype ProjectSourceAddResult = ProjectSource;\ntype ProjectSourceDeleteResult = {\n ok: true;\n};\ntype ProjectSourceUpdateResult = ProjectSource;\ntype ProjectUpdateResult = ProjectResponse;\ninterface ProjectSourcesArea {\n add(args: ProjectSourceAddArgs): Promise;\n delete(args: ProjectSourceDeleteArgs): Promise;\n update(args: ProjectSourceUpdateArgs): Promise;\n}\ninterface ProjectAttachmentsArea {\n copy(args: ProjectAttachmentCopyArgs): Promise;\n read(args: ProjectAttachmentReadArgs): Promise;\n upload(args: ProjectAttachmentUploadArgs): Promise;\n}\ninterface ProjectsArea {\n attachments: ProjectAttachmentsArea;\n branches(args: ProjectBranchesArgs): Promise;\n commands(args: ProjectCommandsArgs): Promise;\n create(args: ProjectCreateArgs): Promise;\n defaultExecutionOptions(args: ProjectDefaultExecutionOptionsArgs): Promise;\n delete(args: ProjectDeleteArgs): Promise;\n fileContent(args: ProjectFileContentArgs): Promise;\n files(args: ProjectFilesArgs): Promise;\n get(args: ProjectGetArgs): Promise;\n list(args?: ProjectListArgs): Promise;\n paths(args: ProjectPathsArgs): Promise;\n promptHistory(args: ProjectPromptHistoryArgs): Promise;\n reorder(args: ProjectReorderArgs): Promise;\n sources: ProjectSourcesArea;\n update(args: ProjectUpdateArgs): Promise;\n}\n\n/** Select exactly one provider-discovery host source, or omit both for primary. */\ntype ProviderHostRoutingArgs = {\n environmentId: string;\n hostId?: never;\n} | {\n environmentId?: never;\n hostId: string;\n} | {\n environmentId?: never;\n hostId?: never;\n};\ntype ProviderListArgs = ProviderHostRoutingArgs & {\n signal?: AbortSignal;\n};\ntype ProviderModelsArgs = ProviderHostRoutingArgs & {\n providerId?: string;\n signal?: AbortSignal;\n};\ntype ProviderListResult = ProviderInfo[];\ntype ProviderModelsResult = SystemExecutionOptionsResponse;\ninterface ProvidersArea {\n /** List providers on the environment host, explicit host, or primary host. */\n list(args?: ProviderListArgs): Promise;\n /** List models on the environment host, explicit host, or primary host. */\n models(args?: ProviderModelsArgs): Promise;\n}\n\ninterface PluginIdArgs {\n pluginId: string;\n}\n/** Install directly from a path:, git:, npm:, or builtin: source spec. */\ninterface PluginInstallArgs {\n /**\n * `path:`, `builtin:`, `npm:[@]`, or\n * `git:[@]`. A git spec is one ref, or a semver range resolved\n * over the repository's `[]vX.Y.Z` release tags:\n * `git:@semver:` and `git:@semver::` say\n * range explicitly, `git:@ref:` says ref explicitly, and a bare\n * `^1.2.0` resolves over tags unless the repository also has a ref of that\n * literal name (which is refused as ambiguous).\n */\n source: string;\n /**\n * Directory of a multi-plugin repository to install, relative to the\n * repository root (`git:` and `path:` sources only).\n */\n subdirectory?: string;\n /**\n * Name of a `.bb/plugins.json` collection entry to install, resolved to its\n * directory in the repository. Mutually exclusive with `subdirectory`.\n */\n plugin?: string;\n}\n/** Install a catalog entry, from BB's official catalog or another marketplace. */\ninterface PluginCatalogInstallArgs {\n entryId: string;\n /**\n * Marketplace that lists the entry. Omitted resolves across every\n * marketplace: exactly one match installs, none falls back to the bundled\n * official plugin of that name, and several are refused as ambiguous.\n */\n marketplace?: string;\n /**\n * Source facts returned by installPlan for a third-party entry. The server\n * refuses the install when the listing or its git commit changed afterward.\n */\n confirmedSource?: PluginCatalogResolvedSource;\n}\n/** Ask what an install would do before confirming it. */\ninterface PluginCatalogInstallPlanArgs {\n entryId: string;\n marketplace?: string;\n signal?: AbortSignal;\n}\n/** Add a marketplace by `https:` manifest URL, `git:[@ref]`, or `path:`. */\ninterface PluginMarketplaceAddArgs {\n source: string;\n}\ninterface PluginMarketplaceListArgs {\n signal?: AbortSignal;\n}\ninterface PluginMarketplaceRefreshArgs {\n /** One marketplace to refresh; omitted refreshes every one of them. */\n name?: string;\n signal?: AbortSignal;\n}\ninterface PluginMarketplaceRemoveArgs {\n name: string;\n}\ninterface PluginReloadArgs {\n pluginId?: string;\n}\ninterface PluginSettingsUpdateArgs extends PluginIdArgs {\n values: Record;\n}\ninterface PluginTokenArgs extends PluginIdArgs {\n rotate?: boolean;\n}\ninterface PluginCheckUpdatesArgs {\n pluginId?: string;\n signal?: AbortSignal;\n}\ninterface PluginRpcArgs extends PluginIdArgs {\n input?: JsonValue$1;\n method: string;\n outputSchema: z$1.ZodType;\n}\ninterface PluginCatalogSearchArgs {\n query: string;\n signal?: AbortSignal;\n}\ninterface PluginCatalogStatusArgs {\n signal?: AbortSignal;\n}\ninterface PluginGetSettingsArgs extends PluginIdArgs {\n signal?: AbortSignal;\n}\ninterface PluginGetSourceArgs extends PluginIdArgs {\n signal?: AbortSignal;\n}\ninterface PluginListArgs {\n signal?: AbortSignal;\n}\ninterface PluginListUpdateResultsArgs {\n signal?: AbortSignal;\n}\ntype PluginDisableResult = InstalledPlugin;\ntype PluginEnableResult = InstalledPlugin;\ntype PluginGetSettingsResult = PluginSettingsResponse;\ntype PluginInstallResult = InstalledPlugin;\ntype PluginListResult = PluginListResponse;\ntype PluginReloadResult = PluginReloadResponse;\ntype PluginRemoveResult = PluginRemoveResponse;\ntype PluginTokenResult = PluginTokenResponse;\ntype PluginUpdateSettingsResult = PluginSettingsResponse;\ntype PluginGetSourceResult = PluginSourceDetail;\ntype PluginCheckUpdatesResult = PluginUpdateCheckEntry[];\ntype PluginApplyUpdateResult = PluginApplyUpdateResult$1;\ntype PluginCatalogStatusResult = PluginCatalogStatus;\ntype PluginCatalogSearchResult = PluginCatalogSearchResult$1[];\ntype PluginCatalogInstallPlanResult = PluginCatalogInstallPlan;\ntype PluginMarketplaceListResult = PluginMarketplace[];\ntype PluginMarketplaceAddResult = PluginMarketplace;\ntype PluginMarketplaceRefreshResult = PluginMarketplaceRefreshResult$1[];\ninterface PluginMarketplaceRemoveResult {\n /** Installs whose provenance became `direct`; they keep running as before. */\n convertedPluginIds: string[];\n}\ninterface PluginCatalogArea {\n install(args: PluginCatalogInstallArgs): Promise;\n /** The true resolved source an install would use, before anything runs. */\n installPlan(args: PluginCatalogInstallPlanArgs): Promise;\n search(args: PluginCatalogSearchArgs): Promise;\n status(args?: PluginCatalogStatusArgs): Promise;\n}\n/** Registered marketplaces. Adding one installs nothing; removing one uninstalls nothing. */\ninterface PluginMarketplacesArea {\n add(args: PluginMarketplaceAddArgs): Promise;\n list(args?: PluginMarketplaceListArgs): Promise;\n refresh(args?: PluginMarketplaceRefreshArgs): Promise;\n remove(args: PluginMarketplaceRemoveArgs): Promise;\n}\ninterface PluginsArea {\n applyUpdate(args: PluginIdArgs): Promise;\n callRpc(args: PluginRpcArgs): Promise;\n checkUpdates(args?: PluginCheckUpdatesArgs): Promise;\n catalog: PluginCatalogArea;\n marketplaces: PluginMarketplacesArea;\n disable(args: PluginIdArgs): Promise;\n enable(args: PluginIdArgs): Promise;\n getSettings(args: PluginGetSettingsArgs): Promise;\n getSource(args: PluginGetSourceArgs): Promise;\n install(args: PluginInstallArgs): Promise;\n list(args?: PluginListArgs): Promise;\n listUpdateResults(args?: PluginListUpdateResultsArgs): Promise;\n reload(args?: PluginReloadArgs): Promise;\n remove(args: PluginIdArgs): Promise;\n token(args: PluginTokenArgs): Promise;\n updateSettings(args: PluginSettingsUpdateArgs): Promise;\n}\n\ntype BbRealtimeUnsubscribe = () => void;\ntype BbRealtimeEventName = \"environment:changed\" | \"host:changed\" | \"project:changed\" | \"realtime:connection\" | \"system:changed\" | \"system:config-changed\" | \"thread:changed\";\ntype ThreadRealtimeEvent = Extract;\ntype ProjectRealtimeEvent = Extract;\ntype EnvironmentRealtimeEvent = Extract;\ntype HostRealtimeEvent = Extract;\ntype SystemRealtimeEvent = Extract;\ntype BbRealtimeConnectionState = \"connected\" | \"connecting\" | \"disconnected\";\ninterface BbRealtimeConnectionEvent {\n reconnectDelayMs: number | null;\n reconnected: boolean;\n state: BbRealtimeConnectionState;\n}\n/**\n * Entity-changed events are delivered as one shared object to every matching\n * listener; their payload types are readonly so a listener cannot mutate what\n * the next listener receives.\n */\ninterface BbRealtimeEventMap {\n \"thread:changed\": ThreadRealtimeEvent;\n \"project:changed\": ProjectRealtimeEvent;\n \"environment:changed\": EnvironmentRealtimeEvent;\n \"host:changed\": HostRealtimeEvent;\n \"system:changed\": SystemRealtimeEvent;\n \"system:config-changed\": SystemRealtimeEvent;\n \"realtime:connection\": BbRealtimeConnectionEvent;\n}\ntype BbRealtimeCallback = (event: BbRealtimeEventMap[TEventName]) => void;\ninterface ThreadRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"thread:changed\">;\n event: \"thread:changed\";\n threadId?: string;\n}\ninterface ProjectRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"project:changed\">;\n event: \"project:changed\";\n projectId?: string;\n}\ninterface EnvironmentRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"environment:changed\">;\n environmentId?: string;\n event: \"environment:changed\";\n}\ninterface HostRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"host:changed\">;\n event: \"host:changed\";\n hostId?: string;\n}\ninterface SystemRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"system:changed\">;\n event: \"system:changed\";\n}\ninterface SystemConfigRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"system:config-changed\">;\n event: \"system:config-changed\";\n}\n/**\n * Connection listeners are pure observers — they never open or hold the\n * socket. A listener registered while a socket already exists receives the\n * latest connection event as a snapshot on the next microtask, so a status\n * UI mounted after connect still learns the current state.\n */\ninterface RealtimeConnectionSubscribeArgs {\n callback: BbRealtimeCallback<\"realtime:connection\">;\n event: \"realtime:connection\";\n}\ntype BbRealtimeSubscribeArgsUnion = ThreadRealtimeSubscribeArgs | ProjectRealtimeSubscribeArgs | EnvironmentRealtimeSubscribeArgs | HostRealtimeSubscribeArgs | SystemRealtimeSubscribeArgs | SystemConfigRealtimeSubscribeArgs | RealtimeConnectionSubscribeArgs;\ntype BbRealtimeSubscribeArgs = Extract;\ninterface BbRealtime {\n subscribe(args: BbRealtimeSubscribeArgs): BbRealtimeUnsubscribe;\n}\n\ninterface StatusGetArgs {\n projectId?: string;\n signal?: AbortSignal;\n threadId?: string;\n}\ninterface StatusThreadSummary {\n environmentId: string | null;\n id: string;\n parentThreadId: string | null;\n pinnedAt: number | null;\n projectId: string;\n status: ThreadStatus;\n title: string | null;\n}\ntype StatusProject = ProjectResponse;\ntype StatusChildThreads = ThreadListResponse;\ninterface StatusResult {\n childThreads: StatusChildThreads | null;\n pendingTodos: ThreadTimelinePendingTodos | null;\n project: StatusProject | null;\n thread: StatusThreadSummary | null;\n}\ninterface StatusArea {\n get(args?: StatusGetArgs): Promise;\n}\n\ninterface SkillWorkspaceArgs {\n projectId: string;\n environmentId: string | null;\n}\ninterface SkillListArgs extends SkillWorkspaceArgs {\n signal?: AbortSignal;\n}\ninterface SkillIdentityArgs extends SkillListArgs {\n skillId: string;\n}\ninterface SkillContentArgs extends SkillIdentityArgs {\n path: string;\n}\ninterface SkillUpdateArgs extends SkillWorkspaceArgs {\n skillId: string;\n content: string;\n revision: string;\n}\ninterface SkillDeleteArgs extends SkillWorkspaceArgs {\n skillId: string;\n}\n/**\n * Registry calls proxy out to skills.sh and GitHub, and the browse grid fans\n * out one per card. Callers pass their query's AbortSignal so abandoning a\n * page cancels its requests instead of leaving them in flight.\n */\ninterface AbortableArgs {\n signal?: AbortSignal;\n}\ninterface RegistrySkillsSearchArgs extends AbortableArgs {\n query?: string;\n page?: number;\n perPage?: number;\n}\ninterface RegistrySkillIdArgs extends AbortableArgs {\n registrySkillId: string;\n}\ninterface RegistrySkillEntriesArgs extends AbortableArgs {\n registrySkillIds: readonly string[];\n}\ninterface RegistrySkillSourceArgs extends AbortableArgs {\n source: string;\n skillId: string;\n}\ninterface RegistryRepositoryArgs extends AbortableArgs {\n source: string;\n}\n/**\n * Install is a mutation and deliberately takes no signal: its body is parsed\n * with a strict schema, so an extra key would throw at runtime.\n */\ninterface RegistrySkillInstallArgs {\n registrySkillId: string;\n}\ninterface SkillsRegistryArea {\n detail(args: RegistrySkillSourceArgs): Promise;\n entries(args: RegistrySkillEntriesArgs): Promise;\n get(args: RegistrySkillIdArgs): Promise;\n install(args: RegistrySkillInstallArgs): Promise;\n repositoryStars(args: RegistryRepositoryArgs): Promise;\n search(args?: RegistrySkillsSearchArgs): Promise;\n}\ninterface SkillsArea {\n getContent(args: SkillContentArgs): Promise;\n list(args: SkillListArgs): Promise;\n listFiles(args: SkillIdentityArgs): Promise;\n registry: SkillsRegistryArea;\n remove(args: SkillDeleteArgs): Promise<{\n deletedPath: string;\n }>;\n update(args: SkillUpdateArgs): Promise<{\n filePath: string;\n revision: string;\n }>;\n}\n\ntype ThemeGetResult = AppTheme;\ntype ThemeCatalogResult = ThemeCatalogResponse;\ntype ThemeSetInput = AppThemeSelection;\ntype ThemeSetResult = AppTheme;\ninterface ThemeCatalogArgs {\n signal?: AbortSignal;\n}\ninterface ThemeGetArgs {\n signal?: AbortSignal;\n}\ninterface ThemeArea {\n /** The active app palette, resolved server-side (built-in id or custom CSS). */\n get(args?: ThemeGetArgs): Promise;\n /** The custom-theme directory plus discovered themes and the active palette. */\n catalog(args?: ThemeCatalogArgs): Promise;\n /** Set the complete app appearance selection in one request. */\n set(selection: ThemeSetInput): Promise;\n /**\n * Activate a palette by id while preserving the active favicon color. This\n * compatibility shorthand reads the active appearance before writing the\n * complete selection; prefer the object form when both values are known.\n */\n set(themeId: string): Promise;\n}\n\ninterface SystemAttentionArgs {\n signal?: AbortSignal;\n}\ninterface SystemConfigArgs {\n signal?: AbortSignal;\n}\ninterface SystemExecutionOptionsArgs extends SystemExecutionOptionsQuery {\n signal?: AbortSignal;\n}\ninterface SystemUsageLimitsArgs extends SystemUsageLimitsQuery {\n signal?: AbortSignal;\n}\ninterface SystemVersionArgs {\n force?: boolean;\n signal?: AbortSignal;\n}\ninterface SystemVoiceTranscriptionArgs {\n file: Blob;\n prompt?: string;\n signal?: AbortSignal;\n}\ntype SystemAttentionResult = SystemAttentionResponse;\ntype SystemConfigResult = SystemConfigResponse;\ntype SystemExecutionOptionsResult = SystemExecutionOptionsResponse;\ntype SystemReloadConfigResult = SystemConfigReloadResponse;\ntype SystemInstallCliSkillsArgs = SystemInstallCliSkillsRequest;\ninterface SystemCliSkillsStatusArgs {\n /** Omit for every enrolled machine. */\n hostIds?: readonly string[];\n signal?: AbortSignal;\n}\ntype SystemCliSkillsStatusResult = SystemCliSkillsStatusResponse;\ntype SystemInstallCliSkillsResult = SystemInstallCliSkillsResponse;\ntype SystemVoiceTranscriptionResult = SystemVoiceTranscriptionResponse;\ntype SystemUpdateExperimentsResult = Experiments;\ntype SystemUpdateGeneralSettingsResult = AppSettings;\ntype SystemUpdateKeyboardSettingsResult = AppKeybindingOverrides;\ntype SystemUsageLimitsResult = ProviderUsageResponse;\ninterface SystemOnboardingArgs extends SystemProvidersQuery {\n signal?: AbortSignal;\n}\ninterface SystemOnboardingReposArgs extends SystemOnboardingReposQuery {\n signal?: AbortSignal;\n}\ntype SystemOnboardingAgentsResult = OnboardingAgentOverview;\ntype SystemOnboardingReposResult = DiscoverReposResult;\ntype SystemVersionResult = SystemVersionResponse;\ninterface SystemArea {\n attention(args?: SystemAttentionArgs): Promise;\n config(args?: SystemConfigArgs): Promise;\n executionOptions(args?: SystemExecutionOptionsArgs): Promise;\n /**\n * Copy bb's built-in CLI skills into each named machine's global agent skill\n * roots (`~/.agents/skills` and `~/.claude/skills`). Machines install\n * independently; the result reports each machine's outcome.\n */\n /** Per-machine install state of bb's built-in CLI skills. */\n cliSkillsStatus(args?: SystemCliSkillsStatusArgs): Promise;\n installCliSkills(args: SystemInstallCliSkillsArgs): Promise;\n reloadConfig(): Promise;\n transcribeVoice(args: SystemVoiceTranscriptionArgs): Promise;\n updateExperiments(args: Experiments): Promise;\n updateGeneralSettings(args: AppSettings): Promise;\n updateKeyboardSettings(args: AppKeybindingOverrides): Promise;\n /** Report one onboarding funnel event to anonymous telemetry. */\n onboardingEvent(args: OnboardingTelemetryEvent): Promise<{\n ok: true;\n }>;\n /** Live agent state for onboarding: install, auth, and plan per provider. */\n onboardingAgents(args?: SystemOnboardingArgs): Promise;\n /** Candidate projects discovered on the host, ranked for onboarding. */\n onboardingRepos(args?: SystemOnboardingReposArgs): Promise;\n usageLimits(args?: SystemUsageLimitsArgs): Promise;\n version(args?: SystemVersionArgs): Promise;\n}\n\ninterface TerminalThreadScope {\n cwd?: never;\n environmentId?: never;\n hostId?: never;\n kind: \"thread\";\n threadId: string;\n}\ninterface TerminalEnvironmentScope {\n environmentId: string;\n cwd?: never;\n hostId?: never;\n kind: \"environment\";\n threadId?: never;\n}\ninterface TerminalHostPathListScope {\n /** Optional exact initial working-directory filter on the selected host. */\n cwd?: string;\n environmentId?: never;\n hostId: string;\n kind: \"host_path\";\n threadId?: never;\n}\ninterface TerminalHostPathCreateScope {\n /** Null starts in the selected host's home directory. */\n cwd: string | null;\n environmentId?: never;\n hostId: string;\n kind: \"host_path\";\n threadId?: never;\n}\ntype TerminalListScope = TerminalThreadScope | TerminalEnvironmentScope | TerminalHostPathListScope;\ntype TerminalCreateScope = TerminalThreadScope | TerminalEnvironmentScope | TerminalHostPathCreateScope;\ninterface TerminalListArgs {\n signal?: AbortSignal;\n scope: TerminalListScope;\n}\ninterface TerminalCreateArgs {\n cols: number;\n rows: number;\n scope: TerminalCreateScope;\n start?: CreateTerminalRequest[\"start\"];\n title?: string;\n}\ninterface TerminalTargetArgs {\n terminalId: string;\n}\ninterface TerminalGetArgs extends TerminalTargetArgs {\n signal?: AbortSignal;\n}\ninterface TerminalRenameArgs extends TerminalTargetArgs {\n title: UpdateTerminalRequest[\"title\"];\n}\ninterface TerminalCloseArgs extends TerminalTargetArgs {\n mode: \"force\" | \"if-clean\";\n}\ninterface TerminalInputArgs extends TerminalTargetArgs {\n dataBase64: TerminalInputRequest[\"dataBase64\"];\n}\ninterface TerminalResizeArgs extends TerminalTargetArgs {\n cols: TerminalResizeRequest[\"cols\"];\n rows: TerminalResizeRequest[\"rows\"];\n}\ninterface TerminalOutputArgs extends TerminalTargetArgs {\n limitChunks?: TerminalOutputQuery[\"limitChunks\"];\n signal?: AbortSignal;\n sinceSeq?: TerminalOutputQuery[\"sinceSeq\"];\n tailBytes?: TerminalOutputQuery[\"tailBytes\"];\n}\ntype TerminalRestartArgs = TerminalTargetArgs;\ntype TerminalListResult = TerminalListResponse;\ntype TerminalCreateResult = TerminalSession;\ntype TerminalGetResult = TerminalSession;\ntype TerminalRenameResult = TerminalSession;\ntype TerminalCloseResult = TerminalSession;\ntype TerminalInputResult = TerminalSession;\ntype TerminalResizeResult = TerminalSession;\ntype TerminalOutputResult = TerminalOutputResponse;\ntype TerminalRestartResult = TerminalSession;\ninterface TerminalsArea {\n close(args: TerminalCloseArgs): Promise;\n create(args: TerminalCreateArgs): Promise;\n get(args: TerminalGetArgs): Promise;\n input(args: TerminalInputArgs): Promise;\n list(args: TerminalListArgs): Promise;\n output(args: TerminalOutputArgs): Promise;\n rename(args: TerminalRenameArgs): Promise;\n /**\n * Replace a terminal with a shell at the same scope, size, and title.\n * The server serializes concurrent restarts and opens the replacement before\n * closing the old session, so a failed open leaves the old terminal running.\n * The original command is not replayed because terminal sessions do not\n * persist launch commands. The replacement has a new terminal ID.\n */\n restart(args: TerminalRestartArgs): Promise;\n resize(args: TerminalResizeArgs): Promise;\n}\n\ninterface ThreadListArgs {\n archived?: boolean;\n sectionId?: string;\n hasParent?: boolean;\n includeHidden?: boolean;\n limit?: number;\n offset?: number;\n originKind?: ThreadListQuery[\"originKind\"];\n originPluginId?: string;\n parentThreadId?: string;\n projectId?: string;\n signal?: AbortSignal;\n sourceThreadId?: string;\n unsectioned?: boolean;\n}\ninterface ThreadSearchArgs extends ThreadSearchQuery {\n signal?: AbortSignal;\n}\ninterface ThreadResolveMentionsArgs extends ResolveThreadMentionsRequest {\n signal?: AbortSignal;\n}\ninterface ThreadGetArgs {\n include?: ThreadGetQuery[\"include\"];\n signal?: AbortSignal;\n threadId: string;\n}\ntype ThreadGetResult = ThreadResponse | ThreadWithIncludesResponse;\ntype ThreadListResult = ThreadListResponse;\ntype ThreadSearchResult = ThreadSearchResponse;\ntype ThreadResolveMentionsResult = ResolveThreadMentionsResponse;\ninterface ThreadOutputResponse {\n output: string | null;\n}\ntype ThreadMutationResult = ThreadResponse;\ntype ThreadSpawnResult = ThreadResponse;\ntype ThreadForkResult = ThreadResponse;\ntype ThreadInteractionGetResult = PendingInteraction;\ntype ThreadInteractionListResult = ThreadPendingInteractionsResponse;\ntype ThreadInteractionResolveResult = PendingInteraction;\ntype ThreadInteractionRespondResult = PendingInteraction;\ntype ThreadInteractionCancelResult = PendingInteraction;\ntype ThreadEventsListResult = ThreadEventRow[];\ntype ThreadEventWaitResult = ThreadEventRow | null;\ntype ThreadTimelineResult = ThreadTimelineResponse;\ntype ThreadArchiveResult = ThreadArchiveAllResponse;\ntype ThreadOpenResult = ThreadOpenResponse;\ntype ThreadPaneActionResult = ThreadPaneActionResponse;\ntype ThreadDeleteResult = {\n ok: true;\n};\ntype ThreadSendResult = {\n ok: true;\n};\ntype ThreadEditMessageResult = EditMessageResponse;\ntype ThreadStopResult = {\n ok: true;\n};\ntype ThreadCompactResult = {\n ok: true;\n};\ntype ThreadBannerActionResult = {\n ok: true;\n};\ntype ThreadUnarchiveResult = {\n ok: true;\n};\ntype ThreadArchiveAllResult = ThreadArchiveAllResponse;\ntype ThreadReadStateResult = ThreadResponse;\ntype ThreadPinOrderResult = ThreadListResponse;\ntype ThreadPromptHistoryResult = PromptHistoryResponse;\ntype ThreadQueuedMessagesResult = ThreadQueuedMessageListResponse;\ntype ThreadQueuedMessageCreateResult = ThreadQueuedMessage;\ntype ThreadQueuedMessageUpdateResult = ThreadQueuedMessage;\ntype ThreadQueuedMessageDeleteResult = {\n ok: true;\n};\ntype ThreadQueuedMessageReorderResult = ThreadQueuedMessageListResponse;\ntype ThreadQueuedMessageSendResult = SendQueuedMessageResponse;\ntype ThreadQueuedMessageGroupBoundaryResult = ThreadQueuedMessageListResponse;\ntype ThreadTabsResult = ThreadTabsResponse;\ntype ThreadTabsUpdateResult = ThreadTabsResponse;\ntype ThreadStorageFilesResult = ThreadStorageFileListResponse;\ntype ThreadStoragePathsResult = ThreadStoragePathListResponse;\ntype ThreadChildSummaryResult = ThreadChildSummaryResponse;\ntype ThreadDefaultExecutionOptionsResult = ResolvedThreadExecutionOptions | null;\ntype ThreadConversationOutlineResult = ThreadConversationOutlineResponse;\ntype ThreadTimelineTurnSummaryDetailsResult = TimelineTurnSummaryDetailsResponse;\ninterface ThreadSpawnBaseArgs extends Omit {\n origin?: CreateThreadRequest[\"origin\"];\n originKind?: CreateThreadRequest[\"originKind\"];\n startedOnBehalfOf?: CreateThreadRequest[\"startedOnBehalfOf\"];\n}\ntype ThreadSpawnArgs = ThreadSpawnBaseArgs & ({\n input: CreateThreadRequest[\"input\"];\n prompt?: never;\n} | {\n input?: never;\n prompt: string;\n});\ninterface ThreadForkArgs extends Omit {\n origin?: ForkThreadRequest[\"origin\"];\n visibility?: ForkThreadRequest[\"visibility\"];\n workspace?: ForkThreadRequest[\"workspace\"];\n}\ninterface ThreadUpdateArgs extends UpdateThreadRequest {\n threadId: string;\n}\ninterface ThreadDeleteArgs extends DeleteThreadRequest {\n threadId: string;\n}\ninterface ThreadSendArgs extends SendMessageRequest {\n threadId: string;\n}\ninterface ThreadEditMessageArgs extends EditMessageRequest {\n threadId: string;\n}\ninterface ThreadActionArgs {\n threadId: string;\n}\ninterface ThreadStatusArgs extends ThreadActionArgs {\n signal?: AbortSignal;\n}\ninterface ThreadPromptHistoryArgs extends PromptHistoryQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadPinOrderArgs extends ReorderPinnedThreadRequest {\n threadId: string;\n}\ninterface ThreadQueuedMessageArgs {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadQueuedMessageCreateArgs extends CreateQueuedMessageRequest {\n threadId: string;\n}\ninterface ThreadQueuedMessageUpdateArgs extends ThreadQueuedMessageTargetArgs, UpdateQueuedMessageRequest {\n}\ninterface ThreadQueuedMessageTargetArgs {\n queuedMessageId: string;\n threadId: string;\n}\ninterface ThreadQueuedMessageSendArgs extends ThreadQueuedMessageTargetArgs, SendQueuedMessageRequest {\n}\ninterface ThreadQueuedMessageReorderArgs extends ThreadQueuedMessageTargetArgs, ReorderQueuedMessageRequest {\n}\ninterface ThreadQueuedMessageGroupBoundaryArgs extends SetQueuedMessageGroupBoundaryRequest {\n threadId: string;\n}\ninterface ThreadStorageFilesArgs extends ThreadStorageFilesQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadStoragePathsArgs extends ThreadStoragePathsQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadTimelineTurnSummaryDetailsArgs extends TimelineTurnSummaryDetailsQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadTabsUpdateArgs extends UpdateThreadTabsRequest {\n threadId: string;\n}\ninterface ThreadOpenArgs {\n threadId: string;\n split?: ThreadOpenSplit;\n file: ThreadOpenFile | null;\n}\ninterface ThreadPaneActionArgs {\n action: ThreadPaneAction;\n threadId: string;\n}\ninterface ThreadEventsListArgs {\n /** Return only events with a sequence greater than this value. */\n afterSeq?: string;\n /** Return only events with a sequence less than this value. */\n beforeSeq?: string;\n limit?: string;\n /** Defaults to ascending sequence order. */\n order?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n threadId: string;\n /** Return only these event types. */\n types?: readonly [ThreadEventType, ...ThreadEventType[]];\n}\ninterface ThreadEventWaitArgs {\n afterSeq?: string;\n signal?: AbortSignal;\n threadId: string;\n type: string;\n waitMs: string;\n}\ninterface ThreadTimelineArgs extends ThreadTimelineQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadOutputArgs {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadInteractionListArgs {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadInteractionTargetArgs {\n interactionId: string;\n threadId: string;\n}\ninterface ThreadInteractionGetArgs extends ThreadInteractionTargetArgs {\n signal?: AbortSignal;\n}\ninterface ThreadInteractionResolveArgs extends ThreadInteractionTargetArgs {\n resolution: PendingInteractionResolution;\n}\ninterface ThreadInteractionRespondArgs extends ThreadInteractionTargetArgs {\n value: JsonValue$1;\n}\ntype ThreadWaitTarget = {\n kind: \"status\";\n status: ThreadStatus;\n} | {\n kind: \"event\";\n eventType: string;\n};\ninterface ThreadWaitArgs {\n event?: string;\n pollIntervalMs?: number;\n signal?: AbortSignal;\n status?: ThreadStatus;\n threadId: string;\n timeoutMs?: number;\n}\ntype ThreadWaitResult = {\n event: NonNullable;\n matched: true;\n target: Extract;\n threadId: string;\n} | {\n matched: true;\n target: Extract;\n thread: ThreadGetResult;\n threadId: string;\n};\ninterface ThreadInteractionsArea {\n cancel(args: ThreadInteractionTargetArgs): Promise;\n get(args: ThreadInteractionGetArgs): Promise;\n list(args: ThreadInteractionListArgs): Promise;\n resolve(args: ThreadInteractionResolveArgs): Promise;\n respond(args: ThreadInteractionRespondArgs): Promise;\n}\ninterface ThreadEventsArea {\n list(args: ThreadEventsListArgs): Promise;\n wait(args: ThreadEventWaitArgs): Promise;\n}\ninterface ThreadQueuedMessagesArea {\n create(args: ThreadQueuedMessageCreateArgs): Promise;\n delete(args: ThreadQueuedMessageTargetArgs): Promise;\n list(args: ThreadQueuedMessageArgs): Promise;\n reorder(args: ThreadQueuedMessageReorderArgs): Promise;\n send(args: ThreadQueuedMessageSendArgs): Promise;\n setGroupBoundary(args: ThreadQueuedMessageGroupBoundaryArgs): Promise;\n update(args: ThreadQueuedMessageUpdateArgs): Promise;\n}\ninterface ThreadTabsArea {\n get(args: ThreadStatusArgs): Promise;\n update(args: ThreadTabsUpdateArgs): Promise;\n}\ninterface ThreadsArea {\n archive(args: ThreadActionArgs): Promise;\n archiveAll(args: ThreadActionArgs): Promise;\n childSummary(args: ThreadStatusArgs): Promise;\n compact(args: ThreadActionArgs): Promise;\n cancelPlan(args: ThreadActionArgs): Promise;\n clearGoal(args: ThreadActionArgs): Promise;\n conversationOutline(args: ThreadStatusArgs): Promise;\n defaultExecutionOptions(args: ThreadStatusArgs): Promise;\n delete(args: ThreadDeleteArgs): Promise;\n editMessage(args: ThreadEditMessageArgs): Promise;\n events: ThreadEventsArea;\n fork(args: ThreadForkArgs): Promise;\n get(args: ThreadGetArgs): Promise;\n interactions: ThreadInteractionsArea;\n list(args?: ThreadListArgs): Promise;\n markRead(args: ThreadActionArgs): Promise;\n markUnread(args: ThreadActionArgs): Promise;\n open(args: ThreadOpenArgs): Promise;\n paneAction(args: ThreadPaneActionArgs): Promise;\n output(args: ThreadOutputArgs): Promise;\n pin(args: ThreadActionArgs): Promise;\n promptHistory(args: ThreadPromptHistoryArgs): Promise;\n queuedMessages: ThreadQueuedMessagesArea;\n reorderPinned(args: ThreadPinOrderArgs): Promise;\n resolveMentions(args: ThreadResolveMentionsArgs): Promise;\n search(args: ThreadSearchArgs): Promise;\n send(args: ThreadSendArgs): Promise;\n spawn(args: ThreadSpawnArgs): Promise;\n /**\n * Stop active work and release the loaded agent runtime. This operation is\n * idempotent and preserves thread history for a later resume.\n */\n stop(args: ThreadActionArgs): Promise;\n tabs: ThreadTabsArea;\n timeline(args: ThreadTimelineArgs): Promise;\n timelineTurnSummaryDetails(args: ThreadTimelineTurnSummaryDetailsArgs): Promise;\n storageFiles(args: ThreadStorageFilesArgs): Promise;\n storagePaths(args: ThreadStoragePathsArgs): Promise;\n unarchive(args: ThreadActionArgs): Promise;\n unpin(args: ThreadActionArgs): Promise;\n update(args: ThreadUpdateArgs): Promise;\n wait(args: ThreadWaitArgs): Promise;\n}\n\ntype ThreadSectionCreateResult = ThreadSectionResponse;\ntype ThreadSectionUpdateResult = ThreadSectionMutationResponse;\ntype ThreadSectionDeleteResult = ThreadSectionMutationResponse;\ntype ThreadSectionListResult = ThreadSectionResponse[];\ninterface ThreadSectionListArgs {\n signal?: AbortSignal;\n}\ninterface ThreadSectionsArea {\n create(args: CreateThreadSectionRequest): Promise;\n delete(args: DeleteThreadSectionRequest): Promise;\n list(args?: ThreadSectionListArgs): Promise;\n update(args: UpdateThreadSectionRequest): Promise;\n}\n\n/**\n * Every server-backed SDK area. The Node SDK adds the local `guide` area on\n * top of this; the browser SDK omits it so the generated guide templates\n * (~112 KB of markdown) stay out of the web app's boot chunk.\n */\ninterface BbSdkAreas extends BbRealtime {\n environments: EnvironmentsArea;\n files: FilesArea;\n hosts: HostsArea;\n projects: ProjectsArea;\n plugins: PluginsArea;\n providers: ProvidersArea;\n skills: SkillsArea;\n status: StatusArea;\n system: SystemArea;\n terminals: TerminalsArea;\n theme: ThemeArea;\n threadSections: ThreadSectionsArea;\n threads: ThreadsArea;\n}\ninterface BbSdk extends BbSdkAreas {\n guide: GuideArea;\n}\n\ninterface ExperimentalHostSignalContract {\n readonly payload: PayloadSchema;\n}\ntype ExperimentalHostSignals = Readonly>;\ninterface ExperimentalHostCallOptions {\n readonly hostId: string;\n readonly signal?: AbortSignal;\n}\ninterface ExperimentalHostClient {\n call(method: MethodName, input: StandardSchemaV1InferInput, options: ExperimentalHostCallOptions): Promise>;\n /**\n * Subscribe to unexpected exits of this plugin's worker on a host daemon.\n * Graceful reload, disable, uninstall, and daemon shutdown do not emit this\n * event. A later call starts a fresh worker.\n */\n experimental_onWorkerExit(handler: (event: {\n readonly hostId: string;\n }) => void | Promise): () => void;\n /** Subscribe to a validated, ephemeral signal from this plugin's host entry. */\n experimental_onSignal(signal: SignalName, handler: (event: ExperimentalHostSignalEvent) => void | Promise): () => void;\n}\ninterface ExperimentalHostSignalEvent {\n readonly hostId: string;\n readonly payload: StandardSchemaV1InferOutput;\n}\ninterface ExperimentalHostPaths {\n /** Persistent directory scoped to this plugin on this daemon. */\n readonly dataDir: string;\n /** Temporary directory scoped to this worker process. */\n readonly tempDir: string;\n}\ntype ExperimentalHostWatchChangeType = \"create\" | \"delete\" | \"update\";\ninterface ExperimentalHostWatchChange {\n readonly path: string;\n readonly type: ExperimentalHostWatchChangeType;\n}\ntype ExperimentalHostWatchEvent = {\n readonly kind: \"changed\";\n readonly changes: readonly ExperimentalHostWatchChange[];\n} | {\n readonly kind: \"rescan-required\";\n} | {\n readonly kind: \"watch-error\";\n readonly message: string;\n};\ninterface ExperimentalHostWatchOptions {\n /** Absolute directory observed by the daemon's native watcher service. */\n readonly rootPath: string;\n /** Root-relative ignore entries using the native watcher syntax. */\n readonly ignoredPaths?: readonly string[];\n /** Quiet period before one coalesced delivery. Defaults to 75 ms. */\n readonly debounceMs?: number;\n /** Maximum time changes may wait. Defaults to 500 ms. */\n readonly maxWaitMs?: number;\n}\ninterface ExperimentalHostWatchSubscription {\n dispose(): Promise;\n}\ninterface ExperimentalHostWorkerLease {\n /** Release this worker-retention lease. Safe to call more than once. */\n dispose(): Promise;\n}\ntype ExperimentalHostWatchListener = (event: ExperimentalHostWatchEvent) => void | Promise;\ninterface ExperimentalHostRpcContext {\n /** Aborted when this request is cancelled or its worker is disposed. */\n readonly signal: AbortSignal;\n /** Aborted once for the lifetime of this worker process. */\n readonly lifecycle: {\n readonly signal: AbortSignal;\n };\n readonly experimental_paths: ExperimentalHostPaths;\n /** Publish a validated, ephemeral event to this plugin's server entry. */\n experimental_emitSignal(signal: SignalName, payload: StandardSchemaV1InferInput): Promise;\n /** Observe raw filesystem changes through the daemon's native watcher. */\n experimental_watch(options: ExperimentalHostWatchOptions, listener: ExperimentalHostWatchListener): Promise;\n /**\n * Keep this worker alive after the current call finishes. Active calls and\n * filesystem watches already retain it; use this only for other background\n * work. The daemon may stop an unretained worker after an idle period.\n */\n experimental_retainWorker(): ExperimentalHostWorkerLease;\n}\ntype ExperimentalHostRpcHandlers = {\n [MethodName in keyof Contract]: (input: StandardSchemaV1InferOutput, context: ExperimentalHostRpcContext) => StandardSchemaV1InferInput | Promise>;\n};\ninterface ExperimentalHostEntry {\n readonly experimental_apiVersion: 1;\n readonly contract: Contract;\n readonly experimental_signals?: Signals;\n readonly handlers: ExperimentalHostRpcHandlers;\n readonly dispose?: () => void | Promise;\n}\n/** Define the single host executable exported by `bb.host`. */\ndeclare function experimental_defineHostEntry(args: {\n contract: Contract;\n experimental_signals?: Signals;\n handlers: ExperimentalHostRpcHandlers;\n dispose?: () => void | Promise;\n}): ExperimentalHostEntry;\n\n/**\n * The backend plugin API contract — the `bb` object handed to a plugin's\n * `server.ts` factory (`export default function plugin(bb: BbPluginApi)`).\n *\n * Types only: the implementation lives in the BB server\n * (apps/server/src/services/plugins/plugin-api.ts), which imports these\n * shapes so the contract and the implementation cannot drift. Plugin authors\n * import them type-only (`import type { BbPluginApi } from\n * \"@get-bb/plugin-sdk\"`); the import is erased when BB loads the file.\n *\n * Runtime classes stay host-side. NeedsConfigurationError in particular is\n * matched by NAME, so plugin code needs no runtime import:\n * `throw Object.assign(new Error(msg), { name: \"NeedsConfigurationError\" })`.\n */\ninterface PluginLogger {\n debug(message: string): void;\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n/**\n * Declarative settings descriptors (`bb.settings.define`). Deliberately plain\n * data — not zod — so the host can render settings forms and the CLI can\n * parse values without executing plugin code.\n */\ntype PluginSettingDescriptor = {\n type: \"string\";\n label: string;\n description?: string;\n /** Stored in a 0600 file under /plugins//secrets/, never in the db or sent to the frontend. */\n secret?: true;\n default?: string;\n} | {\n type: \"boolean\";\n label: string;\n description?: string;\n default?: boolean;\n} | {\n type: \"select\";\n label: string;\n description?: string;\n options: string[];\n default?: string;\n} | {\n type: \"project\";\n label: string;\n description?: string;\n default?: string;\n};\ntype PluginSettingDescriptors = Record;\ntype PluginSettingValue = string | boolean;\n/** `default` present → non-optional value; absent → `T | undefined`. */\ntype PluginSettingsValues> = {\n [K in keyof Ds]: Ds[K] extends {\n default: string | boolean;\n } ? PluginSettingValueOf : PluginSettingValueOf | undefined;\n};\ntype PluginSettingValueOf = D extends {\n type: \"boolean\";\n} ? boolean : string;\ninterface PluginSettingsHandle> {\n /** Load-safe: callable inside the factory. */\n get(): Promise>;\n /** Fires after values change through the settings route/CLI. */\n onChange(listener: (next: PluginSettingsValues, prev: PluginSettingsValues) => void): void;\n}\ninterface PluginSettings {\n define>(descriptors: Ds): PluginSettingsHandle;\n}\ninterface PluginKvStorage {\n get(key: string): Promise;\n set(key: string, value: unknown): Promise;\n delete(key: string): Promise;\n list(prefix?: string): Promise;\n}\ninterface PluginStorage {\n /** Namespaced JSON key-value rows in bb.db; values ≤256KB each. */\n kv: PluginKvStorage;\n /**\n * Open (or reuse the path of) the plugin's own SQLite database at\n * /plugins//data.db — the server's better-sqlite3, WAL mode,\n * busy_timeout 5000. Handles are host-tracked and closed on\n * dispose/reload; a closed handle throws on use.\n */\n database(): Database.Database;\n /**\n * Ordered-statement migration helper: statement index = migration id in a\n * `_bb_migrations` table; unapplied statements run in one transaction.\n * Append-only — never reorder or edit shipped statements.\n */\n migrate(db: Database.Database, statements: string[]): void;\n}\n/**\n * Thread lifecycle events a plugin can observe (design §4.5). Observe-only:\n * handlers run fire-and-forget after the transition is applied and can never\n * block or veto it. `thread` is the same public DTO GET /threads/:id serves.\n */\ninterface PluginThreadEventPayloads {\n /** Fired after a thread row is created. */\n \"thread.created\": {\n thread: ThreadResponse;\n };\n /** Fired when a thread transitions into `active`. */\n \"thread.active\": {\n thread: ThreadResponse;\n };\n /** Fired when a thread transitions into `idle`. `lastAssistantText` is\n * assembled the same way GET /threads/:id/output is. */\n \"thread.idle\": {\n thread: ThreadResponse;\n lastAssistantText: string | null;\n };\n /** Fired when a thread transitions into `error`. `error` is the latest\n * system/error event message, when one exists. */\n \"thread.failed\": {\n thread: ThreadResponse;\n error: string | null;\n };\n /** Fired after a thread is archived (including cascade archives). */\n \"thread.archived\": {\n thread: ThreadResponse;\n };\n /** Fired after a thread is soft-deleted. */\n \"thread.deleted\": {\n thread: ThreadResponse;\n };\n}\ntype PluginThreadEventName = keyof PluginThreadEventPayloads;\ntype PluginThreadEventHandler = (payload: PluginThreadEventPayloads[E]) => void | Promise;\ntype PluginHttpAuthMode = \"local\" | \"none\" | \"token\";\ntype PluginHttpHandler = (context: Context) => Response | Promise;\ninterface PluginHttp {\n /**\n * Register an HTTP route, mounted at\n * `/api/v1/plugins//http/`. Auth modes (default \"local\"):\n * - \"local\": Origin/Host must be a local BB app origin; non-GET requires\n * content-type application/json (forces a CORS preflight).\n * - \"token\": requires the per-plugin token (`bb plugin token `) via\n * the x-bb-plugin-token header or ?token=.\n * - \"none\": no checks — only for signature-verified webhooks.\n */\n route(method: string, path: string, handler: PluginHttpHandler, opts?: {\n auth?: PluginHttpAuthMode;\n }): void;\n}\ninterface PluginRpc {\n /**\n * Register a Standard Schema-driven rpc contract and its inferred handlers,\n * served at POST\n * `/api/v1/plugins//rpc/` with \"local\" auth semantics. The\n * host validates input before invocation and output before strict JSON\n * serialization. The response is `{ ok: true, result }` or\n * `{ ok: false, error: { code, message, issues? } }`.\n */\n register(contract: Contract, handlers: PluginRpcHandlers): void;\n}\ninterface PluginRealtime {\n /**\n * Broadcast an ephemeral `plugin-signal` WS message\n * `{ pluginId, channel, payload }` to every connected client (V1 has no\n * per-channel subscriptions). `payload` must be JSON-serializable;\n * `undefined` is normalized to `null`. Nothing is persisted.\n */\n publish(channel: string, payload: unknown): void;\n}\ninterface PluginBackground {\n /**\n * Register a long-lived background service. `start` runs after the\n * factory completes and should resolve when `signal` aborts\n * (dispose/reload/disable/shutdown). A crash restarts it with capped\n * exponential backoff; throwing NeedsConfigurationError marks the plugin\n * `needs-configuration` and stops restarting until the next load.\n */\n service(name: string, service: {\n start(signal: AbortSignal): void | Promise;\n }): void;\n /**\n * Register a cron schedule (5-field expression, server-local time). The\n * durable row keyed (pluginId, name) is upserted at load; the periodic\n * sweep claims due rows with a CAS on next_run_at, but only while this\n * plugin is loaded. Failures land in last_status/last_error, visible in\n * `bb plugin list`.\n */\n schedule(name: string, cron: string, fn: () => void | Promise): void;\n}\ninterface PluginCliCommandInfo {\n name: string;\n summary: string;\n usage: string;\n}\n/** Context forwarded from the invoking CLI when known; all fields optional. */\ninterface PluginCliContext {\n cwd?: string;\n threadId?: string;\n projectId?: string;\n /** Aborted when the invoking CLI HTTP request disconnects. */\n signal?: AbortSignal;\n}\ntype PluginInteractionCancelReason = \"plugin-disposed\" | \"request-aborted\" | \"server-restarted\" | \"thread-deleted\" | \"thread-stopped\" | \"timeout\" | \"user\";\ntype PluginInteractionResult = {\n outcome: \"submitted\";\n value: JsonValue;\n} | {\n outcome: \"cancelled\";\n reason: PluginInteractionCancelReason;\n};\ninterface PluginInteractionRequest {\n threadId: string;\n rendererId: string;\n title: string;\n payload: JsonValue;\n /** Defaults to ten minutes; capped at one hour. */\n timeoutMs?: number;\n}\ninterface PluginCliResult {\n exitCode: number;\n stdout?: string;\n stderr?: string;\n}\n/**\n * Maximum combined UTF-8 bytes accepted from plugin CLI stdout and stderr.\n * This is the shared source of truth for production and the testing harness.\n */\ndeclare const PLUGIN_CLI_OUTPUT_MAX_BYTES: number;\ninterface PluginCliOutputLimitError {\n code: \"plugin_cli_output_too_large\";\n message: string;\n maxBytes: number;\n stdoutBytes: number;\n stderrBytes: number;\n totalBytes: number;\n}\n/** Normalized host result returned by the plugin CLI HTTP/testing boundary. */\ninterface PluginCliExecutionResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n error?: PluginCliOutputLimitError;\n}\ninterface PluginCliRegistration {\n /** Top-level command name (`bb …`): lowercase [a-z0-9-]+, and not\n * a core bb command (see RESERVED_BB_CLI_COMMANDS in the server). */\n name: string;\n summary: string;\n /** Subcommand metadata rendered in help and the plugin-commands skill\n * without executing plugin code. Parsing argv is plugin-owned. */\n commands?: PluginCliCommandInfo[];\n run(argv: string[], ctx: PluginCliContext): PluginCliResult | Promise;\n}\ninterface PluginCli {\n /**\n * Register this plugin's `bb` subcommand. One registration per factory\n * execution; a repeated call is rejected. Core bb commands always win\n * name collisions; reserved names are rejected at registration.\n */\n register(registration: PluginCliRegistration): void;\n}\n/** Per-turn context handed to bb.agents context providers (design §4.4). */\n/** MCP-style content parts a native tool may return (design §4.4). */\ntype PluginAgentToolContentPart = {\n type: \"text\";\n text: string;\n} | {\n type: \"image\";\n data: string;\n mimeType: string;\n};\ntype PluginAgentToolResult = string | {\n content: PluginAgentToolContentPart[];\n isError?: boolean;\n};\n/** Per-call context handed to a native tool's execute (design §4.4). */\ninterface PluginAgentToolContext {\n threadId: string;\n projectId: string;\n /** The tool-call request's abort signal (aborts if the daemon round-trip\n * is torn down mid-call). */\n signal: AbortSignal;\n}\n/**\n * Native timeline labels for a plugin tool, keyed by BB's own timeline row\n * status. This is experimental: BB may refine its presentation contract\n * before the field is stabilized.\n */\ninterface PluginAgentToolExperimentalStatusLabels {\n /** Label shown while the tool call is pending. */\n pending: string;\n /** Label shown after the tool call completes successfully. */\n completed: string;\n}\ninterface PluginAgentToolRegistrationBase {\n /** Tool name shown to the model: [a-zA-Z0-9_-]+, unique across plugins,\n * and not a built-in dynamic tool (see RESERVED_AGENT_TOOL_NAMES in the\n * server). */\n name: string;\n description: string;\n /**\n * Optional usage snippet appended to the thread instructions whenever\n * this tool is in the session's tool set (mirrors the built-in\n * update_environment_directory guidance). Limited to 4096 characters.\n */\n instructions?: string;\n /**\n * Optional native timeline labels. When omitted, BB shows the standard\n * tool name and arguments (for example, `Ran tool search_docs …`). Labels\n * apply only while the call is pending and after successful completion;\n * approval, error, and interruption states keep BB's standard rendering.\n */\n experimental_statusLabels?: PluginAgentToolExperimentalStatusLabels;\n}\n/** Stable, plain-data context resolved by the server for one agent session. */\ninterface PluginAgentConfigurationContext {\n thread: {\n id: string;\n title: string | null;\n parentThreadId: string | null;\n sourceThreadId: string | null;\n };\n project: {\n id: string;\n kind: \"personal\" | \"standard\";\n name: string;\n gitRemoteUrl: string | null;\n };\n environment: {\n id: string;\n name: string | null;\n path: string | null;\n workspaceProvisionType: \"managed-worktree\" | \"personal\" | \"unmanaged\";\n branchName: string | null;\n };\n host: {\n id: string;\n name: string;\n };\n provider: {\n id: string;\n model: string;\n /**\n * The provider's declared capabilities, so a plugin can decide what to\n * contribute from what the provider says it does rather than from its own\n * copy of a provider id list.\n */\n capabilities: {\n /**\n * The provider ships its own user-question affordance and bb routes it\n * into the pending-interaction path. A plugin offering the same thing\n * should withhold it here, or the model gets two ways to ask once.\n */\n supportsNativeUserQuestion: boolean;\n };\n };\n /** How the thread was spawned. A side chat is the builtin side-chat\n * plugin's fork: `{ kind: \"fork\", pluginId: \"side-chat\" }`. */\n origin: {\n kind: \"fork\" | null;\n pluginId: string | null;\n };\n}\n/** Object form of a {@link PluginAgentConfiguration} tools entry: selects a\n * registered tool and overrides the parameter schema advertised to the\n * provider for this resolution only. */\ninterface PluginAgentToolSelection {\n /** Name of a tool registered by this plugin via `registerTool`. */\n name: string;\n /** JSON-schema object (root `type: \"object\"`, JSON-serializable, at most\n * 128 KiB serialized) sent to the provider in place of the registered\n * parameter schema. Execution-side validation still runs the registered\n * parameters, so the override must only narrow what the registered schema\n * already accepts. Recursive local `$ref` chains are rejected. */\n parameters: Record;\n}\n/** Per-resolution selection returned by {@link PluginAgents.configure}. */\ninterface PluginAgentConfiguration {\n /** Tool names registered by this plugin, or {@link PluginAgentToolSelection}\n * entries to also override a tool's advertised parameter schema for this\n * resolution. Duplicate or unknown names, or an invalid override, reject\n * this plugin's complete selection for the resolution. */\n tools: Array;\n /** Skill frontmatter names from this plugin's manifest skill roots.\n * Duplicate or unknown names reject this plugin's complete selection. */\n skills: string[];\n /** Optional dynamic instructions. Output is truncated to 4096 characters. */\n instructions?: string;\n}\n/**\n * Permission modes a provider can run a session in — BB's own permission\n * vocabulary, ordered least (\"accept-edits\") to most (\"full\") privileged.\n */\ntype PluginProviderPermissionMode = \"accept-edits\" | \"auto\" | \"full\";\n/**\n * Coarse reasoning-effort ladder entries, ordered lowest to highest. The\n * declared ladder is a fallback only: precise per-model reasoning sets come\n * from the provider's model list at runtime.\n */\ntype PluginProviderReasoningLevel = \"high\" | \"low\" | \"max\" | \"medium\" | \"none\" | \"ultra\" | \"ultracode\" | \"xhigh\";\n/**\n * Composer actions a provider supports, by name only. The skills\n * slash-command typeahead is universal — BB injects skills into every\n * provider — so it is implicit and never declared, and the composer owns the\n * trigger syntax (`/plan `, `/goal `) rather than each declaration repeating\n * it.\n */\ntype PluginProviderComposerAction = \"goal\" | \"plan\";\n/**\n * Pre-session capability facts about a provider. A capability earns a field\n * here only when it passes BOTH tests: (1) a consumer outside the provider's\n * own plugin needs the fact, and (2) the fact is needed before / without a\n * live session (picker rendering, route gating, cross-plugin tool\n * composition — including with the host offline). Every boolean is a\n * provider-native fact — the provider implements the feature; the flag only\n * tells external consumers it exists. Everything else is a handshake fact the\n * bridge reports at `initialize`, where it cannot drift from behavior.\n */\ninterface PluginProviderCapabilities {\n /** The provider accepts a fast/priority service-tier choice — shows the\n * service-tier toggle in the picker. */\n supportsServiceTier: boolean;\n /** The provider ships its own native ask-user-question tool — the\n * ask-user-question plugin skips registering its duplicate. */\n supportsNativeUserQuestion: boolean;\n /**\n * How completely the provider can clone a session: `\"none\"` (not at all),\n * `\"tip\"` (only the current end, so thread fork works but edit-past-message\n * rewind cannot), or `\"checkpoint\"` (recreate the session at an earlier\n * point, which rewind needs). Gates the fork and edit-past-message\n * affordances. The bridge reports the same fact at `initialize`, where it\n * may narrow this declaration but never widen it.\n */\n fork: ProviderFork;\n /** The provider accepts an explicit context-compaction request — gates the\n * compact affordance. */\n supportsManualCompaction: boolean;\n /** The provider keeps its own thread archive, so BB mirrors archive and\n * unarchive onto it instead of tracking the state only in bb's own rows. */\n supportsThreadArchive: boolean;\n /** The provider stores a thread name of its own, so BB forwards renames to\n * it. */\n supportsThreadRename: boolean;\n /** The provider can run BB's Workflow tools — gates the workflows opt-in on\n * new threads. */\n supportsWorkflows: boolean;\n /** Permission modes the provider can actually run in. Non-empty, no\n * duplicates. */\n permissionModes: readonly PluginProviderPermissionMode[];\n /** The provider's coarse fallback reasoning ladder (see\n * {@link PluginProviderReasoningLevel}). Non-empty, no duplicates. */\n reasoningLevels: readonly PluginProviderReasoningLevel[];\n}\n/**\n * One provider this plugin contributes to BB's provider registry.\n *\n * Ids are stable public identifiers — thread rows and routes reference them —\n * and are collision-rejected: a declaration whose id matches another plugin's\n * live registration, or reserves a first-party provider it does not own, is\n * refused. Registrations are replaced wholesale on plugin reload, like every\n * other plugin surface.\n *\n * A declaration is metadata only. The implementation is the plugin's own\n * provider bridge, named by `bb.providerBridge` in the manifest and built into\n * the artifact BB ships to hosts — declaring a provider without one is\n * refused, because the picker entry would exist and no turn on it could ever\n * run.\n */\ninterface PluginProviderDeclaration {\n /** Stable provider id: 2–64 characters of lowercase letters, digits, and\n * \"-\", starting with a letter or digit. Existing ids must never change —\n * threads persist them. */\n id: string;\n /** Picker display name: 1–80 characters, non-blank. */\n displayName: string;\n /**\n * Optional picker icon, in the same grammar as `bb.branding.icon`: either a\n * named host glyph (`\"Zap\"`) or a plugin-relative path starting with `\"./\"`\n * (`\"./icons/agent.svg\"`). Paths follow the manifest entry-path escape rules\n * — no leading \"/\", no \"..\" segments, no backslashes.\n */\n icon?: string;\n /** Pre-session capability facts (see the declaration tests on\n * {@link PluginProviderCapabilities}). */\n capabilities: PluginProviderCapabilities;\n /** Composer actions this provider supports. No duplicates; may be empty\n * (the universal skills typeahead is implicit). */\n composerActions: readonly PluginProviderComposerAction[];\n}\ninterface PluginAgents {\n /**\n * Select this plugin's statically registered tools and manifest skills for\n * each thread/session resolution, with optional dynamic instructions. The\n * callback is synchronous and runs at `thread.start` / `turn.submit`; it\n * never rebuilds registrations. Exactly one callback may be registered per\n * factory execution. A throw, malformed result, duplicate id, unknown id,\n * or more than 256 tool/skill ids fails closed for this plugin only.\n *\n * Tools take effect when the provider session is next started or resumed;\n * an already-running session is not hot-mutated. Instructions follow the\n * same boundary: a live provider session keeps the instructions it was\n * constructed with, and a changed selection applies when the session is\n * next constructed. Skill changes follow BB's environment runtime policy:\n * a busy runtime keeps its current catalog until a safe relaunch. Side chats\n * are ordinary plugin-owned forks here — read `origin` to detect them — and\n * their returned tool, skill, and dynamic-instruction selections apply at the\n * same boundaries.\n */\n configure(provider: (context: PluginAgentConfigurationContext) => PluginAgentConfiguration): void;\n /**\n * Register a native dynamic tool (design §4.4). `parameters` is either a\n * zod schema (validated per call; execute receives the parsed value) or a\n * plain JSON-schema object (no validation; execute receives the raw\n * arguments as `unknown`). Tool-set changes apply on the NEXT session\n * start — a tool registered mid-session is not hot-added to running\n * provider sessions. A second registration of the same name within this\n * plugin is rejected; a name already registered by another plugin is\n * rejected and surfaced as this plugin's status detail. Recursive local\n * JSON Schema `$ref` chains are rejected because some model providers reject\n * the complete tool list when any one tool contains them.\n */\n registerTool(tool: PluginAgentToolRegistrationBase & {\n parameters: Schema;\n execute(params: z.output, ctx: PluginAgentToolContext): PluginAgentToolResult | Promise;\n }): void;\n registerTool(tool: PluginAgentToolRegistrationBase & {\n /** Raw JSON-schema escape hatch; params arrive unvalidated. */\n parameters: Record;\n execute(params: unknown, ctx: PluginAgentToolContext): PluginAgentToolResult | Promise;\n }): void;\n /**\n * Contribute a dynamic section appended to thread instructions. The\n * provider runs when a thread's runtime command config is resolved\n * (thread.start / turn.submit); return null to contribute nothing for\n * that resolution. A live provider session keeps the instructions it was\n * constructed with — a changed contribution takes effect when the\n * provider session is next constructed (thread start or resume after a\n * daemon restart, environment switch, or provider restart), never\n * mid-session. Must be synchronous and fast — it sits on the\n * thread-start path. Output longer than 4096 characters is truncated; a\n * throwing provider is logged against the plugin and contributes nothing.\n * A repeated registration within one factory execution is rejected.\n */\n contributeInstructions(provider: (ctx: {\n threadId: string;\n projectId: string;\n }) => string | null): void;\n /**\n * Register an agent provider this plugin contributes (experimental — see\n * docs/api_to_audit.md before relying on it). The declaration is validated\n * at call time; the provider joins the server's provider registry when the\n * plugin load commits and then appears in provider listings. Ids are stable\n * and collision-rejected: an id already claimed by a core provider or\n * another plugin fails this plugin's load. A plugin may register several\n * providers and may re-register after `dispose()` (a settings-driven\n * re-declaration); registrations are replaced wholesale on plugin reload,\n * like every other surface. The disposer removes the registration.\n */\n experimental_registerProvider(declaration: PluginProviderDeclaration): {\n dispose(): void;\n };\n}\ntype PluginMentionTrigger = \"!\" | \"#\" | \"$\" | \"@\" | \"~\";\n/** Search context handed to a mention provider (design §4.9). `projectId`/\n * `threadId` are null when the composer has not committed one yet. */\ninterface PluginMentionSearchContext {\n trigger: PluginMentionTrigger;\n query: string;\n projectId: string | null;\n threadId: string | null;\n}\n/** One row a mention provider returns from `search`. `id` is the provider's\n * own item id — the host namespaces it before it reaches the wire. */\ninterface PluginMentionItem {\n id: string;\n title: string;\n subtitle?: string;\n icon?: string;\n}\ninterface PluginMentionProviderRegistration {\n /** Unique within this plugin: [a-zA-Z0-9_-]+ (no \":\" — the host composes\n * wire item ids as \":\"). */\n id: string;\n /** Section label shown above this provider's rows in the mention menu. */\n label: string;\n /**\n * Composer trigger characters this provider should answer. Omit to use the\n * default `@` mention trigger. Valid triggers are `@`, `#`, `$`, `!`, and `~`.\n */\n triggers?: readonly PluginMentionTrigger[];\n /**\n * Runs server-side as the user types after one of this provider's triggers\n * in the composer. Each call is time-boxed (2s) and failure-isolated: a slow\n * or throwing provider contributes an empty list — it can never break the\n * mention menu.\n */\n search(ctx: PluginMentionSearchContext): PluginMentionItem[] | Promise;\n /**\n * Resolves one picked item into agent context, called once per unique\n * item at message send time. The returned `context` is attached to the\n * message as an agent-visible (user-hidden) prompt input. Throwing blocks\n * the send with a visible error.\n */\n resolve(itemId: string): {\n context: string;\n } | Promise<{\n context: string;\n }>;\n}\ninterface PluginUi {\n /** Block until the app submits or cancels a plugin-owned composer form. */\n requestInput(request: PluginInteractionRequest, options?: {\n signal?: AbortSignal;\n }): Promise;\n /**\n * Register a mention provider for the shipped app's composer (design §4.9).\n * Providers default to the `@` trigger and may opt into `#`, `$`, `!`, or\n * `~` with `triggers`. Items group under `label` in the mention menu; a\n * picked item becomes a `{ kind: \"plugin\" }` mention resource whose context\n * is resolved once at send time. Multiple providers per plugin; ids must be\n * unique within the plugin.\n */\n registerMentionProvider(provider: PluginMentionProviderRegistration): void;\n}\ninterface PluginEvents {\n /**\n * Add a thread lifecycle listener. Multiple listeners for the same event are\n * additive and run independently in registration order.\n */\n on(event: E, handler: PluginThreadEventHandler): void;\n}\ninterface PluginServerApi {\n /**\n * This BB server's own loopback base URL (e.g. \"http://127.0.0.1:38886\"),\n * which serves the SPA + /api + /ws. For plugins that proxy or relay\n * traffic back to the server itself (e.g. a tunnel). Bind-gated like\n * `bb.sdk`: reading it before the server is listening throws, so prefer\n * reading it from handlers, services, and timers.\n */\n readonly loopbackBaseUrl: string;\n}\ninterface PluginSharedPortTunnelIdentity {\n /** Gate routing label assigned to this machine. */\n label: string;\n /** Gate apex without a scheme, e.g. \"getbb.app\". */\n baseDomain: string;\n}\ninterface PluginHosts {\n /** Create the owning plugin's typed client for its singular `bb.host` entry. */\n experimental_client(args: {\n contract: Contract;\n experimental_signals?: Signals;\n }): ExperimentalHostClient;\n /**\n * Ensure this enrolled host has a gate label and return its read-only public\n * identity. The daemon chooses the trusted gate and desired label; plugins\n * cannot influence either credential-bearing destination.\n */\n ensureSharedPortTunnel(hostId: string): Promise;\n /**\n * Replace this plugin's desired shared-loopback ports for one host. The\n * server aggregates declarations, owns generations, and delivers the\n * resulting set to that host's daemon. Tunnel identity is deliberately not\n * accepted here: it is owned by the daemon's trusted enrollment.\n */\n declareSharedPorts(hostId: string, ports: readonly number[]): void;\n}\ninterface PluginStatusApi {\n /**\n * Mark this plugin `needs-configuration` (with a message shown in\n * `bb plugin list` and the UI) instead of failing — e.g. a factory or\n * service that finds no API key configured. Cleared on the next load;\n * saving settings does not auto-reload in V1, so ask the user to\n * `bb plugin reload ` after configuring.\n */\n needsConfiguration(message: string): void;\n}\n/**\n * The API object handed to a plugin's factory (design §4). Implemented by\n * the BB server; this contract is what plugin `server.ts` files compile\n * against.\n */\ninterface BbPluginApi {\n /** The plugin's own id (namespaces storage, routes, commands). */\n readonly pluginId: string;\n /** Leveled, plugin-scoped logger. */\n readonly log: PluginLogger;\n /** Declarative settings (design §4.2). */\n readonly settings: PluginSettings;\n /** Namespaced KV + per-plugin database (design §4.3). */\n readonly storage: PluginStorage;\n /** HTTP routes under /api/v1/plugins//http/* (design §4.6). */\n readonly http: PluginHttp;\n /** RPC methods under /api/v1/plugins//rpc/ (design §4.6). */\n readonly rpc: PluginRpc;\n /** Ephemeral push to connected frontends (design §4.7). */\n readonly realtime: PluginRealtime;\n /** Long-lived services + cron schedules (design §4.8). */\n readonly background: PluginBackground;\n /** Agent-facing `bb` CLI subcommand (design §4.4). */\n readonly cli: PluginCli;\n /** Per-turn agent context contributions (design §4.4). */\n readonly agents: PluginAgents;\n /** Host-rendered UI contributions (design §4.9). */\n readonly ui: PluginUi;\n /** Additive plugin lifecycle listeners (design §4.5). */\n readonly events: PluginEvents;\n /** Plugin-reported status (needs-configuration). */\n readonly status: PluginStatusApi;\n /** Read-only facts about the running server (loopback base URL). */\n readonly server: PluginServerApi;\n /** Server-to-daemon host control-plane declarations. */\n readonly hosts: PluginHosts;\n /**\n * The full BB SDK, bound to this server over loopback (design §4.1).\n * Bind-gated: reading this before the host binds the SDK throws. The real\n * server binds it before loading plugins, so it is available from the\n * moment factories run there — but isolated harnesses may not, so prefer\n * using it from handlers, services, and timers for portability.\n * `threads.spawn` defaults `origin` to \"plugin\" and `originPluginId` to\n * this plugin's id so spawned threads are attributed automatically.\n */\n readonly sdk: BbSdk;\n /**\n * Register cleanup to run on reload/disable/shutdown. Hooks run LIFO.\n * The sanctioned place to clear timers and close connections.\n */\n onDispose(hook: () => void | Promise): void;\n}\n\nexport { PLUGIN_CLI_OUTPUT_MAX_BYTES, defineRpcContract, experimental_defineHostEntry };\nexport type { BbContext, BbNavigate, BbPluginApi, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, ExperimentalHostCallOptions, ExperimentalHostClient, ExperimentalHostEntry, ExperimentalHostPaths, ExperimentalHostRpcContext, ExperimentalHostRpcHandlers, ExperimentalHostSignalContract, ExperimentalHostSignalEvent, ExperimentalHostSignals, ExperimentalHostWatchChange, ExperimentalHostWatchChangeType, ExperimentalHostWatchEvent, ExperimentalHostWatchListener, ExperimentalHostWatchOptions, ExperimentalHostWatchSubscription, ExperimentalHostWorkerLease, JsonValue, MarkdownProps, NewThreadComposerProps, NewThreadRequest, PluginAgentConfiguration, PluginAgentConfigurationContext, PluginAgentToolContentPart, PluginAgentToolContext, PluginAgentToolExperimentalStatusLabels, 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, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderCapabilities, PluginProviderComposerAction, PluginProviderDeclaration, PluginProviderIconRegistration, PluginProviderPermissionMode, PluginProviderReasoningLevel, 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, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginStatusApi, PluginStorage, PluginTargetedPanelActionOpenOptions, PluginThreadEventHandler, PluginThreadEventName, PluginThreadEventPayloads, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, PluginUi, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps };\n"; +export const PLUGIN_SDK_DTS = "// Portable type declarations for `@get-bb/plugin-sdk`. Unpublished BB\n// workspace contracts are flattened; public subpaths may reuse the\n// package root without requiring any other @bb/* package.\n//\n// Confused by the API, or need a symbol that isn't here? Clone the BB repo\n// and read the real source: https://github.com/get-bb/bb\n\nimport * as react from 'react';\nimport { ComponentType, ReactNode } from 'react';\nimport * as z from 'zod';\nimport { z as z$1 } from 'zod';\nimport Database from 'better-sqlite3';\nimport { Context } from 'hono';\n\n/**\n * App-wide server-backed preferences.\n * Client-local settings stay in the frontend localStorage helpers instead.\n */\ndeclare const appSettingsSchema: z$1.ZodObject<{\n claudeCodeMemoryEnabled: z$1.ZodBoolean;\n claudeCodeSubagentsDisabled: z$1.ZodBoolean;\n claudeCodeWorkflowsDisabled: z$1.ZodBoolean;\n codexMemoryEnabled: z$1.ZodBoolean;\n codexSubagentsDisabled: z$1.ZodBoolean;\n onboardingCompletedAt: z$1.ZodNullable;\n showKeyboardHints: z$1.ZodBoolean;\n showUnhandledProviderEvents: z$1.ZodBoolean;\n steerActiveThreadOnEnter: z$1.ZodBoolean;\n}, z$1.core.$strict>;\ntype AppSettings = z$1.infer;\n\ndeclare const appKeybindingOverridesSchema: z$1.ZodArray;\n shortcut: z$1.ZodNullable>;\n}, z$1.core.$strict>>;\ntype AppKeybindingOverrides = z$1.infer;\n\ninterface JsonObject {\n [key: string]: JsonValue$1;\n}\ntype JsonValue$1 = string | number | boolean | null | JsonValue$1[] | JsonObject;\n\ndeclare const appThemeSchema: z$1.ZodObject<{\n customCss: z$1.ZodNullable;\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n resolvedCodeTheme: z$1.ZodDefault>>;\n light: z$1.ZodString;\n }, z$1.core.$strict>>;\n themeId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype AppTheme = z$1.infer;\n/**\n * The complete appearance selection a client sends when changing the palette\n * and/or favicon tint. The server validates `themeId` (built-in id or an\n * existing custom theme) and resolves the CSS from disk for custom themes.\n * Callers changing only one facet must carry the other facet forward explicitly.\n */\ndeclare const appThemeSelectionSchema: z$1.ZodObject<{\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n themeId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype AppThemeSelection = z$1.infer;\n\ndeclare const changedMessageSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"thread\">;\n id: z$1.ZodOptional;\n metadata: z$1.ZodOptional;\n eventTypes: z$1.ZodOptional>>>>;\n hasPendingInteraction: z$1.ZodOptional;\n projectId: z$1.ZodOptional;\n }, z$1.core.$strict>>;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"project\">;\n id: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"environment\">;\n id: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"host\">;\n id: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n changes: z$1.ZodReadonly>>;\n entity: z$1.ZodLiteral<\"system\">;\n type: z$1.ZodLiteral<\"changed\">;\n}, z$1.core.$strict>], \"entity\">;\ntype ChangedMessage = z$1.infer;\n\ndeclare const environmentSchema: z$1.ZodObject<{\n baseBranch: z$1.ZodNullable;\n branchName: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n defaultBranch: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n isGitRepo: z$1.ZodBoolean;\n isWorktree: z$1.ZodBoolean;\n managed: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodNullable;\n name: z$1.ZodNullable;\n path: z$1.ZodNullable;\n projectId: z$1.ZodString;\n status: z$1.ZodEnum<{\n destroyed: \"destroyed\";\n destroying: \"destroying\";\n error: \"error\";\n provisioning: \"provisioning\";\n ready: \"ready\";\n retiring: \"retiring\";\n }>;\n updatedAt: z$1.ZodNumber;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n}, z$1.core.$strip>;\ntype Environment = z$1.infer;\n\ndeclare const experimentsSchema: z$1.ZodRecord, z$1.ZodBoolean>;\ntype Experiments = z$1.infer;\n\ndeclare const hostSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n lastRejectedProtocolVersion: z$1.ZodNullable;\n lastSeenAt: z$1.ZodNullable;\n maxPermissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n name: z$1.ZodString;\n status: z$1.ZodEnum<{\n connected: \"connected\";\n disconnected: \"disconnected\";\n }>;\n type: z$1.ZodEnum<{\n persistent: \"persistent\";\n }>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype Host = z$1.infer;\n\ndeclare const pendingInteractionResolutionSchema: z$1.ZodUnion;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n}, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin_submitted\">;\n}, z$1.core.$strip>]>;\ntype PendingInteractionResolution = z$1.infer;\ndeclare const providerPendingInteractionSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n expiresAt: z$1.ZodOptional>;\n id: z$1.ZodString;\n origin: z$1.ZodOptional;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>>;\n payload: z$1.ZodUnion>;\n kind: z$1.ZodLiteral<\"approval\">;\n reason: z$1.ZodNullable;\n subject: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n actions: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"listFiles\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n command: z$1.ZodString;\n cwd: z$1.ZodNullable;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"command\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"file_change\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n writeScope: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"permission_grant\">;\n permissions: z$1.ZodObject<{\n fileSystem: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plan\">;\n plan: z$1.ZodString;\n planFilePath: z$1.ZodNullable;\n }, z$1.core.$strip>], \"kind\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"user_question\">;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>]>;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n resolution: z$1.ZodNullable;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>]>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype ProviderPendingInteraction = z$1.infer;\ndeclare const pluginPendingInteractionSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n expiresAt: z$1.ZodOptional>;\n id: z$1.ZodString;\n origin: z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin\">;\n pluginId: z$1.ZodString;\n rendererId: z$1.ZodString;\n }, z$1.core.$strip>;\n payload: z$1.ZodObject<{\n data: z$1.ZodType>;\n kind: z$1.ZodLiteral<\"plugin\">;\n title: z$1.ZodString;\n }, z$1.core.$strip>;\n resolution: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype PluginPendingInteraction = z$1.infer;\ntype PendingInteraction = ProviderPendingInteraction | PluginPendingInteraction;\n\ndeclare const projectSourceSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n path: z$1.ZodString;\n projectId: z$1.ZodString;\n type: z$1.ZodLiteral<\"local_path\">;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ProjectSource = z$1.infer;\n\ndeclare const reasoningLevelSchema: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n}>;\ntype ReasoningLevel = z$1.infer;\ndeclare const serviceTierSchema: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n}>;\ntype ServiceTier = z$1.infer;\ndeclare const permissionModeSchema: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n}>;\ntype PermissionMode = z$1.infer;\ndeclare const promptInputSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n mentions: z$1.ZodDefault, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>], \"type\">;\ntype PromptInput = z$1.infer;\ndeclare const resolvedThreadExecutionOptionsSchema: z$1.ZodObject<{\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n seq: z$1.ZodOptional;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n source: z$1.ZodEnum<{\n \"client/thread/start\": \"client/thread/start\";\n \"client/turn/requested\": \"client/turn/requested\";\n \"client/turn/start\": \"client/turn/start\";\n }>;\n}, z$1.core.$strip>;\ntype ResolvedThreadExecutionOptions = z$1.infer;\ndeclare const projectExecutionDefaultsSchema: z$1.ZodObject<{\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n providerId: z$1.ZodString;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n}, z$1.core.$strip>;\ntype ProjectExecutionDefaults = z$1.infer;\n\n/** All thread events — provider-originated or system-originated. */\ndeclare const threadEventSchema: z$1.ZodPipe;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/identity\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n error: z$1.ZodOptional>;\n providerCheckpointId: z$1.ZodOptional;\n providerThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n clientRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/input/accepted\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n threadName: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/name/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/compacted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/context/cleared\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n objective: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n status: z$1.ZodEnum<{\n active: \"active\";\n budgetLimited: \"budgetLimited\";\n complete: \"complete\";\n paused: \"paused\";\n }>;\n threadId: z$1.ZodString;\n timeUsedSeconds: z$1.ZodNumber;\n tokenBudget: z$1.ZodNullable;\n tokensUsed: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"thread/goal/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/goal/cleared\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n clientRequestId: z$1.ZodOptional;\n content: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localFile\">;\n }, z$1.core.$strip>], \"type\">>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"userMessage\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"agentMessage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n aggregatedOutput: z$1.ZodOptional;\n approvalStatus: z$1.ZodNullable>;\n command: z$1.ZodString;\n cwd: z$1.ZodString;\n durationMs: z$1.ZodOptional;\n exitCode: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"commandExecution\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalStatus: z$1.ZodNullable>;\n changes: z$1.ZodArray;\n kind: z$1.ZodEnum<{\n add: \"add\";\n delete: \"delete\";\n update: \"update\";\n }>;\n movePath: z$1.ZodOptional;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n type: z$1.ZodLiteral<\"fileChange\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n queries: z$1.ZodArray;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webSearch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n pattern: z$1.ZodNullable;\n prompt: z$1.ZodNullable;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webFetch\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"imageView\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n arguments: z$1.ZodOptional>;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n result: z$1.ZodOptional;\n server: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusLabels: z$1.ZodOptional>;\n tool: z$1.ZodString;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"toolCall\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n content: z$1.ZodArray;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n summary: z$1.ZodArray;\n type: z$1.ZodLiteral<\"reasoning\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"contextCompaction\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>], \"type\">;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n clientRequestId: z$1.ZodOptional;\n content: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localFile\">;\n }, z$1.core.$strip>], \"type\">>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"userMessage\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"agentMessage\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n aggregatedOutput: z$1.ZodOptional;\n approvalStatus: z$1.ZodNullable>;\n command: z$1.ZodString;\n cwd: z$1.ZodString;\n durationMs: z$1.ZodOptional;\n exitCode: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"commandExecution\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalStatus: z$1.ZodNullable>;\n changes: z$1.ZodArray;\n kind: z$1.ZodEnum<{\n add: \"add\";\n delete: \"delete\";\n update: \"update\";\n }>;\n movePath: z$1.ZodOptional;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n type: z$1.ZodLiteral<\"fileChange\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n queries: z$1.ZodArray;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webSearch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n pattern: z$1.ZodNullable;\n prompt: z$1.ZodNullable;\n resultText: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"webFetch\">;\n url: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"imageView\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n arguments: z$1.ZodOptional>;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n result: z$1.ZodOptional;\n server: z$1.ZodOptional;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusLabels: z$1.ZodOptional>;\n tool: z$1.ZodString;\n truncation: z$1.ZodOptional>;\n result: z$1.ZodOptional>;\n resultText: z$1.ZodOptional>;\n }, z$1.core.$strip>>;\n type: z$1.ZodLiteral<\"toolCall\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n content: z$1.ZodArray;\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n summary: z$1.ZodArray;\n type: z$1.ZodLiteral<\"reasoning\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n id: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"contextCompaction\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>], \"type\">;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/agentMessage/delta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n reset: z$1.ZodOptional;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/commandExecution/outputDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/fileChange/outputDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/reasoning/summaryTextDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/reasoning/textDelta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n delta: z$1.ZodString;\n itemId: z$1.ZodString;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/plan/delta\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n message: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/mcpToolCall/progress\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n message: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/toolCall/progress\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/backgroundTask/progress\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n item: z$1.ZodObject<{\n description: z$1.ZodString;\n error: z$1.ZodOptional;\n id: z$1.ZodString;\n outputFile: z$1.ZodOptional;\n parentToolCallId: z$1.ZodOptional;\n skipTranscript: z$1.ZodBoolean;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodOptional;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n type: z$1.ZodLiteral<\"backgroundTask\">;\n usage: z$1.ZodOptional>;\n workflow: z$1.ZodOptional;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodOptional;\n }, z$1.core.$strip>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"item/backgroundTask/completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n tokenUsage: z$1.ZodObject<{\n last: z$1.ZodObject<{\n cachedInputTokens: z$1.ZodNumber;\n inputTokens: z$1.ZodNumber;\n outputTokens: z$1.ZodNumber;\n reasoningOutputTokens: z$1.ZodNumber;\n totalTokens: z$1.ZodNumber;\n }, z$1.core.$strip>;\n modelContextWindow: z$1.ZodNullable;\n total: z$1.ZodObject<{\n cachedInputTokens: z$1.ZodNumber;\n inputTokens: z$1.ZodNumber;\n outputTokens: z$1.ZodNumber;\n reasoningOutputTokens: z$1.ZodNumber;\n totalTokens: z$1.ZodNumber;\n }, z$1.core.$strip>;\n }, z$1.core.$strip>;\n type: z$1.ZodLiteral<\"thread/tokenUsage/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n contextWindowUsage: z$1.ZodObject<{\n estimated: z$1.ZodBoolean;\n modelContextWindow: z$1.ZodNullable;\n usedTokens: z$1.ZodNullable;\n }, z$1.core.$strip>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread/contextWindowUsage/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n explanation: z$1.ZodOptional;\n plan: z$1.ZodArray>;\n step: z$1.ZodString;\n }, z$1.core.$strip>>;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/plan/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n diff: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn/diff/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n detail: z$1.ZodOptional;\n errorInfo: z$1.ZodOptional;\n httpStatusCode: z$1.ZodNullable;\n providerCode: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n message: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/error\">;\n willRetry: z$1.ZodOptional;\n}, z$1.core.$strip>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n rateLimits: z$1.ZodObject<{\n kind: z$1.ZodEnum<{\n \"spend-control\": \"spend-control\";\n \"subscription-window\": \"subscription-window\";\n credits: \"credits\";\n unknown: \"unknown\";\n }>;\n overageReason: z$1.ZodNullable;\n overageStatus: z$1.ZodNullable>;\n providerId: z$1.ZodString;\n reachedReason: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n allowed: \"allowed\";\n blocked: \"blocked\";\n unknown: \"unknown\";\n warning: \"warning\";\n }>;\n windows: z$1.ZodArray;\n providerKey: z$1.ZodNullable;\n resetsAtMs: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n allowed: \"allowed\";\n blocked: \"blocked\";\n unknown: \"unknown\";\n warning: \"warning\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/rateLimits/updated\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n category: z$1.ZodEnum<{\n \"compaction-skipped\": \"compaction-skipped\";\n config: \"config\";\n deprecation: \"deprecation\";\n general: \"general\";\n }>;\n details: z$1.ZodOptional;\n providerThreadId: z$1.ZodString;\n summary: z$1.ZodOptional;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/warning\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n fallbackModel: z$1.ZodString;\n message: z$1.ZodString;\n originalModel: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n reason: z$1.ZodEnum<{\n provider: \"provider\";\n refusal: \"refusal\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/modelFallback\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n parentToolCallId: z$1.ZodOptional;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n rawEvent: z$1.ZodObject<{\n id: z$1.ZodOptional>;\n jsonrpc: z$1.ZodLiteral<\"2.0\">;\n method: z$1.ZodString;\n params: z$1.ZodOptional>>;\n }, z$1.core.$strip>;\n rawType: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider/unhandled\">;\n}, z$1.core.$strip>], \"type\">, z$1.ZodObject<{\n scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n}, z$1.core.$strip>>, z$1.ZodIntersection;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n request: z$1.ZodObject<{\n method: z$1.ZodEnum<{\n \"thread/start\": \"thread/start\";\n \"turn/start\": \"turn/start\";\n }>;\n params: z$1.ZodRecord;\n }, z$1.core.$strip>;\n source: z$1.ZodEnum<{\n spawn: \"spawn\";\n tell: \"tell\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/thread/start\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n continuationOfRequestId: z$1.ZodOptional;\n direction: z$1.ZodLiteral<\"outbound\">;\n execution: z$1.ZodObject<{\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n \"workspace-write\": \"workspace-write\";\n auto: \"auto\";\n full: \"full\";\n readonly: \"readonly\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n seq: z$1.ZodOptional;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n source: z$1.ZodEnum<{\n \"client/thread/start\": \"client/thread/start\";\n \"client/turn/requested\": \"client/turn/requested\";\n \"client/turn/start\": \"client/turn/start\";\n }>;\n }, z$1.core.$strip>;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n inputGroups: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>>;\n request: z$1.ZodObject<{\n method: z$1.ZodEnum<{\n \"thread/start\": \"thread/start\";\n \"turn/start\": \"turn/start\";\n }>;\n params: z$1.ZodRecord;\n }, z$1.core.$strip>;\n requestId: z$1.ZodString;\n senderThreadId: z$1.ZodNullable;\n source: z$1.ZodEnum<{\n spawn: \"spawn\";\n tell: \"tell\";\n }>;\n systemMessageKind: z$1.ZodOptional>;\n systemMessageSubject: z$1.ZodOptional;\n threadId: z$1.ZodString;\n threadName: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n count: z$1.ZodNumber;\n kind: z$1.ZodLiteral<\"thread-batch\">;\n }, z$1.core.$strip>], \"kind\">>>;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread-start\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"new-turn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"auto\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"steer\">;\n }, z$1.core.$strip>], \"kind\">;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/turn/requested\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n reason: z$1.ZodString;\n requestId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/turn/rejected\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n direction: z$1.ZodLiteral<\"outbound\">;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n request: z$1.ZodObject<{\n method: z$1.ZodEnum<{\n \"thread/start\": \"thread/start\";\n \"turn/start\": \"turn/start\";\n }>;\n params: z$1.ZodRecord;\n }, z$1.core.$strip>;\n source: z$1.ZodEnum<{\n spawn: \"spawn\";\n tell: \"tell\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"client/turn/start\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n code: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n message: z$1.ZodString;\n reconnectAttempt: z$1.ZodOptional;\n reconnectTotal: z$1.ZodOptional;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/error\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n text: z$1.ZodString;\n threadId: z$1.ZodString;\n toolCallId: z$1.ZodOptional;\n turnId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"system/manager/user_message\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n reason: z$1.ZodEnum<{\n \"host-daemon-restarted\": \"host-daemon-restarted\";\n \"manual-stop\": \"manual-stop\";\n \"provider-turn-idle\": \"provider-turn-idle\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/thread/interrupted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n metadata: z$1.ZodOptional>>>;\n operation: z$1.ZodString;\n operationId: z$1.ZodString;\n status: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/operation\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n interactionId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n resolution: z$1.ZodDefault;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">>>;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodDefault>;\n subject: z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"permission_grant\">;\n permissions: z$1.ZodObject<{\n fileSystem: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/permissionGrant/lifecycle\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n interactionId: z$1.ZodString;\n payload: z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"user_question\">;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n resolution: z$1.ZodDefault;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>>>;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodDefault>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/userQuestion/lifecycle\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n entries: z$1.ZodArray>;\n startedAt: z$1.ZodOptional;\n status: z$1.ZodOptional>;\n text: z$1.ZodString;\n type: z$1.ZodEnum<{\n output: \"output\";\n step: \"step\";\n }>;\n }, z$1.core.$strip>>;\n environmentId: z$1.ZodString;\n provisioningId: z$1.ZodString;\n status: z$1.ZodEnum<{\n active: \"active\";\n cancelled: \"cancelled\";\n completed: \"completed\";\n failed: \"failed\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"system/thread-provisioning\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n activeTurnId: z$1.ZodString;\n activeTurnStartedAt: z$1.ZodNumber;\n elapsedMs: z$1.ZodNumber;\n firedAt: z$1.ZodNumber;\n lastActivityEventAt: z$1.ZodNumber;\n lastActivityEventSequence: z$1.ZodNumber;\n lastActivityEventType: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodNullable;\n reason: z$1.ZodLiteral<\"provider-turn-idle\">;\n threadId: z$1.ZodString;\n thresholdMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"system/provider-turn-watchdog\">;\n}, z$1.core.$strip>]>, z$1.ZodObject<{\n scope: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n}, z$1.core.$strip>>]>>;\ntype ThreadEvent = z$1.infer;\ntype ThreadEventType = ThreadEvent[\"type\"];\n\n/**\n * How completely a provider can clone one of its sessions — the single\n * vocabulary shared by the provider declaration\n * (`bb.agents.experimental_registerProvider`), the server→daemon\n * `bridgeLaunch`, and the bridge's `initialize` handshake.\n *\n * - `\"none\"`: sessions cannot be cloned at all.\n * - `\"tip\"`: only the current end of a session can be cloned (ACP\n * `session/fork`), so thread fork works but edit-past-message rewind\n * cannot.\n * - `\"checkpoint\"`: a session can be recreated at an earlier point, which is\n * what edit-past-message rewind needs.\n *\n * The values are ordered least to most capable: a declaration is a ceiling\n * the handshake may narrow but never widen.\n */\ndeclare const PROVIDER_FORK_VALUES: readonly [\"none\", \"tip\", \"checkpoint\"];\ntype ProviderFork = (typeof PROVIDER_FORK_VALUES)[number];\n\ndeclare const providerInfoSchema: z$1.ZodObject<{\n available: z$1.ZodBoolean;\n capabilities: z$1.ZodObject<{\n permissionModes: z$1.ZodArray>;\n supportsFork: z$1.ZodBoolean;\n supportsNativeUserQuestion: z$1.ZodBoolean;\n supportsServiceTier: z$1.ZodBoolean;\n supportsSessionRewind: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n composerActions: z$1.ZodArray;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"goal\">;\n }, z$1.core.$strip>], \"kind\">>;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n logoUrl: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ProviderInfo = z$1.infer;\n\ndeclare const threadEventScopeSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"turn\">;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>], \"kind\">;\ntype ThreadEventScope = z$1.infer;\n\ntype ThreadEventByType = {\n [TType in ThreadEventType]: Extract;\n};\ntype ThreadEventForType = ThreadEventByType[TType];\ntype StoredThreadEventDataFromEvent = Omit;\ninterface ThreadEventRowBase {\n id: string;\n scope: ThreadEventScope;\n threadId: string;\n seq: number;\n createdAt: number;\n}\ntype ThreadEventRowFromEvent = ThreadEventRowBase & {\n type: TEvent[\"type\"];\n data: StoredThreadEventDataFromEvent;\n};\ntype ThreadEventRowOfType = ThreadEventRowFromEvent>;\ntype ThreadEventRow = {\n [TType in ThreadEventType]: ThreadEventRowOfType;\n}[ThreadEventType];\n\ndeclare const threadStatusSchema: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n}>;\ntype ThreadStatus = z$1.infer;\n\ndeclare const threadTimelinePendingTodosSchema: z$1.ZodObject<{\n items: z$1.ZodArray;\n text: z$1.ZodString;\n }, z$1.core.$strip>>;\n sourceSeq: z$1.ZodNumber;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadTimelinePendingTodos = z$1.infer;\n\ndeclare const threadQueuedMessageSchema: z$1.ZodObject<{\n content: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n createdAt: z$1.ZodNumber;\n groupWithNext: z$1.ZodBoolean;\n id: z$1.ZodString;\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadQueuedMessage = z$1.infer;\n\ndeclare const createThreadEnvironmentArgsSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"reuse\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host\">;\n workspace: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branch: z$1.ZodOptional;\n name: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new\">;\n }, z$1.core.$strict>], \"kind\">>;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"unmanaged\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n baseBranch: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"named\">;\n name: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"default\">;\n }, z$1.core.$strip>], \"kind\">;\n type: z$1.ZodLiteral<\"managed-worktree\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"personal\">;\n }, z$1.core.$strip>], \"type\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"project-default\">;\n}, z$1.core.$strip>], \"type\">;\ntype CreateThreadEnvironmentArgs = z$1.infer;\ndeclare const workspaceFileListResponseSchema: z$1.ZodObject<{\n files: z$1.ZodArray>;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype WorkspaceFileListResponse = z$1.infer;\ndeclare const workspacePathListResponseSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n positions: z$1.ZodArray;\n score: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype WorkspacePathListResponse = z$1.infer;\n\ndeclare const createProjectSourceRequestSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n hostId: z$1.ZodString;\n path: z$1.ZodPipe>;\n type: z$1.ZodLiteral<\"local_path\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n hostId: z$1.ZodString;\n remoteUrl: z$1.ZodOptional;\n targetPath: z$1.ZodOptional>>;\n type: z$1.ZodLiteral<\"clone\">;\n}, z$1.core.$strict>], \"type\">;\ntype CreateProjectSourceRequest = z$1.infer;\ndeclare const createProjectRequestSchema: z$1.ZodObject<{\n name: z$1.ZodString;\n source: z$1.ZodObject<{\n hostId: z$1.ZodString;\n path: z$1.ZodPipe>;\n type: z$1.ZodLiteral<\"local_path\">;\n }, z$1.core.$strict>;\n}, z$1.core.$strip>;\ntype CreateProjectRequest = z$1.infer;\ndeclare const threadSectionSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n name: z$1.ZodString;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype ThreadSectionResponse = z$1.infer;\ndeclare const createThreadSectionRequestSchema: z$1.ZodObject<{\n name: z$1.ZodString;\n}, z$1.core.$strict>;\ntype CreateThreadSectionRequest = z$1.infer;\ndeclare const updateThreadSectionRequestSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n name: z$1.ZodString;\n}, z$1.core.$strict>;\ntype UpdateThreadSectionRequest = z$1.infer;\ndeclare const deleteThreadSectionRequestSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n}, z$1.core.$strict>;\ntype DeleteThreadSectionRequest = z$1.infer;\ndeclare const threadSectionMutationResponseSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n name: z$1.ZodString;\n updatedThreadCount: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype ThreadSectionMutationResponse = z$1.infer;\ndeclare const reorderProjectRequestSchema: z$1.ZodObject<{\n nextProjectId: z$1.ZodNullable;\n previousProjectId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ReorderProjectRequest = z$1.infer;\ndeclare const projectListQuerySchema: z$1.ZodObject<{\n include: z$1.ZodOptional;\n includePersonal: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ProjectListQuery = z$1.infer;\ndeclare const projectFilesQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n limit: z$1.ZodOptional>;\n query: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ProjectFilesQuery = z$1.infer;\ndeclare const projectPathsQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n includeDirectories: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n includeFiles: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n limit: z$1.ZodOptional>;\n query: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ProjectPathsQuery = z$1.infer;\ndeclare const projectFileContentQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n path: z$1.ZodString;\n}, z$1.core.$strip>;\ntype ProjectFileContentQuery = z$1.infer;\ndeclare const projectBranchesQuerySchema: z$1.ZodObject<{\n hostId: z$1.ZodString;\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n selectedBranch: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ProjectBranchesQuery = z$1.infer;\ndeclare const projectBranchesResponseSchema: z$1.ZodObject<{\n branches: z$1.ZodArray;\n branchesTruncated: z$1.ZodBoolean;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n defaultBranch: z$1.ZodNullable;\n defaultBranchRelation: z$1.ZodNullable>;\n defaultWorktreeBaseBranch: z$1.ZodNullable;\n hasUncommittedChanges: z$1.ZodBoolean;\n operation: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"none\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"merge\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"rebase\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"cherry-pick\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"revert\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n originDefaultBranch: z$1.ZodNullable;\n remoteBranches: z$1.ZodArray;\n remoteBranchesTruncated: z$1.ZodBoolean;\n selectedBranch: z$1.ZodNullable;\n name: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype ProjectBranchesResponse = z$1.infer;\ndeclare const promptHistoryQuerySchema: z$1.ZodObject<{\n limit: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype PromptHistoryQuery = z$1.infer;\ndeclare const promptHistoryResponseSchema: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n}, z$1.core.$strip>>;\ntype PromptHistoryResponse = z$1.infer;\ndeclare const updateProjectRequestSchema: z$1.ZodObject<{\n name: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype UpdateProjectRequest = z$1.infer;\ndeclare const updateProjectSourceRequestSchema: z$1.ZodObject<{\n isDefault: z$1.ZodOptional>;\n path: z$1.ZodOptional>>;\n type: z$1.ZodLiteral<\"local_path\">;\n}, z$1.core.$strict>;\ntype UpdateProjectSourceRequest = z$1.infer;\ndeclare const commandListResponseSchema: z$1.ZodObject<{\n commands: z$1.ZodArray;\n description: z$1.ZodNullable;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n pluginId: z$1.ZodOptional;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype CommandListResponse = z$1.infer;\n/** Query for the complete command catalog available to a project and provider. */\ndeclare const projectCommandsQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional, z$1.ZodOptional>>;\n hostId: z$1.ZodOptional;\n provider: z$1.ZodString;\n}, z$1.core.$strict>;\ntype ProjectCommandsQuery = z$1.infer;\ndeclare const skillListResponseSchema: z$1.ZodObject<{\n skills: z$1.ZodArray;\n filePath: z$1.ZodString;\n id: z$1.ZodString;\n manageable: z$1.ZodBoolean;\n name: z$1.ZodString;\n pluginId: z$1.ZodNullable;\n provider: z$1.ZodNullable;\n registrySkillId: z$1.ZodNullable;\n scope: z$1.ZodEnum<{\n \"bb-builtin\": \"bb-builtin\";\n \"bb-project\": \"bb-project\";\n \"bb-user\": \"bb-user\";\n \"provider-project\": \"provider-project\";\n \"provider-user\": \"provider-user\";\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n plugin: \"plugin\";\n }>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype SkillListResponse = z$1.infer;\ndeclare const skillContentResponseSchema: z$1.ZodObject<{\n content: z$1.ZodString;\n revision: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SkillContentResponse = z$1.infer;\ndeclare const skillFilesResponseSchema: z$1.ZodObject<{\n files: z$1.ZodArray;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype SkillFilesResponse = z$1.infer;\ndeclare const projectResponseSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n gitRemoteUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n personal: \"personal\";\n standard: \"standard\";\n }>;\n name: z$1.ZodString;\n sources: z$1.ZodArray;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ProjectResponse = z$1.infer;\ndeclare const projectWithThreadsResponseSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n defaultExecutionOptions: z$1.ZodNullable;\n providerId: z$1.ZodString;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n }, z$1.core.$strip>>;\n gitRemoteUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n personal: \"personal\";\n standard: \"standard\";\n }>;\n name: z$1.ZodString;\n sources: z$1.ZodArray;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n threads: z$1.ZodArray;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n }, z$1.core.$strip>>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ProjectWithThreadsResponse = z$1.infer;\ndeclare const uploadedPromptAttachmentSchema: z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodString;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n type: z$1.ZodEnum<{\n localFile: \"localFile\";\n localImage: \"localImage\";\n }>;\n}, z$1.core.$strip>;\ntype UploadedPromptAttachment = z$1.infer;\ndeclare const copyProjectAttachmentsRequestSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n sourceProjectId: z$1.ZodString;\n}, z$1.core.$strict>;\ntype CopyProjectAttachmentsRequest = z$1.infer;\n\ndeclare const registrySkillSchema: z$1.ZodObject<{\n id: z$1.ZodString;\n installUrl: z$1.ZodNullable;\n installs: z$1.ZodNumber;\n name: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n stars: z$1.ZodNullable;\n summary: z$1.ZodNullable;\n topic: z$1.ZodNullable;\n url: z$1.ZodString;\n}, z$1.core.$strip>;\ntype RegistrySkill = z$1.infer;\ndeclare const registrySkillsPageSchema: z$1.ZodObject<{\n pagination: z$1.ZodObject<{\n hasMore: z$1.ZodBoolean;\n page: z$1.ZodNumber;\n perPage: z$1.ZodNumber;\n total: z$1.ZodNumber;\n }, z$1.core.$strip>;\n ranking: z$1.ZodEnum<{\n \"all-time\": \"all-time\";\n trending: \"trending\";\n }>;\n skills: z$1.ZodArray;\n installs: z$1.ZodNumber;\n name: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n stars: z$1.ZodNullable;\n summary: z$1.ZodNullable;\n topic: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype RegistrySkillsPage = z$1.infer;\ndeclare const registryRepositoryStarsSchema: z$1.ZodObject<{\n stars: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype RegistryRepositoryStars = z$1.infer;\ndeclare const registrySkillDetailSchema: z$1.ZodObject<{\n files: z$1.ZodNullable>>;\n hash: z$1.ZodNullable;\n id: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n}, z$1.core.$strip>;\ntype RegistrySkillDetail = z$1.infer;\n/**\n * Entries that could not be resolved (dead detail page, malformed id) are\n * omitted rather than failing the batch: each entry is independent upstream,\n * and callers already treat a missing entry as \"unknown\" per card.\n */\ndeclare const registrySkillEntriesResponseSchema: z$1.ZodObject<{\n entries: z$1.ZodArray;\n installs: z$1.ZodNumber;\n name: z$1.ZodString;\n skillId: z$1.ZodString;\n source: z$1.ZodString;\n stars: z$1.ZodNullable;\n summary: z$1.ZodNullable;\n topic: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype RegistrySkillEntriesResponse = z$1.infer;\ndeclare const registrySkillInstallResponseSchema: z$1.ZodObject<{\n filePath: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype RegistrySkillInstallResponse = z$1.infer;\n\ndeclare const updateEnvironmentRequestSchema: z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodOptional>;\n name: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype UpdateEnvironmentRequest = z$1.infer;\n/**\n * Query for searching paths in an environment's workspace. Unlike the\n * project-scoped variant this needs no `environmentId` — the environment is\n * the route param — and is project-agnostic, so it works for projectless\n * (personal) environments too.\n */\ndeclare const environmentPathsQuerySchema: z$1.ZodObject<{\n includeDirectories: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n includeFiles: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype EnvironmentPathsQuery = z$1.infer;\ndeclare const environmentDiffBranchesQuerySchema: z$1.ZodObject<{\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n selectedBranch: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype EnvironmentDiffBranchesQuery = z$1.infer;\ndeclare const environmentDiffBranchesResponseSchema: z$1.ZodObject<{\n branches: z$1.ZodArray;\n branchesTruncated: z$1.ZodBoolean;\n remoteBranches: z$1.ZodArray;\n remoteBranchesTruncated: z$1.ZodBoolean;\n selectedBranch: z$1.ZodNullable;\n name: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype EnvironmentDiffBranchesResponse = z$1.infer;\ndeclare const environmentStatusQuerySchema: z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype EnvironmentStatusQuery = z$1.infer;\ndeclare const environmentDiffQuerySchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n target: z$1.ZodLiteral<\"uncommitted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodPipe;\n target: z$1.ZodLiteral<\"branch_committed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodPipe;\n target: z$1.ZodLiteral<\"all\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n target: z$1.ZodLiteral<\"commit\">;\n}, z$1.core.$strip>], \"target\">;\ntype EnvironmentDiffQuery = z$1.infer;\n/**\n * Query for fetching a single file's contents at one side of a diff target.\n * Used by the diff card to reparse the card's patch with full old/new contents\n * so `@pierre/diffs` can render expand-context buttons between hunks.\n *\n * For `branch_committed` / `all`, callers pass the resolved merge-base SHA\n * (`mergeBaseRef`, surfaced by `workspace.diff`) rather than the branch name\n * — the diff itself was computed against that SHA, so reading the old side\n * from the same SHA keeps the file content aligned with the hunk line\n * numbers. Reading from the branch tip is wrong whenever the branch has\n * moved past the merge-base since the file existed there.\n */\ndeclare const environmentDiffFileQuerySchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n path: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"uncommitted\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseRef: z$1.ZodString;\n path: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"branch_committed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseRef: z$1.ZodString;\n path: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"all\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n sha: z$1.ZodString;\n side: z$1.ZodEnum<{\n new: \"new\";\n old: \"old\";\n }>;\n target: z$1.ZodLiteral<\"commit\">;\n}, z$1.core.$strip>], \"target\">;\ntype EnvironmentDiffFileQuery = z$1.infer;\ndeclare const environmentDiffFileResponseSchema: z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n mimeType: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype EnvironmentDiffFileResponse = z$1.infer;\ndeclare const environmentArchiveThreadsResponseSchema: z$1.ZodObject<{\n archivedThreadIds: z$1.ZodArray;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype EnvironmentArchiveThreadsResponse = z$1.infer;\ndeclare const pullRequestMergeMethodSchema: z$1.ZodEnum<{\n merge: \"merge\";\n rebase: \"rebase\";\n squash: \"squash\";\n}>;\ntype PullRequestMergeMethod = z$1.infer;\ndeclare const commitActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"commit\">;\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype CommitActionResponse = z$1.infer;\ndeclare const squashMergeActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"squash_merge\">;\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n merged: z$1.ZodBoolean;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype SquashMergeActionResponse = z$1.infer;\ndeclare const pullRequestReadyActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"pull_request_ready\">;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PullRequestReadyActionResponse = z$1.infer;\ndeclare const pullRequestMergeActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"pull_request_merge\">;\n message: z$1.ZodString;\n method: z$1.ZodEnum<{\n merge: \"merge\";\n rebase: \"rebase\";\n squash: \"squash\";\n }>;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PullRequestMergeActionResponse = z$1.infer;\ndeclare const pullRequestDraftActionResponseSchema: z$1.ZodObject<{\n action: z$1.ZodLiteral<\"pull_request_draft\">;\n message: z$1.ZodString;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PullRequestDraftActionResponse = z$1.infer;\ndeclare const environmentStatusResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n workspace: z$1.ZodObject<{\n branch: z$1.ZodObject<{\n currentBranch: z$1.ZodNullable;\n defaultBranch: z$1.ZodString;\n }, z$1.core.$strip>;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n mergeBase: z$1.ZodNullable;\n behindCount: z$1.ZodNumber;\n commits: z$1.ZodArray>;\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasCommittedUnmergedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodString;\n }, z$1.core.$strip>>;\n workingTree: z$1.ZodObject<{\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasUncommittedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n state: z$1.ZodEnum<{\n clean: \"clean\";\n committed_unmerged: \"committed_unmerged\";\n dirty_and_committed_unmerged: \"dirty_and_committed_unmerged\";\n dirty_uncommitted: \"dirty_uncommitted\";\n untracked: \"untracked\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strip>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\n/**\n * Structured pull-request lookup outcome. \"absent\" is a real answer — the\n * host checked and the branch has no PR (non-git environments resolve to\n * \"absent\" without a daemon call). \"unavailable\" means the lookup itself\n * failed (gh missing, not authenticated, timeout, unreachable workspace), so\n * callers must not render it as \"no PR exists\".\n */\ndeclare const environmentPullRequestResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n pullRequest: z$1.ZodObject<{\n attention: z$1.ZodEnum<{\n blocked: \"blocked\";\n changes_requested: \"changes_requested\";\n checks_failed: \"checks_failed\";\n checks_pending: \"checks_pending\";\n closed: \"closed\";\n conflicts: \"conflicts\";\n draft: \"draft\";\n merged: \"merged\";\n none: \"none\";\n ready_to_merge: \"ready_to_merge\";\n review_requested: \"review_requested\";\n }>;\n baseRefName: z$1.ZodString;\n checks: z$1.ZodObject<{\n failedCount: z$1.ZodNumber;\n passedCount: z$1.ZodNumber;\n pendingCount: z$1.ZodNumber;\n state: z$1.ZodEnum<{\n failing: \"failing\";\n no_checks: \"no_checks\";\n passing: \"passing\";\n pending: \"pending\";\n unknown: \"unknown\";\n }>;\n totalCount: z$1.ZodNumber;\n }, z$1.core.$strict>;\n headRefName: z$1.ZodString;\n mergeability: z$1.ZodObject<{\n mergeStateStatus: z$1.ZodNullable>;\n mergeable: z$1.ZodNullable>;\n state: z$1.ZodEnum<{\n blocked: \"blocked\";\n conflicts: \"conflicts\";\n draft: \"draft\";\n mergeable: \"mergeable\";\n unknown: \"unknown\";\n }>;\n }, z$1.core.$strict>;\n number: z$1.ZodNumber;\n review: z$1.ZodObject<{\n reviewRequestCount: z$1.ZodNumber;\n state: z$1.ZodEnum<{\n approved: \"approved\";\n changes_requested: \"changes_requested\";\n none: \"none\";\n review_requested: \"review_requested\";\n review_required: \"review_required\";\n }>;\n }, z$1.core.$strict>;\n state: z$1.ZodEnum<{\n closed: \"closed\";\n draft: \"draft\";\n merged: \"merged\";\n open: \"open\";\n }>;\n title: z$1.ZodString;\n updatedAt: z$1.ZodString;\n url: z$1.ZodString;\n }, z$1.core.$strict>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"absent\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentPullRequestResponse = z$1.infer;\ndeclare const environmentDiffResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n diff: z$1.ZodObject<{\n diff: z$1.ZodString;\n files: z$1.ZodString;\n mergeBaseRef: z$1.ZodNullable;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n outcome: z$1.ZodLiteral<\"available\">;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentDiffResponse = z$1.infer;\ndeclare const environmentDiffFilesResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n files: z$1.ZodArray;\n deletions: z$1.ZodNumber;\n loadMode: z$1.ZodEnum<{\n auto: \"auto\";\n on_demand: \"on_demand\";\n too_large: \"too_large\";\n }>;\n origin: z$1.ZodEnum<{\n tracked: \"tracked\";\n untracked: \"untracked\";\n }>;\n path: z$1.ZodString;\n previousPath: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n initialPatches: z$1.ZodArray>;\n mergeBaseRef: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"available\">;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentDiffFilesResponse = z$1.infer;\ndeclare const environmentDiffPatchResponseSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n patches: z$1.ZodArray>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"not_applicable\">;\n reason: z$1.ZodEnum<{\n non_git_environment: \"non_git_environment\";\n }>;\n}, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n}, z$1.core.$strict>], \"outcome\">;\ntype EnvironmentDiffPatchResponse = z$1.infer;\n/**\n * Body for `POST /diff/patch`: the diff target plus the list of new paths whose\n * patches the client wants. A POST (not GET) because the repeated `paths` array\n * cannot survive flat query parsing. The client supplies only new paths; the\n * server re-derives each file's rename/copy pairing (`previousPath`) from its\n * own TOC.\n */\ndeclare const environmentDiffPatchRequestSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n}, z$1.core.$strict>;\ntype EnvironmentDiffPatchRequest = z$1.infer;\ntype EnvironmentStatusResponse = z$1.infer;\n\ndeclare const providerUsageResponseSchema: z$1.ZodObject<{\n claudeCode: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n codex: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n cursor: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n}, z$1.core.$strip>;\ntype ProviderUsageResponse = z$1.infer;\ndeclare const discoverReposResultSchema: z$1.ZodObject<{\n repos: z$1.ZodArray;\n lastActivityAt: z$1.ZodString;\n name: z$1.ZodString;\n originUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>>;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strict>;\ntype DiscoverReposResult = z$1.infer;\ntype HostDaemonCommandTransport = \"onlineRpc\" | \"settled\";\ntype HostDaemonCommandEnvironmentLane = \"read\" | \"write\";\ntype HostDaemonFlushEventsBeforeResult = boolean | \"when-initiated\";\ninterface HostDaemonCommandDescriptor {\n type: Type;\n schema: Schema;\n resultSchema: ResultSchema;\n transport: Transport;\n retryable: Retryable;\n flushEventsBeforeResult: HostDaemonFlushEventsBeforeResult;\n envLane: HostDaemonCommandEnvironmentLane | null;\n}\ndeclare const hostDaemonCommandRegistry: {\n \"thread.rewind.discard\": HostDaemonCommandDescriptor<\"thread.rewind.discard\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n leaseId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.rewind.discard\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"thread.rewind.prepare\": HostDaemonCommandDescriptor<\"thread.rewind.prepare\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n environmentId: z$1.ZodString;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n leaseId: z$1.ZodString;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n retainThroughProviderCheckpoint: z$1.ZodString;\n sourceProviderThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.rewind.prepare\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"thread.start\": HostDaemonCommandDescriptor<\"thread.start\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n environmentId: z$1.ZodString;\n fork: z$1.ZodOptional>;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n inputGroups: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n requestId: z$1.ZodString;\n threadId: z$1.ZodString;\n threadStoragePath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"thread.start\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"turn.submit\": HostDaemonCommandDescriptor<\"turn.submit\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n inputGroups: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>>;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n requestId: z$1.ZodString;\n resumeContext: z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n mode: z$1.ZodLiteral<\"start\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n mode: z$1.ZodLiteral<\"auto\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n expectedTurnId: z$1.ZodNullable;\n mode: z$1.ZodLiteral<\"steer\">;\n }, z$1.core.$strip>], \"mode\">;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"turn.submit\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n appliedAs: z$1.ZodEnum<{\n \"new-turn\": \"new-turn\";\n steer: \"steer\";\n }>;\n }, z$1.core.$strip>, \"settled\", false>;\n \"thread.stop\": HostDaemonCommandDescriptor<\"thread.stop\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n intent: z$1.ZodEnum<{\n interrupt: \"interrupt\";\n release: \"release\";\n }>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.stop\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n providerCheckpointId: z$1.ZodNullable;\n }, z$1.core.$strict>, \"settled\", false>;\n \"thread.goal.clear\": HostDaemonCommandDescriptor<\"thread.goal.clear\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n options: z$1.ZodIntersection>;\n claudeCodePermissionMode: z$1.ZodOptional>;\n memoryEnabled: z$1.ZodOptional;\n model: z$1.ZodString;\n providerSubagentsEnabled: z$1.ZodOptional;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n workflowsEnabled: z$1.ZodBoolean;\n }, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"user\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"accept-edits\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodLiteral<\"automatic\">;\n permissionEscalation: z$1.ZodEnum<{\n ask: \"ask\";\n deny: \"deny\";\n }>;\n permissionMode: z$1.ZodLiteral<\"auto\">;\n permissionScope: z$1.ZodLiteral<\"workspace\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n approvalReviewer: z$1.ZodNull;\n permissionEscalation: z$1.ZodNull;\n permissionMode: z$1.ZodLiteral<\"full\">;\n permissionScope: z$1.ZodLiteral<\"full\">;\n }, z$1.core.$strip>], \"permissionMode\">>;\n resumeContext: z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n disallowedTools: z$1.ZodOptional>;\n dynamicTools: z$1.ZodArray>;\n injectedSkillSources: z$1.ZodArray;\n name: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"data-dir\": \"data-dir\";\n builtin: \"builtin\";\n }>;\n treeHash: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n description: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-path\">;\n name: z$1.ZodString;\n skillFilePath: z$1.ZodString;\n sourceRootPath: z$1.ZodString;\n sourceType: z$1.ZodEnum<{\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n }>;\n }, z$1.core.$strict>], \"kind\">>;\n instructionMode: z$1.ZodEnum<{\n append: \"append\";\n replace: \"replace\";\n }>;\n instructions: z$1.ZodString;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.goal.clear\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cleared: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"settled\", false>;\n \"thread.plan.cancel\": HostDaemonCommandDescriptor<\"thread.plan.cancel\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n expectedTurnId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.plan.cancel\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cancelled: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"settled\", false>;\n \"thread.rename\": HostDaemonCommandDescriptor<\"thread.rename\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.rename\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"thread.archive\": HostDaemonCommandDescriptor<\"thread.archive\", z$1.ZodObject<{\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.archive\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"thread.unarchive\": HostDaemonCommandDescriptor<\"thread.unarchive\", z$1.ZodObject<{\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n environmentId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"thread.unarchive\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"interactive.resolve\": HostDaemonCommandDescriptor<\"interactive.resolve\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n interactionId: z$1.ZodString;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n resolution: z$1.ZodUnion;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin_submitted\">;\n }, z$1.core.$strip>]>;\n threadId: z$1.ZodString;\n type: z$1.ZodLiteral<\"interactive.resolve\">;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"codex.inference.complete\": HostDaemonCommandDescriptor<\"codex.inference.complete\", z$1.ZodObject<{\n model: z$1.ZodString;\n outputSchema: z$1.ZodType>;\n prompt: z$1.ZodString;\n reasoningEffort: z$1.ZodLiteral<\"none\">;\n timeoutMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"codex.inference.complete\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n model: z$1.ZodString;\n value: z$1.ZodType>;\n }, z$1.core.$strip>, \"settled\", false>;\n \"codex.voice.transcribe\": HostDaemonCommandDescriptor<\"codex.voice.transcribe\", z$1.ZodObject<{\n audioBase64: z$1.ZodString;\n filename: z$1.ZodString;\n mimeType: z$1.ZodString;\n model: z$1.ZodString;\n prompt: z$1.ZodNullable;\n timeoutMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"codex.voice.transcribe\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n model: z$1.ZodString;\n text: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"environment.provision\": HostDaemonCommandDescriptor<\"environment.provision\", z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n checkout: z$1.ZodOptional;\n name: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new\">;\n name: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n environmentId: z$1.ZodString;\n initiator: z$1.ZodNullable>;\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision\">;\n workspaceProvisionType: z$1.ZodLiteral<\"unmanaged\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodNullable;\n branchName: z$1.ZodString;\n environmentId: z$1.ZodString;\n initiator: z$1.ZodNullable>;\n setupTimeoutMs: z$1.ZodNumber;\n sourcePath: z$1.ZodString;\n targetPath: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision\">;\n workspaceProvisionType: z$1.ZodLiteral<\"managed-worktree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n initiator: z$1.ZodNullable>;\n targetPath: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision\">;\n workspaceProvisionType: z$1.ZodLiteral<\"personal\">;\n }, z$1.core.$strict>], \"workspaceProvisionType\">, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n defaultBranch: z$1.ZodNullable;\n isGitRepo: z$1.ZodBoolean;\n isWorktree: z$1.ZodBoolean;\n path: z$1.ZodString;\n transcript: z$1.ZodArray>;\n startedAt: z$1.ZodOptional;\n status: z$1.ZodOptional>;\n text: z$1.ZodString;\n type: z$1.ZodEnum<{\n output: \"output\";\n step: \"step\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"settled\", false>;\n \"project.clone\": HostDaemonCommandDescriptor<\"project.clone\", z$1.ZodObject<{\n projectSlug: z$1.ZodString;\n remoteUrl: z$1.ZodString;\n targetPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"project.clone\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n gitRemoteUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>, \"settled\", false>;\n \"environment.provision.cancel\": HostDaemonCommandDescriptor<\"environment.provision.cancel\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.provision.cancel\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n aborted: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"settled\", false>;\n \"environment.destroy\": HostDaemonCommandDescriptor<\"environment.destroy\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"environment.destroy\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{}, z$1.core.$strip>, \"settled\", false>;\n \"workspace.commit\": HostDaemonCommandDescriptor<\"workspace.commit\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n message: z$1.ZodString;\n type: z$1.ZodLiteral<\"workspace.commit\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n }, z$1.core.$strip>, \"settled\", false>;\n \"workspace.squash_merge\": HostDaemonCommandDescriptor<\"workspace.squash_merge\", z$1.ZodObject<{\n commitMessage: z$1.ZodString;\n environmentId: z$1.ZodString;\n targetBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"workspace.squash_merge\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n commitSha: z$1.ZodString;\n commitSubject: z$1.ZodString;\n merged: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"settled\", false>;\n \"workspace.pull_request_action\": HostDaemonCommandDescriptor<\"workspace.pull_request_action\", z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n environmentId: z$1.ZodString;\n operation: z$1.ZodLiteral<\"ready\">;\n type: z$1.ZodLiteral<\"workspace.pull_request_action\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n operation: z$1.ZodLiteral<\"draft\">;\n type: z$1.ZodLiteral<\"workspace.pull_request_action\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n method: z$1.ZodEnum<{\n merge: \"merge\";\n rebase: \"rebase\";\n squash: \"squash\";\n }>;\n operation: z$1.ZodLiteral<\"merge\">;\n type: z$1.ZodLiteral<\"workspace.pull_request_action\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>], \"operation\">, z$1.ZodObject<{}, z$1.core.$strict>, \"settled\", false>;\n \"host.list_files\": HostDaemonCommandDescriptor<\"host.list_files\", z$1.ZodObject<{\n limit: z$1.ZodNumber;\n path: z$1.ZodString;\n query: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.list_files\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n files: z$1.ZodArray>;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.list_paths\": HostDaemonCommandDescriptor<\"host.list_paths\", z$1.ZodObject<{\n includeDirectories: z$1.ZodBoolean;\n includeFiles: z$1.ZodBoolean;\n limit: z$1.ZodNumber;\n path: z$1.ZodString;\n query: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.list_paths\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n paths: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n positions: z$1.ZodArray;\n score: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.mkdir\": HostDaemonCommandDescriptor<\"host.mkdir\", z$1.ZodObject<{\n path: z$1.ZodString;\n recursive: z$1.ZodBoolean;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.mkdir\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.move_path\": HostDaemonCommandDescriptor<\"host.move_path\", z$1.ZodObject<{\n destinationPath: z$1.ZodString;\n rootPath: z$1.ZodOptional;\n sourcePath: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.move_path\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.remove_path\": HostDaemonCommandDescriptor<\"host.remove_path\", z$1.ZodObject<{\n path: z$1.ZodString;\n recursive: z$1.ZodBoolean;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.remove_path\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.browse_directory\": HostDaemonCommandDescriptor<\"host.browse_directory\", z$1.ZodObject<{\n path: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.browse_directory\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n directory: z$1.ZodString;\n entries: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n parent: z$1.ZodNullable;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.paths_exist\": HostDaemonCommandDescriptor<\"host.paths_exist\", z$1.ZodObject<{\n paths: z$1.ZodPipe, z$1.ZodTransform>;\n type: z$1.ZodLiteral<\"host.paths_exist\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n existence: z$1.ZodRecord;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"project.inspect\": HostDaemonCommandDescriptor<\"project.inspect\", z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"project.inspect\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n gitRemoteUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"project.clone_default_path\": HostDaemonCommandDescriptor<\"project.clone_default_path\", z$1.ZodObject<{\n projectSlug: z$1.ZodString;\n type: z$1.ZodLiteral<\"project.clone_default_path\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n path: z$1.ZodString;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"host.pick_folder\": HostDaemonCommandDescriptor<\"host.pick_folder\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"host.pick_folder\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n path: z$1.ZodNullable;\n }, z$1.core.$strip>, \"onlineRpc\", false>;\n \"plugin.host.call\": HostDaemonCommandDescriptor<\"plugin.host.call\", z$1.ZodObject<{\n artifact: z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n }, z$1.core.$strict>;\n callId: z$1.ZodString;\n generation: z$1.ZodString;\n input: z$1.ZodType>;\n method: z$1.ZodString;\n pluginId: z$1.ZodString;\n timeoutMs: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"plugin.host.call\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n output: z$1.ZodType>;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"plugin.host.cancel\": HostDaemonCommandDescriptor<\"plugin.host.cancel\", z$1.ZodObject<{\n callId: z$1.ZodString;\n generation: z$1.ZodString;\n pluginId: z$1.ZodString;\n type: z$1.ZodLiteral<\"plugin.host.cancel\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cancelled: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"plugin.host.dispose\": HostDaemonCommandDescriptor<\"plugin.host.dispose\", z$1.ZodObject<{\n generation: z$1.ZodString;\n pluginId: z$1.ZodString;\n type: z$1.ZodLiteral<\"plugin.host.dispose\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n disposed: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"connect-tunnel.ensure-identity\": HostDaemonCommandDescriptor<\"connect-tunnel.ensure-identity\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"connect-tunnel.ensure-identity\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseDomain: z$1.ZodString;\n label: z$1.ZodString;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"host.list_commands\": HostDaemonCommandDescriptor<\"host.list_commands\", z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n providerId: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.list_commands\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n commands: z$1.ZodArray;\n description: z$1.ZodNullable;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.list_skills\": HostDaemonCommandDescriptor<\"host.list_skills\", z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n providerId: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.list_skills\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n skills: z$1.ZodArray;\n filePath: z$1.ZodString;\n id: z$1.ZodString;\n linked: z$1.ZodBoolean;\n name: z$1.ZodString;\n rootKind: z$1.ZodEnum<{\n \"bb-builtin\": \"bb-builtin\";\n \"bb-data-dir\": \"bb-data-dir\";\n \"bb-project\": \"bb-project\";\n \"provider-project\": \"provider-project\";\n \"provider-user\": \"provider-user\";\n \"shared-project\": \"shared-project\";\n \"shared-user\": \"shared-user\";\n plugin: \"plugin\";\n }>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.delete_skill\": HostDaemonCommandDescriptor<\"host.delete_skill\", z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n name: z$1.ZodString;\n rootPath: z$1.ZodNullable;\n scope: z$1.ZodEnum<{\n \"bb-project\": \"bb-project\";\n \"bb-user\": \"bb-user\";\n \"provider-project\": \"provider-project\";\n \"provider-user\": \"provider-user\";\n }>;\n type: z$1.ZodLiteral<\"host.delete_skill\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n deletedPath: z$1.ZodString;\n }, z$1.core.$strip>, \"onlineRpc\", false>;\n \"host.write_skill\": HostDaemonCommandDescriptor<\"host.write_skill\", z$1.ZodObject<{\n content: z$1.ZodString;\n cwd: z$1.ZodNullable;\n expectedSha256: z$1.ZodString;\n name: z$1.ZodString;\n scope: z$1.ZodEnum<{\n \"bb-project\": \"bb-project\";\n \"bb-user\": \"bb-user\";\n }>;\n type: z$1.ZodLiteral<\"host.write_skill\">;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n filePath: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"written\">;\n sha256: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n currentSha256: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"conflict\">;\n }, z$1.core.$strip>], \"outcome\">, \"onlineRpc\", false>;\n \"host.install_global_skills\": HostDaemonCommandDescriptor<\"host.install_global_skills\", z$1.ZodObject<{\n skills: z$1.ZodArray>;\n type: z$1.ZodLiteral<\"host.install_global_skills\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n installations: z$1.ZodArray>;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"host.global_skills_status\": HostDaemonCommandDescriptor<\"host.global_skills_status\", z$1.ZodObject<{\n names: z$1.ZodArray;\n type: z$1.ZodLiteral<\"host.global_skills_status\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n entries: z$1.ZodArray;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"host.list_branches\": HostDaemonCommandDescriptor<\"host.list_branches\", z$1.ZodObject<{\n limit: z$1.ZodNumber;\n path: z$1.ZodString;\n query: z$1.ZodOptional;\n selectedBranch: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.list_branches\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branches: z$1.ZodArray;\n branchesTruncated: z$1.ZodBoolean;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n defaultBranch: z$1.ZodNullable;\n defaultBranchRelation: z$1.ZodNullable>;\n hasUncommittedChanges: z$1.ZodBoolean;\n operation: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"none\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"merge\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"rebase\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"cherry-pick\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"revert\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hasConflicts: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n originDefaultBranch: z$1.ZodNullable;\n remoteBranches: z$1.ZodArray;\n remoteBranchesTruncated: z$1.ZodBoolean;\n selectedBranch: z$1.ZodNullable;\n name: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.file_metadata\": HostDaemonCommandDescriptor<\"host.file_metadata\", z$1.ZodObject<{\n path: z$1.ZodString;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.file_metadata\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n modifiedAtMs: z$1.ZodNumber;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.read_file\": HostDaemonCommandDescriptor<\"host.read_file\", z$1.ZodObject<{\n path: z$1.ZodString;\n ref: z$1.ZodOptional;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.read_file\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n mimeType: z$1.ZodOptional;\n modifiedAtMs: z$1.ZodOptional;\n path: z$1.ZodString;\n sha256: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.read_file_relative\": HostDaemonCommandDescriptor<\"host.read_file_relative\", z$1.ZodObject<{\n dotfiles: z$1.ZodEnum<{\n allow: \"allow\";\n deny: \"deny\";\n }>;\n path: z$1.ZodString;\n rootPath: z$1.ZodString;\n type: z$1.ZodLiteral<\"host.read_file_relative\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n mimeType: z$1.ZodOptional;\n modifiedAtMs: z$1.ZodOptional;\n path: z$1.ZodString;\n sha256: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"host.write_file\": HostDaemonCommandDescriptor<\"host.write_file\", z$1.ZodObject<{\n content: z$1.ZodString;\n contentEncoding: z$1.ZodEnum<{\n base64: \"base64\";\n utf8: \"utf8\";\n }>;\n createParents: z$1.ZodBoolean;\n expectedSha256: z$1.ZodOptional>;\n mode: z$1.ZodOptional;\n path: z$1.ZodString;\n rootPath: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host.write_file\">;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"written\">;\n sha256: z$1.ZodString;\n sizeBytes: z$1.ZodNumber;\n }, z$1.core.$strict>, z$1.ZodObject<{\n currentSha256: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"conflict\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", false>;\n \"provider.list_models\": HostDaemonCommandDescriptor<\"provider.list_models\", z$1.ZodObject<{\n acpLaunchSpec: z$1.ZodOptional;\n command: z$1.ZodString;\n cwd: z$1.ZodOptional;\n displayName: z$1.ZodString;\n env: z$1.ZodRecord;\n modelCli: z$1.ZodOptional;\n primaryModels: z$1.ZodArray;\n selectFlag: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodTransform<{\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n } | undefined, {\n listArgs: string[];\n primaryModels: string[];\n selectFlag?: string | undefined;\n }>>>;\n nativeReasoning: z$1.ZodOptional>;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n nativeSkillRoots: z$1.ZodOptional>;\n user: z$1.ZodDefault>;\n }, z$1.core.$strict>>;\n permissionCli: z$1.ZodOptional>;\n insertAfterArgs: z$1.ZodOptional;\n readonly: z$1.ZodOptional>;\n workspaceWrite: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n reasoningCli: z$1.ZodOptional>;\n flag: z$1.ZodString;\n levelValues: z$1.ZodOptional & z$1.core.$partial, z$1.ZodString>>;\n supportedLevels: z$1.ZodArray>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>>;\n bridgeLaunch: z$1.ZodObject<{\n capabilities: z$1.ZodObject<{\n fork: z$1.ZodEnum<{\n checkpoint: \"checkpoint\";\n none: \"none\";\n tip: \"tip\";\n }>;\n permissionModes: z$1.ZodArray>;\n supportsServiceTier: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n pluginId: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n byteLength: z$1.ZodNumber;\n digest: z$1.ZodString;\n kind: z$1.ZodLiteral<\"artifact\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"daemon-bundled\">;\n }, z$1.core.$strict>], \"kind\">;\n }, z$1.core.$strict>;\n cwd: z$1.ZodOptional;\n providerId: z$1.ZodString;\n type: z$1.ZodLiteral<\"provider.list_models\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n models: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n selectedOnlyModels: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"known_acp_agents.status\": HostDaemonCommandDescriptor<\"known_acp_agents.status\", z$1.ZodObject<{\n agents: z$1.ZodArray>;\n type: z$1.ZodLiteral<\"known_acp_agents.status\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n agents: z$1.ZodArray;\n id: z$1.ZodString;\n installed: z$1.ZodBoolean;\n }, z$1.core.$strict>>;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"provider.usage\": HostDaemonCommandDescriptor<\"provider.usage\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"provider.usage\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n claudeCode: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n codex: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n cursor: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n accountEmail: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n status: z$1.ZodLiteral<\"ok\">;\n windows: z$1.ZodArray>;\n label: z$1.ZodString;\n resetsAt: z$1.ZodNullable;\n usedPercent: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"not_installed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"unauthenticated\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n status: z$1.ZodLiteral<\"expired\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n accountEmail: z$1.ZodDefault>;\n message: z$1.ZodString;\n planLabel: z$1.ZodDefault>;\n status: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"status\">;\n }, z$1.core.$strip>, \"onlineRpc\", true>;\n \"workspace.discover_repos\": HostDaemonCommandDescriptor<\"workspace.discover_repos\", z$1.ZodObject<{\n limit: z$1.ZodNumber;\n maxDepth: z$1.ZodNumber;\n sinceDays: z$1.ZodNumber;\n type: z$1.ZodLiteral<\"workspace.discover_repos\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n repos: z$1.ZodArray;\n lastActivityAt: z$1.ZodString;\n name: z$1.ZodString;\n originUrl: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strict>>;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strict>, \"onlineRpc\", true>;\n \"provider_cli.status\": HostDaemonCommandDescriptor<\"provider_cli.status\", z$1.ZodObject<{\n type: z$1.ZodLiteral<\"provider_cli.status\">;\n }, z$1.core.$strict>, z$1.ZodRecord, z$1.ZodObject<{\n currentVersion: z$1.ZodNullable;\n displayName: z$1.ZodString;\n executableName: z$1.ZodString;\n executablePath: z$1.ZodNullable;\n installAction: z$1.ZodNullable;\n kind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n label: z$1.ZodEnum<{\n Install: \"Install\";\n Update: \"Update\";\n }>;\n }, z$1.core.$strip>>;\n installSource: z$1.ZodEnum<{\n external: \"external\";\n notInstalled: \"notInstalled\";\n npmGlobal: \"npmGlobal\";\n }>;\n installed: z$1.ZodBoolean;\n latestVersion: z$1.ZodNullable;\n minimumSupportedVersion: z$1.ZodNullable;\n needsUpdate: z$1.ZodBoolean;\n npmGlobalPackageVersion: z$1.ZodNullable;\n npmPackageName: z$1.ZodNullable;\n versionUnsupported: z$1.ZodBoolean;\n }, z$1.core.$strip>>, \"onlineRpc\", true>;\n \"provider_cli.install\": HostDaemonCommandDescriptor<\"provider_cli.install\", z$1.ZodObject<{\n actionKind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"provider_cli.install\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n events: z$1.ZodArray;\n type: z$1.ZodLiteral<\"started\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n stream: z$1.ZodEnum<{\n stderr: \"stderr\";\n stdout: \"stdout\";\n }>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"output\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n exitCode: z$1.ZodNullable;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n signal: z$1.ZodNullable;\n success: z$1.ZodBoolean;\n type: z$1.ZodLiteral<\"completed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"error\">;\n }, z$1.core.$strip>], \"type\">>;\n }, z$1.core.$strict>, \"onlineRpc\", false>;\n \"workspace.status\": HostDaemonCommandDescriptor<\"workspace.status\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxUntrackedLineStatBytes: z$1.ZodNumber;\n maxUntrackedLineStatFiles: z$1.ZodNumber;\n mergeBaseBranch: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"workspace.status\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n workspaceStatus: z$1.ZodObject<{\n branch: z$1.ZodObject<{\n currentBranch: z$1.ZodNullable;\n defaultBranch: z$1.ZodString;\n }, z$1.core.$strip>;\n checkout: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branchName: z$1.ZodString;\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"branch\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n headSha: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"detached\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n branchName: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"unborn\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"unknown\">;\n reason: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">;\n mergeBase: z$1.ZodNullable;\n behindCount: z$1.ZodNumber;\n commits: z$1.ZodArray>;\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasCommittedUnmergedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodString;\n }, z$1.core.$strip>>;\n workingTree: z$1.ZodObject<{\n deletions: z$1.ZodNumber;\n files: z$1.ZodArray;\n insertions: z$1.ZodNullable;\n path: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"?\": \"?\";\n \"??\": \"??\";\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n U: \"U\";\n }>;\n }, z$1.core.$strip>>;\n hasUncommittedChanges: z$1.ZodBoolean;\n insertions: z$1.ZodNumber;\n lineStatsComplete: z$1.ZodBoolean;\n state: z$1.ZodEnum<{\n clean: \"clean\";\n committed_unmerged: \"committed_unmerged\";\n dirty_and_committed_unmerged: \"dirty_and_committed_unmerged\";\n dirty_uncommitted: \"dirty_uncommitted\";\n untracked: \"untracked\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.diff\": HostDaemonCommandDescriptor<\"workspace.diff\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxDiffBytes: z$1.ZodNumber;\n maxFileListBytes: z$1.ZodNumber;\n maxUntrackedFiles: z$1.ZodNumber;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n type: z$1.ZodLiteral<\"workspace.diff\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n diff: z$1.ZodObject<{\n diff: z$1.ZodString;\n files: z$1.ZodString;\n mergeBaseRef: z$1.ZodNullable;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n outcome: z$1.ZodLiteral<\"available\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.diffFiles\": HostDaemonCommandDescriptor<\"workspace.diffFiles\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxFiles: z$1.ZodNumber;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n type: z$1.ZodLiteral<\"workspace.diffFiles\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n files: z$1.ZodArray;\n path: z$1.ZodString;\n previousPath: z$1.ZodNullable;\n statusLetter: z$1.ZodEnum<{\n A: \"A\";\n C: \"C\";\n D: \"D\";\n M: \"M\";\n R: \"R\";\n T: \"T\";\n }>;\n }, z$1.core.$strip>>;\n mergeBaseRef: z$1.ZodNullable;\n outcome: z$1.ZodLiteral<\"available\">;\n shortstat: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.diffPatch\": HostDaemonCommandDescriptor<\"workspace.diffPatch\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n maxBytesPerFile: z$1.ZodNumber;\n paths: z$1.ZodArray;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n type: z$1.ZodLiteral<\"uncommitted\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"branch_committed\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mergeBaseBranch: z$1.ZodString;\n type: z$1.ZodLiteral<\"all\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n sha: z$1.ZodString;\n type: z$1.ZodLiteral<\"commit\">;\n }, z$1.core.$strip>], \"type\">;\n type: z$1.ZodLiteral<\"workspace.diffPatch\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n patches: z$1.ZodArray>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n failure: z$1.ZodObject<{\n code: z$1.ZodEnum<{\n not_git_repo: \"not_git_repo\";\n not_worktree: \"not_worktree\";\n path_not_found: \"path_not_found\";\n permission_denied: \"permission_denied\";\n unknown: \"unknown\";\n unknown_environment: \"unknown_environment\";\n workspace_type_mismatch: \"workspace_type_mismatch\";\n }>;\n message: z$1.ZodString;\n workspacePath: z$1.ZodString;\n }, z$1.core.$strict>;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n \"workspace.pull_request\": HostDaemonCommandDescriptor<\"workspace.pull_request\", z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"workspace.pull_request\">;\n workspaceContext: z$1.ZodObject<{\n workspacePath: z$1.ZodString;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"available\">;\n pullRequest: z$1.ZodObject<{\n baseRefName: z$1.ZodString;\n checks: z$1.ZodArray>;\n name: z$1.ZodString;\n startedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n in_progress: \"in_progress\";\n queued: \"queued\";\n unknown: \"unknown\";\n }>;\n url: z$1.ZodNullable;\n }, z$1.core.$strict>>;\n headRefName: z$1.ZodString;\n isDraft: z$1.ZodBoolean;\n mergeStateStatus: z$1.ZodNullable>;\n mergeable: z$1.ZodNullable>;\n number: z$1.ZodNumber;\n reviewDecision: z$1.ZodNullable>;\n reviewRequestCount: z$1.ZodNumber;\n state: z$1.ZodEnum<{\n CLOSED: \"CLOSED\";\n MERGED: \"MERGED\";\n OPEN: \"OPEN\";\n }>;\n title: z$1.ZodString;\n updatedAt: z$1.ZodString;\n url: z$1.ZodString;\n }, z$1.core.$strict>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n outcome: z$1.ZodLiteral<\"absent\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n message: z$1.ZodString;\n outcome: z$1.ZodLiteral<\"unavailable\">;\n }, z$1.core.$strict>], \"outcome\">, \"onlineRpc\", true>;\n};\ntype HostDaemonCommandRegistry = typeof hostDaemonCommandRegistry;\ntype AnyHostDaemonCommandDescriptor = HostDaemonCommandRegistry[keyof HostDaemonCommandRegistry];\ntype HostDaemonCommandDescriptorForTransport = Extract;\ntype HostDaemonResultSchemaMapForTransport = {\n [Descriptor in HostDaemonCommandDescriptorForTransport as Descriptor[\"type\"]]: Descriptor[\"resultSchema\"];\n};\ntype HostDaemonOnlineRpcResultSchemaMap = HostDaemonResultSchemaMapForTransport<\"onlineRpc\">;\ntype HostDaemonOnlineRpcResultByType = {\n [K in keyof HostDaemonOnlineRpcResultSchemaMap]: z$1.infer;\n};\n\ndeclare const pickFolderResponseSchema: z$1.ZodObject<{\n path: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype PickFolderResponse = z$1.infer;\ndeclare const pathsExistRequestSchema: z$1.ZodObject<{\n paths: z$1.ZodPipe, z$1.ZodTransform>;\n}, z$1.core.$strip>;\ntype PathsExistRequest = z$1.infer;\ndeclare const pathsExistResponseSchema: z$1.ZodObject<{\n existence: z$1.ZodRecord;\n}, z$1.core.$strip>;\ntype PathsExistResponse = z$1.infer;\ndeclare const providerCliStatusResponseSchema: z$1.ZodRecord, z$1.ZodObject<{\n currentVersion: z$1.ZodNullable;\n displayName: z$1.ZodString;\n executableName: z$1.ZodString;\n executablePath: z$1.ZodNullable;\n installAction: z$1.ZodNullable;\n kind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n label: z$1.ZodEnum<{\n Install: \"Install\";\n Update: \"Update\";\n }>;\n }, z$1.core.$strip>>;\n installSource: z$1.ZodEnum<{\n external: \"external\";\n notInstalled: \"notInstalled\";\n npmGlobal: \"npmGlobal\";\n }>;\n installed: z$1.ZodBoolean;\n latestVersion: z$1.ZodNullable;\n minimumSupportedVersion: z$1.ZodNullable;\n needsUpdate: z$1.ZodBoolean;\n npmGlobalPackageVersion: z$1.ZodNullable;\n npmPackageName: z$1.ZodNullable;\n versionUnsupported: z$1.ZodBoolean;\n}, z$1.core.$strip>>;\ntype ProviderCliStatusResponse = z$1.infer;\ndeclare const providerCliInstallRequestSchema: z$1.ZodObject<{\n actionKind: z$1.ZodEnum<{\n install: \"install\";\n update: \"update\";\n }>;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n}, z$1.core.$strip>;\ntype ProviderCliInstallRequest = z$1.infer;\ndeclare const providerCliInstallEventSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n command: z$1.ZodString;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n stream: z$1.ZodEnum<{\n stderr: \"stderr\";\n stdout: \"stdout\";\n }>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"output\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n exitCode: z$1.ZodNullable;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n signal: z$1.ZodNullable;\n success: z$1.ZodBoolean;\n type: z$1.ZodLiteral<\"completed\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n message: z$1.ZodString;\n provider: z$1.ZodEnum<{\n claudeCode: \"claudeCode\";\n codex: \"codex\";\n cursor: \"cursor\";\n }>;\n type: z$1.ZodLiteral<\"error\">;\n}, z$1.core.$strip>], \"type\">;\ntype ProviderCliInstallEvent = z$1.infer;\n\ninterface CreateFilePreviewResponse {\n baseUrl: string;\n expiresAtMs: number;\n}\ntype HostFileReadResponse = HostDaemonOnlineRpcResultByType[\"host.read_file\"];\ntype HostFileWriteResponse = HostDaemonOnlineRpcResultByType[\"host.write_file\"];\ntype HostFileListResponse = HostDaemonOnlineRpcResultByType[\"host.list_files\"];\ntype HostPathListResponse = HostDaemonOnlineRpcResultByType[\"host.list_paths\"];\ntype HostMkdirResponse = HostDaemonOnlineRpcResultByType[\"host.mkdir\"];\ntype HostMovePathResponse = HostDaemonOnlineRpcResultByType[\"host.move_path\"];\ntype HostRemovePathResponse = HostDaemonOnlineRpcResultByType[\"host.remove_path\"];\n\n/**\n * Query for `GET /hosts/:id/directory`, the interactive path browser's\n * single-level directory read. `path` is an absolute directory on the host;\n * omitting it lists the host's home directory (the daemon resolves it, since a\n * remote caller cannot know the host's home).\n */\ndeclare const hostDirectoryQuerySchema: z$1.ZodObject<{\n path: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype HostDirectoryQuery = z$1.infer;\ndeclare const hostDirectoryListingSchema: z$1.ZodObject<{\n directory: z$1.ZodString;\n entries: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n }, z$1.core.$strip>>;\n parent: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype HostDirectoryListing = z$1.infer;\n/** Project name is sent so the daemon can derive its host-local checkout path. */\ndeclare const hostCloneDefaultPathQuerySchema: z$1.ZodObject<{\n projectId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype HostCloneDefaultPathQuery = z$1.infer;\ndeclare const hostCloneDefaultPathResponseSchema: z$1.ZodObject<{\n path: z$1.ZodString;\n}, z$1.core.$strict>;\ntype HostCloneDefaultPathResponse = z$1.infer;\ndeclare const createHostJoinCodeResponseSchema: z$1.ZodObject<{\n expiresAt: z$1.ZodNumber;\n hostId: z$1.ZodString;\n joinCode: z$1.ZodString;\n}, z$1.core.$strip>;\ntype CreateHostJoinCodeResponse = z$1.infer;\ndeclare const updateHostRequestSchema: z$1.ZodObject<{\n name: z$1.ZodString;\n}, z$1.core.$strict>;\ntype UpdateHostRequest = z$1.infer;\ndeclare const hostRetryUpdateResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n}, z$1.core.$strict>;\ntype HostRetryUpdateResponse = z$1.infer;\ntype HostPathsExistRequest = PathsExistRequest;\ntype HostPathsExistResponse = PathsExistResponse;\ndeclare const hostPickFolderRequestSchema: z$1.ZodObject<{\n clientHostId: z$1.ZodString;\n}, z$1.core.$strict>;\ntype HostPickFolderRequest = z$1.infer;\ntype HostPickFolderResponse = PickFolderResponse;\ntype HostProviderCliStatusResponse = ProviderCliStatusResponse;\ntype HostProviderCliInstallRequest = ProviderCliInstallRequest;\ntype HostProviderCliInstallEvent = ProviderCliInstallEvent;\n\ndeclare const pluginUpdateCheckEntrySchema: z$1.ZodObject<{\n blocked: z$1.ZodOptional;\n version: z$1.ZodString;\n }, z$1.core.$strip>>;\n candidate: z$1.ZodOptional>;\n detail: z$1.ZodOptional;\n devMode: z$1.ZodOptional>;\n id: z$1.ZodString;\n installed: z$1.ZodObject<{\n display: z$1.ZodString;\n version: z$1.ZodString;\n }, z$1.core.$strip>;\n outcome: z$1.ZodEnum<{\n \"update-available\": \"update-available\";\n current: \"current\";\n incompatible: \"incompatible\";\n pinned: \"pinned\";\n unavailable: \"unavailable\";\n }>;\n}, z$1.core.$strip>;\ntype PluginUpdateCheckEntry = z$1.infer;\ndeclare const pluginApplyUpdateResultSchema: z$1.ZodObject<{\n applied: z$1.ZodBoolean;\n detail: z$1.ZodOptional;\n from: z$1.ZodObject<{\n display: z$1.ZodString;\n version: z$1.ZodString;\n }, z$1.core.$strip>;\n outcome: z$1.ZodEnum<{\n \"rolled-back\": \"rolled-back\";\n current: \"current\";\n updated: \"updated\";\n }>;\n to: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype PluginApplyUpdateResult$1 = z$1.infer;\ndeclare const pluginSourceDetailSchema: z$1.ZodObject<{\n engines: z$1.ZodObject<{\n bb: z$1.ZodOptional;\n bbPluginSdk: z$1.ZodOptional;\n }, z$1.core.$strip>;\n history: z$1.ZodArray>;\n installedAt: z$1.ZodOptional;\n integrity: z$1.ZodOptional;\n range: z$1.ZodOptional;\n registry: z$1.ZodOptional;\n requested: z$1.ZodString;\n resolved: z$1.ZodString;\n resolvedTag: z$1.ZodOptional;\n subdirectory: z$1.ZodOptional;\n tagPrefix: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype PluginSourceDetail = z$1.infer;\ndeclare const installedPluginSchema: z$1.ZodObject<{\n app: z$1.ZodObject<{\n bundle: z$1.ZodNullable;\n hash: z$1.ZodString;\n jsBytes: z$1.ZodNumber;\n jsUrl: z$1.ZodString;\n sdkMajor: z$1.ZodNumber;\n sdkVersion: z$1.ZodString;\n }, z$1.core.$strip>>;\n hasApp: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n capabilities: z$1.ZodDefault;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n \"agent-tool\": \"agent-tool\";\n \"thread-integration\": \"thread-integration\";\n skill: \"skill\";\n theme: \"theme\";\n }>;\n label: z$1.ZodString;\n }, z$1.core.$strip>>>;\n catalogEntryId: z$1.ZodOptional;\n catalogMarketplaceName: z$1.ZodOptional;\n cliCommand: z$1.ZodNullable>;\n description: z$1.ZodNullable;\n enabled: z$1.ZodBoolean;\n handlerStats: z$1.ZodObject<{\n count: z$1.ZodNumber;\n errorCount: z$1.ZodNumber;\n maxMs: z$1.ZodNumber;\n totalMs: z$1.ZodNumber;\n }, z$1.core.$strip>;\n hasSettings: z$1.ZodBoolean;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n isOrphanedBuiltin: z$1.ZodBoolean;\n logoDarkUrl: z$1.ZodNullable;\n logoUrl: z$1.ZodNullable;\n name: z$1.ZodNullable;\n provenance: z$1.ZodEnum<{\n builtin: \"builtin\";\n catalog: \"catalog\";\n direct: \"direct\";\n }>;\n publisherLabel: z$1.ZodDefault>;\n rootDir: z$1.ZodString;\n schedules: z$1.ZodArray;\n lastRunAt: z$1.ZodNullable;\n lastStatus: z$1.ZodNullable>;\n name: z$1.ZodString;\n nextRunAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n services: z$1.ZodArray;\n }, z$1.core.$strip>>;\n source: z$1.ZodString;\n sourceDisplay: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"needs-configuration\": \"needs-configuration\";\n degraded: \"degraded\";\n disabled: \"disabled\";\n error: \"error\";\n incompatible: \"incompatible\";\n missing: \"missing\";\n running: \"running\";\n }>;\n statusDetail: z$1.ZodNullable;\n updateState: z$1.ZodObject<{\n availableVersion: z$1.ZodOptional;\n blockedReasons: z$1.ZodOptional>;\n blockedVersion: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n lastCheckAt: z$1.ZodOptional;\n lastFailure: z$1.ZodOptional>;\n outcome: z$1.ZodOptional>;\n }, z$1.core.$strip>;\n version: z$1.ZodString;\n}, z$1.core.$strip>;\ntype InstalledPlugin = z$1.infer;\ndeclare const pluginListResponseSchema: z$1.ZodObject<{\n plugins: z$1.ZodArray;\n hash: z$1.ZodString;\n jsBytes: z$1.ZodNumber;\n jsUrl: z$1.ZodString;\n sdkMajor: z$1.ZodNumber;\n sdkVersion: z$1.ZodString;\n }, z$1.core.$strip>>;\n hasApp: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n capabilities: z$1.ZodDefault;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n \"agent-tool\": \"agent-tool\";\n \"thread-integration\": \"thread-integration\";\n skill: \"skill\";\n theme: \"theme\";\n }>;\n label: z$1.ZodString;\n }, z$1.core.$strip>>>;\n catalogEntryId: z$1.ZodOptional;\n catalogMarketplaceName: z$1.ZodOptional;\n cliCommand: z$1.ZodNullable>;\n description: z$1.ZodNullable;\n enabled: z$1.ZodBoolean;\n handlerStats: z$1.ZodObject<{\n count: z$1.ZodNumber;\n errorCount: z$1.ZodNumber;\n maxMs: z$1.ZodNumber;\n totalMs: z$1.ZodNumber;\n }, z$1.core.$strip>;\n hasSettings: z$1.ZodBoolean;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n isOrphanedBuiltin: z$1.ZodBoolean;\n logoDarkUrl: z$1.ZodNullable;\n logoUrl: z$1.ZodNullable;\n name: z$1.ZodNullable;\n provenance: z$1.ZodEnum<{\n builtin: \"builtin\";\n catalog: \"catalog\";\n direct: \"direct\";\n }>;\n publisherLabel: z$1.ZodDefault>;\n rootDir: z$1.ZodString;\n schedules: z$1.ZodArray;\n lastRunAt: z$1.ZodNullable;\n lastStatus: z$1.ZodNullable>;\n name: z$1.ZodString;\n nextRunAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n services: z$1.ZodArray;\n }, z$1.core.$strip>>;\n source: z$1.ZodString;\n sourceDisplay: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"needs-configuration\": \"needs-configuration\";\n degraded: \"degraded\";\n disabled: \"disabled\";\n error: \"error\";\n incompatible: \"incompatible\";\n missing: \"missing\";\n running: \"running\";\n }>;\n statusDetail: z$1.ZodNullable;\n updateState: z$1.ZodObject<{\n availableVersion: z$1.ZodOptional;\n blockedReasons: z$1.ZodOptional>;\n blockedVersion: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n lastCheckAt: z$1.ZodOptional;\n lastFailure: z$1.ZodOptional>;\n outcome: z$1.ZodOptional>;\n }, z$1.core.$strip>;\n version: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype PluginListResponse = z$1.infer;\ndeclare const pluginReloadResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n plugins: z$1.ZodArray;\n hash: z$1.ZodString;\n jsBytes: z$1.ZodNumber;\n jsUrl: z$1.ZodString;\n sdkMajor: z$1.ZodNumber;\n sdkVersion: z$1.ZodString;\n }, z$1.core.$strip>>;\n hasApp: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n capabilities: z$1.ZodDefault;\n id: z$1.ZodString;\n kind: z$1.ZodEnum<{\n \"agent-tool\": \"agent-tool\";\n \"thread-integration\": \"thread-integration\";\n skill: \"skill\";\n theme: \"theme\";\n }>;\n label: z$1.ZodString;\n }, z$1.core.$strip>>>;\n catalogEntryId: z$1.ZodOptional;\n catalogMarketplaceName: z$1.ZodOptional;\n cliCommand: z$1.ZodNullable>;\n description: z$1.ZodNullable;\n enabled: z$1.ZodBoolean;\n handlerStats: z$1.ZodObject<{\n count: z$1.ZodNumber;\n errorCount: z$1.ZodNumber;\n maxMs: z$1.ZodNumber;\n totalMs: z$1.ZodNumber;\n }, z$1.core.$strip>;\n hasSettings: z$1.ZodBoolean;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n id: z$1.ZodString;\n isOrphanedBuiltin: z$1.ZodBoolean;\n logoDarkUrl: z$1.ZodNullable;\n logoUrl: z$1.ZodNullable;\n name: z$1.ZodNullable;\n provenance: z$1.ZodEnum<{\n builtin: \"builtin\";\n catalog: \"catalog\";\n direct: \"direct\";\n }>;\n publisherLabel: z$1.ZodDefault>;\n rootDir: z$1.ZodString;\n schedules: z$1.ZodArray;\n lastRunAt: z$1.ZodNullable;\n lastStatus: z$1.ZodNullable>;\n name: z$1.ZodString;\n nextRunAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n services: z$1.ZodArray;\n }, z$1.core.$strip>>;\n source: z$1.ZodString;\n sourceDisplay: z$1.ZodString;\n status: z$1.ZodEnum<{\n \"needs-configuration\": \"needs-configuration\";\n degraded: \"degraded\";\n disabled: \"disabled\";\n error: \"error\";\n incompatible: \"incompatible\";\n missing: \"missing\";\n running: \"running\";\n }>;\n statusDetail: z$1.ZodNullable;\n updateState: z$1.ZodObject<{\n availableVersion: z$1.ZodOptional;\n blockedReasons: z$1.ZodOptional>;\n blockedVersion: z$1.ZodOptional;\n detail: z$1.ZodOptional;\n lastCheckAt: z$1.ZodOptional;\n lastFailure: z$1.ZodOptional>;\n outcome: z$1.ZodOptional>;\n }, z$1.core.$strip>;\n version: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype PluginReloadResponse = z$1.infer;\ndeclare const pluginRemoveResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype PluginRemoveResponse = z$1.infer;\ndeclare const pluginSettingsResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n schema: z$1.ZodRecord;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n secret: z$1.ZodOptional>;\n type: z$1.ZodLiteral<\"string\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n default: z$1.ZodOptional;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n type: z$1.ZodLiteral<\"boolean\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n default: z$1.ZodOptional;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n options: z$1.ZodArray;\n type: z$1.ZodLiteral<\"select\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n default: z$1.ZodOptional;\n description: z$1.ZodOptional;\n label: z$1.ZodString;\n type: z$1.ZodLiteral<\"project\">;\n }, z$1.core.$strict>], \"type\">>;\n values: z$1.ZodRecord>>;\n}, z$1.core.$strip>;\ntype PluginSettingsResponse = z$1.infer;\ndeclare const pluginTokenResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n token: z$1.ZodString;\n}, z$1.core.$strip>;\ntype PluginTokenResponse = z$1.infer;\ndeclare const pluginCatalogStatusSchema: z$1.ZodObject<{\n includedPluginCount: z$1.ZodNumber;\n optionalPluginCount: z$1.ZodNumber;\n pluginCount: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype PluginCatalogStatus = z$1.infer;\ndeclare const pluginCatalogSearchResultSchema: z$1.ZodObject<{\n author: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n category: z$1.ZodString;\n compatible: z$1.ZodBoolean;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n entryId: z$1.ZodString;\n icon: z$1.ZodNullable;\n iconUrl: z$1.ZodNullable;\n incompatibleReason: z$1.ZodNullable;\n installed: z$1.ZodBoolean;\n marketplace: z$1.ZodString;\n marketplaceDisplayName: z$1.ZodString;\n official: z$1.ZodBoolean;\n pluginId: z$1.ZodString;\n publisherKey: z$1.ZodString;\n publisherLabel: z$1.ZodString;\n source: z$1.ZodString;\n}, z$1.core.$strip>;\ntype PluginCatalogSearchResult$1 = z$1.infer;\n/**\n * The true source an install will run against, resolved before anything runs.\n * Both kinds report the exact artifact they resolve to right now — a commit\n * for git, a version and its integrity for npm — so a range or tag install is\n * confirmed against the exact code it will fetch.\n */\ndeclare const pluginCatalogResolvedSourceSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"npm\">;\n package: z$1.ZodString;\n range: z$1.ZodOptional;\n registry: z$1.ZodOptional;\n resolvedIntegrity: z$1.ZodOptional;\n resolvedVersion: z$1.ZodOptional;\n tag: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n}, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"git\">;\n range: z$1.ZodOptional;\n ref: z$1.ZodOptional;\n resolvedCommit: z$1.ZodOptional;\n resolvedTag: z$1.ZodOptional;\n subdir: z$1.ZodOptional;\n tagPrefix: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n url: z$1.ZodString;\n}, z$1.core.$strict>], \"kind\">;\ntype PluginCatalogResolvedSource = z$1.infer;\n/**\n * What `POST /plugin-catalog/install` would do with the same arguments, shown\n * to the user before anything runs. `bundled` entries install from the copy\n * inside the app; `marketplace` entries install from their listed source.\n */\ndeclare const pluginCatalogInstallPlanSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n compatible: z$1.ZodBoolean;\n displayName: z$1.ZodString;\n entryId: z$1.ZodString;\n incompatibleReason: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"bundled\">;\n pluginId: z$1.ZodString;\n source: z$1.ZodString;\n}, z$1.core.$strip>, z$1.ZodObject<{\n author: z$1.ZodObject<{\n name: z$1.ZodString;\n url: z$1.ZodNullable;\n }, z$1.core.$strip>;\n compatible: z$1.ZodBoolean;\n displayName: z$1.ZodString;\n entryId: z$1.ZodString;\n incompatibleReason: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"marketplace\">;\n marketplace: z$1.ZodString;\n marketplaceDisplayName: z$1.ZodString;\n official: z$1.ZodBoolean;\n pluginId: z$1.ZodString;\n resolvedSource: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"npm\">;\n package: z$1.ZodString;\n range: z$1.ZodOptional;\n registry: z$1.ZodOptional;\n resolvedIntegrity: z$1.ZodOptional;\n resolvedVersion: z$1.ZodOptional;\n tag: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"git\">;\n range: z$1.ZodOptional;\n ref: z$1.ZodOptional;\n resolvedCommit: z$1.ZodOptional;\n resolvedTag: z$1.ZodOptional;\n subdir: z$1.ZodOptional;\n tagPrefix: z$1.ZodOptional;\n unresolvedReason: z$1.ZodOptional;\n url: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n source: z$1.ZodString;\n}, z$1.core.$strip>], \"kind\">;\ntype PluginCatalogInstallPlan = z$1.infer;\ndeclare const pluginMarketplaceSchema: z$1.ZodObject<{\n description: z$1.ZodNullable;\n displayName: z$1.ZodString;\n entryCount: z$1.ZodNumber;\n lastAttemptAt: z$1.ZodNullable;\n lastError: z$1.ZodNullable;\n lastRefreshAt: z$1.ZodNullable;\n name: z$1.ZodString;\n official: z$1.ZodBoolean;\n resolvedCommit: z$1.ZodNullable;\n source: z$1.ZodString;\n sourceKind: z$1.ZodEnum<{\n git: \"git\";\n https: \"https\";\n path: \"path\";\n }>;\n}, z$1.core.$strip>;\ntype PluginMarketplace = z$1.infer;\ndeclare const pluginMarketplaceRefreshResultSchema: z$1.ZodObject<{\n error: z$1.ZodNullable;\n marketplace: z$1.ZodObject<{\n description: z$1.ZodNullable;\n displayName: z$1.ZodString;\n entryCount: z$1.ZodNumber;\n lastAttemptAt: z$1.ZodNullable;\n lastError: z$1.ZodNullable;\n lastRefreshAt: z$1.ZodNullable;\n name: z$1.ZodString;\n official: z$1.ZodBoolean;\n resolvedCommit: z$1.ZodNullable;\n source: z$1.ZodString;\n sourceKind: z$1.ZodEnum<{\n git: \"git\";\n https: \"https\";\n path: \"path\";\n }>;\n }, z$1.core.$strip>;\n name: z$1.ZodString;\n ok: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype PluginMarketplaceRefreshResult$1 = z$1.infer;\n\ndeclare const systemExecutionOptionsResponseSchema: z$1.ZodObject<{\n modelLoadError: z$1.ZodNullable;\n providerId: z$1.ZodString;\n }, z$1.core.$strip>>;\n models: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n permissionCeiling: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n providers: z$1.ZodArray>;\n supportsFork: z$1.ZodBoolean;\n supportsNativeUserQuestion: z$1.ZodBoolean;\n supportsServiceTier: z$1.ZodBoolean;\n supportsSessionRewind: z$1.ZodBoolean;\n supportsThreadArchive: z$1.ZodBoolean;\n supportsThreadRename: z$1.ZodBoolean;\n }, z$1.core.$strip>;\n composerActions: z$1.ZodArray;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"plan\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodObject<{\n name: z$1.ZodString;\n trailingText: z$1.ZodString;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>;\n kind: z$1.ZodLiteral<\"goal\">;\n }, z$1.core.$strip>], \"kind\">>;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n logoUrl: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n selectedOnlyModels: z$1.ZodArray;\n description: z$1.ZodString;\n displayName: z$1.ZodString;\n id: z$1.ZodString;\n isDefault: z$1.ZodBoolean;\n model: z$1.ZodString;\n routeProviderId: z$1.ZodOptional;\n supportedReasoningEfforts: z$1.ZodArray;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype SystemExecutionOptionsResponse = z$1.infer;\n/**\n * Routes provider discovery through an environment's host or an explicit\n * host. Omitting both preserves the primary-host fallback.\n */\ndeclare const systemProvidersQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional;\n hostId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemProvidersQuery = z$1.infer;\ndeclare const systemExecutionOptionsQuerySchema: z$1.ZodObject<{\n environmentId: z$1.ZodOptional;\n hostId: z$1.ZodOptional;\n providerId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemExecutionOptionsQuery = z$1.infer;\n/** Omission preserves the existing behavior of reading the primary machine. */\ndeclare const systemUsageLimitsQuerySchema: z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemUsageLimitsQuery = z$1.infer;\ndeclare const systemVoiceTranscriptionResponseSchema: z$1.ZodObject<{\n text: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SystemVoiceTranscriptionResponse = z$1.infer;\ndeclare const onboardingAgentOverviewSchema: z$1.ZodObject<{\n agents: z$1.ZodArray;\n canInstall: z$1.ZodBoolean;\n displayName: z$1.ZodString;\n loginCommand: z$1.ZodNullable;\n planLabel: z$1.ZodNullable;\n providerId: z$1.ZodString;\n status: z$1.ZodEnum<{\n connected: \"connected\";\n expired: \"expired\";\n not_installed: \"not_installed\";\n unauthenticated: \"unauthenticated\";\n }>;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype OnboardingAgentOverview = z$1.infer;\n/** Omission reads the primary machine, matching the usage-limits route. */\ndeclare const systemOnboardingReposQuerySchema: z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype SystemOnboardingReposQuery = z$1.infer;\n/**\n * Onboarding funnel events, reported by the app and forwarded to the server's\n * anonymous telemetry. Categorical or counts only — never paths, project names,\n * or account emails.\n */\ndeclare const onboardingTelemetryEventSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n agentState: z$1.ZodEnum<{\n connected: \"connected\";\n none: \"none\";\n signed_out: \"signed_out\";\n }>;\n detectedAgentCount: z$1.ZodNumber;\n name: z$1.ZodLiteral<\"onboarding_started\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n name: z$1.ZodLiteral<\"onboarding_step_completed\">;\n step: z$1.ZodEnum<{\n agents: \"agents\";\n projects: \"projects\";\n }>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n name: z$1.ZodLiteral<\"onboarding_step_skipped\">;\n step: z$1.ZodEnum<{\n agents: \"agents\";\n projects: \"projects\";\n }>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n agentState: z$1.ZodEnum<{\n connected: \"connected\";\n none: \"none\";\n signed_out: \"signed_out\";\n }>;\n durationMs: z$1.ZodNumber;\n name: z$1.ZodLiteral<\"onboarding_completed\">;\n projectsAdded: z$1.ZodNumber;\n}, z$1.core.$strip>, z$1.ZodObject<{\n name: z$1.ZodLiteral<\"onboarding_dismissed\">;\n step: z$1.ZodEnum<{\n agents: \"agents\";\n projects: \"projects\";\n }>;\n}, z$1.core.$strip>], \"name\">;\ntype OnboardingTelemetryEvent = z$1.infer;\ndeclare const systemConfigResponseSchema: z$1.ZodObject<{\n appearance: z$1.ZodObject<{\n customCss: z$1.ZodNullable;\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n resolvedCodeTheme: z$1.ZodDefault>>;\n light: z$1.ZodString;\n }, z$1.core.$strict>>;\n themeId: z$1.ZodString;\n }, z$1.core.$strip>;\n customThemes: z$1.ZodArray;\n dataDir: z$1.ZodString;\n defaultKeybindings: z$1.ZodArray;\n desktopOnly: z$1.ZodBoolean;\n shortcut: z$1.ZodNullable>;\n when: z$1.ZodObject<{\n all: z$1.ZodArray>;\n none: z$1.ZodArray>;\n }, z$1.core.$strict>;\n }, z$1.core.$strict>>;\n experiments: z$1.ZodRecord, z$1.ZodBoolean>;\n featureFlags: z$1.ZodObject<{\n placeholder: z$1.ZodBoolean;\n timelineWindowEventBudget: z$1.ZodNumber;\n }, z$1.core.$strip>;\n generalSettings: z$1.ZodObject<{\n claudeCodeMemoryEnabled: z$1.ZodBoolean;\n claudeCodeSubagentsDisabled: z$1.ZodBoolean;\n claudeCodeWorkflowsDisabled: z$1.ZodBoolean;\n codexMemoryEnabled: z$1.ZodBoolean;\n codexSubagentsDisabled: z$1.ZodBoolean;\n onboardingCompletedAt: z$1.ZodNullable;\n showKeyboardHints: z$1.ZodBoolean;\n showUnhandledProviderEvents: z$1.ZodBoolean;\n steerActiveThreadOnEnter: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n hostDaemonPort: z$1.ZodNullable;\n keybindingOverrides: z$1.ZodArray;\n shortcut: z$1.ZodNullable>;\n }, z$1.core.$strict>>;\n keybindings: z$1.ZodArray;\n desktopOnly: z$1.ZodBoolean;\n shortcut: z$1.ZodObject<{\n alt: z$1.ZodBoolean;\n control: z$1.ZodBoolean;\n key: z$1.ZodString;\n meta: z$1.ZodBoolean;\n mod: z$1.ZodBoolean;\n shift: z$1.ZodBoolean;\n }, z$1.core.$strict>;\n when: z$1.ZodObject<{\n all: z$1.ZodArray>;\n none: z$1.ZodArray>;\n }, z$1.core.$strict>;\n }, z$1.core.$strict>>;\n pluginThemes: z$1.ZodArray;\n id: z$1.ZodString;\n name: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>>;\n primaryHostId: z$1.ZodNullable;\n primaryHostPlatform: z$1.ZodNullable>;\n serverUrl: z$1.ZodString;\n voiceTranscriptionEnabled: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype SystemConfigResponse = z$1.infer;\ndeclare const systemAttentionResponseSchema: z$1.ZodObject<{\n hasAttention: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype SystemAttentionResponse = z$1.infer;\n/**\n * Theme catalog: the on-disk custom-theme directory plus the discovered custom\n * themes and the active palette. Drives `bb theme list` / `bb theme dir`.\n */\ndeclare const themeCatalogResponseSchema: z$1.ZodObject<{\n active: z$1.ZodObject<{\n customCss: z$1.ZodNullable;\n faviconColor: z$1.ZodEnum<{\n blue: \"blue\";\n default: \"default\";\n green: \"green\";\n orange: \"orange\";\n pink: \"pink\";\n purple: \"purple\";\n red: \"red\";\n teal: \"teal\";\n yellow: \"yellow\";\n }>;\n resolvedCodeTheme: z$1.ZodDefault>>;\n light: z$1.ZodString;\n }, z$1.core.$strict>>;\n themeId: z$1.ZodString;\n }, z$1.core.$strip>;\n custom: z$1.ZodArray;\n dir: z$1.ZodString;\n plugins: z$1.ZodArray;\n id: z$1.ZodString;\n name: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype ThemeCatalogResponse = z$1.infer;\ndeclare const systemVersionResponseSchema: z$1.ZodObject<{\n currentVersion: z$1.ZodString;\n isDevelopment: z$1.ZodBoolean;\n latestVersion: z$1.ZodNullable;\n source: z$1.ZodLiteral<\"npm\">;\n updateAvailable: z$1.ZodBoolean;\n upgradeCommand: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SystemVersionResponse = z$1.infer;\ndeclare const systemConfigReloadResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ndeclare const systemCliSkillsStatusResponseSchema: z$1.ZodObject<{\n machines: z$1.ZodArray;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype SystemCliSkillsStatusResponse = z$1.infer;\n/** The machines to copy the built-in bb CLI skills onto. */\ndeclare const systemInstallCliSkillsRequestSchema: z$1.ZodObject<{\n hostIds: z$1.ZodArray;\n}, z$1.core.$strip>;\ntype SystemInstallCliSkillsRequest = z$1.infer;\n/**\n * One entry per requested machine. A machine that is offline or otherwise\n * refuses the install fails on its own without taking the others down, so the\n * caller can report exactly which machines got the skills.\n */\ndeclare const systemInstallCliSkillsResponseSchema: z$1.ZodObject<{\n results: z$1.ZodArray>;\n ok: z$1.ZodLiteral;\n }, z$1.core.$strip>, z$1.ZodObject<{\n errorMessage: z$1.ZodString;\n hostId: z$1.ZodString;\n hostName: z$1.ZodString;\n ok: z$1.ZodLiteral;\n }, z$1.core.$strip>], \"ok\">>;\n}, z$1.core.$strip>;\ntype SystemInstallCliSkillsResponse = z$1.infer;\ntype SystemConfigReloadResponse = z$1.infer;\n\ndeclare const terminalSessionSchema: z$1.ZodObject<{\n closeReason: z$1.ZodNullable>;\n cols: z$1.ZodNumber;\n createdAt: z$1.ZodNumber;\n environmentId: z$1.ZodNullable;\n exitCode: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n initialCwd: z$1.ZodString;\n lastUserInputAt: z$1.ZodNullable;\n rows: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n disconnected: \"disconnected\";\n exited: \"exited\";\n running: \"running\";\n starting: \"starting\";\n }>;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype TerminalSession = z$1.infer;\ndeclare const terminalListResponseSchema: z$1.ZodObject<{\n sessions: z$1.ZodArray>;\n cols: z$1.ZodNumber;\n createdAt: z$1.ZodNumber;\n environmentId: z$1.ZodNullable;\n exitCode: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n initialCwd: z$1.ZodString;\n lastUserInputAt: z$1.ZodNullable;\n rows: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n disconnected: \"disconnected\";\n exited: \"exited\";\n running: \"running\";\n starting: \"starting\";\n }>;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n}, z$1.core.$strip>;\ntype TerminalListResponse = z$1.infer;\ndeclare const createTerminalRequestSchema: z$1.ZodObject<{\n cols: z$1.ZodNumber;\n rows: z$1.ZodNumber;\n start: z$1.ZodOptional;\n }, z$1.core.$strict>, z$1.ZodObject<{\n command: z$1.ZodString;\n mode: z$1.ZodLiteral<\"command\">;\n }, z$1.core.$strict>], \"mode\">>;\n target: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"environment\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n hostId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host_path\">;\n }, z$1.core.$strict>], \"kind\">;\n title: z$1.ZodOptional;\n}, z$1.core.$strict>;\ntype CreateTerminalRequest = z$1.infer;\ndeclare const updateTerminalRequestSchema: z$1.ZodObject<{\n title: z$1.ZodString;\n}, z$1.core.$strict>;\ntype UpdateTerminalRequest = z$1.infer;\ndeclare const terminalInputRequestSchema: z$1.ZodObject<{\n dataBase64: z$1.ZodString;\n}, z$1.core.$strict>;\ntype TerminalInputRequest = z$1.infer;\ndeclare const terminalResizeRequestSchema: z$1.ZodObject<{\n cols: z$1.ZodNumber;\n rows: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype TerminalResizeRequest = z$1.infer;\ndeclare const terminalOutputQuerySchema: z$1.ZodObject<{\n limitChunks: z$1.ZodOptional>;\n sinceSeq: z$1.ZodOptional>;\n tailBytes: z$1.ZodOptional>;\n}, z$1.core.$strict>;\ntype TerminalOutputQuery = z$1.infer;\ndeclare const terminalOutputResponseSchema: z$1.ZodObject<{\n chunks: z$1.ZodArray>;\n nextSeq: z$1.ZodNumber;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strict>;\ntype TerminalOutputResponse = z$1.infer;\n\ndeclare const timelineRowStatusSchema: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n}>;\ntype TimelineRowStatus = z$1.infer;\ndeclare const timelineRowBaseSchema: z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype TimelineRowBase = z$1.infer;\ndeclare const timelineConversationRowSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n attachments: z$1.ZodNullable;\n localFilePaths: z$1.ZodArray;\n localFiles: z$1.ZodNumber;\n localImagePaths: z$1.ZodArray;\n localImages: z$1.ZodNumber;\n webImages: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n initiator: z$1.ZodEnum<{\n agent: \"agent\";\n system: \"system\";\n user: \"user\";\n }>;\n kind: z$1.ZodLiteral<\"conversation\">;\n mentions: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n role: z$1.ZodLiteral<\"user\">;\n senderThreadId: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n systemMessageKind: z$1.ZodEnum<{\n \"child-completed\": \"child-completed\";\n \"child-failed\": \"child-failed\";\n \"child-interrupted\": \"child-interrupted\";\n \"child-needs-attention\": \"child-needs-attention\";\n \"child-outcome-batch\": \"child-outcome-batch\";\n \"ownership-assigned\": \"ownership-assigned\";\n \"ownership-removed\": \"ownership-removed\";\n unlabeled: \"unlabeled\";\n }>;\n systemMessageSubject: z$1.ZodNullable;\n threadId: z$1.ZodString;\n threadName: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n count: z$1.ZodNumber;\n kind: z$1.ZodLiteral<\"thread-batch\">;\n }, z$1.core.$strip>], \"kind\">>;\n text: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n turnRequest: z$1.ZodObject<{\n isGrouped: z$1.ZodBoolean;\n kind: z$1.ZodEnum<{\n message: \"message\";\n steer: \"steer\";\n }>;\n status: z$1.ZodEnum<{\n accepted: \"accepted\";\n pending: \"pending\";\n rejected: \"rejected\";\n }>;\n }, z$1.core.$strip>;\n}, z$1.core.$strip>, z$1.ZodObject<{\n attachments: z$1.ZodNullable;\n localFilePaths: z$1.ZodArray;\n localFiles: z$1.ZodNumber;\n localImagePaths: z$1.ZodArray;\n localImages: z$1.ZodNumber;\n webImages: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"conversation\">;\n role: z$1.ZodLiteral<\"assistant\">;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n text: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n turnRequest: z$1.ZodNull;\n}, z$1.core.$strip>], \"role\">;\ntype TimelineConversationRow = z$1.infer;\ndeclare const timelineSystemRowSchema: z$1.ZodUnion;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"system\">;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodNullable>;\n systemKind: z$1.ZodEnum<{\n debug: \"debug\";\n error: \"error\";\n reconnect: \"reconnect\";\n }>;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n detail: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"system\">;\n operationKind: z$1.ZodEnum<{\n \"context-clear\": \"context-clear\";\n \"provider-unhandled\": \"provider-unhandled\";\n \"thread-interrupted\": \"thread-interrupted\";\n \"thread-provisioning\": \"thread-provisioning\";\n compaction: \"compaction\";\n deprecation: \"deprecation\";\n generic: \"generic\";\n warning: \"warning\";\n }>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodNullable>;\n systemKind: z$1.ZodLiteral<\"operation\">;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>, z$1.ZodObject<{\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n detail: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"system\">;\n operationKind: z$1.ZodLiteral<\"parent-change\">;\n parentChange: z$1.ZodObject<{\n action: z$1.ZodEnum<{\n assign: \"assign\";\n release: \"release\";\n transfer: \"transfer\";\n }>;\n nextParentThreadId: z$1.ZodNullable;\n nextParentThreadTitle: z$1.ZodNullable;\n previousParentThreadId: z$1.ZodNullable;\n previousParentThreadTitle: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n systemKind: z$1.ZodLiteral<\"operation\">;\n threadId: z$1.ZodString;\n title: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>], \"operationKind\">]>;\ntype TimelineSystemRow = z$1.infer;\ninterface TimelineWorkRowBase extends TimelineRowBase {\n kind: \"work\";\n status: TimelineRowStatus;\n}\ndeclare const timelineCommandWorkRowSchema: z$1.ZodObject<{\n activityIntents: z$1.ZodArray;\n type: z$1.ZodLiteral<\"read\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"list_files\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n approvalStatus: z$1.ZodNullable>;\n callId: z$1.ZodString;\n command: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n cwd: z$1.ZodNullable;\n exitCode: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n output: z$1.ZodString;\n outputPreview: z$1.ZodOptional>;\n source: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"command\">;\n}, z$1.core.$strip>;\ntype TimelineCommandWorkRow = z$1.infer;\ndeclare const timelineToolWorkRowSchema: z$1.ZodObject<{\n activityIntents: z$1.ZodArray;\n type: z$1.ZodLiteral<\"read\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"list_files\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n approvalStatus: z$1.ZodNullable>;\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n output: z$1.ZodString;\n outputPreview: z$1.ZodOptional>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusLabels: z$1.ZodOptional>;\n threadId: z$1.ZodString;\n toolArgs: z$1.ZodNullable>>>;\n toolName: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"tool\">;\n}, z$1.core.$strip>;\ntype TimelineToolWorkRow = z$1.infer;\ndeclare const timelineFileChangeWorkRowSchema: z$1.ZodObject<{\n approvalStatus: z$1.ZodNullable>;\n callId: z$1.ZodString;\n change: z$1.ZodObject<{\n diff: z$1.ZodNullable;\n diffStats: z$1.ZodObject<{\n added: z$1.ZodNumber;\n removed: z$1.ZodNumber;\n }, z$1.core.$strip>;\n kind: z$1.ZodNullable;\n movePath: z$1.ZodNullable;\n path: z$1.ZodString;\n }, z$1.core.$strip>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n stderr: z$1.ZodNullable;\n stdout: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"file-change\">;\n}, z$1.core.$strip>;\ntype TimelineFileChangeWorkRow = z$1.infer;\ndeclare const timelineWebSearchWorkRowSchema: z$1.ZodObject<{\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n queries: z$1.ZodArray;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"web-search\">;\n}, z$1.core.$strip>;\ntype TimelineWebSearchWorkRow = z$1.infer;\ndeclare const timelineWebFetchWorkRowSchema: z$1.ZodObject<{\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n pattern: z$1.ZodNullable;\n prompt: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n url: z$1.ZodString;\n workKind: z$1.ZodLiteral<\"web-fetch\">;\n}, z$1.core.$strip>;\ntype TimelineWebFetchWorkRow = z$1.infer;\ndeclare const timelineImageViewWorkRowSchema: z$1.ZodObject<{\n callId: z$1.ZodString;\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n path: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"image-view\">;\n}, z$1.core.$strip>;\ntype TimelineImageViewWorkRow = z$1.infer;\ndeclare const timelineApprovalWorkRowSchema: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n approvalKind: z$1.ZodLiteral<\"file-edit\">;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n interactionId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n lifecycle: z$1.ZodEnum<{\n denied: \"denied\";\n waiting: \"waiting\";\n }>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n target: z$1.ZodObject<{\n itemId: z$1.ZodString;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"approval\">;\n}, z$1.core.$strip>, z$1.ZodObject<{\n approvalKind: z$1.ZodLiteral<\"permission-grant\">;\n createdAt: z$1.ZodNumber;\n grantScope: z$1.ZodNullable>;\n id: z$1.ZodString;\n interactionId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n lifecycle: z$1.ZodEnum<{\n denied: \"denied\";\n granted: \"granted\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolving: \"resolving\";\n }>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusReason: z$1.ZodNullable;\n target: z$1.ZodObject<{\n itemId: z$1.ZodString;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"approval\">;\n}, z$1.core.$strip>], \"approvalKind\">;\ntype TimelineApprovalWorkRow = z$1.infer;\ndeclare const timelineQuestionWorkRowSchema: z$1.ZodObject<{\n answers: z$1.ZodNullable;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>>;\n createdAt: z$1.ZodNumber;\n id: z$1.ZodString;\n interactionId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n lifecycle: z$1.ZodEnum<{\n answered: \"answered\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolving: \"resolving\";\n }>;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n workKind: z$1.ZodLiteral<\"question\">;\n}, z$1.core.$strip>;\ntype TimelineQuestionWorkRow = z$1.infer;\ninterface TimelineDelegationWorkRow extends TimelineWorkRowBase {\n workKind: \"delegation\";\n callId: string;\n toolName: string;\n subagentType: string | null;\n description: string | null;\n output: string;\n completedAt: number | null;\n childRows: TimelineRow[];\n}\n/**\n * A provider background task — a dynamic workflow (Claude Code Workflow tool)\n * or a backgrounded shell command (Bash run_in_background), discriminated by\n * `taskType`. The row outlives its spawning turn: progress and terminal state\n * arrive via thread-scoped events folded into this single row. `workflow` is\n * the merged phase/agent tree, present only for workflows; null for shell\n * commands and for workflows the provider reported no progress records for\n * (degraded rendering falls back to description + summary). `model` is the\n * spawning delegation's requested model for background agents; null for\n * commands, workflows, legacy events, and providers that do not expose it.\n */\ndeclare const timelineWorkflowWorkRowSchema: z$1.ZodObject<{\n completedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n description: z$1.ZodString;\n error: z$1.ZodNullable;\n id: z$1.ZodString;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n model: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodNullable;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n usage: z$1.ZodNullable>;\n workKind: z$1.ZodLiteral<\"workflow\">;\n workflow: z$1.ZodNullable;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype TimelineWorkflowWorkRow = z$1.infer;\ntype TimelineWorkRow = TimelineCommandWorkRow | TimelineToolWorkRow | TimelineFileChangeWorkRow | TimelineWebSearchWorkRow | TimelineWebFetchWorkRow | TimelineImageViewWorkRow | TimelineApprovalWorkRow | TimelineQuestionWorkRow | TimelineDelegationWorkRow | TimelineWorkflowWorkRow;\ninterface TimelineTurnRow extends TimelineRowBase {\n kind: \"turn\";\n turnId: string;\n status: TimelineRowStatus;\n summaryCount: number;\n completedAt: number | null;\n children: TimelineRow[] | null;\n}\ntype TimelineSourceRow = TimelineConversationRow | TimelineWorkRow | TimelineSystemRow;\ntype TimelineRow = TimelineSourceRow | TimelineTurnRow;\n\ndeclare const createExecutionInputSourcesSchema: z$1.ZodObject<{\n model: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n providerId: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strict>;\ntype CreateExecutionInputSources = z$1.infer;\ndeclare const createThreadRequestSchema: z$1.ZodObject<{\n environment: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n environmentId: z$1.ZodString;\n type: z$1.ZodLiteral<\"reuse\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n hostId: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"host\">;\n workspace: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n branch: z$1.ZodOptional;\n name: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n baseBranch: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new\">;\n }, z$1.core.$strict>], \"kind\">>;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"unmanaged\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n baseBranch: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"named\">;\n name: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"default\">;\n }, z$1.core.$strip>], \"kind\">;\n type: z$1.ZodLiteral<\"managed-worktree\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"personal\">;\n }, z$1.core.$strip>], \"type\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"project-default\">;\n }, z$1.core.$strip>], \"type\">;\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n providerId: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n model: z$1.ZodOptional;\n origin: z$1.ZodEnum<{\n app: \"app\";\n cli: \"cli\";\n plugin: \"plugin\";\n sdk: \"sdk\";\n }>;\n originKind: z$1.ZodDefault>>;\n originPluginId: z$1.ZodOptional;\n parentThreadId: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n projectId: z$1.ZodString;\n providerId: z$1.ZodOptional;\n reasoningLevel: z$1.ZodOptional>;\n sectionId: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n sourceSeqEnd: z$1.ZodOptional;\n sourceThreadId: z$1.ZodOptional;\n startedOnBehalfOf: z$1.ZodDefault;\n senderThreadId: z$1.ZodString;\n }, z$1.core.$strip>>>;\n title: z$1.ZodOptional;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype CreateThreadRequest = z$1.infer;\ndeclare const forkThreadRequestSchema: z$1.ZodObject<{\n agentContextSeed: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">, z$1.ZodObject<{\n visibility: z$1.ZodLiteral<\"agent-only\">;\n }, z$1.core.$strip>>>>;\n input: z$1.ZodOptional, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>>;\n origin: z$1.ZodDefault>;\n originPluginId: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n sourceSeqEnd: z$1.ZodOptional;\n sourceThreadId: z$1.ZodString;\n title: z$1.ZodOptional;\n visibility: z$1.ZodDefault>;\n workspace: z$1.ZodDefault>;\n}, z$1.core.$strip>;\ntype ForkThreadRequest = z$1.infer;\ndeclare const sendMessageRequestSchema: z$1.ZodObject<{\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n mode: z$1.ZodEnum<{\n \"queue-if-active\": \"queue-if-active\";\n \"steer-if-active\": \"steer-if-active\";\n auto: \"auto\";\n start: \"start\";\n steer: \"steer\";\n }>;\n model: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n reasoningLevel: z$1.ZodOptional>;\n senderThreadId: z$1.ZodOptional;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype SendMessageRequest = z$1.infer;\ndeclare const editMessageRequestSchema: z$1.ZodObject<{\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n expectedRequestSequence: z$1.ZodOptional;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n model: z$1.ZodOptional;\n operationId: z$1.ZodString;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n reasoningLevel: z$1.ZodOptional>;\n senderThreadId: z$1.ZodOptional;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strict>;\ntype EditMessageRequest = z$1.infer;\ndeclare const editMessageResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n operationId: z$1.ZodString;\n requestSequence: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype EditMessageResponse = z$1.infer;\ndeclare const createQueuedMessageRequestSchema: z$1.ZodObject<{\n executionInputSources: z$1.ZodOptional>;\n permissionMode: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>;\n serviceTier: z$1.ZodOptional>;\n }, z$1.core.$strict>>;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n model: z$1.ZodOptional;\n permissionMode: z$1.ZodOptional, z$1.ZodLiteral<\"workspace-write\">]>, z$1.ZodTransform<\"accept-edits\" | \"auto\" | \"full\", \"accept-edits\" | \"auto\" | \"full\" | \"workspace-write\">>>;\n reasoningLevel: z$1.ZodOptional>;\n senderThreadId: z$1.ZodOptional;\n serviceTier: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype CreateQueuedMessageRequest = z$1.infer;\ndeclare const updateQueuedMessageRequestSchema: z$1.ZodObject<{\n expectedUpdatedAt: z$1.ZodNumber;\n input: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n}, z$1.core.$strip>;\ntype UpdateQueuedMessageRequest = z$1.infer;\ndeclare const sendQueuedMessageRequestSchema: z$1.ZodObject<{\n mode: z$1.ZodEnum<{\n auto: \"auto\";\n steer: \"steer\";\n }>;\n}, z$1.core.$strip>;\ntype SendQueuedMessageRequest = z$1.infer;\ndeclare const reorderQueuedMessageRequestSchema: z$1.ZodObject<{\n groupBoundaryQueuedMessageId: z$1.ZodOptional;\n nextQueuedMessageId: z$1.ZodNullable;\n previousQueuedMessageId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ReorderQueuedMessageRequest = z$1.infer;\ndeclare const setQueuedMessageGroupBoundaryRequestSchema: z$1.ZodObject<{\n expectedGroupedPrefixQueuedMessageIds: z$1.ZodArray;\n groupBoundaryQueuedMessageId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype SetQueuedMessageGroupBoundaryRequest = z$1.infer;\ndeclare const sendQueuedMessageResponseSchema: z$1.ZodObject<{\n ok: z$1.ZodLiteral;\n queuedMessage: z$1.ZodObject<{\n content: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n createdAt: z$1.ZodNumber;\n groupWithNext: z$1.ZodBoolean;\n id: z$1.ZodString;\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>;\n}, z$1.core.$strip>;\ntype SendQueuedMessageResponse = z$1.infer;\ndeclare const threadListResponseSchema: z$1.ZodArray;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n}, z$1.core.$strip>>;\ntype ThreadListResponse = z$1.infer;\ndeclare const resolveThreadMentionsRequestSchema: z$1.ZodObject<{\n threadIds: z$1.ZodArray;\n}, z$1.core.$strict>;\ntype ResolveThreadMentionsRequest = z$1.infer;\ndeclare const resolveThreadMentionsResponseSchema: z$1.ZodArray>;\ntype ResolveThreadMentionsResponse = z$1.infer;\ndeclare const threadSearchResponseSchema: z$1.ZodObject<{\n active: z$1.ZodObject<{\n results: z$1.ZodArray>;\n sourceKind: z$1.ZodEnum<{\n assistant_message: \"assistant_message\";\n system_message: \"system_message\";\n title: \"title\";\n title_fallback: \"title_fallback\";\n user_message: \"user_message\";\n }>;\n sourceSeq: z$1.ZodNullable;\n text: z$1.ZodString;\n }, z$1.core.$strict>>;\n thread: z$1.ZodObject<{\n activity: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n activeBackgroundCommandCount: z$1.ZodNumber;\n activeGoalCount: z$1.ZodNumber;\n activePlanModeCount: z$1.ZodNumber;\n activeWorkflowCount: z$1.ZodNumber;\n }, z$1.core.$strip>;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>>;\n total: z$1.ZodNumber;\n }, z$1.core.$strict>;\n archived: z$1.ZodObject<{\n results: z$1.ZodArray>;\n sourceKind: z$1.ZodEnum<{\n assistant_message: \"assistant_message\";\n system_message: \"system_message\";\n title: \"title\";\n title_fallback: \"title_fallback\";\n user_message: \"user_message\";\n }>;\n sourceSeq: z$1.ZodNullable;\n text: z$1.ZodString;\n }, z$1.core.$strict>>;\n thread: z$1.ZodObject<{\n activity: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n activeBackgroundCommandCount: z$1.ZodNumber;\n activeGoalCount: z$1.ZodNumber;\n activePlanModeCount: z$1.ZodNumber;\n activeWorkflowCount: z$1.ZodNumber;\n }, z$1.core.$strip>;\n archivedAt: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentBranchName: z$1.ZodNullable;\n environmentHostId: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n environmentName: z$1.ZodNullable;\n environmentWorkspaceDisplayKind: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n \"unmanaged-worktree\": \"unmanaged-worktree\";\n other: \"other\";\n }>;\n hasPendingInteraction: z$1.ZodBoolean;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinSortKey: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n }, z$1.core.$strip>;\n }, z$1.core.$strict>>;\n total: z$1.ZodNumber;\n }, z$1.core.$strict>;\n}, z$1.core.$strict>;\ntype ThreadSearchResponse = z$1.infer;\ndeclare const threadResponseSchema: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n archivedAt: z$1.ZodNullable;\n canSpawnChild: z$1.ZodBoolean;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n}, z$1.core.$strip>;\ntype ThreadResponse = z$1.infer;\ndeclare const threadGetQuerySchema: z$1.ZodObject<{\n include: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ThreadGetQuery = z$1.infer;\ndeclare const threadWithIncludesResponseSchema: z$1.ZodObject<{\n activeBackgroundAgentCount: z$1.ZodNumber;\n archivedAt: z$1.ZodNullable;\n canSpawnChild: z$1.ZodBoolean;\n createdAt: z$1.ZodNumber;\n deletedAt: z$1.ZodNullable;\n environment: z$1.ZodOptional;\n branchName: z$1.ZodNullable;\n createdAt: z$1.ZodNumber;\n defaultBranch: z$1.ZodNullable;\n hostId: z$1.ZodString;\n id: z$1.ZodString;\n isGitRepo: z$1.ZodBoolean;\n isWorktree: z$1.ZodBoolean;\n managed: z$1.ZodBoolean;\n mergeBaseBranch: z$1.ZodNullable;\n name: z$1.ZodNullable;\n path: z$1.ZodNullable;\n projectId: z$1.ZodString;\n status: z$1.ZodEnum<{\n destroyed: \"destroyed\";\n destroying: \"destroying\";\n error: \"error\";\n provisioning: \"provisioning\";\n ready: \"ready\";\n retiring: \"retiring\";\n }>;\n updatedAt: z$1.ZodNumber;\n workspaceProvisionType: z$1.ZodEnum<{\n \"managed-worktree\": \"managed-worktree\";\n personal: \"personal\";\n unmanaged: \"unmanaged\";\n }>;\n }, z$1.core.$strip>>>;\n environmentId: z$1.ZodNullable;\n host: z$1.ZodOptional;\n lastSeenAt: z$1.ZodNullable;\n maxPermissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n name: z$1.ZodString;\n status: z$1.ZodEnum<{\n connected: \"connected\";\n disconnected: \"disconnected\";\n }>;\n type: z$1.ZodEnum<{\n persistent: \"persistent\";\n }>;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n id: z$1.ZodString;\n lastReadAt: z$1.ZodNullable;\n latestAttentionAt: z$1.ZodNumber;\n originKind: z$1.ZodNullable>;\n originPluginId: z$1.ZodNullable;\n parentThreadId: z$1.ZodNullable;\n pinnedAt: z$1.ZodNullable;\n projectId: z$1.ZodString;\n providerId: z$1.ZodString;\n runtime: z$1.ZodObject<{\n displayStatus: z$1.ZodEnum<{\n \"host-reconnecting\": \"host-reconnecting\";\n \"waiting-for-host\": \"waiting-for-host\";\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n provisioning: \"provisioning\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n hostReconnectGraceExpiresAt: z$1.ZodNullable;\n }, z$1.core.$strip>;\n sectionId: z$1.ZodNullable;\n sourceThreadId: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n active: \"active\";\n error: \"error\";\n idle: \"idle\";\n starting: \"starting\";\n stopping: \"stopping\";\n }>;\n title: z$1.ZodNullable;\n titleFallback: z$1.ZodNullable;\n updatedAt: z$1.ZodNumber;\n visibility: z$1.ZodEnum<{\n hidden: \"hidden\";\n visible: \"visible\";\n }>;\n}, z$1.core.$strip>;\ntype ThreadWithIncludesResponse = z$1.infer;\ndeclare const threadPendingInteractionsResponseSchema: z$1.ZodArray>;\n id: z$1.ZodString;\n origin: z$1.ZodOptional;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n }, z$1.core.$strip>>;\n payload: z$1.ZodUnion>;\n kind: z$1.ZodLiteral<\"approval\">;\n reason: z$1.ZodNullable;\n subject: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n actions: z$1.ZodArray;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"listFiles\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n path: z$1.ZodNullable;\n query: z$1.ZodNullable;\n type: z$1.ZodLiteral<\"search\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n command: z$1.ZodString;\n type: z$1.ZodLiteral<\"unknown\">;\n }, z$1.core.$strip>], \"type\">>;\n command: z$1.ZodString;\n cwd: z$1.ZodNullable;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"command\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"file_change\">;\n sessionGrant: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n writeScope: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"permission_grant\">;\n permissions: z$1.ZodObject<{\n fileSystem: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>;\n toolName: z$1.ZodNullable;\n }, z$1.core.$strip>, z$1.ZodObject<{\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plan\">;\n plan: z$1.ZodString;\n planFilePath: z$1.ZodNullable;\n }, z$1.core.$strip>], \"kind\">;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"user_question\">;\n questions: z$1.ZodArray;\n label: z$1.ZodString;\n value: z$1.ZodString;\n }, z$1.core.$strip>>>;\n prompt: z$1.ZodString;\n shortLabel: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>]>;\n providerId: z$1.ZodString;\n providerRequestId: z$1.ZodString;\n providerThreadId: z$1.ZodString;\n resolution: z$1.ZodNullable;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"allow_for_session\">;\n grantedPermissions: z$1.ZodNullable;\n write: z$1.ZodArray;\n }, z$1.core.$strip>>;\n network: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n }, z$1.core.$strict>>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n decision: z$1.ZodLiteral<\"deny\">;\n }, z$1.core.$strip>], \"decision\">, z$1.ZodObject<{\n answers: z$1.ZodRecord;\n selected: z$1.ZodArray;\n }, z$1.core.$strip>>;\n kind: z$1.ZodLiteral<\"user_answer\">;\n }, z$1.core.$strip>]>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>, z$1.ZodObject<{\n createdAt: z$1.ZodNumber;\n expiresAt: z$1.ZodOptional>;\n id: z$1.ZodString;\n origin: z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"plugin\">;\n pluginId: z$1.ZodString;\n rendererId: z$1.ZodString;\n }, z$1.core.$strip>;\n payload: z$1.ZodObject<{\n data: z$1.ZodType>;\n kind: z$1.ZodLiteral<\"plugin\">;\n title: z$1.ZodString;\n }, z$1.core.$strip>;\n resolution: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n resolvedAt: z$1.ZodNullable;\n status: z$1.ZodEnum<{\n interrupted: \"interrupted\";\n pending: \"pending\";\n resolved: \"resolved\";\n resolving: \"resolving\";\n }>;\n statusReason: z$1.ZodNullable;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n}, z$1.core.$strip>]>>;\ntype ThreadPendingInteractionsResponse = z$1.infer;\ndeclare const threadQueuedMessageListResponseSchema: z$1.ZodArray, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"thread\">;\n label: z$1.ZodString;\n projectId: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"project\">;\n label: z$1.ZodString;\n projectId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"section\">;\n label: z$1.ZodString;\n sectionId: z$1.ZodString;\n }, z$1.core.$strip>, z$1.ZodObject<{\n entryKind: z$1.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z$1.ZodLiteral<\"path\">;\n label: z$1.ZodString;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n argumentHint: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"command\">;\n label: z$1.ZodString;\n name: z$1.ZodString;\n origin: z$1.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z$1.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z$1.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n icon: z$1.ZodOptional>;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin\">;\n label: z$1.ZodString;\n pluginId: z$1.ZodString;\n }, z$1.core.$strip>], \"kind\">>;\n start: z$1.ZodNumber;\n }, z$1.core.$strip>>>;\n text: z$1.ZodString;\n type: z$1.ZodLiteral<\"text\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n type: z$1.ZodLiteral<\"image\">;\n url: z$1.ZodString;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n path: z$1.ZodString;\n type: z$1.ZodLiteral<\"localImage\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>, z$1.ZodObject<{\n mimeType: z$1.ZodOptional;\n name: z$1.ZodOptional;\n path: z$1.ZodString;\n sizeBytes: z$1.ZodOptional;\n type: z$1.ZodLiteral<\"localFile\">;\n visibility: z$1.ZodOptional>;\n }, z$1.core.$strip>], \"type\">>;\n createdAt: z$1.ZodNumber;\n groupWithNext: z$1.ZodBoolean;\n id: z$1.ZodString;\n model: z$1.ZodString;\n permissionMode: z$1.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n }>;\n reasoningLevel: z$1.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n }>;\n serviceTier: z$1.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n }>;\n updatedAt: z$1.ZodNumber;\n}, z$1.core.$strip>>;\ntype ThreadQueuedMessageListResponse = z$1.infer;\ndeclare const threadChildSummaryResponseSchema: z$1.ZodObject<{\n nonDeletedChildCount: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadChildSummaryResponse = z$1.infer;\ndeclare const deleteThreadRequestSchema: z$1.ZodObject<{\n childThreadsConfirmed: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype DeleteThreadRequest = z$1.infer;\ndeclare const updateThreadRequestSchema: z$1.ZodObject<{\n model: z$1.ZodOptional>;\n parentThreadId: z$1.ZodOptional>;\n reasoningLevel: z$1.ZodOptional>>;\n sectionId: z$1.ZodOptional>;\n title: z$1.ZodOptional>;\n visibility: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype UpdateThreadRequest = z$1.infer;\ndeclare const reorderPinnedThreadRequestSchema: z$1.ZodObject<{\n nextThreadId: z$1.ZodNullable;\n previousThreadId: z$1.ZodNullable;\n}, z$1.core.$strip>;\ntype ReorderPinnedThreadRequest = z$1.infer;\n/**\n * Requested placement for a thread opened in the app's split layout. Edge\n * placements add panes through the eighth pane; at the cap they replace the\n * focused pane. `replace` always replaces the focused pane.\n */\ndeclare const threadOpenSplitSchema: z$1.ZodEnum<{\n down: \"down\";\n left: \"left\";\n replace: \"replace\";\n right: \"right\";\n top: \"top\";\n}>;\ntype ThreadOpenSplit = z$1.infer;\n/** Optional secondary-panel file to open with a thread. */\ndeclare const threadOpenFileSchema: z$1.ZodObject<{\n lineNumber: z$1.ZodNullable;\n path: z$1.ZodString;\n source: z$1.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n}, z$1.core.$strict>;\ntype ThreadOpenFile = z$1.infer;\n/** Response for POST /threads/:id/open: how many connected clients received it. */\ndeclare const threadOpenResponseSchema: z$1.ZodObject<{\n delivered: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadOpenResponse = z$1.infer;\n/** Presentation action for one thread pane in each connected app window. */\ndeclare const threadPaneActionSchema: z$1.ZodEnum<{\n \"clear-spotlight\": \"clear-spotlight\";\n maximize: \"maximize\";\n restore: \"restore\";\n spotlight: \"spotlight\";\n toggle: \"toggle\";\n}>;\ntype ThreadPaneAction = z$1.infer;\n/** Number of connected app clients that received the pane action. */\ndeclare const threadPaneActionResponseSchema: z$1.ZodObject<{\n delivered: z$1.ZodNumber;\n}, z$1.core.$strip>;\ntype ThreadPaneActionResponse = z$1.infer;\ndeclare const threadArchiveAllResponseSchema: z$1.ZodObject<{\n archivedThreadIds: z$1.ZodArray;\n ok: z$1.ZodLiteral;\n}, z$1.core.$strip>;\ntype ThreadArchiveAllResponse = z$1.infer;\ndeclare const threadListQuerySchema: z$1.ZodObject<{\n archived: z$1.ZodOptional>;\n hasParent: z$1.ZodOptional>;\n includeHidden: z$1.ZodOptional>;\n limit: z$1.ZodOptional;\n offset: z$1.ZodOptional;\n originKind: z$1.ZodOptional>;\n originPluginId: z$1.ZodOptional;\n parentThreadId: z$1.ZodOptional;\n projectId: z$1.ZodOptional;\n sectionId: z$1.ZodOptional;\n sourceThreadId: z$1.ZodOptional;\n unsectioned: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ThreadListQuery = z$1.infer;\ndeclare const threadSearchQuerySchema: z$1.ZodObject<{\n limitPerGroup: z$1.ZodOptional;\n query: z$1.ZodString;\n}, z$1.core.$strip>;\ntype ThreadSearchQuery = z$1.infer;\ndeclare const threadTimelineQuerySchema: z$1.ZodObject<{\n afterSequence: z$1.ZodOptional;\n beforeAnchorId: z$1.ZodOptional;\n beforeAnchorSeq: z$1.ZodOptional;\n includeNestedRows: z$1.ZodOptional>;\n segmentLimit: z$1.ZodOptional;\n summaryOnly: z$1.ZodOptional>;\n}, z$1.core.$strip>;\ntype ThreadTimelineQuery = z$1.infer;\ndeclare const timelineTurnSummaryDetailsQuerySchema: z$1.ZodObject<{\n sourceSeqEnd: z$1.ZodString;\n sourceSeqStart: z$1.ZodString;\n turnId: z$1.ZodString;\n}, z$1.core.$strip>;\ntype TimelineTurnSummaryDetailsQuery = z$1.infer;\ndeclare const threadStorageFilesQuerySchema: z$1.ZodObject<{\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ThreadStorageFilesQuery = z$1.infer;\ndeclare const threadStoragePathsQuerySchema: z$1.ZodObject<{\n includeDirectories: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n includeFiles: z$1.ZodEnum<{\n false: \"false\";\n true: \"true\";\n }>;\n limit: z$1.ZodOptional;\n query: z$1.ZodOptional;\n}, z$1.core.$strip>;\ntype ThreadStoragePathsQuery = z$1.infer;\ndeclare const timelineTurnSummaryDetailsResponseSchema: z$1.ZodObject<{\n rows: z$1.ZodArray>>;\n}, z$1.core.$strip>;\ntype TimelineTurnSummaryDetailsResponse = z$1.infer;\ndeclare const threadTimelineResponseSchema: z$1.ZodObject<{\n activeBackgroundCommands: z$1.ZodArray;\n createdAt: z$1.ZodNumber;\n description: z$1.ZodString;\n error: z$1.ZodNullable;\n id: z$1.ZodString;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n model: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodNullable;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n usage: z$1.ZodNullable>;\n workKind: z$1.ZodLiteral<\"workflow\">;\n workflow: z$1.ZodNullable;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n activePromptMode: z$1.ZodNullable;\n prompt: z$1.ZodString;\n providerId: z$1.ZodString;\n }, z$1.core.$strict>>;\n activeThinking: z$1.ZodNullable>;\n activeWorkflows: z$1.ZodArray;\n createdAt: z$1.ZodNumber;\n description: z$1.ZodString;\n error: z$1.ZodNullable;\n id: z$1.ZodString;\n itemId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"work\">;\n model: z$1.ZodNullable;\n sourceSeqEnd: z$1.ZodNumber;\n sourceSeqStart: z$1.ZodNumber;\n startedAt: z$1.ZodNumber;\n status: z$1.ZodEnum<{\n completed: \"completed\";\n error: \"error\";\n interrupted: \"interrupted\";\n pending: \"pending\";\n }>;\n summary: z$1.ZodNullable;\n taskStatus: z$1.ZodEnum<{\n completed: \"completed\";\n failed: \"failed\";\n killed: \"killed\";\n paused: \"paused\";\n pending: \"pending\";\n running: \"running\";\n stopped: \"stopped\";\n }>;\n taskType: z$1.ZodString;\n threadId: z$1.ZodString;\n turnId: z$1.ZodNullable;\n usage: z$1.ZodNullable>;\n workKind: z$1.ZodLiteral<\"workflow\">;\n workflow: z$1.ZodNullable;\n attempt: z$1.ZodNumber;\n cached: z$1.ZodBoolean;\n durationMs: z$1.ZodOptional;\n error: z$1.ZodOptional;\n index: z$1.ZodNumber;\n isolation: z$1.ZodOptional;\n label: z$1.ZodString;\n lastProgressAt: z$1.ZodNumber;\n lastToolName: z$1.ZodOptional;\n lastToolSummary: z$1.ZodOptional;\n model: z$1.ZodString;\n phaseIndex: z$1.ZodOptional;\n phaseTitle: z$1.ZodOptional;\n promptPreview: z$1.ZodOptional;\n queuedAt: z$1.ZodOptional;\n resultPreview: z$1.ZodOptional;\n startedAt: z$1.ZodOptional;\n state: z$1.ZodEnum<{\n done: \"done\";\n failed: \"failed\";\n queued: \"queued\";\n running: \"running\";\n skipped: \"skipped\";\n }>;\n tokens: z$1.ZodOptional;\n toolCalls: z$1.ZodOptional;\n }, z$1.core.$strip>>;\n phases: z$1.ZodArray;\n title: z$1.ZodString;\n }, z$1.core.$strip>>;\n }, z$1.core.$strip>>;\n workflowName: z$1.ZodNullable;\n }, z$1.core.$strip>>;\n contextWindowUsage: z$1.ZodOptional>;\n delta: z$1.ZodOptional>;\n upsertRows: z$1.ZodArray>>;\n }, z$1.core.$strip>>;\n goal: z$1.ZodNullable;\n timeUsedSeconds: z$1.ZodNumber;\n tokenBudget: z$1.ZodNullable;\n tokensUsed: z$1.ZodNumber;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n maxSeq: z$1.ZodNumber;\n modelFallback: z$1.ZodNullable;\n sourceSeq: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n pendingTodos: z$1.ZodNullable;\n text: z$1.ZodString;\n }, z$1.core.$strip>>;\n sourceSeq: z$1.ZodNumber;\n updatedAt: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n rows: z$1.ZodArray>>;\n timelinePage: z$1.ZodObject<{\n hasOlderRows: z$1.ZodBoolean;\n kind: z$1.ZodEnum<{\n latest: \"latest\";\n older: \"older\";\n }>;\n olderCursor: z$1.ZodNullable>;\n returnedSegmentCount: z$1.ZodNumber;\n segmentLimit: z$1.ZodNumber;\n }, z$1.core.$strict>;\n}, z$1.core.$strip>;\ntype ThreadTimelineResponse = z$1.infer;\ndeclare const threadConversationOutlineResponseSchema: z$1.ZodObject<{\n items: z$1.ZodArray>;\n id: z$1.ZodString;\n preview: z$1.ZodString;\n role: z$1.ZodEnum<{\n assistant: \"assistant\";\n user: \"user\";\n }>;\n }, z$1.core.$strict>>;\n maxSeq: z$1.ZodNumber;\n}, z$1.core.$strict>;\ntype ThreadConversationOutlineResponse = z$1.infer;\ndeclare const threadStorageFileListResponseSchema: z$1.ZodObject<{\n files: z$1.ZodArray>;\n storageRootPath: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype ThreadStorageFileListResponse = z$1.infer;\ndeclare const threadStoragePathListResponseSchema: z$1.ZodObject<{\n paths: z$1.ZodArray;\n name: z$1.ZodString;\n path: z$1.ZodString;\n positions: z$1.ZodArray;\n score: z$1.ZodNumber;\n }, z$1.core.$strip>>;\n storageRootPath: z$1.ZodString;\n truncated: z$1.ZodBoolean;\n}, z$1.core.$strip>;\ntype ThreadStoragePathListResponse = z$1.infer;\n\ndeclare const threadTabsResponseSchema: z$1.ZodObject<{\n revision: z$1.ZodNumber;\n tabs: z$1.ZodArray;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"git-diff\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n actionId: z$1.ZodString;\n fileOpenerOwner: z$1.ZodOptional;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n projectId: z$1.ZodNullable;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin-panel\">;\n paramsJson: z$1.ZodNullable;\n pluginId: z$1.ZodString;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n projectId: z$1.ZodNullable;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n isPinned: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"browser\">;\n title: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new-tab\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"side-chat\">;\n sourceMessageText: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNullable;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"terminal\">;\n target: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"environment\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n hostId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host_path\">;\n }, z$1.core.$strict>], \"kind\">>;\n terminalId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n}, z$1.core.$strict>;\ntype ThreadTabsResponse = z$1.infer;\ndeclare const updateThreadTabsRequestSchema: z$1.ZodObject<{\n expectedRevision: z$1.ZodNumber;\n tabs: z$1.ZodArray;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"git-diff\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n actionId: z$1.ZodString;\n fileOpenerOwner: z$1.ZodOptional;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n projectId: z$1.ZodNullable;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n tab: z$1.ZodObject<{\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n }, z$1.core.$strict>;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"plugin-panel\">;\n paramsJson: z$1.ZodNullable;\n pluginId: z$1.ZodString;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"workspace-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n projectId: z$1.ZodNullable;\n source: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"working-tree\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"head\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n kind: z$1.ZodLiteral<\"merge-base\">;\n ref: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">;\n statusLabel: z$1.ZodNullable>;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n isPinned: z$1.ZodBoolean;\n kind: z$1.ZodLiteral<\"thread-storage-file-preview\">;\n lineRange: z$1.ZodNullable>;\n path: z$1.ZodString;\n threadId: z$1.ZodNullable;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodNullable;\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"browser\">;\n title: z$1.ZodNullable;\n url: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"new-tab\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"side-chat\">;\n sourceMessageText: z$1.ZodString;\n sourceSeqEnd: z$1.ZodNullable;\n threadId: z$1.ZodNullable;\n title: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n id: z$1.ZodString;\n kind: z$1.ZodLiteral<\"terminal\">;\n target: z$1.ZodOptional;\n threadId: z$1.ZodString;\n }, z$1.core.$strict>, z$1.ZodObject<{\n environmentId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"environment\">;\n }, z$1.core.$strict>, z$1.ZodObject<{\n cwd: z$1.ZodNullable;\n hostId: z$1.ZodString;\n kind: z$1.ZodLiteral<\"host_path\">;\n }, z$1.core.$strict>], \"kind\">>;\n terminalId: z$1.ZodString;\n }, z$1.core.$strict>], \"kind\">>;\n}, z$1.core.$strict>;\ntype UpdateThreadTabsRequest = z$1.infer;\n\n/**\n * A value that survives a JSON round trip without coercion or data loss.\n *\n * Host boundaries still validate values at runtime because TypeScript cannot\n * exclude non-finite numbers and plugin bundles can bypass static types.\n */\ntype JsonValue = string | number | boolean | null | JsonValue[] | {\n [key: string]: JsonValue;\n};\n\n/** A JSON-safe path segment reported by a Standard Schema validation issue. */\ntype PluginRpcIssuePathSegment = string | number;\n/** Validator-neutral validation detail carried by an RPC error envelope. */\ninterface PluginRpcValidationIssue {\n message: string;\n path?: PluginRpcIssuePathSegment[];\n}\n/** Stable wire error categories for plugin RPC. */\ntype PluginRpcErrorCode = \"handler_error\" | \"invalid_input\" | \"invalid_json\" | \"invalid_output\" | \"non_json_result\" | \"unknown_method\";\n/** Structured RPC failure returned as `{ ok: false, error }`. */\ninterface PluginRpcError {\n code: PluginRpcErrorCode;\n message: string;\n issues?: PluginRpcValidationIssue[];\n}\n/**\n * The validator-neutral subset of Standard Schema v1 used by plugin RPC.\n * Zod 4 schemas implement this interface directly; other validators can do\n * the same without becoming part of BB's public protocol.\n */\ninterface StandardSchemaV1 {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardSchemaV1Result | Promise>;\n readonly types?: {\n readonly input: Input;\n readonly output: Output;\n };\n };\n}\ntype StandardSchemaV1Result = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: readonly StandardSchemaV1Issue[];\n};\ninterface StandardSchemaV1Issue {\n readonly message: string;\n readonly path?: PropertyKey | readonly (PropertyKey | {\n readonly key: PropertyKey;\n })[];\n}\ntype StandardSchemaV1InferInput = NonNullable[\"input\"];\ntype StandardSchemaV1InferOutput = NonNullable[\"output\"];\ninterface PluginRpcMethodContract {\n readonly input: InputSchema;\n readonly output: OutputSchema;\n}\ntype PluginRpcContract = Readonly>;\n/** Define a shared RPC contract while preserving exact method/schema types. */\ndeclare function defineRpcContract(contract: Contract): Contract;\ntype PluginRpcHandlers = {\n [Method in keyof Contract]: (input: StandardSchemaV1InferOutput) => StandardSchemaV1InferInput | Promise>;\n};\ntype PluginRpcCallInput = StandardSchemaV1InferInput;\ntype PluginRpcCallArgs = null extends PluginRpcCallInput ? [input?: PluginRpcCallInput] : [input: PluginRpcCallInput];\ntype PluginRpcResult = StandardSchemaV1InferOutput;\n\n/**\n * The `@get-bb/plugin-sdk/app` contract (plugin design §5.2) — pure types with no\n * side effects. The BB app imports these to keep its real implementation in\n * sync (`satisfies PluginSdkApp`). Plugin authors import the same shapes through\n * `@get-bb/plugin-sdk/app`.\n *\n * Per-slot props are versioned contracts: additive-only within an SDK major.\n */\n/** Props passed to a `homepageSection` component. */\ninterface PluginHomepageSectionProps {\n /** Project in view on the compose surface; null when none is selected. */\n projectId: string | null;\n}\n/**\n * Props passed to a `settingsSection` component.\n *\n * Deliberately empty in V1; versioned additive like the other slot props.\n */\ninterface PluginSettingsSectionProps {\n}\n/** Props passed to a `navPanel` component (it owns its whole route). */\ninterface PluginNavPanelProps {\n /**\n * The route remainder after the panel root, \"\" at the root. The panel's\n * route is `/plugins///*`, so a deep link like\n * `/plugins/notes/notes/work/ideas.md` renders the panel with\n * `subPath: \"work/ideas.md\"`. Navigate within the panel via\n * `useBbNavigate().toPluginPanel(path, { subPath })` — browser\n * back/forward then walks panel-internal history.\n */\n subPath: string;\n}\n/**\n * Props passed to a panel tab opened by a `threadPanelAction`.\n *\n * This slot is rendered only for an existing thread. Use\n * `experimental_newThreadPanelAction` for the root New thread screen.\n */\ninterface PluginThreadPanelProps {\n threadId: string;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\n/** Props passed to a panel tab opened by `experimental_newThreadPanelAction`. */\ninterface PluginNewThreadPanelProps {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\ninterface PluginPendingInteractionView {\n id: string;\n threadId: string;\n title: string;\n payload: JsonValue;\n createdAt: number;\n expiresAt: number | null;\n}\ninterface PluginPendingInteractionProps {\n interaction: PluginPendingInteractionView;\n submit(value: JsonValue): Promise;\n cancel(): Promise;\n}\n/**\n * Props for a `sidebarFooterAction` — host-rendered (no plugin component).\n * Deliberately empty; the registration's `run` carries the behavior.\n */\ninterface PluginSidebarFooterActionProps {\n}\n/**\n * Props passed to an `experimental_threadList` component — the sidebar's\n * scrolling thread area, replaced wholesale by one plugin.\n */\ninterface PluginThreadListProps {\n /** The thread the route currently shows; null on non-thread routes. */\n activeThreadId: string | null;\n /** The project the route currently shows; null when none is selected. */\n activeProjectId: string | null;\n /** True on phone-width viewports and coarse pointers. */\n isCompactViewport: boolean;\n /**\n * Call after the user opens a thread. It closes the mobile sidebar drawer,\n * and it clears the host search field on every viewport. Always call it, or\n * the sidebar stays in search mode after the thread opens.\n */\n onNavigate: () => void;\n /**\n * The host search field's current text, or \"\" when the field is closed.\n * The host owns that field, so a plugin list filters by this rather than\n * shipping a second search box.\n */\n searchQuery: string;\n /**\n * BB's thread list, bound to this sidebar instance. Render it to delegate\n * conditionally without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Props passed to an `experimental_threadHeaderAction` component, rendered in\n * the thread header's action row.\n */\ninterface PluginThreadHeaderActionProps {\n /**\n * The thread this header belongs to. Never null: the slot is not rendered\n * on the compose screen or other non-thread routes. A split layout renders\n * one header per pane, so the component mounts once per visible thread,\n * each with its own id — keep per-thread state in the component, never in a\n * module-level singleton.\n */\n threadId: string;\n projectId: string;\n /**\n * True on phone-width viewports and coarse pointers. Collapse to an\n * icon-sized control when it is true — the row is short.\n */\n isCompactViewport: boolean;\n}\n/**\n * Where a file being opened by a `fileOpener` lives. `path` semantics follow\n * the source: workspace paths are relative to the environment's worktree,\n * thread-storage paths are relative to the thread's storage root, host paths\n * are absolute on the thread's host.\n */\ninterface PluginFileOpenerSource {\n kind: \"host\" | \"thread-storage\" | \"workspace\";\n threadId: string | null;\n environmentId: string | null;\n projectId: string | null;\n}\n/** Props passed to a `fileOpener` component (rendered as a panel file tab). */\ninterface PluginFileOpenerProps {\n path: string;\n source: PluginFileOpenerSource;\n /**\n * BB's file preview, bound to this file. Render it to delegate conditionally\n * without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Message context passed to a `messageDirective` component — the assistant\n * (or nested agent) message that contained the directive.\n */\ninterface PluginMessageDirectiveMessage {\n id: string;\n threadId: string;\n turnId: string | null;\n projectId: string | null;\n}\n/**\n * Open a worktree-relative file in the host's workspace file viewer. Returns\n * true when the host accepted the path; false when the path is invalid or the\n * viewer declined it.\n */\ntype PluginMessageDirectiveOpenWorkspaceFile = (path: string) => boolean;\n/**\n * Props passed to a `messageDirective` component. Attributes are untrusted\n * strings parsed from the directive; the plugin validates its own fields.\n */\ninterface PluginMessageDirectiveProps {\n /** Parsed, untrusted directive attributes (e.g. `{ file: \"demo.html\" }`). */\n attributes: Readonly>;\n /** Original directive source text (useful for diagnostics / crash fallback). */\n source: string;\n message: PluginMessageDirectiveMessage;\n /**\n * Opens a worktree-relative file in the host's workspace file viewer. Null\n * when the message surface has no workspace viewer available.\n */\n openWorkspaceFile: PluginMessageDirectiveOpenWorkspaceFile | null;\n}\ninterface PluginHomepageSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n component: ComponentType;\n}\ninterface PluginSettingsSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Optional host-rendered section heading. */\n title?: string;\n /**\n * Optional one-line host-rendered subheading under `title`, in the built-in\n * SettingsSection idiom (ignored when `title` is absent).\n */\n description?: string;\n component: ComponentType;\n}\ninterface PluginNavPanelRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /** URL segment under `/plugins//`; letters, digits, `-`, `_`. */\n path: string;\n component: ComponentType;\n /**\n * Ordered, non-closable tabs shown in this page's host-owned right panel.\n * BB owns selection and persistence and always includes its native Browser\n * and Terminal tools beside them. Components mount only while their tab is\n * active and the panel is open, and receive the same `subPath` as the page\n * component.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_fixedTabs?: readonly {\n /** Unique within this nav panel; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n component: ComponentType;\n /** `flush` lets the component own padding and scrolling. */\n layout?: \"flush\" | \"padded\";\n }[];\n /**\n * Optional presentational component rendered at the trailing edge of this\n * panel's sidebar row. It receives no props so it can own a narrow live\n * value through the ordinary SDK hooks without coupling that state to the\n * host sidebar. The host does not mount it on compact viewports and clips it\n * to a small, single-line box on wider viewports. It shares the trailing\n * action column, fading out for the host's options button on hover or focus;\n * do not render controls or rely on unbounded content here.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_sidebarAccessory?: ComponentType;\n /**\n * Optional component rendered on the right side of the shared title bar\n * (e.g. a sync button or a count). Contained separately from the body: a\n * throwing headerContent is hidden without breaking the title bar.\n */\n headerContent?: ComponentType;\n}\n/**\n * What a plugin action passes when it asks the host to open one of its panel\n * tabs. Shared by every `openPanel` entry point so a plugin registering more\n * than one kind of action can write a single open routine;\n * `PluginTargetedPanelActionOpenOptions` adds the `actionId` a caller\n * outside a panel action must pass to name the panel it wants.\n */\ninterface PluginPanelActionOpenOptions {\n /** Tab label. Default: the action's `title`. */\n title?: string;\n /**\n * Persisted with the tab and handed to the component as its `params` prop.\n * Must be a JSON value; anything else is a declined open.\n */\n params?: JsonValue;\n}\n/**\n * Context handed to a `threadPanelAction`'s `run`.\n *\n * The action is thread-only and is never offered on the root New thread\n * screen, so `threadId` is always present.\n */\ninterface PluginThreadPanelActionContext {\n /** The thread whose panel launcher invoked the action. */\n threadId: string;\n /**\n * Open a tab in the thread's side panel rendering this action's\n * `component`. `title` labels the tab (default: the action's `title`);\n * `params` must be JSON-serializable — it is persisted with the tab and\n * reaches the component as its `params` prop. Opening with params\n * identical to an already-open tab of this action focuses that tab\n * (updating its title) instead of duplicating it. May be called more than\n * once (different params ⇒ multiple tabs) or not at all.\n *\n * Returns true when the host accepted the open; false when it declined —\n * from this launcher, only a `params` that is not a JSON value. The true /\n * false contract is shared with `messageAction`'s `openPanel` and\n * `useBbNavigate().openThreadPanel` (which decline for more reasons) so one\n * open routine can serve every action kind. A decline is never thrown: the\n * host logs it and reports it here.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\ninterface PluginThreadPanelActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /**\n * Icon hint (BB icon name) used when the plugin ships no logo; the\n * launcher row and opened tabs prefer the plugin's logo.\n */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /**\n * How the host frames the tab content. \"padded\" (default) wraps the\n * component in the panel's scroll container with standard padding —\n * right for document-like content. \"flush\" gives the component the full\n * tab area (no padding, definite height, no host scrolling) — right for\n * app-like content that manages its own layout, such as\n * `ThreadChat`.\n */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action: call your RPC methods, show a\n * toast, and/or open panel tabs via `context.openPanel`. Omitted =\n * immediately open a panel tab with defaults. Errors (sync or async) are\n * contained and logged; they never break the launcher.\n */\n run?(context: PluginThreadPanelActionContext): void | Promise;\n}\n/** Context handed to an `experimental_newThreadPanelAction`'s `run`. */\ninterface PluginNewThreadPanelActionContext {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * Open a tab in the root New thread screen's side panel rendering this\n * action's `component`. The title, params, deduplication, return value, and\n * error semantics match `threadPanelAction`.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\n/** Registration for the root New thread screen's panel Actions list. */\ninterface PluginNewThreadPanelActionRegistration {\n /** Unique within this slot for the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /** Icon hint (BB icon name) used when the plugin ships no logo. */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /** Host framing; matches `threadPanelAction`. */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action. Omitted = immediately open a\n * panel tab with defaults. Errors are contained and logged.\n */\n run?(context: PluginNewThreadPanelActionContext): void | Promise;\n}\ninterface PluginPendingInteractionRegistration {\n /** Matches `rendererId` passed to `bb.ui.requestInput`. */\n id: string;\n component: ComponentType;\n}\n/** Context handed to a `sidebarFooterAction`'s `run`. */\ninterface PluginSidebarFooterActionContext {\n /**\n * Navigate to this plugin's detail page in Tools, where declarative settings\n * and `settingsSection` slots render.\n */\n openSettings(): void;\n}\n/**\n * An icon button in the app sidebar footer (next to Settings / bug report).\n * Host-rendered for consistent chrome — plugins supply icon, label, and\n * `run` behavior only.\n */\ninterface PluginSidebarFooterActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip and accessible label for the icon button. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /**\n * Runs when the user activates the action (e.g. call `openSettings()`,\n * open a panel via other surfaces, toast). Errors (sync or async) are\n * contained and logged; they never break the sidebar.\n */\n run(context: PluginSidebarFooterActionContext): void | Promise;\n}\n/**\n * The one status bb would paint for a thread, already resolved through the\n * host's precedence (attention before work; plan and goal before the generic\n * spinner). Draw your own glyph for it — the SDK ships no status component.\n *\n * Treat an unrecognized value as \"none\": bb adds kinds over time, and an\n * older plugin must degrade to drawing nothing rather than throwing.\n *\n * \"draft\" and \"working-draft\" are never reported here: an unsubmitted composer\n * draft is per-client state the host reads per row, which an array-wide view\n * cannot. A thread holding a draft reports whatever it would report without\n * one.\n */\ntype PluginSidebarThreadIndicator = \"background-agent\" | \"background-command\" | \"draft\" | \"goal\" | \"none\" | \"plan-mode\" | \"runtime\" | \"unread-error\" | \"unread-success\" | \"waiting-for-input\" | \"workflow\" | \"working-draft\";\n/**\n * How a thread's environment presents its workspace: a worktree bb manages,\n * a worktree the user manages, or anything else (a plain checkout).\n */\ntype PluginSidebarWorkspaceKind = \"managed-worktree\" | \"other\" | \"unmanaged-worktree\";\n/** Live work counts on a thread. All zero means nothing is running. */\ninterface PluginSidebarThreadActivity {\n workflows: number;\n backgroundAgents: number;\n backgroundCommands: number;\n planMode: number;\n goals: number;\n}\n/**\n * One thread in the sidebar's live view.\n *\n * A deliberate copy of the fields a sidebar needs — not a re-export of the\n * host's internal thread row type, which changes whenever the app needs a\n * field. Timestamps are epoch milliseconds.\n */\ninterface PluginSidebarThread {\n id: string;\n projectId: string;\n /** Null while a thread is still unnamed; pair with `titleFallback`. */\n title: string | null;\n titleFallback: string | null;\n /** The thread this one was forked from or spawned under; null at the root. */\n parentThreadId: string | null;\n sectionId: string | null;\n /** How this thread came to exist under its parent; null for root threads. */\n originKind: \"fork\" | null;\n /** The plugin that spawned it, or null for non-plugin origins. */\n originPluginId: string | null;\n /** The agent provider this thread runs on, e.g. \"codex\", \"claude-code\". */\n providerId: string;\n /** The agent is blocked on the user: an approval or a question. */\n hasPendingInteraction: boolean;\n activity: PluginSidebarThreadActivity;\n indicator: PluginSidebarThreadIndicator;\n /**\n * The host's accessible label for `indicator`, e.g. \"Thread needs user\n * input\"; null when the indicator is \"none\". Use it for `aria-label` so\n * screen-reader text stays consistent across sidebars.\n */\n indicatorLabel: string | null;\n isUnread: boolean;\n isPinned: boolean;\n isArchived: boolean;\n environment: {\n id: string | null;\n name: string | null;\n branchName: string | null;\n workspaceDisplayKind: PluginSidebarWorkspaceKind;\n } | null;\n /**\n * The machine this thread's work runs on, with the name resolved for you.\n * Null when the thread has no environment yet, or when its host is not in\n * the known-hosts list. Useful where a thread has no branch to show — a\n * personal-project thread has a machine but no worktree.\n */\n host: {\n id: string;\n name: string;\n } | null;\n createdAt: number;\n updatedAt: number;\n lastReadAt: number | null;\n latestAttentionAt: number;\n}\n/**\n * The pull request for a thread's branch, narrowed to what a sidebar row\n * needs. `attention` is bb's rolled-up \"does this need you\" signal, so a row\n * can colour a badge without reading checks, review, and mergeability itself.\n */\ninterface PluginSidebarPullRequest {\n number: number;\n title: string;\n url: string;\n state: \"closed\" | \"draft\" | \"merged\" | \"open\";\n attention: \"blocked\" | \"changes_requested\" | \"checks_failed\" | \"checks_pending\" | \"closed\" | \"conflicts\" | \"draft\" | \"merged\" | \"none\" | \"ready_to_merge\" | \"review_requested\";\n}\ninterface PluginSidebarThreadPullRequestState {\n /** True while the first lookup for this thread's environment is in flight. */\n isLoading: boolean;\n /**\n * The pull request, or null when the branch has none, the thread has no\n * environment, or the lookup could not run (a git-host hiccup). A row should\n * treat null as \"nothing to show\", never as an error.\n */\n pullRequest: PluginSidebarPullRequest | null;\n}\n/** One project in the sidebar's live view. */\ninterface PluginSidebarProject {\n id: string;\n name: string;\n /** True for the implicit personal project. */\n isPersonal: boolean;\n}\ninterface PluginSidebarThreadsState {\n status: \"error\" | \"loading\" | \"ready\";\n threads: readonly PluginSidebarThread[];\n projects: readonly PluginSidebarProject[];\n}\n/**\n * Act on threads from a plugin surface. Every method routes to the host's own\n * flow, so optimistic updates, toasts, dialogs, pane closing, and route repair\n * behave exactly as they do in the built-in sidebar. Unknown thread ids are\n * ignored by `open` and rejected by the rest.\n */\ninterface PluginSidebarThreadActions {\n /**\n * Navigate to a thread. `split: true` applies bb's split placement rules —\n * a right split by default, focus when the thread is already open, replace\n * at the pane cap — and falls back to plain navigation where splits are off.\n */\n open(threadId: string, options?: {\n split?: boolean;\n }): void;\n /**\n * Go to the new-thread screen. Passing `projectId` also makes that project\n * the composer's selection, so the thread is created where you asked.\n */\n openNewThread(options?: {\n projectId?: string;\n focusPrompt?: boolean;\n }): void;\n setPinned(threadId: string, pinned: boolean): Promise;\n setRead(threadId: string, read: boolean): Promise;\n /** Silent rename — no dialog. For inline editing in your own row. */\n rename(threadId: string, title: string): Promise;\n /** Archives the thread AND its children, closing any panes showing them. */\n archive(threadId: string): void;\n /**\n * Opens bb's delete confirmation, which counts child threads first. Deletion\n * is destructive and recursive, so the host owns the confirmation: there is\n * deliberately no silent `delete`.\n */\n requestDelete(threadId: string): void;\n}\n/**\n * Render a plugin component in the thread header's action row.\n *\n * The frontend sibling of the backend `bb.ui.registerThreadAction`, which\n * renders a host-owned button and runs server-side. Use that one for \"do a\n * thing\"; use this one when the control must draw live state.\n *\n * The host places it at the left end of the action row, before the workspace\n * button, git actions, the panel toggle, maximize, and close. That row is a\n * 48px chrome row with 28px controls: render one inline control that fits, and\n * put anything taller in a portalled popover.\n */\ninterface PluginThreadHeaderActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Names the region the host wraps around your component (a labelled group).\n * It does NOT label your control: an icon-only button still needs its own\n * accessible name.\n */\n title: string;\n component: ComponentType;\n}\n/** One pane's place in the split layout, as fractions of the split area. */\ninterface PluginSidebarSplitPane {\n paneId: string;\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n /** This pane holds the thread the row represents. */\n isMe: boolean;\n isFocused: boolean;\n}\n/**\n * Drag-to-split support for one row, plus where that thread currently sits in\n * the split layout.\n */\ninterface PluginSidebarThreadSplit {\n /**\n * Spread onto the row's interactive element. Carries the pointer handler\n * that starts a split drag; empty when splits are unavailable, so spreading\n * it is always safe.\n *\n * The host owns every rule: the gesture engages only once the pointer leaves\n * the sidebar toward the main area (so a list with its own drag-to-reorder\n * keeps working), an edge drop splits, a center drop replaces, an\n * already-open thread focuses its pane, and the pane cap coerces a split\n * into a replace.\n */\n splitProps: {\n onPointerDown?: (event: react.PointerEvent) => void;\n };\n /**\n * False on compact viewports, when the user disabled splits, and for an\n * unknown thread id. Gate any \"open in split\" affordance you draw on it.\n */\n isAvailable: boolean;\n /**\n * Where this thread sits in the split layout, or null when it is not open in\n * one (including single-pane layouts). Draw a mini-map, a tint, or nothing.\n */\n layout: {\n panes: readonly PluginSidebarSplitPane[];\n } | null;\n}\n/**\n * Replace the sidebar's thread list with a plugin component.\n *\n * Unlike every other slot, this one is EXCLUSIVE: two lists cannot share one\n * scroll area. Registering activates the replacement while the plugin is\n * enabled. If multiple plugins register one, the first in deterministic slot\n * order is active by default; removing it reveals the next. The user can pin\n * BB's list or a specific provider under Settings → Appearance. A plugin can\n * also use its own setting and render `experimental_Original` conditionally.\n * An absent or crashing replacement falls back to BB's list rather than\n * leaving the user with no sidebar.\n *\n * The plugin gets the scrolling list and nothing else. The New-thread button,\n * the search field, the plugin nav rows, and the footer stay host-rendered in\n * every sidebar — they are shared surfaces (other plugins live in two of\n * them), and a replaced list must not be able to remove them.\n */\ninterface PluginThreadListRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label shown in Settings → Appearance and capability details. */\n title: string;\n /** Optional one-line description shown with the provider choice. */\n description?: string;\n component: ComponentType;\n}\n/**\n * Register this plugin as a viewer/editor for file extensions. By default,\n * matching files render the first applicable opener in deterministic slot\n * order. The user can pin BB's preview or a specific opener per extension\n * under Settings → Files. The file tab's \"Open with\" menu can override that\n * choice for one open. A plugin can also use its own setting and render\n * `experimental_Original` conditionally. Applies to working-tree, host, and\n * thread-storage files — never to git-ref snapshots (diff views always use\n * BB's preview).\n */\ninterface PluginFileOpenerRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label in the \"Open with\" menu (e.g. \"Notes editor\"). */\n title: string;\n /** Lowercase extensions without the dot (e.g. [\"md\", \"mdx\"]). */\n extensions: readonly string[];\n component: ComponentType;\n}\n/**\n * Register a leaf message directive rendered inside assistant (and nested\n * agent) message Markdown. `id` is the directive name: `inline-vis` matches\n * `::inline-vis{file=\"demo.html\"}`.\n */\ninterface PluginMessageDirectiveRegistration {\n /**\n * The directive name. Lowercase kebab-case beginning with a letter.\n */\n id: string;\n component: ComponentType;\n}\n/**\n * A narrow, stable reference to one rendered chat message — NOT an internal\n * timeline row. `sourceSeqEnd` is the last source event sequence the message\n * covers, the anchor the server accepts for provider-history forks.\n */\ninterface ThreadChatMessageReference {\n id: string;\n threadId: string;\n role: \"assistant\" | \"user\";\n /** Visible text of the message. */\n text: string;\n sourceSeqEnd: number;\n}\n/**\n * What a caller that is *not* itself a panel action passes to open one — a\n * `messageAction`'s `run`, or any component via `useBbNavigate()`. A panel\n * action opening its own tab is already the target, so it passes the bare\n * {@link PluginPanelActionOpenOptions} instead.\n */\ninterface PluginTargetedPanelActionOpenOptions extends PluginPanelActionOpenOptions {\n /** A `threadPanelAction` id registered by this same plugin. */\n actionId: string;\n}\n/** Context handed to a `messageAction`'s `run`. */\ninterface PluginMessageActionContext {\n /** The thread whose timeline surfaced the action. */\n threadId: string;\n message: ThreadChatMessageReference;\n /**\n * Present only when the action was invoked from the text-selection menu;\n * the exact text the user highlighted inside `message`.\n */\n selectedText?: string;\n /**\n * Open one of this plugin's `threadPanelAction` components in the current\n * thread's side panel — the registration-callback equivalent of\n * `useBbNavigate().openThreadPanel`.\n *\n * Returns true when the host accepted the open; false when it declined —\n * `params` was not a JSON value, the action id names no `threadPanelAction`\n * of this plugin, or the surface has no side panel (only the main thread\n * view does; a `ThreadChat` embedded in a plugin panel does not). A decline\n * is never thrown: the host logs it and reports it here.\n */\n openPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * An action on chat messages: an icon button in the per-message action bar\n * (user and assistant messages) and an entry in the assistant-message\n * text-selection menu. Host-rendered chrome — the plugin supplies title,\n * icon hint, and `run` behavior only.\n */\ninterface PluginMessageActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(context: PluginMessageActionContext): void | Promise;\n}\n/**\n * Supply the inline React mark bb draws for one agent provider.\n *\n * A manifest `branding.icon` (or a provider's `logoUrl`) is fetched and drawn\n * through ``, a separate document where `currentColor` resolves to black\n * — invisible on dark themes and unreachable from app CSS. A component is\n * rendered inline, so it inherits the app's theme colors and the host's sizing\n * classes. Register a static color logo as a file and a theme-aware mark here.\n *\n * The host passes only `className` (sizing plus the provider's color class);\n * the component must render an inline SVG (or other inline markup) and must\n * not fetch. One registration per provider id per plugin; when two plugins\n * claim the same provider id the host keeps the first by plugin id and warns.\n */\ninterface PluginProviderIconRegistration {\n /**\n * The provider this mark is for — the id bb knows the provider by (the\n * provider declaration's id, e.g. `codex` or `acp-cursor`), not the plugin\n * id. Letters, digits, `-`, `_`.\n */\n providerId: string;\n /** Inline, theme-aware mark. Receives the host's sizing/color className. */\n icon: ComponentType<{\n className?: string;\n }>;\n}\ninterface PluginAppSlots {\n homepageSection(registration: PluginHomepageSectionRegistration): void;\n settingsSection(registration: PluginSettingsSectionRegistration): void;\n navPanel(registration: PluginNavPanelRegistration): void;\n /**\n * Add an action to an existing thread's panel launcher. This slot is\n * thread-only; use `experimental_newThreadPanelAction` for root compose.\n */\n threadPanelAction(registration: PluginThreadPanelActionRegistration): void;\n /**\n * Add an action to the root New thread screen's panel launcher (see\n * {@link PluginNewThreadPanelActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_newThreadPanelAction(registration: PluginNewThreadPanelActionRegistration): void;\n pendingInteraction(registration: PluginPendingInteractionRegistration): void;\n sidebarFooterAction(registration: PluginSidebarFooterActionRegistration): void;\n /**\n * Replace the sidebar's thread list (see\n * {@link PluginThreadListRegistration}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_threadList(registration: PluginThreadListRegistration): void;\n /**\n * Render a component in the thread header's action row (see\n * {@link PluginThreadHeaderActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_threadHeaderAction(registration: PluginThreadHeaderActionRegistration): void;\n fileOpener(registration: PluginFileOpenerRegistration): void;\n messageDirective(registration: PluginMessageDirectiveRegistration): void;\n messageAction(registration: PluginMessageActionRegistration): void;\n /**\n * Draw one agent provider's icon with an inline React component instead of\n * its ``-rendered logo file (see\n * {@link PluginProviderIconRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_providerIcon(registration: PluginProviderIconRegistration): void;\n}\ninterface PluginAppComposer {\n customize(registration: ComposerCustomization): void;\n}\n/** Stable lifecycle values for one content-script instance in one bb client. */\ninterface PluginContentScriptContext {\n /** The id of the plugin that owns this script. */\n readonly pluginId: string;\n /** Monotonic per-client generation, starting at 1. */\n readonly generation: number;\n /** Aborted before cleanup begins on replacement, deactivation, or teardown. */\n readonly signal: AbortSignal;\n /**\n * Persistently decorate any thread row for this plugin generation.\n *\n * The status is owned by the frontend generation and therefore survives\n * route changes. Passing `null` clears the plugin's status for that thread.\n * The host clears every remaining status when the frontend generation\n * deactivates.\n *\n * Optional so bundles can feature-detect support while this experimental\n * surface rolls out across 0.x clients.\n */\n readonly experimental_setThreadRowStatus?: (threadId: string, status: PluginComposerThreadRowStatus | null) => void;\n}\n/** Cleanup returned by a frontend content script. */\ntype PluginContentScriptDisposer = () => void | Promise;\n/**\n * Trusted same-origin JavaScript/TypeScript mounted once per active frontend\n * generation in each bb app window or browser tab.\n */\ninterface PluginContentScriptRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Install behavior into the bb app shell. The host awaits a returned\n * promise, contains failures, and calls the returned disposer exactly once.\n */\n mount(context: PluginContentScriptContext): void | PluginContentScriptDisposer | Promise;\n}\n/** Lifecycle surface for trusted frontend content scripts. */\ninterface PluginAppContentScripts {\n register(registration: PluginContentScriptRegistration): void;\n}\ninterface PluginAppBuilder {\n slots: PluginAppSlots;\n composer: PluginAppComposer;\n contentScripts: PluginAppContentScripts;\n}\ntype PluginAppSetup = (app: PluginAppBuilder) => void;\n/**\n * The opaque product of `definePluginApp` — a plugin's `app.tsx` default\n * export. The host re-runs `setup` against a fresh collector on every\n * (re)interpretation, replacing that plugin's registrations wholesale.\n */\ninterface PluginAppDefinition {\n /** Brand the host checks before interpreting a bundle's default export. */\n readonly __bbPluginApp: true;\n readonly setup: PluginAppSetup;\n}\ninterface PluginRpcClient {\n /**\n * Invoke one of the plugin's `bb.rpc` methods (POST\n * /api/v1/plugins/<id>/rpc/<method>). Resolves with the method's\n * inferred output; rejects with an `Error` carrying the server's message,\n * stable `code`, and validation `issues` when present.\n */\n call>(method: Method, ...args: PluginRpcCallArgs): Promise>;\n}\ninterface PluginSettingsState {\n /**\n * Effective non-secret setting values (secret settings are excluded —\n * read them server-side). Undefined while loading or unavailable.\n */\n values: Record | undefined;\n isLoading: boolean;\n}\n/** State of the app's shared realtime connection to the bb server. */\ntype PluginRealtimeConnectionState = \"connected\" | \"connecting\" | \"reconnecting\";\n/** Where `useComposer()` writes. */\ntype PluginComposerScope = {\n kind: \"thread\";\n threadId: string;\n} | {\n kind: \"queued-message\";\n threadId: string;\n queuedMessageId: string;\n} | {\n kind: \"side-chat\";\n projectId: string;\n parentThreadId: string;\n tabId: string;\n childThreadId: string | null;\n} | {\n kind: \"new-thread\";\n /** Root compose's effective selected project; null only while unresolved. */\n projectId: string | null;\n};\n/** One plugin-owned composer customization registration. */\ninterface ComposerCustomization {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Composer kinds where this customization is active; omit for all kinds. */\n scopes?: readonly PluginComposerScope[\"kind\"][];\n actions?: readonly {\n id: string;\n component: ComponentType;\n }[];\n banners?: readonly {\n id: string;\n /** Host chrome around the banner. Defaults to `\"card\"`. */\n chrome?: \"bare\" | \"card\";\n component: ComponentType;\n }[];\n plusMenu?: readonly ComposerPlusMenuItem[];\n richText?: ComposerRichTextSpec;\n}\n/** Host-rendered menu row in the composer's `+` menu. */\ninterface ComposerPlusMenuItem {\n id: string;\n label: string;\n /** BB icon name; unknown names fall back to the generic plugin icon. */\n icon?: string;\n /** Accessible description for the host-rendered row. */\n description?: string;\n disabled?: boolean | ((view: ComposerView) => boolean);\n run(context: {\n composer: PluginComposerApi;\n view: ComposerView;\n }): void | Promise;\n}\n/** Reactive read-side of the composer a plugin surface is mounted in. */\ninterface ComposerView {\n scope: PluginComposerScope;\n layout: \"compact\" | \"expanded\" | \"zen\";\n draft: {\n text: string;\n isEmpty: boolean;\n attachmentCount: number;\n };\n run: {\n isRunning: boolean;\n isSubmitting: boolean;\n };\n}\ninterface ComposerRichTextSpec {\n /** Content-derived paint: match ranges receive `className`; text is never mutated. */\n effects?: readonly {\n id: string;\n /** Plain-text offsets into the current structured draft. */\n match(text: string): readonly {\n from: number;\n to: number;\n }[];\n className: string;\n }[];\n /** Debounced, read-only observation of the structured draft. */\n onDraftChange?(draft: ComposerStructuredDraft, view: ComposerView): void;\n}\ninterface ComposerStructuredDraft {\n text: string;\n mentions: readonly {\n from: number;\n to: number;\n provider: string;\n id: string;\n label: string;\n }[];\n}\n/** Host-rendered paint applied to the editable composer text. */\ninterface PluginComposerTextEffect {\n className: string;\n}\n/** Host-rendered status that temporarily replaces a thread's draft glyph. */\ninterface PluginComposerThreadRowStatus {\n /** BB icon-name hint; unknown names fall back to the generic plugin icon. */\n icon: string;\n /** Accessible label for the status glyph. */\n label: string;\n /**\n * Semantic host treatment for the status glyph. `running` automatically\n * shimmers; terminal `success` and `error` tones are static. Defaults to the\n * neutral tone.\n */\n tone?: \"default\" | \"error\" | \"running\" | \"success\";\n}\n/** An @-mention pill bound to one of the calling plugin's mention providers. */\ninterface PluginComposerMention {\n /** Mention provider id registered by THIS plugin via `bb.ui.registerMentionProvider`. */\n provider: string;\n /** Item id your provider's `resolve` will receive at send time. */\n id: string;\n /** Pill text shown in the composer. */\n label: string;\n}\n/**\n * Programmatic access to the chat composer draft — the same shared draft the\n * built-in \"Add to chat\" affordances (file preview, diff, terminal selections)\n * write to. While a queued message is being edited, writes land in that\n * message's inline editor. In a side chat, writes land in the visible side-chat\n * draft. Otherwise, inside a thread context writes land in that thread's draft;\n * anywhere else (nav panel, homepage section) they seed the new-thread composer\n * draft, which persists until the user sends or clears it.\n */\ninterface PluginComposerApi {\n scope: PluginComposerScope;\n /** Current plain text for this composer scope. */\n readonly text: string;\n /**\n * Replace the draft's plain text. Attachments are preserved. Inline mentions\n * outside the changed range are preserved and rebased; mentions overlapped\n * by the replacement are removed because their text representation changed.\n */\n setText(next: string): void;\n /**\n * Replace the draft's plain text from the latest committed value. Uses the\n * same structured-state reconciliation as `setText`.\n */\n updateText(updater: (current: string) => string): void;\n /** Clear plain text without clearing independently attached files. */\n clear(): void;\n /**\n * Apply a host-rendered effect to this composer's editable text, or clear it.\n * Effects are scoped to the calling plugin and automatically clear when the\n * slot unmounts or its composer scope changes.\n */\n setTextEffect(effect: PluginComposerTextEffect | null): void;\n /**\n * Lock or unlock editing for this composer. Locks are scoped to the calling\n * plugin and automatically release when the slot unmounts or its composer\n * scope changes.\n */\n setInputLock(locked: boolean): void;\n /**\n * Append text to the draft as a `> ` blockquote block and focus the\n * composer. Blank text is a no-op. This is the \"reference this selection\n * in chat\" primitive.\n */\n addQuote(text: string): void;\n /**\n * Insert an @-mention pill that resolves through this plugin's mention\n * provider at send time — the durable way to reference an entity whose\n * content should be fetched fresh when the message is sent.\n */\n insertMention(mention: PluginComposerMention): void;\n /** Focus the composer caret at the end of the draft. */\n focus(): void;\n}\n/**\n * A consumer-supplied action on the messages of one `ThreadChat` instance,\n * rendered in the embedded timeline's per-message action bar alongside the\n * native and slot-registered actions. Unlike the `messageAction` slot this is\n * scoped to the rendering component, not registered globally.\n */\ninterface ThreadChatMessageAction {\n /** Unique within this ThreadChat instance; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Message roles the action applies to. Omitted = both user and assistant\n * messages.\n */\n roles?: readonly (\"assistant\" | \"user\")[];\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(message: ThreadChatMessageReference): void | Promise;\n}\n/**\n * Props of the host-owned `ThreadChat` component — one thread's chat\n * (timeline, and for the composer variants the full send/queue/draft\n * engine), rendered by the BB app inside a plugin slot. This is the\n * deliberate exception to the no-host-components rule (§5.5): a stable\n * product capability, not a UI kit. Versioned additive like slot props;\n * internal timeline rows, query hooks, and prompt-box configuration are\n * deliberately not exposed.\n */\ninterface ThreadChatProps {\n threadId: string;\n /**\n * \"full\" (default) is the page presentation (centered reading width);\n * \"compact\" is the side-panel presentation; \"timeline\" renders the\n * transcript without a composer.\n */\n variant?: \"compact\" | \"full\" | \"timeline\";\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the composer (ignored by `variant: \"timeline\"`). */\n focusRequest?: number;\n /**\n * Who controls the permission mode sends run with. \"inherit\" (default)\n * pins every send to the thread's own resolved default and renders the\n * picker as a dimmed label — a plugin surface can never widen it.\n * \"editable\" gives this chat its own picker, so the user can raise or\n * lower permissions for this thread independently of the thread it was\n * forked from. Ignored by `variant: \"timeline\"` (no composer).\n */\n permissionPolicy?: \"editable\" | \"inherit\";\n className?: string;\n /** Rendered above the conversation, scrolling with it. */\n leadingContent?: ReactNode;\n /**\n * Actions rendered in this instance's per-message action bar (see\n * {@link ThreadChatMessageAction}).\n */\n messageActions?: readonly ThreadChatMessageAction[];\n}\n/**\n * Every selection the composer resolved, JSON-serializable so a plugin can\n * forward it to its own backend rpc verbatim and hand it straight to\n * `bb.sdk.threads.spawn`.\n *\n * The split is deliberate: the composer owns *user selections*, the plugin\n * owns *filing and attribution*. `bb.sdk.threads.spawn` auto-fills\n * `origin: \"plugin\"` and `originPluginId`, so a thread created this way stays\n * attributed to the plugin — which it would not be if the component created\n * the thread itself. The plugin adds `sectionId`, `parentThreadId`, `title`,\n * and `visibility` to the request on its own; they are deliberately not\n * composer props.\n */\ninterface NewThreadRequest {\n /**\n * The selected project id. Choosing \"Don't work in a project\" submits BB's\n * personal-project id (not `null`) together with a `personal` workspace\n * environment. Forward those fields unchanged to `threads.spawn`; if the\n * plugin needs project metadata, request it from the plugin backend with\n * `bb.sdk.projects.list({ includePersonal: true })`.\n */\n projectId: string;\n providerId: string;\n model: string;\n reasoningLevel: ReasoningLevel;\n permissionMode: PermissionMode;\n /** Omitted when the selected provider has no service tiers. */\n serviceTier?: ServiceTier;\n /**\n * Per-field provenance (caller-explicit vs. default) for the execution\n * options above, forwarded to `spawn` so the server records what the user\n * actually chose.\n */\n executionInputSources: CreateExecutionInputSources;\n environment: CreateThreadEnvironmentArgs;\n input: PromptInput[];\n}\n/**\n * Props of the host-owned `experimental_NewThreadComposer` component — bb's\n * full new-thread compose surface (prompt editor with @-mentions and expand,\n * attachments, provider/model/reasoning picker, voice, submit, and the row\n * beneath with project, environment, branch-from, and permission mode),\n * rendered by the BB app inside a plugin slot.\n *\n * It is the create-side counterpart to `ThreadChat`: same deliberate\n * exception to the no-host-components rule (§5.5), same additive versioning.\n */\ninterface NewThreadComposerProps {\n /**\n * Seeds the project picker. The user can change it, including choosing\n * \"Don't work in a project\"; see {@link NewThreadRequest.projectId} for the\n * submitted projectless shape.\n */\n defaultProjectId?: string;\n /**\n * Seeds the provider picker. Like every `default*` prop this is a SEED, not\n * a controlled value: the composer stays uncontrolled, the user can change\n * it, and when omitted the composer falls back to the project's remembered\n * execution defaults exactly as before. When provided it takes precedence\n * over those project defaults.\n *\n * Re-seeding: the `default*` props are value-compared each render. When any\n * of them changes after mount, the composer re-seeds EVERY execution and\n * environment selection from the new props — including selections the user\n * had already touched — so switching between two saved records in the same\n * mounted composer reloads that record's values (the same rule\n * `defaultProjectId` already follows).\n *\n * Every seeded field is reported as caller-explicit in the submitted\n * request's `executionInputSources`. That is what makes the seed survive\n * `threads.spawn`: the server drops a requested `providerId`/`model` that\n * carries no provenance source and re-derives it from the project's stored\n * defaults, which would silently undo the seed.\n */\n defaultProviderId?: string;\n /** Seeds the model picker. Same seed semantics as {@link defaultProviderId}. */\n defaultModel?: string;\n /**\n * Seeds the reasoning-level picker. Same seed semantics as\n * {@link defaultProviderId}. If the seeded model does not support this\n * level, the composer reconciles to the closest supported one.\n */\n defaultReasoningLevel?: ReasoningLevel;\n /**\n * Seeds the service-tier picker. Same seed semantics as\n * {@link defaultProviderId}. Ignored (and omitted from the submitted\n * request) when the selected provider has no service tiers.\n */\n defaultServiceTier?: ServiceTier;\n /** Seeds the permission-mode picker. Same seed semantics as {@link defaultProviderId}. */\n defaultPermissionMode?: PermissionMode;\n /**\n * Seeds the environment and branch pickers from a previously submitted\n * `NewThreadRequest.environment`. Same seed semantics as\n * {@link defaultProviderId}: a seed the user can change, taking precedence\n * over the composer's own environment default when provided.\n *\n * Round trip: feeding a submitted request's `environment` back in and\n * resubmitting untouched reproduces an equivalent environment, with these\n * documented limits — the composer cannot represent every args variant:\n *\n * - `{ type: \"project-default\" }` seeds nothing; the composer resolves its\n * own default and submits that concrete environment instead.\n * - A `host` environment whose host no longer exists (or whose project has\n * no source on it) falls back to the composer's default host, exactly as\n * the primary compose surface would.\n * - A `reuse` environment whose worktree no longer has unarchived threads\n * falls back the same way.\n * - An `unmanaged` workspace's `path` has no composer control; the seeded\n * selection submits `path: null` (the host's configured checkout). The\n * composer itself never produces a non-null `path`, so real round trips\n * are unaffected.\n * - A `managed-worktree` with `baseBranch: { kind: \"default\" }` leaves the\n * branch picker on its default, which may resolve to a named base branch\n * when the project configures a dedicated worktree base — the same branch\n * the original `default` submission would have created from.\n */\n defaultEnvironment?: CreateThreadEnvironmentArgs;\n /** Seeds the draft, only while the draft is still empty. */\n initialPrompt?: string;\n placeholder?: string;\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the editor. */\n focusRequest?: number;\n className?: string;\n /**\n * Where the draft persists. Drafts survive reloads and are shared by every\n * composer using the same key; defaults to a key scoped to this plugin.\n */\n draftKey?: string;\n /**\n * Fires on submit with every selection resolved. The draft clears when this\n * resolves and is KEPT if it throws, so a failed create never loses what the\n * user typed.\n */\n onSubmit: (request: NewThreadRequest) => void | Promise;\n}\n/**\n * Props of the host-owned `Markdown` component — bb's chat message renderer\n * (the same typography, spacing, and code styling as timeline messages).\n * Use it wherever plugin UI quotes or previews message content so it reads\n * like the rest of the chat. Like `ThreadChat`, this is a stable product\n * capability, not a UI kit; renderer internals stay private.\n */\ninterface MarkdownProps {\n /** Markdown source, rendered exactly like a chat message body. */\n content: string;\n className?: string;\n}\n/** Current app selection, derived from the route. */\ninterface BbContext {\n projectId: string | null;\n threadId: string | null;\n}\ninterface BbNavigate {\n toThread(threadId: string): void;\n toProject(projectId: string): void;\n /**\n * Navigate to one of this plugin's own nav panels by its `path`.\n * `subPath` targets a location inside the panel (the component's\n * `subPath` prop); `replace` swaps the current history entry instead of\n * pushing — use it for redirects so back does not bounce.\n */\n toPluginPanel(path: string, options?: {\n subPath?: string;\n replace?: boolean;\n }): void;\n /**\n * Navigate to the root compose surface (the new-thread screen). Pass\n * `initialPrompt` to seed the composer draft and `focusPrompt` to focus the\n * composer on arrival — the pairing behind \"Create via chat\" style entry\n * points that drop the user into chat with a prefilled prompt.\n */\n toCompose(options?: {\n initialPrompt?: string;\n focusPrompt?: boolean;\n }): void;\n /**\n * Open one of this plugin's registered thread-panel actions in the current\n * thread surface. Returns false when the surface has no thread side panel or\n * the action is unavailable.\n */\n openThreadPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * Everything `@get-bb/plugin-sdk/app` resolves to at runtime. The BB app builds\n * the real implementation and `satisfies` this interface; `bb plugin build`\n * shims the specifier to that object on `globalThis.__bbPluginRuntime`.\n */\ninterface PluginSdkApp {\n definePluginApp(setup: PluginAppSetup): PluginAppDefinition;\n useRpc(): PluginRpcClient;\n useRealtime(channel: string, handler: (payload: unknown) => void): void;\n /**\n * Observe the same shared connection that delivers `useRealtime` signals.\n * Use a subsequent transition to `connected` to reconcile server state that\n * may have changed while ephemeral signals could not be delivered. The first\n * connection can transition from `connecting` and is not a reconnection.\n */\n useRealtimeConnectionState(): PluginRealtimeConnectionState;\n useSettings(): PluginSettingsState;\n useBbContext(): BbContext;\n useBbNavigate(): BbNavigate;\n useComposer(): PluginComposerApi;\n /**\n * The sidebar's live thread view (see {@link PluginSidebarThreadsState}).\n * Reads the host's own cache and realtime subscriptions, so it costs no\n * extra request and updates exactly when the built-in sidebar does.\n *\n * `threads` is one array of every visible thread and is not capped. Thread\n * objects keep their identity across updates while the underlying entry is\n * unchanged, so a memoized row re-renders only when its own thread changed;\n * the array itself is new on every update. Window your rows (render only\n * what is on screen) as the built-in sidebar does — a list that mounts one\n * row per thread is slow on phones with many threads.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreads(): PluginSidebarThreadsState;\n /**\n * Thread actions bound to the host's mutations (see\n * {@link PluginSidebarThreadActions}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_useSidebarThreadActions(): PluginSidebarThreadActions;\n /**\n * The pull request for one thread's branch (see\n * {@link PluginSidebarThreadPullRequestState}).\n *\n * Per row and opt-in, because it costs a git-host lookup: it is NOT on the\n * thread payload every sidebar loads. Threads sharing an environment share\n * one query, and the host owns the polling and staleness rules — an open PR\n * with pending checks refreshes, a merged one does not.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadPullRequest(threadId: string): PluginSidebarThreadPullRequestState;\n /**\n * Per-row drag-to-split support (see {@link PluginSidebarThreadSplit}).\n * Call it once per rendered row, like the built-in sidebar does.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadSplit(threadId: string): PluginSidebarThreadSplit;\n /**\n * The host-owned chat component (see {@link ThreadChatProps}). Together\n * with `Markdown`, the only components the SDK ships — everything else\n * stays vendored per §5.5.\n */\n ThreadChat: ComponentType;\n /**\n * The host-owned chat-message markdown renderer (see\n * {@link MarkdownProps}).\n */\n Markdown: ComponentType;\n /**\n * The host-owned new-thread compose surface (see\n * {@link NewThreadComposerProps}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_NewThreadComposer: ComponentType;\n useComposerView(): ComposerView;\n}\n\ninterface EnvironmentActionArgs {\n environmentId: string;\n}\ninterface EnvironmentGetArgs extends EnvironmentActionArgs {\n signal?: AbortSignal;\n}\ntype EnvironmentMergeBaseBranchUpdateValue = Exclude;\ntype EnvironmentNameUpdateValue = Exclude;\ninterface EnvironmentMergeBaseBranchUpdate {\n mergeBaseBranch: EnvironmentMergeBaseBranchUpdateValue;\n name?: EnvironmentNameUpdateValue;\n}\ninterface EnvironmentNameUpdate {\n mergeBaseBranch?: EnvironmentMergeBaseBranchUpdateValue;\n name: EnvironmentNameUpdateValue;\n}\ntype EnvironmentUpdateFields = EnvironmentMergeBaseBranchUpdate | EnvironmentNameUpdate;\ntype EnvironmentUpdateArgs = EnvironmentUpdateFields & {\n environmentId: string;\n};\ninterface EnvironmentStatusArgs extends EnvironmentStatusQuery {\n environmentId: string;\n signal?: AbortSignal;\n}\ntype EnvironmentDiffArgs = EnvironmentDiffQuery & {\n environmentId: string;\n signal?: AbortSignal;\n};\ntype EnvironmentDiffFileArgs = EnvironmentDiffFileQuery & {\n environmentId: string;\n signal?: AbortSignal;\n};\ninterface EnvironmentDiffBranchesArgs extends EnvironmentDiffBranchesQuery {\n environmentId: string;\n signal?: AbortSignal;\n}\ninterface EnvironmentCommitArgs {\n environmentId: string;\n}\ninterface EnvironmentSquashMergeArgs {\n environmentId: string;\n mergeBaseBranch: string;\n}\ninterface EnvironmentPullRequestMergeArgs {\n environmentId: string;\n method: PullRequestMergeMethod;\n}\ntype EnvironmentDiffPatchArgs = EnvironmentDiffPatchRequest & {\n environmentId: string;\n signal?: AbortSignal;\n};\ninterface EnvironmentPathsArgs extends EnvironmentPathsQuery {\n environmentId: string;\n signal?: AbortSignal;\n}\ntype EnvironmentArchiveThreadsResult = EnvironmentArchiveThreadsResponse;\ntype EnvironmentCommitResult = CommitActionResponse;\ntype EnvironmentDiffResult = EnvironmentDiffResponse;\ntype EnvironmentDiffBranchesResult = EnvironmentDiffBranchesResponse;\ntype EnvironmentDiffFileResult = EnvironmentDiffFileResponse;\ntype EnvironmentDiffFilesResult = EnvironmentDiffFilesResponse;\ntype EnvironmentDiffPatchResult = EnvironmentDiffPatchResponse;\ntype EnvironmentGetResult = Environment;\ntype EnvironmentMarkPullRequestDraftResult = PullRequestDraftActionResponse;\ntype EnvironmentMarkPullRequestReadyResult = PullRequestReadyActionResponse;\ntype EnvironmentMergePullRequestResult = PullRequestMergeActionResponse;\ntype EnvironmentPathsResult = WorkspacePathListResponse;\ntype EnvironmentPullRequestResult = EnvironmentPullRequestResponse;\ntype EnvironmentSquashMergeResult = SquashMergeActionResponse;\ntype EnvironmentStatusResult = EnvironmentStatusResponse;\ntype EnvironmentUpdateResult = Environment;\ninterface EnvironmentsArea {\n archiveThreads(args: EnvironmentActionArgs): Promise;\n commit(args: EnvironmentCommitArgs): Promise;\n diff(args: EnvironmentDiffArgs): Promise;\n diffBranches(args: EnvironmentDiffBranchesArgs): Promise;\n diffFile(args: EnvironmentDiffFileArgs): Promise;\n diffFiles(args: EnvironmentDiffArgs): Promise;\n diffPatch(args: EnvironmentDiffPatchArgs): Promise;\n get(args: EnvironmentGetArgs): Promise;\n pullRequest(args: EnvironmentGetArgs): Promise;\n markPullRequestDraft(args: EnvironmentActionArgs): Promise;\n markPullRequestReady(args: EnvironmentActionArgs): Promise;\n mergePullRequest(args: EnvironmentPullRequestMergeArgs): Promise;\n paths(args: EnvironmentPathsArgs): Promise;\n squashMerge(args: EnvironmentSquashMergeArgs): Promise;\n status(args: EnvironmentStatusArgs): Promise;\n update(args: EnvironmentUpdateArgs): Promise;\n}\n\n/**\n * Host file primitives. `hostId` may be omitted to target the server's\n * primary (local) host. `rootPath`, when set, confines the target beneath\n * that absolute root on the host (symlink-safe).\n */\ninterface FileReadArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n signal?: AbortSignal;\n}\ninterface FileWriteArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n content: string;\n /** Defaults to \"utf8\". */\n contentEncoding?: \"base64\" | \"utf8\";\n /** Defaults to false. */\n createParents?: boolean;\n /**\n * Optimistic-concurrency guard: omitted → unconditional write; a hash →\n * write only when the current content hashes to it (use `read().sha256`);\n * null → create-only. A failed guard resolves to the `conflict` outcome.\n */\n expectedSha256?: string | null;\n /** POSIX permission bits used when creating a file (for example 0o600). */\n mode?: number;\n}\ninterface FileListArgs {\n hostId?: string;\n path: string;\n query?: string;\n limit?: number;\n signal?: AbortSignal;\n}\ninterface PathListArgs extends FileListArgs {\n includeFiles: boolean;\n includeDirectories: boolean;\n}\ninterface FileMkdirArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n recursive?: boolean;\n}\ninterface FileMoveArgs {\n hostId?: string;\n sourcePath: string;\n destinationPath: string;\n rootPath?: string;\n}\ninterface FileRemoveArgs {\n hostId?: string;\n path: string;\n rootPath?: string;\n recursive?: boolean;\n}\ninterface FilePreviewArgs {\n hostId?: string;\n rootPath: string;\n signal?: AbortSignal;\n ttlMs?: number;\n}\ntype FileReadResult = HostFileReadResponse;\ntype FileWriteResult = HostFileWriteResponse;\ntype FileListResult = HostFileListResponse;\ntype PathListResult = HostPathListResponse;\ntype FileMkdirResult = HostMkdirResponse;\ntype FileMoveResult = HostMovePathResponse;\ntype FileRemoveResult = HostRemovePathResponse;\ntype FilePreviewResult = CreateFilePreviewResponse;\ninterface FilesArea {\n read(args: FileReadArgs): Promise;\n write(args: FileWriteArgs): Promise;\n list(args: FileListArgs): Promise;\n listPaths(args: PathListArgs): Promise;\n mkdir(args: FileMkdirArgs): Promise;\n move(args: FileMoveArgs): Promise;\n remove(args: FileRemoveArgs): Promise;\n createPreview(args: FilePreviewArgs): Promise;\n}\n\ninterface GuideRenderArgs {\n chapter?: string;\n}\ninterface GuideRenderResult {\n chapter?: string;\n content: string;\n}\ninterface GuideArea {\n render(args?: GuideRenderArgs): GuideRenderResult;\n}\n\ninterface HostGetArgs {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostDeleteArgs {\n hostId: string;\n}\ninterface HostUpdateArgs extends UpdateHostRequest {\n hostId: string;\n}\ninterface HostRetryUpdateArgs {\n hostId: string;\n}\ninterface HostDirectoryArgs extends HostDirectoryQuery {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostCloneDefaultPathArgs extends HostCloneDefaultPathQuery {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostPathsExistArgs extends HostPathsExistRequest {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostPickFolderArgs extends HostPickFolderRequest {\n hostId: string;\n signal?: AbortSignal;\n}\ninterface HostProviderCliInstallArgs extends HostProviderCliInstallRequest {\n hostId: string;\n}\ninterface HostListArgs {\n signal?: AbortSignal;\n}\ntype HostCreateJoinCodeResult = CreateHostJoinCodeResponse;\ntype HostDeleteResult = {\n ok: true;\n};\ntype HostDirectoryResult = HostDirectoryListing;\ntype HostGetResult = Host;\ntype HostCloneDefaultPathResult = HostCloneDefaultPathResponse;\ntype HostProviderCliInstallResult = HostProviderCliInstallEvent[];\ntype HostListResult = Host[];\ntype HostPathsExistResult = HostPathsExistResponse;\ntype HostPickFolderResult = HostPickFolderResponse;\ntype HostProviderCliStatusResult = HostProviderCliStatusResponse;\ntype HostRetryUpdateResult = HostRetryUpdateResponse;\ntype HostUpdateResult = Host;\ninterface HostsArea {\n createJoinCode(): Promise;\n delete(args: HostDeleteArgs): Promise;\n directory(args: HostDirectoryArgs): Promise;\n get(args: HostGetArgs): Promise;\n cloneDefaultPath(args: HostCloneDefaultPathArgs): Promise;\n installProviderCli(args: HostProviderCliInstallArgs): Promise;\n list(args?: HostListArgs): Promise;\n pathsExist(args: HostPathsExistArgs): Promise;\n pickFolder(args: HostPickFolderArgs): Promise;\n providerCliStatus(args: HostGetArgs): Promise;\n retryUpdate(args: HostRetryUpdateArgs): Promise;\n update(args: HostUpdateArgs): Promise;\n}\n\ninterface ProjectListArgs {\n include?: ProjectListQuery[\"include\"];\n /** Include the singleton personal project. Defaults to false for compatibility. */\n includePersonal?: boolean;\n signal?: AbortSignal;\n}\ninterface ProjectCreateArgs extends CreateProjectRequest {\n}\ninterface ProjectGetArgs {\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectUpdateArgs extends UpdateProjectRequest {\n projectId: string;\n}\ninterface ProjectDeleteArgs {\n projectId: string;\n}\ninterface ProjectReorderArgs extends ReorderProjectRequest {\n projectId: string;\n}\ninterface ProjectPromptHistoryArgs extends PromptHistoryQuery {\n projectId: string;\n signal?: AbortSignal;\n}\n/** Select one project workspace source, or omit both for the primary host. */\ntype ProjectWorkspaceRoutingArgs = {\n environmentId: string;\n hostId?: never;\n} | {\n environmentId?: never;\n hostId: string;\n} | {\n environmentId?: never;\n hostId?: never;\n};\ntype ProjectFilesArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ntype ProjectPathsArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ntype ProjectCommandsArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ntype ProjectFileContentArgs = ProjectWorkspaceRoutingArgs & Omit & {\n projectId: string;\n signal?: AbortSignal;\n};\ninterface ProjectBranchesArgs extends ProjectBranchesQuery {\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectDefaultExecutionOptionsArgs {\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectAttachmentFileLike {\n arrayBuffer(): Promise;\n readonly name: string;\n readonly type?: string;\n}\ninterface ProjectAttachmentUploadArgsBase {\n /** MIME override. Omit to use the File/Blob type, when available. */\n mimeType?: string;\n projectId: string;\n}\n/**\n * Upload bytes owned by this SDK client. A bare Blob/byte buffer needs an\n * explicit filename; File-like values can supply their own name.\n */\ntype ProjectAttachmentUploadArgs = ProjectAttachmentUploadArgsBase & ({\n clientFile: ProjectAttachmentFileLike;\n filename?: string;\n} | {\n clientFile: ArrayBuffer | Blob | Uint8Array;\n filename: string;\n});\ninterface ProjectAttachmentReadArgs {\n path: string;\n projectId: string;\n signal?: AbortSignal;\n}\ninterface ProjectAttachmentCopyArgs extends CopyProjectAttachmentsRequest {\n projectId: string;\n}\ntype ProjectSourceAddArgs = CreateProjectSourceRequest & {\n projectId: string;\n};\ninterface ProjectSourceUpdateArgs extends UpdateProjectSourceRequest {\n projectId: string;\n sourceId: string;\n}\ninterface ProjectSourceDeleteArgs {\n projectId: string;\n sourceId: string;\n}\ntype ProjectBranchesResult = ProjectBranchesResponse;\ninterface ProjectAttachmentReadResult {\n bytes: Uint8Array;\n mimeType: string;\n sizeBytes: number;\n}\ntype ProjectAttachmentUploadResult = UploadedPromptAttachment;\ntype ProjectCommandsResult = CommandListResponse;\ntype ProjectCreateResult = ProjectResponse;\ntype ProjectDefaultExecutionOptionsResult = ProjectExecutionDefaults | null;\ntype ProjectDeleteResult = {\n ok: true;\n};\ninterface ProjectFileContentResult {\n /** UTF-8 text or base64, as selected by `contentEncoding`. */\n content: string;\n contentEncoding: \"base64\" | \"utf8\";\n mimeType: string;\n sizeBytes: number;\n}\ntype ProjectFilesResult = WorkspaceFileListResponse;\ntype ProjectGetResult = ProjectResponse;\ntype ProjectListResult = ProjectResponse[] | ProjectWithThreadsResponse[];\ntype ProjectPathsResult = WorkspacePathListResponse;\ntype ProjectPromptHistoryResult = PromptHistoryResponse;\ntype ProjectReorderResult = ProjectResponse[];\ntype ProjectSourceAddResult = ProjectSource;\ntype ProjectSourceDeleteResult = {\n ok: true;\n};\ntype ProjectSourceUpdateResult = ProjectSource;\ntype ProjectUpdateResult = ProjectResponse;\ninterface ProjectSourcesArea {\n add(args: ProjectSourceAddArgs): Promise;\n delete(args: ProjectSourceDeleteArgs): Promise;\n update(args: ProjectSourceUpdateArgs): Promise;\n}\ninterface ProjectAttachmentsArea {\n copy(args: ProjectAttachmentCopyArgs): Promise;\n read(args: ProjectAttachmentReadArgs): Promise;\n upload(args: ProjectAttachmentUploadArgs): Promise;\n}\ninterface ProjectsArea {\n attachments: ProjectAttachmentsArea;\n branches(args: ProjectBranchesArgs): Promise;\n commands(args: ProjectCommandsArgs): Promise;\n create(args: ProjectCreateArgs): Promise;\n defaultExecutionOptions(args: ProjectDefaultExecutionOptionsArgs): Promise;\n delete(args: ProjectDeleteArgs): Promise;\n fileContent(args: ProjectFileContentArgs): Promise;\n files(args: ProjectFilesArgs): Promise;\n get(args: ProjectGetArgs): Promise;\n list(args?: ProjectListArgs): Promise;\n paths(args: ProjectPathsArgs): Promise;\n promptHistory(args: ProjectPromptHistoryArgs): Promise;\n reorder(args: ProjectReorderArgs): Promise;\n sources: ProjectSourcesArea;\n update(args: ProjectUpdateArgs): Promise;\n}\n\n/** Select exactly one provider-discovery host source, or omit both for primary. */\ntype ProviderHostRoutingArgs = {\n environmentId: string;\n hostId?: never;\n} | {\n environmentId?: never;\n hostId: string;\n} | {\n environmentId?: never;\n hostId?: never;\n};\ntype ProviderListArgs = ProviderHostRoutingArgs & {\n signal?: AbortSignal;\n};\ntype ProviderModelsArgs = ProviderHostRoutingArgs & {\n providerId?: string;\n signal?: AbortSignal;\n};\ntype ProviderListResult = ProviderInfo[];\ntype ProviderModelsResult = SystemExecutionOptionsResponse;\ninterface ProvidersArea {\n /** List providers on the environment host, explicit host, or primary host. */\n list(args?: ProviderListArgs): Promise;\n /** List models on the environment host, explicit host, or primary host. */\n models(args?: ProviderModelsArgs): Promise;\n}\n\ninterface PluginIdArgs {\n pluginId: string;\n}\n/** Install directly from a path:, git:, npm:, or builtin: source spec. */\ninterface PluginInstallArgs {\n /**\n * `path:`, `builtin:`, `npm:[@]`, or\n * `git:[@]`. A git spec is one ref, or a semver range resolved\n * over the repository's `[]vX.Y.Z` release tags:\n * `git:@semver:` and `git:@semver::` say\n * range explicitly, `git:@ref:` says ref explicitly, and a bare\n * `^1.2.0` resolves over tags unless the repository also has a ref of that\n * literal name (which is refused as ambiguous).\n */\n source: string;\n /**\n * Directory of a multi-plugin repository to install, relative to the\n * repository root (`git:` and `path:` sources only).\n */\n subdirectory?: string;\n /**\n * Name of a `.bb/plugins.json` collection entry to install, resolved to its\n * directory in the repository. Mutually exclusive with `subdirectory`.\n */\n plugin?: string;\n}\n/** Install a catalog entry, from BB's official catalog or another marketplace. */\ninterface PluginCatalogInstallArgs {\n entryId: string;\n /**\n * Marketplace that lists the entry. Omitted resolves across every\n * marketplace: exactly one match installs, none falls back to the bundled\n * official plugin of that name, and several are refused as ambiguous.\n */\n marketplace?: string;\n /**\n * Source facts returned by installPlan for a third-party entry. The server\n * refuses the install when the listing or its git commit changed afterward.\n */\n confirmedSource?: PluginCatalogResolvedSource;\n}\n/** Ask what an install would do before confirming it. */\ninterface PluginCatalogInstallPlanArgs {\n entryId: string;\n marketplace?: string;\n signal?: AbortSignal;\n}\n/** Add a marketplace by `https:` manifest URL, `git:[@ref]`, or `path:`. */\ninterface PluginMarketplaceAddArgs {\n source: string;\n}\ninterface PluginMarketplaceListArgs {\n signal?: AbortSignal;\n}\ninterface PluginMarketplaceRefreshArgs {\n /** One marketplace to refresh; omitted refreshes every one of them. */\n name?: string;\n signal?: AbortSignal;\n}\ninterface PluginMarketplaceRemoveArgs {\n name: string;\n}\ninterface PluginReloadArgs {\n pluginId?: string;\n}\ninterface PluginSettingsUpdateArgs extends PluginIdArgs {\n values: Record;\n}\ninterface PluginTokenArgs extends PluginIdArgs {\n rotate?: boolean;\n}\ninterface PluginCheckUpdatesArgs {\n pluginId?: string;\n signal?: AbortSignal;\n}\ninterface PluginRpcArgs extends PluginIdArgs {\n input?: JsonValue$1;\n method: string;\n outputSchema: z$1.ZodType;\n}\ninterface PluginCatalogSearchArgs {\n query: string;\n signal?: AbortSignal;\n}\ninterface PluginCatalogStatusArgs {\n signal?: AbortSignal;\n}\ninterface PluginGetSettingsArgs extends PluginIdArgs {\n signal?: AbortSignal;\n}\ninterface PluginGetSourceArgs extends PluginIdArgs {\n signal?: AbortSignal;\n}\ninterface PluginListArgs {\n signal?: AbortSignal;\n}\ninterface PluginListUpdateResultsArgs {\n signal?: AbortSignal;\n}\ntype PluginDisableResult = InstalledPlugin;\ntype PluginEnableResult = InstalledPlugin;\ntype PluginGetSettingsResult = PluginSettingsResponse;\ntype PluginInstallResult = InstalledPlugin;\ntype PluginListResult = PluginListResponse;\ntype PluginReloadResult = PluginReloadResponse;\ntype PluginRemoveResult = PluginRemoveResponse;\ntype PluginTokenResult = PluginTokenResponse;\ntype PluginUpdateSettingsResult = PluginSettingsResponse;\ntype PluginGetSourceResult = PluginSourceDetail;\ntype PluginCheckUpdatesResult = PluginUpdateCheckEntry[];\ntype PluginApplyUpdateResult = PluginApplyUpdateResult$1;\ntype PluginCatalogStatusResult = PluginCatalogStatus;\ntype PluginCatalogSearchResult = PluginCatalogSearchResult$1[];\ntype PluginCatalogInstallPlanResult = PluginCatalogInstallPlan;\ntype PluginMarketplaceListResult = PluginMarketplace[];\ntype PluginMarketplaceAddResult = PluginMarketplace;\ntype PluginMarketplaceRefreshResult = PluginMarketplaceRefreshResult$1[];\ninterface PluginMarketplaceRemoveResult {\n /** Installs whose provenance became `direct`; they keep running as before. */\n convertedPluginIds: string[];\n}\ninterface PluginCatalogArea {\n install(args: PluginCatalogInstallArgs): Promise;\n /** The true resolved source an install would use, before anything runs. */\n installPlan(args: PluginCatalogInstallPlanArgs): Promise;\n search(args: PluginCatalogSearchArgs): Promise;\n status(args?: PluginCatalogStatusArgs): Promise;\n}\n/** Registered marketplaces. Adding one installs nothing; removing one uninstalls nothing. */\ninterface PluginMarketplacesArea {\n add(args: PluginMarketplaceAddArgs): Promise;\n list(args?: PluginMarketplaceListArgs): Promise;\n refresh(args?: PluginMarketplaceRefreshArgs): Promise;\n remove(args: PluginMarketplaceRemoveArgs): Promise;\n}\ninterface PluginsArea {\n applyUpdate(args: PluginIdArgs): Promise;\n callRpc(args: PluginRpcArgs): Promise;\n checkUpdates(args?: PluginCheckUpdatesArgs): Promise;\n catalog: PluginCatalogArea;\n marketplaces: PluginMarketplacesArea;\n disable(args: PluginIdArgs): Promise;\n enable(args: PluginIdArgs): Promise;\n getSettings(args: PluginGetSettingsArgs): Promise;\n getSource(args: PluginGetSourceArgs): Promise;\n install(args: PluginInstallArgs): Promise;\n list(args?: PluginListArgs): Promise;\n listUpdateResults(args?: PluginListUpdateResultsArgs): Promise;\n reload(args?: PluginReloadArgs): Promise;\n remove(args: PluginIdArgs): Promise;\n token(args: PluginTokenArgs): Promise;\n updateSettings(args: PluginSettingsUpdateArgs): Promise;\n}\n\ntype BbRealtimeUnsubscribe = () => void;\ntype BbRealtimeEventName = \"environment:changed\" | \"host:changed\" | \"project:changed\" | \"realtime:connection\" | \"system:changed\" | \"system:config-changed\" | \"thread:changed\";\ntype ThreadRealtimeEvent = Extract;\ntype ProjectRealtimeEvent = Extract;\ntype EnvironmentRealtimeEvent = Extract;\ntype HostRealtimeEvent = Extract;\ntype SystemRealtimeEvent = Extract;\ntype BbRealtimeConnectionState = \"connected\" | \"connecting\" | \"disconnected\";\ninterface BbRealtimeConnectionEvent {\n reconnectDelayMs: number | null;\n reconnected: boolean;\n state: BbRealtimeConnectionState;\n}\n/**\n * Entity-changed events are delivered as one shared object to every matching\n * listener; their payload types are readonly so a listener cannot mutate what\n * the next listener receives.\n */\ninterface BbRealtimeEventMap {\n \"thread:changed\": ThreadRealtimeEvent;\n \"project:changed\": ProjectRealtimeEvent;\n \"environment:changed\": EnvironmentRealtimeEvent;\n \"host:changed\": HostRealtimeEvent;\n \"system:changed\": SystemRealtimeEvent;\n \"system:config-changed\": SystemRealtimeEvent;\n \"realtime:connection\": BbRealtimeConnectionEvent;\n}\ntype BbRealtimeCallback = (event: BbRealtimeEventMap[TEventName]) => void;\ninterface ThreadRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"thread:changed\">;\n event: \"thread:changed\";\n threadId?: string;\n}\ninterface ProjectRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"project:changed\">;\n event: \"project:changed\";\n projectId?: string;\n}\ninterface EnvironmentRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"environment:changed\">;\n environmentId?: string;\n event: \"environment:changed\";\n}\ninterface HostRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"host:changed\">;\n event: \"host:changed\";\n hostId?: string;\n}\ninterface SystemRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"system:changed\">;\n event: \"system:changed\";\n}\ninterface SystemConfigRealtimeSubscribeArgs {\n callback: BbRealtimeCallback<\"system:config-changed\">;\n event: \"system:config-changed\";\n}\n/**\n * Connection listeners are pure observers — they never open or hold the\n * socket. A listener registered while a socket already exists receives the\n * latest connection event as a snapshot on the next microtask, so a status\n * UI mounted after connect still learns the current state.\n */\ninterface RealtimeConnectionSubscribeArgs {\n callback: BbRealtimeCallback<\"realtime:connection\">;\n event: \"realtime:connection\";\n}\ntype BbRealtimeSubscribeArgsUnion = ThreadRealtimeSubscribeArgs | ProjectRealtimeSubscribeArgs | EnvironmentRealtimeSubscribeArgs | HostRealtimeSubscribeArgs | SystemRealtimeSubscribeArgs | SystemConfigRealtimeSubscribeArgs | RealtimeConnectionSubscribeArgs;\ntype BbRealtimeSubscribeArgs = Extract;\ninterface BbRealtime {\n subscribe(args: BbRealtimeSubscribeArgs): BbRealtimeUnsubscribe;\n}\n\ninterface StatusGetArgs {\n projectId?: string;\n signal?: AbortSignal;\n threadId?: string;\n}\ninterface StatusThreadSummary {\n environmentId: string | null;\n id: string;\n parentThreadId: string | null;\n pinnedAt: number | null;\n projectId: string;\n status: ThreadStatus;\n title: string | null;\n}\ntype StatusProject = ProjectResponse;\ntype StatusChildThreads = ThreadListResponse;\ninterface StatusResult {\n childThreads: StatusChildThreads | null;\n pendingTodos: ThreadTimelinePendingTodos | null;\n project: StatusProject | null;\n thread: StatusThreadSummary | null;\n}\ninterface StatusArea {\n get(args?: StatusGetArgs): Promise;\n}\n\ninterface SkillWorkspaceArgs {\n projectId: string;\n environmentId: string | null;\n}\ninterface SkillListArgs extends SkillWorkspaceArgs {\n signal?: AbortSignal;\n}\ninterface SkillIdentityArgs extends SkillListArgs {\n skillId: string;\n}\ninterface SkillContentArgs extends SkillIdentityArgs {\n path: string;\n}\ninterface SkillUpdateArgs extends SkillWorkspaceArgs {\n skillId: string;\n content: string;\n revision: string;\n}\ninterface SkillDeleteArgs extends SkillWorkspaceArgs {\n skillId: string;\n}\n/**\n * Registry calls proxy out to skills.sh and GitHub, and the browse grid fans\n * out one per card. Callers pass their query's AbortSignal so abandoning a\n * page cancels its requests instead of leaving them in flight.\n */\ninterface AbortableArgs {\n signal?: AbortSignal;\n}\ninterface RegistrySkillsSearchArgs extends AbortableArgs {\n query?: string;\n page?: number;\n perPage?: number;\n}\ninterface RegistrySkillIdArgs extends AbortableArgs {\n registrySkillId: string;\n}\ninterface RegistrySkillEntriesArgs extends AbortableArgs {\n registrySkillIds: readonly string[];\n}\ninterface RegistrySkillSourceArgs extends AbortableArgs {\n source: string;\n skillId: string;\n}\ninterface RegistryRepositoryArgs extends AbortableArgs {\n source: string;\n}\n/**\n * Install is a mutation and deliberately takes no signal: its body is parsed\n * with a strict schema, so an extra key would throw at runtime.\n */\ninterface RegistrySkillInstallArgs {\n registrySkillId: string;\n}\ninterface SkillsRegistryArea {\n detail(args: RegistrySkillSourceArgs): Promise;\n entries(args: RegistrySkillEntriesArgs): Promise;\n get(args: RegistrySkillIdArgs): Promise;\n install(args: RegistrySkillInstallArgs): Promise;\n repositoryStars(args: RegistryRepositoryArgs): Promise;\n search(args?: RegistrySkillsSearchArgs): Promise;\n}\ninterface SkillsArea {\n getContent(args: SkillContentArgs): Promise;\n list(args: SkillListArgs): Promise;\n listFiles(args: SkillIdentityArgs): Promise;\n registry: SkillsRegistryArea;\n remove(args: SkillDeleteArgs): Promise<{\n deletedPath: string;\n }>;\n update(args: SkillUpdateArgs): Promise<{\n filePath: string;\n revision: string;\n }>;\n}\n\ntype ThemeGetResult = AppTheme;\ntype ThemeCatalogResult = ThemeCatalogResponse;\ntype ThemeSetInput = AppThemeSelection;\ntype ThemeSetResult = AppTheme;\ninterface ThemeCatalogArgs {\n signal?: AbortSignal;\n}\ninterface ThemeGetArgs {\n signal?: AbortSignal;\n}\ninterface ThemeArea {\n /** The active app palette, resolved server-side (built-in id or custom CSS). */\n get(args?: ThemeGetArgs): Promise;\n /** The custom-theme directory plus discovered themes and the active palette. */\n catalog(args?: ThemeCatalogArgs): Promise;\n /** Set the complete app appearance selection in one request. */\n set(selection: ThemeSetInput): Promise;\n /**\n * Activate a palette by id while preserving the active favicon color. This\n * compatibility shorthand reads the active appearance before writing the\n * complete selection; prefer the object form when both values are known.\n */\n set(themeId: string): Promise;\n}\n\ninterface SystemAttentionArgs {\n signal?: AbortSignal;\n}\ninterface SystemConfigArgs {\n signal?: AbortSignal;\n}\ninterface SystemExecutionOptionsArgs extends SystemExecutionOptionsQuery {\n signal?: AbortSignal;\n}\ninterface SystemUsageLimitsArgs extends SystemUsageLimitsQuery {\n signal?: AbortSignal;\n}\ninterface SystemVersionArgs {\n force?: boolean;\n signal?: AbortSignal;\n}\ninterface SystemVoiceTranscriptionArgs {\n file: Blob;\n prompt?: string;\n signal?: AbortSignal;\n}\ntype SystemAttentionResult = SystemAttentionResponse;\ntype SystemConfigResult = SystemConfigResponse;\ntype SystemExecutionOptionsResult = SystemExecutionOptionsResponse;\ntype SystemReloadConfigResult = SystemConfigReloadResponse;\ntype SystemInstallCliSkillsArgs = SystemInstallCliSkillsRequest;\ninterface SystemCliSkillsStatusArgs {\n /** Omit for every enrolled machine. */\n hostIds?: readonly string[];\n signal?: AbortSignal;\n}\ntype SystemCliSkillsStatusResult = SystemCliSkillsStatusResponse;\ntype SystemInstallCliSkillsResult = SystemInstallCliSkillsResponse;\ntype SystemVoiceTranscriptionResult = SystemVoiceTranscriptionResponse;\ntype SystemUpdateExperimentsResult = Experiments;\ntype SystemUpdateGeneralSettingsResult = AppSettings;\ntype SystemUpdateKeyboardSettingsResult = AppKeybindingOverrides;\ntype SystemUsageLimitsResult = ProviderUsageResponse;\ninterface SystemOnboardingArgs extends SystemProvidersQuery {\n signal?: AbortSignal;\n}\ninterface SystemOnboardingReposArgs extends SystemOnboardingReposQuery {\n signal?: AbortSignal;\n}\ntype SystemOnboardingAgentsResult = OnboardingAgentOverview;\ntype SystemOnboardingReposResult = DiscoverReposResult;\ntype SystemVersionResult = SystemVersionResponse;\ninterface SystemArea {\n attention(args?: SystemAttentionArgs): Promise;\n config(args?: SystemConfigArgs): Promise;\n executionOptions(args?: SystemExecutionOptionsArgs): Promise;\n /**\n * Copy bb's built-in CLI skills into each named machine's global agent skill\n * roots (`~/.agents/skills` and `~/.claude/skills`). Machines install\n * independently; the result reports each machine's outcome.\n */\n /** Per-machine install state of bb's built-in CLI skills. */\n cliSkillsStatus(args?: SystemCliSkillsStatusArgs): Promise;\n installCliSkills(args: SystemInstallCliSkillsArgs): Promise;\n reloadConfig(): Promise;\n transcribeVoice(args: SystemVoiceTranscriptionArgs): Promise;\n updateExperiments(args: Experiments): Promise;\n updateGeneralSettings(args: AppSettings): Promise;\n updateKeyboardSettings(args: AppKeybindingOverrides): Promise;\n /** Report one onboarding funnel event to anonymous telemetry. */\n onboardingEvent(args: OnboardingTelemetryEvent): Promise<{\n ok: true;\n }>;\n /** Live agent state for onboarding: install, auth, and plan per provider. */\n onboardingAgents(args?: SystemOnboardingArgs): Promise;\n /** Candidate projects discovered on the host, ranked for onboarding. */\n onboardingRepos(args?: SystemOnboardingReposArgs): Promise;\n usageLimits(args?: SystemUsageLimitsArgs): Promise;\n version(args?: SystemVersionArgs): Promise;\n}\n\ninterface TerminalThreadScope {\n cwd?: never;\n environmentId?: never;\n hostId?: never;\n kind: \"thread\";\n threadId: string;\n}\ninterface TerminalEnvironmentScope {\n environmentId: string;\n cwd?: never;\n hostId?: never;\n kind: \"environment\";\n threadId?: never;\n}\ninterface TerminalHostPathListScope {\n /** Optional exact initial working-directory filter on the selected host. */\n cwd?: string;\n environmentId?: never;\n hostId: string;\n kind: \"host_path\";\n threadId?: never;\n}\ninterface TerminalHostPathCreateScope {\n /** Null starts in the selected host's home directory. */\n cwd: string | null;\n environmentId?: never;\n hostId: string;\n kind: \"host_path\";\n threadId?: never;\n}\ntype TerminalListScope = TerminalThreadScope | TerminalEnvironmentScope | TerminalHostPathListScope;\ntype TerminalCreateScope = TerminalThreadScope | TerminalEnvironmentScope | TerminalHostPathCreateScope;\ninterface TerminalListArgs {\n signal?: AbortSignal;\n scope: TerminalListScope;\n}\ninterface TerminalCreateArgs {\n cols: number;\n rows: number;\n scope: TerminalCreateScope;\n start?: CreateTerminalRequest[\"start\"];\n title?: string;\n}\ninterface TerminalTargetArgs {\n terminalId: string;\n}\ninterface TerminalGetArgs extends TerminalTargetArgs {\n signal?: AbortSignal;\n}\ninterface TerminalRenameArgs extends TerminalTargetArgs {\n title: UpdateTerminalRequest[\"title\"];\n}\ninterface TerminalCloseArgs extends TerminalTargetArgs {\n mode: \"force\" | \"if-clean\";\n}\ninterface TerminalInputArgs extends TerminalTargetArgs {\n dataBase64: TerminalInputRequest[\"dataBase64\"];\n}\ninterface TerminalResizeArgs extends TerminalTargetArgs {\n cols: TerminalResizeRequest[\"cols\"];\n rows: TerminalResizeRequest[\"rows\"];\n}\ninterface TerminalOutputArgs extends TerminalTargetArgs {\n limitChunks?: TerminalOutputQuery[\"limitChunks\"];\n signal?: AbortSignal;\n sinceSeq?: TerminalOutputQuery[\"sinceSeq\"];\n tailBytes?: TerminalOutputQuery[\"tailBytes\"];\n}\ntype TerminalRestartArgs = TerminalTargetArgs;\ntype TerminalListResult = TerminalListResponse;\ntype TerminalCreateResult = TerminalSession;\ntype TerminalGetResult = TerminalSession;\ntype TerminalRenameResult = TerminalSession;\ntype TerminalCloseResult = TerminalSession;\ntype TerminalInputResult = TerminalSession;\ntype TerminalResizeResult = TerminalSession;\ntype TerminalOutputResult = TerminalOutputResponse;\ntype TerminalRestartResult = TerminalSession;\ninterface TerminalsArea {\n close(args: TerminalCloseArgs): Promise;\n create(args: TerminalCreateArgs): Promise;\n get(args: TerminalGetArgs): Promise;\n input(args: TerminalInputArgs): Promise;\n list(args: TerminalListArgs): Promise;\n output(args: TerminalOutputArgs): Promise;\n rename(args: TerminalRenameArgs): Promise;\n /**\n * Replace a terminal with a shell at the same scope, size, and title.\n * The server serializes concurrent restarts and opens the replacement before\n * closing the old session, so a failed open leaves the old terminal running.\n * The original command is not replayed because terminal sessions do not\n * persist launch commands. The replacement has a new terminal ID.\n */\n restart(args: TerminalRestartArgs): Promise;\n resize(args: TerminalResizeArgs): Promise;\n}\n\ninterface ThreadListArgs {\n archived?: boolean;\n sectionId?: string;\n hasParent?: boolean;\n includeHidden?: boolean;\n limit?: number;\n offset?: number;\n originKind?: ThreadListQuery[\"originKind\"];\n originPluginId?: string;\n parentThreadId?: string;\n projectId?: string;\n signal?: AbortSignal;\n sourceThreadId?: string;\n unsectioned?: boolean;\n}\ninterface ThreadSearchArgs extends ThreadSearchQuery {\n signal?: AbortSignal;\n}\ninterface ThreadResolveMentionsArgs extends ResolveThreadMentionsRequest {\n signal?: AbortSignal;\n}\ninterface ThreadGetArgs {\n include?: ThreadGetQuery[\"include\"];\n signal?: AbortSignal;\n threadId: string;\n}\ntype ThreadGetResult = ThreadResponse | ThreadWithIncludesResponse;\ntype ThreadListResult = ThreadListResponse;\ntype ThreadSearchResult = ThreadSearchResponse;\ntype ThreadResolveMentionsResult = ResolveThreadMentionsResponse;\ninterface ThreadOutputResponse {\n output: string | null;\n}\ntype ThreadMutationResult = ThreadResponse;\ntype ThreadSpawnResult = ThreadResponse;\ntype ThreadForkResult = ThreadResponse;\ntype ThreadInteractionGetResult = PendingInteraction;\ntype ThreadInteractionListResult = ThreadPendingInteractionsResponse;\ntype ThreadInteractionResolveResult = PendingInteraction;\ntype ThreadInteractionRespondResult = PendingInteraction;\ntype ThreadInteractionCancelResult = PendingInteraction;\ntype ThreadEventsListResult = ThreadEventRow[];\ntype ThreadEventWaitResult = ThreadEventRow | null;\ntype ThreadTimelineResult = ThreadTimelineResponse;\ntype ThreadArchiveResult = ThreadArchiveAllResponse;\ntype ThreadOpenResult = ThreadOpenResponse;\ntype ThreadPaneActionResult = ThreadPaneActionResponse;\ntype ThreadDeleteResult = {\n ok: true;\n};\ntype ThreadSendResult = {\n ok: true;\n};\ntype ThreadEditMessageResult = EditMessageResponse;\ntype ThreadStopResult = {\n ok: true;\n};\ntype ThreadCompactResult = {\n ok: true;\n};\ntype ThreadBannerActionResult = {\n ok: true;\n};\ntype ThreadUnarchiveResult = {\n ok: true;\n};\ntype ThreadArchiveAllResult = ThreadArchiveAllResponse;\ntype ThreadReadStateResult = ThreadResponse;\ntype ThreadPinOrderResult = ThreadListResponse;\ntype ThreadPromptHistoryResult = PromptHistoryResponse;\ntype ThreadQueuedMessagesResult = ThreadQueuedMessageListResponse;\ntype ThreadQueuedMessageCreateResult = ThreadQueuedMessage;\ntype ThreadQueuedMessageUpdateResult = ThreadQueuedMessage;\ntype ThreadQueuedMessageDeleteResult = {\n ok: true;\n};\ntype ThreadQueuedMessageReorderResult = ThreadQueuedMessageListResponse;\ntype ThreadQueuedMessageSendResult = SendQueuedMessageResponse;\ntype ThreadQueuedMessageGroupBoundaryResult = ThreadQueuedMessageListResponse;\ntype ThreadTabsResult = ThreadTabsResponse;\ntype ThreadTabsUpdateResult = ThreadTabsResponse;\ntype ThreadStorageFilesResult = ThreadStorageFileListResponse;\ntype ThreadStoragePathsResult = ThreadStoragePathListResponse;\ntype ThreadChildSummaryResult = ThreadChildSummaryResponse;\ntype ThreadDefaultExecutionOptionsResult = ResolvedThreadExecutionOptions | null;\ntype ThreadConversationOutlineResult = ThreadConversationOutlineResponse;\ntype ThreadTimelineTurnSummaryDetailsResult = TimelineTurnSummaryDetailsResponse;\ninterface ThreadSpawnBaseArgs extends Omit {\n origin?: CreateThreadRequest[\"origin\"];\n originKind?: CreateThreadRequest[\"originKind\"];\n startedOnBehalfOf?: CreateThreadRequest[\"startedOnBehalfOf\"];\n}\ntype ThreadSpawnArgs = ThreadSpawnBaseArgs & ({\n input: CreateThreadRequest[\"input\"];\n prompt?: never;\n} | {\n input?: never;\n prompt: string;\n});\ninterface ThreadForkArgs extends Omit {\n origin?: ForkThreadRequest[\"origin\"];\n visibility?: ForkThreadRequest[\"visibility\"];\n workspace?: ForkThreadRequest[\"workspace\"];\n}\ninterface ThreadUpdateArgs extends UpdateThreadRequest {\n threadId: string;\n}\ninterface ThreadDeleteArgs extends DeleteThreadRequest {\n threadId: string;\n}\ninterface ThreadSendArgs extends SendMessageRequest {\n threadId: string;\n}\ninterface ThreadEditMessageArgs extends EditMessageRequest {\n threadId: string;\n}\ninterface ThreadActionArgs {\n threadId: string;\n}\ninterface ThreadStatusArgs extends ThreadActionArgs {\n signal?: AbortSignal;\n}\ninterface ThreadPromptHistoryArgs extends PromptHistoryQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadPinOrderArgs extends ReorderPinnedThreadRequest {\n threadId: string;\n}\ninterface ThreadQueuedMessageArgs {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadQueuedMessageCreateArgs extends CreateQueuedMessageRequest {\n threadId: string;\n}\ninterface ThreadQueuedMessageUpdateArgs extends ThreadQueuedMessageTargetArgs, UpdateQueuedMessageRequest {\n}\ninterface ThreadQueuedMessageTargetArgs {\n queuedMessageId: string;\n threadId: string;\n}\ninterface ThreadQueuedMessageSendArgs extends ThreadQueuedMessageTargetArgs, SendQueuedMessageRequest {\n}\ninterface ThreadQueuedMessageReorderArgs extends ThreadQueuedMessageTargetArgs, ReorderQueuedMessageRequest {\n}\ninterface ThreadQueuedMessageGroupBoundaryArgs extends SetQueuedMessageGroupBoundaryRequest {\n threadId: string;\n}\ninterface ThreadStorageFilesArgs extends ThreadStorageFilesQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadStoragePathsArgs extends ThreadStoragePathsQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadTimelineTurnSummaryDetailsArgs extends TimelineTurnSummaryDetailsQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadTabsUpdateArgs extends UpdateThreadTabsRequest {\n threadId: string;\n}\ninterface ThreadOpenArgs {\n threadId: string;\n split?: ThreadOpenSplit;\n file: ThreadOpenFile | null;\n}\ninterface ThreadPaneActionArgs {\n action: ThreadPaneAction;\n threadId: string;\n}\ninterface ThreadEventsListArgs {\n /** Return only events with a sequence greater than this value. */\n afterSeq?: string;\n /** Return only events with a sequence less than this value. */\n beforeSeq?: string;\n limit?: string;\n /** Defaults to ascending sequence order. */\n order?: \"asc\" | \"desc\";\n signal?: AbortSignal;\n threadId: string;\n /** Return only these event types. */\n types?: readonly [ThreadEventType, ...ThreadEventType[]];\n}\ninterface ThreadEventWaitArgs {\n afterSeq?: string;\n signal?: AbortSignal;\n threadId: string;\n type: string;\n waitMs: string;\n}\ninterface ThreadTimelineArgs extends ThreadTimelineQuery {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadOutputArgs {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadInteractionListArgs {\n signal?: AbortSignal;\n threadId: string;\n}\ninterface ThreadInteractionTargetArgs {\n interactionId: string;\n threadId: string;\n}\ninterface ThreadInteractionGetArgs extends ThreadInteractionTargetArgs {\n signal?: AbortSignal;\n}\ninterface ThreadInteractionResolveArgs extends ThreadInteractionTargetArgs {\n resolution: PendingInteractionResolution;\n}\ninterface ThreadInteractionRespondArgs extends ThreadInteractionTargetArgs {\n value: JsonValue$1;\n}\ntype ThreadWaitTarget = {\n kind: \"status\";\n status: ThreadStatus;\n} | {\n kind: \"event\";\n eventType: string;\n};\ninterface ThreadWaitArgs {\n event?: string;\n pollIntervalMs?: number;\n signal?: AbortSignal;\n status?: ThreadStatus;\n threadId: string;\n timeoutMs?: number;\n}\ntype ThreadWaitResult = {\n event: NonNullable;\n matched: true;\n target: Extract;\n threadId: string;\n} | {\n matched: true;\n target: Extract;\n thread: ThreadGetResult;\n threadId: string;\n};\ninterface ThreadInteractionsArea {\n cancel(args: ThreadInteractionTargetArgs): Promise;\n get(args: ThreadInteractionGetArgs): Promise;\n list(args: ThreadInteractionListArgs): Promise;\n resolve(args: ThreadInteractionResolveArgs): Promise;\n respond(args: ThreadInteractionRespondArgs): Promise;\n}\ninterface ThreadEventsArea {\n list(args: ThreadEventsListArgs): Promise;\n wait(args: ThreadEventWaitArgs): Promise;\n}\ninterface ThreadQueuedMessagesArea {\n create(args: ThreadQueuedMessageCreateArgs): Promise;\n delete(args: ThreadQueuedMessageTargetArgs): Promise;\n list(args: ThreadQueuedMessageArgs): Promise;\n reorder(args: ThreadQueuedMessageReorderArgs): Promise;\n send(args: ThreadQueuedMessageSendArgs): Promise;\n setGroupBoundary(args: ThreadQueuedMessageGroupBoundaryArgs): Promise;\n update(args: ThreadQueuedMessageUpdateArgs): Promise;\n}\ninterface ThreadTabsArea {\n get(args: ThreadStatusArgs): Promise;\n update(args: ThreadTabsUpdateArgs): Promise;\n}\ninterface ThreadsArea {\n archive(args: ThreadActionArgs): Promise;\n archiveAll(args: ThreadActionArgs): Promise;\n childSummary(args: ThreadStatusArgs): Promise;\n compact(args: ThreadActionArgs): Promise;\n cancelPlan(args: ThreadActionArgs): Promise;\n clearGoal(args: ThreadActionArgs): Promise;\n conversationOutline(args: ThreadStatusArgs): Promise;\n defaultExecutionOptions(args: ThreadStatusArgs): Promise;\n delete(args: ThreadDeleteArgs): Promise;\n editMessage(args: ThreadEditMessageArgs): Promise;\n events: ThreadEventsArea;\n fork(args: ThreadForkArgs): Promise;\n get(args: ThreadGetArgs): Promise;\n interactions: ThreadInteractionsArea;\n list(args?: ThreadListArgs): Promise;\n markRead(args: ThreadActionArgs): Promise;\n markUnread(args: ThreadActionArgs): Promise;\n open(args: ThreadOpenArgs): Promise;\n paneAction(args: ThreadPaneActionArgs): Promise;\n output(args: ThreadOutputArgs): Promise;\n pin(args: ThreadActionArgs): Promise;\n promptHistory(args: ThreadPromptHistoryArgs): Promise;\n queuedMessages: ThreadQueuedMessagesArea;\n reorderPinned(args: ThreadPinOrderArgs): Promise;\n resolveMentions(args: ThreadResolveMentionsArgs): Promise;\n search(args: ThreadSearchArgs): Promise;\n send(args: ThreadSendArgs): Promise;\n spawn(args: ThreadSpawnArgs): Promise;\n /**\n * Stop active work and release the loaded agent runtime. This operation is\n * idempotent and preserves thread history for a later resume.\n */\n stop(args: ThreadActionArgs): Promise;\n tabs: ThreadTabsArea;\n timeline(args: ThreadTimelineArgs): Promise;\n timelineTurnSummaryDetails(args: ThreadTimelineTurnSummaryDetailsArgs): Promise;\n storageFiles(args: ThreadStorageFilesArgs): Promise;\n storagePaths(args: ThreadStoragePathsArgs): Promise;\n unarchive(args: ThreadActionArgs): Promise;\n unpin(args: ThreadActionArgs): Promise;\n update(args: ThreadUpdateArgs): Promise;\n wait(args: ThreadWaitArgs): Promise;\n}\n\ntype ThreadSectionCreateResult = ThreadSectionResponse;\ntype ThreadSectionUpdateResult = ThreadSectionMutationResponse;\ntype ThreadSectionDeleteResult = ThreadSectionMutationResponse;\ntype ThreadSectionListResult = ThreadSectionResponse[];\ninterface ThreadSectionListArgs {\n signal?: AbortSignal;\n}\ninterface ThreadSectionsArea {\n create(args: CreateThreadSectionRequest): Promise;\n delete(args: DeleteThreadSectionRequest): Promise;\n list(args?: ThreadSectionListArgs): Promise;\n update(args: UpdateThreadSectionRequest): Promise;\n}\n\n/**\n * Every server-backed SDK area. The Node SDK adds the local `guide` area on\n * top of this; the browser SDK omits it so the generated guide templates\n * (~112 KB of markdown) stay out of the web app's boot chunk.\n */\ninterface BbSdkAreas extends BbRealtime {\n environments: EnvironmentsArea;\n files: FilesArea;\n hosts: HostsArea;\n projects: ProjectsArea;\n plugins: PluginsArea;\n providers: ProvidersArea;\n skills: SkillsArea;\n status: StatusArea;\n system: SystemArea;\n terminals: TerminalsArea;\n theme: ThemeArea;\n threadSections: ThreadSectionsArea;\n threads: ThreadsArea;\n}\ninterface BbSdk extends BbSdkAreas {\n guide: GuideArea;\n}\n\ninterface ExperimentalHostSignalContract {\n readonly payload: PayloadSchema;\n}\ntype ExperimentalHostSignals = Readonly>;\ninterface ExperimentalHostCallOptions {\n readonly hostId: string;\n readonly signal?: AbortSignal;\n}\ninterface ExperimentalHostClient {\n call(method: MethodName, input: StandardSchemaV1InferInput, options: ExperimentalHostCallOptions): Promise>;\n /**\n * Subscribe to unexpected exits of this plugin's worker on a host daemon.\n * Graceful reload, disable, uninstall, and daemon shutdown do not emit this\n * event. A later call starts a fresh worker.\n */\n experimental_onWorkerExit(handler: (event: {\n readonly hostId: string;\n }) => void | Promise): () => void;\n /** Subscribe to a validated, ephemeral signal from this plugin's host entry. */\n experimental_onSignal(signal: SignalName, handler: (event: ExperimentalHostSignalEvent) => void | Promise): () => void;\n}\ninterface ExperimentalHostSignalEvent {\n readonly hostId: string;\n readonly payload: StandardSchemaV1InferOutput;\n}\ninterface ExperimentalHostPaths {\n /** Persistent directory scoped to this plugin on this daemon. */\n readonly dataDir: string;\n /** Temporary directory scoped to this worker process. */\n readonly tempDir: string;\n}\ntype ExperimentalHostWatchChangeType = \"create\" | \"delete\" | \"update\";\ninterface ExperimentalHostWatchChange {\n readonly path: string;\n readonly type: ExperimentalHostWatchChangeType;\n}\ntype ExperimentalHostWatchEvent = {\n readonly kind: \"changed\";\n readonly changes: readonly ExperimentalHostWatchChange[];\n} | {\n readonly kind: \"rescan-required\";\n} | {\n readonly kind: \"watch-error\";\n readonly message: string;\n};\ninterface ExperimentalHostWatchOptions {\n /** Absolute directory observed by the daemon's native watcher service. */\n readonly rootPath: string;\n /** Root-relative ignore entries using the native watcher syntax. */\n readonly ignoredPaths?: readonly string[];\n /** Quiet period before one coalesced delivery. Defaults to 75 ms. */\n readonly debounceMs?: number;\n /** Maximum time changes may wait. Defaults to 500 ms. */\n readonly maxWaitMs?: number;\n}\ninterface ExperimentalHostWatchSubscription {\n dispose(): Promise;\n}\ninterface ExperimentalHostWorkerLease {\n /** Release this worker-retention lease. Safe to call more than once. */\n dispose(): Promise;\n}\ntype ExperimentalHostWatchListener = (event: ExperimentalHostWatchEvent) => void | Promise;\ninterface ExperimentalHostRpcContext {\n /** Aborted when this request is cancelled or its worker is disposed. */\n readonly signal: AbortSignal;\n /** Aborted once for the lifetime of this worker process. */\n readonly lifecycle: {\n readonly signal: AbortSignal;\n };\n readonly experimental_paths: ExperimentalHostPaths;\n /** Publish a validated, ephemeral event to this plugin's server entry. */\n experimental_emitSignal(signal: SignalName, payload: StandardSchemaV1InferInput): Promise;\n /** Observe raw filesystem changes through the daemon's native watcher. */\n experimental_watch(options: ExperimentalHostWatchOptions, listener: ExperimentalHostWatchListener): Promise;\n /**\n * Keep this worker alive after the current call finishes. Active calls and\n * filesystem watches already retain it; use this only for other background\n * work. The daemon may stop an unretained worker after an idle period.\n */\n experimental_retainWorker(): ExperimentalHostWorkerLease;\n}\ntype ExperimentalHostRpcHandlers = {\n [MethodName in keyof Contract]: (input: StandardSchemaV1InferOutput, context: ExperimentalHostRpcContext) => StandardSchemaV1InferInput | Promise>;\n};\ninterface ExperimentalHostEntry {\n readonly experimental_apiVersion: 1;\n readonly contract: Contract;\n readonly experimental_signals?: Signals;\n readonly handlers: ExperimentalHostRpcHandlers;\n readonly dispose?: () => void | Promise;\n}\n/** Define the single host executable exported by `bb.host`. */\ndeclare function experimental_defineHostEntry(args: {\n contract: Contract;\n experimental_signals?: Signals;\n handlers: ExperimentalHostRpcHandlers;\n dispose?: () => void | Promise;\n}): ExperimentalHostEntry;\n\n/**\n * The backend plugin API contract — the `bb` object handed to a plugin's\n * `server.ts` factory (`export default function plugin(bb: BbPluginApi)`).\n *\n * Types only: the implementation lives in the BB server\n * (apps/server/src/services/plugins/plugin-api.ts), which imports these\n * shapes so the contract and the implementation cannot drift. Plugin authors\n * import them type-only (`import type { BbPluginApi } from\n * \"@get-bb/plugin-sdk\"`); the import is erased when BB loads the file.\n *\n * Runtime classes stay host-side. NeedsConfigurationError in particular is\n * matched by NAME, so plugin code needs no runtime import:\n * `throw Object.assign(new Error(msg), { name: \"NeedsConfigurationError\" })`.\n */\ninterface PluginLogger {\n debug(message: string): void;\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n/**\n * Declarative settings descriptors (`bb.settings.define`). Deliberately plain\n * data — not zod — so the host can render settings forms and the CLI can\n * parse values without executing plugin code.\n */\ntype PluginSettingDescriptor = {\n type: \"string\";\n label: string;\n description?: string;\n /** Stored in a 0600 file under /plugins//secrets/, never in the db or sent to the frontend. */\n secret?: true;\n default?: string;\n} | {\n type: \"boolean\";\n label: string;\n description?: string;\n default?: boolean;\n} | {\n type: \"select\";\n label: string;\n description?: string;\n options: string[];\n default?: string;\n} | {\n type: \"project\";\n label: string;\n description?: string;\n default?: string;\n};\ntype PluginSettingDescriptors = Record;\ntype PluginSettingValue = string | boolean;\n/** `default` present → non-optional value; absent → `T | undefined`. */\ntype PluginSettingsValues> = {\n [K in keyof Ds]: Ds[K] extends {\n default: string | boolean;\n } ? PluginSettingValueOf : PluginSettingValueOf | undefined;\n};\ntype PluginSettingValueOf = D extends {\n type: \"boolean\";\n} ? boolean : string;\ninterface PluginSettingsHandle> {\n /** Load-safe: callable inside the factory. */\n get(): Promise>;\n /** Fires after values change through the settings route/CLI. */\n onChange(listener: (next: PluginSettingsValues, prev: PluginSettingsValues) => void): void;\n}\ninterface PluginSettings {\n define>(descriptors: Ds): PluginSettingsHandle;\n}\ninterface PluginKvStorage {\n get(key: string): Promise;\n set(key: string, value: unknown): Promise;\n delete(key: string): Promise;\n list(prefix?: string): Promise;\n}\ninterface PluginStorage {\n /** Namespaced JSON key-value rows in bb.db; values ≤256KB each. */\n kv: PluginKvStorage;\n /**\n * Open (or reuse the path of) the plugin's own SQLite database at\n * /plugins//data.db — the server's better-sqlite3, WAL mode,\n * busy_timeout 5000. Handles are host-tracked and closed on\n * dispose/reload; a closed handle throws on use.\n */\n database(): Database.Database;\n /**\n * Ordered-statement migration helper: statement index = migration id in a\n * `_bb_migrations` table; unapplied statements run in one transaction.\n * Append-only — never reorder or edit shipped statements.\n */\n migrate(db: Database.Database, statements: string[]): void;\n}\n/**\n * Thread lifecycle events a plugin can observe (design §4.5). Observe-only:\n * handlers run fire-and-forget after the transition is applied and can never\n * block or veto it. `thread` is the same public DTO GET /threads/:id serves.\n */\ninterface PluginThreadEventPayloads {\n /** Fired after a thread row is created. */\n \"thread.created\": {\n thread: ThreadResponse;\n };\n /** Fired when a thread transitions into `active`. */\n \"thread.active\": {\n thread: ThreadResponse;\n };\n /** Fired when a thread transitions into `idle`. `lastAssistantText` is\n * assembled the same way GET /threads/:id/output is. */\n \"thread.idle\": {\n thread: ThreadResponse;\n lastAssistantText: string | null;\n };\n /** Fired when a thread transitions into `error`. `error` is the latest\n * system/error event message, when one exists. */\n \"thread.failed\": {\n thread: ThreadResponse;\n error: string | null;\n };\n /** Fired after a thread is archived (including cascade archives). */\n \"thread.archived\": {\n thread: ThreadResponse;\n };\n /** Fired after a thread is soft-deleted. */\n \"thread.deleted\": {\n thread: ThreadResponse;\n };\n}\ntype PluginThreadEventName = keyof PluginThreadEventPayloads;\ntype PluginThreadEventHandler = (payload: PluginThreadEventPayloads[E]) => void | Promise;\ntype PluginHttpAuthMode = \"local\" | \"none\" | \"token\";\ntype PluginHttpHandler = (context: Context) => Response | Promise;\ninterface PluginHttp {\n /**\n * Register an HTTP route, mounted at\n * `/api/v1/plugins//http/`. Auth modes (default \"local\"):\n * - \"local\": Origin/Host must be a local BB app origin; non-GET requires\n * content-type application/json (forces a CORS preflight).\n * - \"token\": requires the per-plugin token (`bb plugin token `) via\n * the x-bb-plugin-token header or ?token=.\n * - \"none\": no checks — only for signature-verified webhooks.\n */\n route(method: string, path: string, handler: PluginHttpHandler, opts?: {\n auth?: PluginHttpAuthMode;\n }): void;\n}\ninterface PluginRpc {\n /**\n * Register a Standard Schema-driven rpc contract and its inferred handlers,\n * served at POST\n * `/api/v1/plugins//rpc/` with \"local\" auth semantics. The\n * host validates input before invocation and output before strict JSON\n * serialization. The response is `{ ok: true, result }` or\n * `{ ok: false, error: { code, message, issues? } }`.\n */\n register(contract: Contract, handlers: PluginRpcHandlers): void;\n}\ninterface PluginRealtime {\n /**\n * Broadcast an ephemeral `plugin-signal` WS message\n * `{ pluginId, channel, payload }` to every connected client (V1 has no\n * per-channel subscriptions). `payload` must be JSON-serializable;\n * `undefined` is normalized to `null`. Nothing is persisted.\n */\n publish(channel: string, payload: unknown): void;\n}\ninterface PluginBackground {\n /**\n * Register a long-lived background service. `start` runs after the\n * factory completes and should resolve when `signal` aborts\n * (dispose/reload/disable/shutdown). A crash restarts it with capped\n * exponential backoff; throwing NeedsConfigurationError marks the plugin\n * `needs-configuration` and stops restarting until the next load.\n */\n service(name: string, service: {\n start(signal: AbortSignal): void | Promise;\n }): void;\n /**\n * Register a cron schedule (5-field expression, server-local time). The\n * durable row keyed (pluginId, name) is upserted at load; the periodic\n * sweep claims due rows with a CAS on next_run_at, but only while this\n * plugin is loaded. Failures land in last_status/last_error, visible in\n * `bb plugin list`.\n */\n schedule(name: string, cron: string, fn: () => void | Promise): void;\n}\ninterface PluginCliCommandInfo {\n name: string;\n summary: string;\n usage: string;\n}\n/** Context forwarded from the invoking CLI when known; all fields optional. */\ninterface PluginCliContext {\n cwd?: string;\n threadId?: string;\n projectId?: string;\n /** Aborted when the invoking CLI HTTP request disconnects. */\n signal?: AbortSignal;\n}\ntype PluginInteractionCancelReason = \"plugin-disposed\" | \"request-aborted\" | \"server-restarted\" | \"thread-deleted\" | \"thread-stopped\" | \"timeout\" | \"user\";\ntype PluginInteractionResult = {\n outcome: \"submitted\";\n value: JsonValue;\n} | {\n outcome: \"cancelled\";\n reason: PluginInteractionCancelReason;\n};\ninterface PluginInteractionRequest {\n threadId: string;\n rendererId: string;\n title: string;\n payload: JsonValue;\n /** Defaults to ten minutes; capped at one hour. */\n timeoutMs?: number;\n}\ninterface PluginCliResult {\n exitCode: number;\n stdout?: string;\n stderr?: string;\n}\n/**\n * Maximum combined UTF-8 bytes accepted from plugin CLI stdout and stderr.\n * This is the shared source of truth for production and the testing harness.\n */\ndeclare const PLUGIN_CLI_OUTPUT_MAX_BYTES: number;\ninterface PluginCliOutputLimitError {\n code: \"plugin_cli_output_too_large\";\n message: string;\n maxBytes: number;\n stdoutBytes: number;\n stderrBytes: number;\n totalBytes: number;\n}\n/** Normalized host result returned by the plugin CLI HTTP/testing boundary. */\ninterface PluginCliExecutionResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n error?: PluginCliOutputLimitError;\n}\ninterface PluginCliRegistration {\n /** Top-level command name (`bb …`): lowercase [a-z0-9-]+, and not\n * a core bb command (see RESERVED_BB_CLI_COMMANDS in the server). */\n name: string;\n summary: string;\n /** Subcommand metadata rendered in help and the plugin-commands skill\n * without executing plugin code. Parsing argv is plugin-owned. */\n commands?: PluginCliCommandInfo[];\n run(argv: string[], ctx: PluginCliContext): PluginCliResult | Promise;\n}\ninterface PluginCli {\n /**\n * Register this plugin's `bb` subcommand. One registration per factory\n * execution; a repeated call is rejected. Core bb commands always win\n * name collisions; reserved names are rejected at registration.\n */\n register(registration: PluginCliRegistration): void;\n}\n/** Per-turn context handed to bb.agents context providers (design §4.4). */\n/** MCP-style content parts a native tool may return (design §4.4). */\ntype PluginAgentToolContentPart = {\n type: \"text\";\n text: string;\n} | {\n type: \"image\";\n data: string;\n mimeType: string;\n};\ntype PluginAgentToolResult = string | {\n content: PluginAgentToolContentPart[];\n isError?: boolean;\n};\n/** Per-call context handed to a native tool's execute (design §4.4). */\ninterface PluginAgentToolContext {\n threadId: string;\n projectId: string;\n /** The tool-call request's abort signal (aborts if the daemon round-trip\n * is torn down mid-call). */\n signal: AbortSignal;\n}\n/**\n * Native timeline labels for a plugin tool, keyed by BB's own timeline row\n * status. This is experimental: BB may refine its presentation contract\n * before the field is stabilized.\n */\ninterface PluginAgentToolExperimentalStatusLabels {\n /** Label shown while the tool call is pending. */\n pending: string;\n /** Label shown after the tool call completes successfully. */\n completed: string;\n}\ninterface PluginAgentToolRegistrationBase {\n /** Tool name shown to the model: [a-zA-Z0-9_-]+, unique across plugins,\n * and not a built-in dynamic tool (see RESERVED_AGENT_TOOL_NAMES in the\n * server). */\n name: string;\n description: string;\n /**\n * Optional usage snippet appended to the thread instructions whenever\n * this tool is in the session's tool set (mirrors the built-in\n * update_environment_directory guidance). Limited to 4096 characters.\n */\n instructions?: string;\n /**\n * Optional native timeline labels. When omitted, BB shows the standard\n * tool name and arguments (for example, `Ran tool search_docs …`). Labels\n * apply only while the call is pending and after successful completion;\n * approval, error, and interruption states keep BB's standard rendering.\n */\n experimental_statusLabels?: PluginAgentToolExperimentalStatusLabels;\n}\n/** Stable, plain-data context resolved by the server for one agent session. */\ninterface PluginAgentConfigurationContext {\n thread: {\n id: string;\n title: string | null;\n parentThreadId: string | null;\n sourceThreadId: string | null;\n };\n project: {\n id: string;\n kind: \"personal\" | \"standard\";\n name: string;\n gitRemoteUrl: string | null;\n };\n environment: {\n id: string;\n name: string | null;\n path: string | null;\n workspaceProvisionType: \"managed-worktree\" | \"personal\" | \"unmanaged\";\n branchName: string | null;\n };\n host: {\n id: string;\n name: string;\n };\n provider: {\n id: string;\n model: string;\n /**\n * The provider's declared capabilities, so a plugin can decide what to\n * contribute from what the provider says it does rather than from its own\n * copy of a provider id list.\n */\n capabilities: {\n /**\n * The provider ships its own user-question affordance and bb routes it\n * into the pending-interaction path. A plugin offering the same thing\n * should withhold it here, or the model gets two ways to ask once.\n */\n supportsNativeUserQuestion: boolean;\n };\n };\n /** How the thread was spawned. A side chat is the builtin side-chat\n * plugin's fork: `{ kind: \"fork\", pluginId: \"side-chat\" }`. */\n origin: {\n kind: \"fork\" | null;\n pluginId: string | null;\n };\n}\n/** Object form of a {@link PluginAgentConfiguration} tools entry: selects a\n * registered tool and overrides the parameter schema advertised to the\n * provider for this resolution only. */\ninterface PluginAgentToolSelection {\n /** Name of a tool registered by this plugin via `registerTool`. */\n name: string;\n /** JSON-schema object (root `type: \"object\"`, JSON-serializable, at most\n * 128 KiB serialized) sent to the provider in place of the registered\n * parameter schema. Execution-side validation still runs the registered\n * parameters, so the override must only narrow what the registered schema\n * already accepts. Recursive local `$ref` chains are rejected. */\n parameters: Record;\n}\n/** Per-resolution selection returned by {@link PluginAgents.configure}. */\ninterface PluginAgentConfiguration {\n /** Tool names registered by this plugin, or {@link PluginAgentToolSelection}\n * entries to also override a tool's advertised parameter schema for this\n * resolution. Duplicate or unknown names, or an invalid override, reject\n * this plugin's complete selection for the resolution. */\n tools: Array;\n /** Skill frontmatter names from this plugin's manifest skill roots.\n * Duplicate or unknown names reject this plugin's complete selection. */\n skills: string[];\n /** Optional dynamic instructions. Output is truncated to 4096 characters. */\n instructions?: string;\n}\n/**\n * Permission modes a provider can run a session in — BB's own permission\n * vocabulary, ordered least (\"accept-edits\") to most (\"full\") privileged.\n */\ntype PluginProviderPermissionMode = \"accept-edits\" | \"auto\" | \"full\";\n/**\n * Coarse reasoning-effort ladder entries, ordered lowest to highest. The\n * declared ladder is a fallback only: precise per-model reasoning sets come\n * from the provider's model list at runtime.\n */\ntype PluginProviderReasoningLevel = \"high\" | \"low\" | \"max\" | \"medium\" | \"none\" | \"ultra\" | \"ultracode\" | \"xhigh\";\n/**\n * Composer actions a provider supports, by name only. The skills\n * slash-command typeahead is universal — BB injects skills into every\n * provider — so it is implicit and never declared, and the composer owns the\n * trigger syntax (`/plan `, `/goal `) rather than each declaration repeating\n * it.\n */\ntype PluginProviderComposerAction = \"goal\" | \"plan\";\n/**\n * Pre-session capability facts about a provider. A capability earns a field\n * here only when it passes BOTH tests: (1) a consumer outside the provider's\n * own plugin needs the fact, and (2) the fact is needed before / without a\n * live session (picker rendering, route gating, cross-plugin tool\n * composition — including with the host offline). Every boolean is a\n * provider-native fact — the provider implements the feature; the flag only\n * tells external consumers it exists. Everything else is a handshake fact the\n * bridge reports at `initialize`, where it cannot drift from behavior.\n */\ninterface PluginProviderCapabilities {\n /** The provider accepts a fast/priority service-tier choice — shows the\n * service-tier toggle in the picker. */\n supportsServiceTier: boolean;\n /** The provider ships its own native ask-user-question tool — the\n * ask-user-question plugin skips registering its duplicate. */\n supportsNativeUserQuestion: boolean;\n /**\n * How completely the provider can clone a session: `\"none\"` (not at all),\n * `\"tip\"` (only the current end, so thread fork works but edit-past-message\n * rewind cannot), or `\"checkpoint\"` (recreate the session at an earlier\n * point, which rewind needs). Gates the fork and edit-past-message\n * affordances. The bridge reports the same fact at `initialize`, where it\n * may narrow this declaration but never widen it.\n */\n fork: ProviderFork;\n /** The provider accepts an explicit context-compaction request — gates the\n * compact affordance. */\n supportsManualCompaction: boolean;\n /** The provider keeps its own thread archive, so BB mirrors archive and\n * unarchive onto it instead of tracking the state only in bb's own rows. */\n supportsThreadArchive: boolean;\n /** The provider stores a thread name of its own, so BB forwards renames to\n * it. */\n supportsThreadRename: boolean;\n /** The provider can run BB's Workflow tools — gates the workflows opt-in on\n * new threads. */\n supportsWorkflows: boolean;\n /** Permission modes the provider can actually run in. Non-empty, no\n * duplicates. */\n permissionModes: readonly PluginProviderPermissionMode[];\n /** The provider's coarse fallback reasoning ladder (see\n * {@link PluginProviderReasoningLevel}). Non-empty, no duplicates. */\n reasoningLevels: readonly PluginProviderReasoningLevel[];\n}\n/**\n * One provider this plugin contributes to BB's provider registry.\n *\n * Ids are stable public identifiers — thread rows and routes reference them —\n * and are collision-rejected: a declaration whose id matches another plugin's\n * live registration, or reserves a first-party provider it does not own, is\n * refused. Registrations are replaced wholesale on plugin reload, like every\n * other plugin surface.\n *\n * A declaration is metadata only. The implementation is the plugin's own\n * provider bridge, named by `bb.providerBridge` in the manifest and built into\n * the artifact BB ships to hosts — declaring a provider without one is\n * refused, because the picker entry would exist and no turn on it could ever\n * run.\n */\ninterface PluginProviderDeclaration {\n /** Stable provider id: 2–64 characters of lowercase letters, digits, and\n * \"-\", starting with a letter or digit. Existing ids must never change —\n * threads persist them. */\n id: string;\n /** Picker display name: 1–80 characters, non-blank. */\n displayName: string;\n /**\n * Optional picker icon, in the same grammar as `bb.branding.icon`: either a\n * named host glyph (`\"Zap\"`) or a plugin-relative path starting with `\"./\"`\n * (`\"./icons/agent.svg\"`). Paths follow the manifest entry-path escape rules\n * — no leading \"/\", no \"..\" segments, no backslashes.\n */\n icon?: string;\n /** Pre-session capability facts (see the declaration tests on\n * {@link PluginProviderCapabilities}). */\n capabilities: PluginProviderCapabilities;\n /** Composer actions this provider supports. No duplicates; may be empty\n * (the universal skills typeahead is implicit). */\n composerActions: readonly PluginProviderComposerAction[];\n}\ninterface PluginAgents {\n /**\n * Select this plugin's statically registered tools and manifest skills for\n * each thread/session resolution, with optional dynamic instructions. The\n * callback is synchronous and runs at `thread.start` / `turn.submit`; it\n * never rebuilds registrations. Exactly one callback may be registered per\n * factory execution. A throw, malformed result, duplicate id, unknown id,\n * or more than 256 tool/skill ids fails closed for this plugin only.\n *\n * Tools take effect when the provider session is next started or resumed;\n * an already-running session is not hot-mutated. Instructions follow the\n * same boundary: a live provider session keeps the instructions it was\n * constructed with, and a changed selection applies when the session is\n * next constructed. Skill changes follow BB's environment runtime policy:\n * a busy runtime keeps its current catalog until a safe relaunch. Side chats\n * are ordinary plugin-owned forks here — read `origin` to detect them — and\n * their returned tool, skill, and dynamic-instruction selections apply at the\n * same boundaries.\n */\n configure(provider: (context: PluginAgentConfigurationContext) => PluginAgentConfiguration): void;\n /**\n * Register a native dynamic tool (design §4.4). `parameters` is either a\n * zod schema (validated per call; execute receives the parsed value) or a\n * plain JSON-schema object (no validation; execute receives the raw\n * arguments as `unknown`). Tool-set changes apply on the NEXT session\n * start — a tool registered mid-session is not hot-added to running\n * provider sessions. A second registration of the same name within this\n * plugin is rejected; a name already registered by another plugin is\n * rejected and surfaced as this plugin's status detail. Recursive local\n * JSON Schema `$ref` chains are rejected because some model providers reject\n * the complete tool list when any one tool contains them.\n */\n registerTool(tool: PluginAgentToolRegistrationBase & {\n parameters: Schema;\n execute(params: z.output, ctx: PluginAgentToolContext): PluginAgentToolResult | Promise;\n }): void;\n registerTool(tool: PluginAgentToolRegistrationBase & {\n /** Raw JSON-schema escape hatch; params arrive unvalidated. */\n parameters: Record;\n execute(params: unknown, ctx: PluginAgentToolContext): PluginAgentToolResult | Promise;\n }): void;\n /**\n * Contribute a dynamic section appended to thread instructions. The\n * provider runs when a thread's runtime command config is resolved\n * (thread.start / turn.submit); return null to contribute nothing for\n * that resolution. A live provider session keeps the instructions it was\n * constructed with — a changed contribution takes effect when the\n * provider session is next constructed (thread start or resume after a\n * daemon restart, environment switch, or provider restart), never\n * mid-session. Must be synchronous and fast — it sits on the\n * thread-start path. Output longer than 4096 characters is truncated; a\n * throwing provider is logged against the plugin and contributes nothing.\n * A repeated registration within one factory execution is rejected.\n */\n contributeInstructions(provider: (ctx: {\n threadId: string;\n projectId: string;\n }) => string | null): void;\n /**\n * Register an agent provider this plugin contributes (experimental — see\n * docs/api_to_audit.md before relying on it). The declaration is validated\n * at call time; the provider joins the server's provider registry when the\n * plugin load commits and then appears in provider listings. Ids are stable\n * and collision-rejected: an id already claimed by a core provider or\n * another plugin fails this plugin's load. A plugin may register several\n * providers and may re-register after `dispose()` (a settings-driven\n * re-declaration); registrations are replaced wholesale on plugin reload,\n * like every other surface. The disposer removes the registration.\n */\n experimental_registerProvider(declaration: PluginProviderDeclaration): {\n dispose(): void;\n };\n}\ntype PluginMentionTrigger = \"!\" | \"#\" | \"$\" | \"@\" | \"~\";\n/** Search context handed to a mention provider (design §4.9). `projectId`/\n * `threadId` are null when the composer has not committed one yet. */\ninterface PluginMentionSearchContext {\n trigger: PluginMentionTrigger;\n query: string;\n projectId: string | null;\n threadId: string | null;\n}\n/** One row a mention provider returns from `search`. `id` is the provider's\n * own item id — the host namespaces it before it reaches the wire. */\ninterface PluginMentionItem {\n id: string;\n title: string;\n subtitle?: string;\n icon?: string;\n}\ninterface PluginMentionProviderRegistration {\n /** Unique within this plugin: [a-zA-Z0-9_-]+ (no \":\" — the host composes\n * wire item ids as \":\"). */\n id: string;\n /** Section label shown above this provider's rows in the mention menu. */\n label: string;\n /**\n * Composer trigger characters this provider should answer. Omit to use the\n * default `@` mention trigger. Valid triggers are `@`, `#`, `$`, `!`, and `~`.\n */\n triggers?: readonly PluginMentionTrigger[];\n /**\n * Runs server-side as the user types after one of this provider's triggers\n * in the composer. Each call is time-boxed (2s) and failure-isolated: a slow\n * or throwing provider contributes an empty list — it can never break the\n * mention menu.\n */\n search(ctx: PluginMentionSearchContext): PluginMentionItem[] | Promise;\n /**\n * Resolves one picked item into agent context, called once per unique\n * item at message send time. The returned `context` is attached to the\n * message as an agent-visible (user-hidden) prompt input. Throwing blocks\n * the send with a visible error.\n */\n resolve(itemId: string): {\n context: string;\n } | Promise<{\n context: string;\n }>;\n}\ninterface PluginUi {\n /** Block until the app submits or cancels a plugin-owned composer form. */\n requestInput(request: PluginInteractionRequest, options?: {\n signal?: AbortSignal;\n }): Promise;\n /**\n * Register a mention provider for the shipped app's composer (design §4.9).\n * Providers default to the `@` trigger and may opt into `#`, `$`, `!`, or\n * `~` with `triggers`. Items group under `label` in the mention menu; a\n * picked item becomes a `{ kind: \"plugin\" }` mention resource whose context\n * is resolved once at send time. Multiple providers per plugin; ids must be\n * unique within the plugin.\n */\n registerMentionProvider(provider: PluginMentionProviderRegistration): void;\n}\ninterface PluginEvents {\n /**\n * Add a thread lifecycle listener. Multiple listeners for the same event are\n * additive and run independently in registration order.\n */\n on(event: E, handler: PluginThreadEventHandler): void;\n}\ninterface PluginServerApi {\n /**\n * This BB server's own loopback base URL (e.g. \"http://127.0.0.1:38886\"),\n * which serves the SPA + /api + /ws. For plugins that proxy or relay\n * traffic back to the server itself (e.g. a tunnel). Bind-gated like\n * `bb.sdk`: reading it before the server is listening throws, so prefer\n * reading it from handlers, services, and timers.\n */\n readonly loopbackBaseUrl: string;\n}\ninterface PluginSharedPortTunnelIdentity {\n /** Gate routing label assigned to this machine. */\n label: string;\n /** Gate apex without a scheme, e.g. \"getbb.app\". */\n baseDomain: string;\n}\ninterface PluginHosts {\n /** Create the owning plugin's typed client for its singular `bb.host` entry. */\n experimental_client(args: {\n contract: Contract;\n experimental_signals?: Signals;\n }): ExperimentalHostClient;\n /**\n * Ensure this enrolled host has a gate label and return its read-only public\n * identity. The daemon chooses the trusted gate and desired label; plugins\n * cannot influence either credential-bearing destination.\n */\n ensureSharedPortTunnel(hostId: string): Promise;\n /**\n * Replace this plugin's desired shared-loopback ports for one host. The\n * server aggregates declarations, owns generations, and delivers the\n * resulting set to that host's daemon. Tunnel identity is deliberately not\n * accepted here: it is owned by the daemon's trusted enrollment.\n */\n declareSharedPorts(hostId: string, ports: readonly number[]): void;\n}\ninterface PluginStatusApi {\n /**\n * Mark this plugin `needs-configuration` (with a message shown in\n * `bb plugin list` and the UI) instead of failing — e.g. a factory or\n * service that finds no API key configured. Cleared on the next load;\n * saving settings does not auto-reload in V1, so ask the user to\n * `bb plugin reload ` after configuring.\n */\n needsConfiguration(message: string): void;\n}\n/**\n * The API object handed to a plugin's factory (design §4). Implemented by\n * the BB server; this contract is what plugin `server.ts` files compile\n * against.\n */\ninterface BbPluginApi {\n /** The plugin's own id (namespaces storage, routes, commands). */\n readonly pluginId: string;\n /** Leveled, plugin-scoped logger. */\n readonly log: PluginLogger;\n /** Declarative settings (design §4.2). */\n readonly settings: PluginSettings;\n /** Namespaced KV + per-plugin database (design §4.3). */\n readonly storage: PluginStorage;\n /** HTTP routes under /api/v1/plugins//http/* (design §4.6). */\n readonly http: PluginHttp;\n /** RPC methods under /api/v1/plugins//rpc/ (design §4.6). */\n readonly rpc: PluginRpc;\n /** Ephemeral push to connected frontends (design §4.7). */\n readonly realtime: PluginRealtime;\n /** Long-lived services + cron schedules (design §4.8). */\n readonly background: PluginBackground;\n /** Agent-facing `bb` CLI subcommand (design §4.4). */\n readonly cli: PluginCli;\n /** Per-turn agent context contributions (design §4.4). */\n readonly agents: PluginAgents;\n /** Host-rendered UI contributions (design §4.9). */\n readonly ui: PluginUi;\n /** Additive plugin lifecycle listeners (design §4.5). */\n readonly events: PluginEvents;\n /** Plugin-reported status (needs-configuration). */\n readonly status: PluginStatusApi;\n /** Read-only facts about the running server (loopback base URL). */\n readonly server: PluginServerApi;\n /** Server-to-daemon host control-plane declarations. */\n readonly hosts: PluginHosts;\n /**\n * The full BB SDK, bound to this server over loopback (design §4.1).\n * Bind-gated: reading this before the host binds the SDK throws. The real\n * server binds it before loading plugins, so it is available from the\n * moment factories run there — but isolated harnesses may not, so prefer\n * using it from handlers, services, and timers for portability.\n * `threads.spawn` defaults `origin` to \"plugin\" and `originPluginId` to\n * this plugin's id so spawned threads are attributed automatically.\n */\n readonly sdk: BbSdk;\n /**\n * Register cleanup to run on reload/disable/shutdown. Hooks run LIFO.\n * The sanctioned place to clear timers and close connections.\n */\n onDispose(hook: () => void | Promise): void;\n}\n\nexport { PLUGIN_CLI_OUTPUT_MAX_BYTES, defineRpcContract, experimental_defineHostEntry };\nexport type { BbContext, BbNavigate, BbPluginApi, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, ExperimentalHostCallOptions, ExperimentalHostClient, ExperimentalHostEntry, ExperimentalHostPaths, ExperimentalHostRpcContext, ExperimentalHostRpcHandlers, ExperimentalHostSignalContract, ExperimentalHostSignalEvent, ExperimentalHostSignals, ExperimentalHostWatchChange, ExperimentalHostWatchChangeType, ExperimentalHostWatchEvent, ExperimentalHostWatchListener, ExperimentalHostWatchOptions, ExperimentalHostWatchSubscription, ExperimentalHostWorkerLease, JsonValue, MarkdownProps, NewThreadComposerProps, NewThreadRequest, PluginAgentConfiguration, PluginAgentConfigurationContext, PluginAgentToolContentPart, PluginAgentToolContext, PluginAgentToolExperimentalStatusLabels, 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, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderCapabilities, PluginProviderComposerAction, PluginProviderDeclaration, PluginProviderIconRegistration, PluginProviderPermissionMode, PluginProviderReasoningLevel, 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, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginStatusApi, PluginStorage, PluginTargetedPanelActionOpenOptions, PluginThreadEventHandler, PluginThreadEventName, PluginThreadEventPayloads, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, PluginUi, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps };\n"; -export const PLUGIN_SDK_APP_DTS = "// Portable type declarations for `@get-bb/plugin-sdk`. Unpublished BB\n// workspace contracts are flattened; public subpaths may reuse the\n// package root without requiring any other @bb/* package.\n//\n// Confused by the API, or need a symbol that isn't here? Clone the BB repo\n// and read the real source: https://github.com/get-bb/bb\n\nimport * as react from 'react';\nimport { ComponentType, ReactNode } from 'react';\nimport { z } from 'zod';\n\n/** A JSON-safe path segment reported by a Standard Schema validation issue. */\ntype PluginRpcIssuePathSegment = string | number;\n/** Validator-neutral validation detail carried by an RPC error envelope. */\ninterface PluginRpcValidationIssue {\n message: string;\n path?: PluginRpcIssuePathSegment[];\n}\n/** Stable wire error categories for plugin RPC. */\ntype PluginRpcErrorCode = \"handler_error\" | \"invalid_input\" | \"invalid_json\" | \"invalid_output\" | \"non_json_result\" | \"unknown_method\";\n/** Structured RPC failure returned as `{ ok: false, error }`. */\ninterface PluginRpcError {\n code: PluginRpcErrorCode;\n message: string;\n issues?: PluginRpcValidationIssue[];\n}\n/**\n * The validator-neutral subset of Standard Schema v1 used by plugin RPC.\n * Zod 4 schemas implement this interface directly; other validators can do\n * the same without becoming part of BB's public protocol.\n */\ninterface StandardSchemaV1 {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardSchemaV1Result | Promise>;\n readonly types?: {\n readonly input: Input;\n readonly output: Output;\n };\n };\n}\ntype StandardSchemaV1Result = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: readonly StandardSchemaV1Issue[];\n};\ninterface StandardSchemaV1Issue {\n readonly message: string;\n readonly path?: PropertyKey | readonly (PropertyKey | {\n readonly key: PropertyKey;\n })[];\n}\ntype StandardSchemaV1InferInput = NonNullable[\"input\"];\ntype StandardSchemaV1InferOutput = NonNullable[\"output\"];\ninterface PluginRpcMethodContract {\n readonly input: InputSchema;\n readonly output: OutputSchema;\n}\ntype PluginRpcContract = Readonly>;\ntype PluginRpcHandlers = {\n [Method in keyof Contract]: (input: StandardSchemaV1InferOutput) => StandardSchemaV1InferInput | Promise>;\n};\ntype PluginRpcCallInput = StandardSchemaV1InferInput;\ntype PluginRpcCallArgs = null extends PluginRpcCallInput ? [input?: PluginRpcCallInput] : [input: PluginRpcCallInput];\ntype PluginRpcResult = StandardSchemaV1InferOutput;\n\ndeclare const reasoningLevelSchema: z.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n}>;\ntype ReasoningLevel = z.infer;\ndeclare const serviceTierSchema: z.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n}>;\ntype ServiceTier = z.infer;\ndeclare const permissionModeSchema: z.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n}>;\ntype PermissionMode = z.infer;\ndeclare const promptInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{\n mentions: z.ZodDefault, z.ZodDiscriminatedUnion<[z.ZodObject<{\n kind: z.ZodLiteral<\"thread\">;\n label: z.ZodString;\n projectId: z.ZodOptional;\n threadId: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n kind: z.ZodLiteral<\"project\">;\n label: z.ZodString;\n projectId: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n kind: z.ZodLiteral<\"section\">;\n label: z.ZodString;\n sectionId: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n entryKind: z.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z.ZodLiteral<\"path\">;\n label: z.ZodString;\n path: z.ZodString;\n source: z.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z.core.$strip>, z.ZodObject<{\n argumentHint: z.ZodNullable;\n kind: z.ZodLiteral<\"command\">;\n label: z.ZodString;\n name: z.ZodString;\n origin: z.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z.core.$strip>, z.ZodObject<{\n icon: z.ZodOptional>;\n itemId: z.ZodString;\n kind: z.ZodLiteral<\"plugin\">;\n label: z.ZodString;\n pluginId: z.ZodString;\n }, z.core.$strip>], \"kind\">>;\n start: z.ZodNumber;\n }, z.core.$strip>>>;\n text: z.ZodString;\n type: z.ZodLiteral<\"text\">;\n visibility: z.ZodOptional>;\n}, z.core.$strip>, z.ZodObject<{\n type: z.ZodLiteral<\"image\">;\n url: z.ZodString;\n visibility: z.ZodOptional>;\n}, z.core.$strip>, z.ZodObject<{\n path: z.ZodString;\n type: z.ZodLiteral<\"localImage\">;\n visibility: z.ZodOptional>;\n}, z.core.$strip>, z.ZodObject<{\n mimeType: z.ZodOptional;\n name: z.ZodOptional;\n path: z.ZodString;\n sizeBytes: z.ZodOptional;\n type: z.ZodLiteral<\"localFile\">;\n visibility: z.ZodOptional>;\n}, z.core.$strip>], \"type\">;\ntype PromptInput = z.infer;\n\ndeclare const createThreadEnvironmentArgsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{\n environmentId: z.ZodString;\n type: z.ZodLiteral<\"reuse\">;\n}, z.core.$strip>, z.ZodObject<{\n hostId: z.ZodOptional;\n type: z.ZodLiteral<\"host\">;\n workspace: z.ZodDiscriminatedUnion<[z.ZodObject<{\n branch: z.ZodOptional;\n name: z.ZodString;\n }, z.core.$strict>, z.ZodObject<{\n baseBranch: z.ZodString;\n kind: z.ZodLiteral<\"new\">;\n }, z.core.$strict>], \"kind\">>;\n path: z.ZodNullable;\n type: z.ZodLiteral<\"unmanaged\">;\n }, z.core.$strip>, z.ZodObject<{\n baseBranch: z.ZodDiscriminatedUnion<[z.ZodObject<{\n kind: z.ZodLiteral<\"named\">;\n name: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n kind: z.ZodLiteral<\"default\">;\n }, z.core.$strip>], \"kind\">;\n type: z.ZodLiteral<\"managed-worktree\">;\n }, z.core.$strip>, z.ZodObject<{\n type: z.ZodLiteral<\"personal\">;\n }, z.core.$strip>], \"type\">;\n}, z.core.$strip>, z.ZodObject<{\n type: z.ZodLiteral<\"project-default\">;\n}, z.core.$strip>], \"type\">;\ntype CreateThreadEnvironmentArgs = z.infer;\n\ndeclare const createExecutionInputSourcesSchema: z.ZodObject<{\n model: z.ZodOptional>;\n permissionMode: z.ZodOptional>;\n providerId: z.ZodOptional>;\n reasoningLevel: z.ZodOptional>;\n serviceTier: z.ZodOptional>;\n}, z.core.$strict>;\ntype CreateExecutionInputSources = z.infer;\n\n/**\n * A value that survives a JSON round trip without coercion or data loss.\n *\n * Host boundaries still validate values at runtime because TypeScript cannot\n * exclude non-finite numbers and plugin bundles can bypass static types.\n */\ntype JsonValue = string | number | boolean | null | JsonValue[] | {\n [key: string]: JsonValue;\n};\n\n/**\n * The `@get-bb/plugin-sdk/app` contract (plugin design §5.2) — pure types with no\n * side effects. The BB app imports these to keep its real implementation in\n * sync (`satisfies PluginSdkApp`). Plugin authors import the same shapes through\n * `@get-bb/plugin-sdk/app`.\n *\n * Per-slot props are versioned contracts: additive-only within an SDK major.\n */\n/** Props passed to a `homepageSection` component. */\ninterface PluginHomepageSectionProps {\n /** Project in view on the compose surface; null when none is selected. */\n projectId: string | null;\n}\n/**\n * Props passed to a `settingsSection` component.\n *\n * Deliberately empty in V1; versioned additive like the other slot props.\n */\ninterface PluginSettingsSectionProps {\n}\n/** Props passed to a `navPanel` component (it owns its whole route). */\ninterface PluginNavPanelProps {\n /**\n * The route remainder after the panel root, \"\" at the root. The panel's\n * route is `/plugins///*`, so a deep link like\n * `/plugins/notes/notes/work/ideas.md` renders the panel with\n * `subPath: \"work/ideas.md\"`. Navigate within the panel via\n * `useBbNavigate().toPluginPanel(path, { subPath })` — browser\n * back/forward then walks panel-internal history.\n */\n subPath: string;\n}\n/**\n * Props passed to a panel tab opened by a `threadPanelAction`.\n *\n * This slot is rendered only for an existing thread. Use\n * `experimental_newThreadPanelAction` for the root New thread screen.\n */\ninterface PluginThreadPanelProps {\n threadId: string;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\n/** Props passed to a panel tab opened by `experimental_newThreadPanelAction`. */\ninterface PluginNewThreadPanelProps {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\ninterface PluginPendingInteractionView {\n id: string;\n threadId: string;\n title: string;\n payload: JsonValue;\n createdAt: number;\n expiresAt: number | null;\n}\ninterface PluginPendingInteractionProps {\n interaction: PluginPendingInteractionView;\n submit(value: JsonValue): Promise;\n cancel(): Promise;\n}\n/**\n * Props for a `sidebarFooterAction` — host-rendered (no plugin component).\n * Deliberately empty; the registration's `run` carries the behavior.\n */\ninterface PluginSidebarFooterActionProps {\n}\n/**\n * Props passed to an `experimental_threadList` component — the sidebar's\n * scrolling thread area, replaced wholesale by one plugin.\n */\ninterface PluginThreadListProps {\n /** The thread the route currently shows; null on non-thread routes. */\n activeThreadId: string | null;\n /** The project the route currently shows; null when none is selected. */\n activeProjectId: string | null;\n /** True on phone-width viewports and coarse pointers. */\n isCompactViewport: boolean;\n /**\n * Call after the user opens a thread. It closes the mobile sidebar drawer,\n * and it clears the host search field on every viewport. Always call it, or\n * the sidebar stays in search mode after the thread opens.\n */\n onNavigate: () => void;\n /**\n * The host search field's current text, or \"\" when the field is closed.\n * The host owns that field, so a plugin list filters by this rather than\n * shipping a second search box.\n */\n searchQuery: string;\n /**\n * BB's thread list, bound to this sidebar instance. Render it to delegate\n * conditionally without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Props passed to an `experimental_threadHeaderAction` component, rendered in\n * the thread header's action row.\n */\ninterface PluginThreadHeaderActionProps {\n /**\n * The thread this header belongs to. Never null: the slot is not rendered\n * on the compose screen or other non-thread routes. A split layout renders\n * one header per pane, so the component mounts once per visible thread,\n * each with its own id — keep per-thread state in the component, never in a\n * module-level singleton.\n */\n threadId: string;\n projectId: string;\n /**\n * True on phone-width viewports and coarse pointers. Collapse to an\n * icon-sized control when it is true — the row is short.\n */\n isCompactViewport: boolean;\n}\n/**\n * Where a file being opened by a `fileOpener` lives. `path` semantics follow\n * the source: workspace paths are relative to the environment's worktree,\n * thread-storage paths are relative to the thread's storage root, host paths\n * are absolute on the thread's host.\n */\ninterface PluginFileOpenerSource {\n kind: \"host\" | \"thread-storage\" | \"workspace\";\n threadId: string | null;\n environmentId: string | null;\n projectId: string | null;\n}\n/** Props passed to a `fileOpener` component (rendered as a panel file tab). */\ninterface PluginFileOpenerProps {\n path: string;\n source: PluginFileOpenerSource;\n /**\n * BB's file preview, bound to this file. Render it to delegate conditionally\n * without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Message context passed to a `messageDirective` component — the assistant\n * (or nested agent) message that contained the directive.\n */\ninterface PluginMessageDirectiveMessage {\n id: string;\n threadId: string;\n turnId: string | null;\n projectId: string | null;\n}\n/**\n * Open a worktree-relative file in the host's workspace file viewer. Returns\n * true when the host accepted the path; false when the path is invalid or the\n * viewer declined it.\n */\ntype PluginMessageDirectiveOpenWorkspaceFile = (path: string) => boolean;\n/**\n * Props passed to a `messageDirective` component. Attributes are untrusted\n * strings parsed from the directive; the plugin validates its own fields.\n */\ninterface PluginMessageDirectiveProps {\n /** Parsed, untrusted directive attributes (e.g. `{ file: \"demo.html\" }`). */\n attributes: Readonly>;\n /** Original directive source text (useful for diagnostics / crash fallback). */\n source: string;\n message: PluginMessageDirectiveMessage;\n /**\n * Opens a worktree-relative file in the host's workspace file viewer. Null\n * when the message surface has no workspace viewer available.\n */\n openWorkspaceFile: PluginMessageDirectiveOpenWorkspaceFile | null;\n}\ninterface PluginHomepageSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n component: ComponentType;\n}\ninterface PluginSettingsSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Optional host-rendered section heading. */\n title?: string;\n /**\n * Optional one-line host-rendered subheading under `title`, in the built-in\n * SettingsSection idiom (ignored when `title` is absent).\n */\n description?: string;\n component: ComponentType;\n}\ninterface PluginNavPanelRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /** URL segment under `/plugins//`; letters, digits, `-`, `_`. */\n path: string;\n component: ComponentType;\n /**\n * Ordered, non-closable tabs shown in this page's host-owned right panel.\n * BB owns selection and persistence and always includes its native Browser\n * and Terminal tools beside them. Components mount only while their tab is\n * active and the panel is open, and receive the same `subPath` as the page\n * component.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_fixedTabs?: readonly {\n /** Unique within this nav panel; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n component: ComponentType;\n /** `flush` lets the component own padding and scrolling. */\n layout?: \"flush\" | \"padded\";\n }[];\n /**\n * Optional presentational component rendered at the trailing edge of this\n * panel's sidebar row. It receives no props so it can own a narrow live\n * value through the ordinary SDK hooks without coupling that state to the\n * host sidebar. The host does not mount it on compact viewports and clips it\n * to a small, single-line box on wider viewports. It shares the trailing\n * action column, fading out for the host's options button on hover or focus;\n * do not render controls or rely on unbounded content here.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_sidebarAccessory?: ComponentType;\n /**\n * Optional component rendered on the right side of the shared title bar\n * (e.g. a sync button or a count). Contained separately from the body: a\n * throwing headerContent is hidden without breaking the title bar.\n */\n headerContent?: ComponentType;\n}\n/**\n * What a plugin action passes when it asks the host to open one of its panel\n * tabs. Shared by every `openPanel` entry point so a plugin registering more\n * than one kind of action can write a single open routine;\n * `PluginTargetedPanelActionOpenOptions` adds the `actionId` a caller\n * outside a panel action must pass to name the panel it wants.\n */\ninterface PluginPanelActionOpenOptions {\n /** Tab label. Default: the action's `title`. */\n title?: string;\n /**\n * Persisted with the tab and handed to the component as its `params` prop.\n * Must be a JSON value; anything else is a declined open.\n */\n params?: JsonValue;\n}\n/**\n * Context handed to a `threadPanelAction`'s `run`.\n *\n * The action is thread-only and is never offered on the root New thread\n * screen, so `threadId` is always present.\n */\ninterface PluginThreadPanelActionContext {\n /** The thread whose panel launcher invoked the action. */\n threadId: string;\n /**\n * Open a tab in the thread's side panel rendering this action's\n * `component`. `title` labels the tab (default: the action's `title`);\n * `params` must be JSON-serializable — it is persisted with the tab and\n * reaches the component as its `params` prop. Opening with params\n * identical to an already-open tab of this action focuses that tab\n * (updating its title) instead of duplicating it. May be called more than\n * once (different params ⇒ multiple tabs) or not at all.\n *\n * Returns true when the host accepted the open; false when it declined —\n * from this launcher, only a `params` that is not a JSON value. The true /\n * false contract is shared with `messageAction`'s `openPanel` and\n * `useBbNavigate().openThreadPanel` (which decline for more reasons) so one\n * open routine can serve every action kind. A decline is never thrown: the\n * host logs it and reports it here.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\ninterface PluginThreadPanelActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /**\n * Icon hint (BB icon name) used when the plugin ships no logo; the\n * launcher row and opened tabs prefer the plugin's logo.\n */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /**\n * How the host frames the tab content. \"padded\" (default) wraps the\n * component in the panel's scroll container with standard padding —\n * right for document-like content. \"flush\" gives the component the full\n * tab area (no padding, definite height, no host scrolling) — right for\n * app-like content that manages its own layout, such as\n * `ThreadChat`.\n */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action: call your RPC methods, show a\n * toast, and/or open panel tabs via `context.openPanel`. Omitted =\n * immediately open a panel tab with defaults. Errors (sync or async) are\n * contained and logged; they never break the launcher.\n */\n run?(context: PluginThreadPanelActionContext): void | Promise;\n}\n/** Context handed to an `experimental_newThreadPanelAction`'s `run`. */\ninterface PluginNewThreadPanelActionContext {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * Open a tab in the root New thread screen's side panel rendering this\n * action's `component`. The title, params, deduplication, return value, and\n * error semantics match `threadPanelAction`.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\n/** Registration for the root New thread screen's panel Actions list. */\ninterface PluginNewThreadPanelActionRegistration {\n /** Unique within this slot for the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /** Icon hint (BB icon name) used when the plugin ships no logo. */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /** Host framing; matches `threadPanelAction`. */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action. Omitted = immediately open a\n * panel tab with defaults. Errors are contained and logged.\n */\n run?(context: PluginNewThreadPanelActionContext): void | Promise;\n}\ninterface PluginPendingInteractionRegistration {\n /** Matches `rendererId` passed to `bb.ui.requestInput`. */\n id: string;\n component: ComponentType;\n}\n/** Context handed to a `sidebarFooterAction`'s `run`. */\ninterface PluginSidebarFooterActionContext {\n /**\n * Navigate to this plugin's detail page in Tools, where declarative settings\n * and `settingsSection` slots render.\n */\n openSettings(): void;\n}\n/**\n * An icon button in the app sidebar footer (next to Settings / bug report).\n * Host-rendered for consistent chrome — plugins supply icon, label, and\n * `run` behavior only.\n */\ninterface PluginSidebarFooterActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip and accessible label for the icon button. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /**\n * Runs when the user activates the action (e.g. call `openSettings()`,\n * open a panel via other surfaces, toast). Errors (sync or async) are\n * contained and logged; they never break the sidebar.\n */\n run(context: PluginSidebarFooterActionContext): void | Promise;\n}\n/**\n * The one status bb would paint for a thread, already resolved through the\n * host's precedence (attention before work; plan and goal before the generic\n * spinner). Draw your own glyph for it — the SDK ships no status component.\n *\n * Treat an unrecognized value as \"none\": bb adds kinds over time, and an\n * older plugin must degrade to drawing nothing rather than throwing.\n *\n * \"draft\" and \"working-draft\" are never reported here: an unsubmitted composer\n * draft is per-client state the host reads per row, which an array-wide view\n * cannot. A thread holding a draft reports whatever it would report without\n * one.\n */\ntype PluginSidebarThreadIndicator = \"background-agent\" | \"background-command\" | \"draft\" | \"goal\" | \"none\" | \"plan-mode\" | \"runtime\" | \"unread-error\" | \"unread-success\" | \"waiting-for-input\" | \"workflow\" | \"working-draft\";\n/**\n * How a thread's environment presents its workspace: a worktree bb manages,\n * a worktree the user manages, or anything else (a plain checkout).\n */\ntype PluginSidebarWorkspaceKind = \"managed-worktree\" | \"other\" | \"unmanaged-worktree\";\n/** Live work counts on a thread. All zero means nothing is running. */\ninterface PluginSidebarThreadActivity {\n workflows: number;\n backgroundAgents: number;\n backgroundCommands: number;\n planMode: number;\n goals: number;\n}\n/**\n * One thread in the sidebar's live view.\n *\n * A deliberate copy of the fields a sidebar needs — not a re-export of the\n * host's internal thread row type, which changes whenever the app needs a\n * field. Timestamps are epoch milliseconds.\n */\ninterface PluginSidebarThread {\n id: string;\n projectId: string;\n /** Null while a thread is still unnamed; pair with `titleFallback`. */\n title: string | null;\n titleFallback: string | null;\n /** The thread this one was forked from or spawned under; null at the root. */\n parentThreadId: string | null;\n sectionId: string | null;\n /** How this thread came to exist under its parent; null for root threads. */\n originKind: \"fork\" | null;\n /** The plugin that spawned it, or null for non-plugin origins. */\n originPluginId: string | null;\n /** The agent provider this thread runs on, e.g. \"codex\", \"claude-code\". */\n providerId: string;\n /** The agent is blocked on the user: an approval or a question. */\n hasPendingInteraction: boolean;\n activity: PluginSidebarThreadActivity;\n indicator: PluginSidebarThreadIndicator;\n /**\n * The host's accessible label for `indicator`, e.g. \"Thread needs user\n * input\"; null when the indicator is \"none\". Use it for `aria-label` so\n * screen-reader text stays consistent across sidebars.\n */\n indicatorLabel: string | null;\n isUnread: boolean;\n isPinned: boolean;\n isArchived: boolean;\n environment: {\n id: string | null;\n name: string | null;\n branchName: string | null;\n workspaceDisplayKind: PluginSidebarWorkspaceKind;\n } | null;\n /**\n * The machine this thread's work runs on, with the name resolved for you.\n * Null when the thread has no environment yet, or when its host is not in\n * the known-hosts list. Useful where a thread has no branch to show — a\n * personal-project thread has a machine but no worktree.\n */\n host: {\n id: string;\n name: string;\n } | null;\n createdAt: number;\n updatedAt: number;\n lastReadAt: number | null;\n latestAttentionAt: number;\n}\n/**\n * The pull request for a thread's branch, narrowed to what a sidebar row\n * needs. `attention` is bb's rolled-up \"does this need you\" signal, so a row\n * can colour a badge without reading checks, review, and mergeability itself.\n */\ninterface PluginSidebarPullRequest {\n number: number;\n title: string;\n url: string;\n state: \"closed\" | \"draft\" | \"merged\" | \"open\";\n attention: \"blocked\" | \"changes_requested\" | \"checks_failed\" | \"checks_pending\" | \"closed\" | \"conflicts\" | \"draft\" | \"merged\" | \"none\" | \"ready_to_merge\" | \"review_requested\";\n}\ninterface PluginSidebarThreadPullRequestState {\n /** True while the first lookup for this thread's environment is in flight. */\n isLoading: boolean;\n /**\n * The pull request, or null when the branch has none, the thread has no\n * environment, or the lookup could not run (a git-host hiccup). A row should\n * treat null as \"nothing to show\", never as an error.\n */\n pullRequest: PluginSidebarPullRequest | null;\n}\n/** One project in the sidebar's live view. */\ninterface PluginSidebarProject {\n id: string;\n name: string;\n /** True for the implicit personal project. */\n isPersonal: boolean;\n}\ninterface PluginSidebarThreadsState {\n status: \"error\" | \"loading\" | \"ready\";\n threads: readonly PluginSidebarThread[];\n projects: readonly PluginSidebarProject[];\n}\n/**\n * Act on threads from a plugin surface. Every method routes to the host's own\n * flow, so optimistic updates, toasts, dialogs, pane closing, and route repair\n * behave exactly as they do in the built-in sidebar. Unknown thread ids are\n * ignored by `open` and rejected by the rest.\n */\ninterface PluginSidebarThreadActions {\n /**\n * Navigate to a thread. `split: true` applies bb's split placement rules —\n * a right split by default, focus when the thread is already open, replace\n * at the pane cap — and falls back to plain navigation where splits are off.\n */\n open(threadId: string, options?: {\n split?: boolean;\n }): void;\n /**\n * Go to the new-thread screen. Passing `projectId` also makes that project\n * the composer's selection, so the thread is created where you asked.\n */\n openNewThread(options?: {\n projectId?: string;\n focusPrompt?: boolean;\n }): void;\n setPinned(threadId: string, pinned: boolean): Promise;\n setRead(threadId: string, read: boolean): Promise;\n /** Silent rename — no dialog. For inline editing in your own row. */\n rename(threadId: string, title: string): Promise;\n /** Archives the thread AND its children, closing any panes showing them. */\n archive(threadId: string): void;\n /**\n * Opens bb's delete confirmation, which counts child threads first. Deletion\n * is destructive and recursive, so the host owns the confirmation: there is\n * deliberately no silent `delete`.\n */\n requestDelete(threadId: string): void;\n}\n/**\n * Render a plugin component in the thread header's action row.\n *\n * The frontend sibling of the backend `bb.ui.registerThreadAction`, which\n * renders a host-owned button and runs server-side. Use that one for \"do a\n * thing\"; use this one when the control must draw live state.\n *\n * The host places it at the left end of the action row, before the workspace\n * button, git actions, the panel toggle, maximize, and close. That row is a\n * 48px chrome row with 28px controls: render one inline control that fits, and\n * put anything taller in a portalled popover.\n */\ninterface PluginThreadHeaderActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Names the region the host wraps around your component (a labelled group).\n * It does NOT label your control: an icon-only button still needs its own\n * accessible name.\n */\n title: string;\n component: ComponentType;\n}\n/** One pane's place in the split layout, as fractions of the split area. */\ninterface PluginSidebarSplitPane {\n paneId: string;\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n /** This pane holds the thread the row represents. */\n isMe: boolean;\n isFocused: boolean;\n}\n/**\n * Drag-to-split support for one row, plus where that thread currently sits in\n * the split layout.\n */\ninterface PluginSidebarThreadSplit {\n /**\n * Spread onto the row's interactive element. Carries the pointer handler\n * that starts a split drag; empty when splits are unavailable, so spreading\n * it is always safe.\n *\n * The host owns every rule: the gesture engages only once the pointer leaves\n * the sidebar toward the main area (so a list with its own drag-to-reorder\n * keeps working), an edge drop splits, a center drop replaces, an\n * already-open thread focuses its pane, and the pane cap coerces a split\n * into a replace.\n */\n splitProps: {\n onPointerDown?: (event: react.PointerEvent) => void;\n };\n /**\n * False on compact viewports, when the user disabled splits, and for an\n * unknown thread id. Gate any \"open in split\" affordance you draw on it.\n */\n isAvailable: boolean;\n /**\n * Where this thread sits in the split layout, or null when it is not open in\n * one (including single-pane layouts). Draw a mini-map, a tint, or nothing.\n */\n layout: {\n panes: readonly PluginSidebarSplitPane[];\n } | null;\n}\n/**\n * Replace the sidebar's thread list with a plugin component.\n *\n * Unlike every other slot, this one is EXCLUSIVE: two lists cannot share one\n * scroll area. Registering activates the replacement while the plugin is\n * enabled. If multiple plugins register one, the first in deterministic slot\n * order is active by default; removing it reveals the next. The user can pin\n * BB's list or a specific provider under Settings → Appearance. A plugin can\n * also use its own setting and render `experimental_Original` conditionally.\n * An absent or crashing replacement falls back to BB's list rather than\n * leaving the user with no sidebar.\n *\n * The plugin gets the scrolling list and nothing else. The New-thread button,\n * the search field, the plugin nav rows, and the footer stay host-rendered in\n * every sidebar — they are shared surfaces (other plugins live in two of\n * them), and a replaced list must not be able to remove them.\n */\ninterface PluginThreadListRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label shown in Settings → Appearance and capability details. */\n title: string;\n /** Optional one-line description shown with the provider choice. */\n description?: string;\n component: ComponentType;\n}\n/**\n * Register this plugin as a viewer/editor for file extensions. By default,\n * matching files render the first applicable opener in deterministic slot\n * order. The user can pin BB's preview or a specific opener per extension\n * under Settings → Files. The file tab's \"Open with\" menu can override that\n * choice for one open. A plugin can also use its own setting and render\n * `experimental_Original` conditionally. Applies to working-tree, host, and\n * thread-storage files — never to git-ref snapshots (diff views always use\n * BB's preview).\n */\ninterface PluginFileOpenerRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label in the \"Open with\" menu (e.g. \"Notes editor\"). */\n title: string;\n /** Lowercase extensions without the dot (e.g. [\"md\", \"mdx\"]). */\n extensions: readonly string[];\n component: ComponentType;\n}\n/**\n * Register a leaf message directive rendered inside assistant (and nested\n * agent) message Markdown. `id` is the directive name: `inline-vis` matches\n * `::inline-vis{file=\"demo.html\"}`.\n */\ninterface PluginMessageDirectiveRegistration {\n /**\n * The directive name. Lowercase kebab-case beginning with a letter.\n */\n id: string;\n component: ComponentType;\n}\n/**\n * A narrow, stable reference to one rendered chat message — NOT an internal\n * timeline row. `sourceSeqEnd` is the last source event sequence the message\n * covers, the anchor the server accepts for provider-history forks.\n */\ninterface ThreadChatMessageReference {\n id: string;\n threadId: string;\n role: \"assistant\" | \"user\";\n /** Visible text of the message. */\n text: string;\n sourceSeqEnd: number;\n}\n/**\n * What a caller that is *not* itself a panel action passes to open one — a\n * `messageAction`'s `run`, or any component via `useBbNavigate()`. A panel\n * action opening its own tab is already the target, so it passes the bare\n * {@link PluginPanelActionOpenOptions} instead.\n */\ninterface PluginTargetedPanelActionOpenOptions extends PluginPanelActionOpenOptions {\n /** A `threadPanelAction` id registered by this same plugin. */\n actionId: string;\n}\n/** Context handed to a `messageAction`'s `run`. */\ninterface PluginMessageActionContext {\n /** The thread whose timeline surfaced the action. */\n threadId: string;\n message: ThreadChatMessageReference;\n /**\n * Present only when the action was invoked from the text-selection menu;\n * the exact text the user highlighted inside `message`.\n */\n selectedText?: string;\n /**\n * Open one of this plugin's `threadPanelAction` components in the current\n * thread's side panel — the registration-callback equivalent of\n * `useBbNavigate().openThreadPanel`.\n *\n * Returns true when the host accepted the open; false when it declined —\n * `params` was not a JSON value, the action id names no `threadPanelAction`\n * of this plugin, or the surface has no side panel (only the main thread\n * view does; a `ThreadChat` embedded in a plugin panel does not). A decline\n * is never thrown: the host logs it and reports it here.\n */\n openPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * An action on chat messages: an icon button in the per-message action bar\n * (user and assistant messages) and an entry in the assistant-message\n * text-selection menu. Host-rendered chrome — the plugin supplies title,\n * icon hint, and `run` behavior only.\n */\ninterface PluginMessageActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(context: PluginMessageActionContext): void | Promise;\n}\n/**\n * Supply the inline React mark bb draws for one agent provider.\n *\n * A manifest `branding.icon` (or a provider's `logoUrl`) is fetched and drawn\n * through ``, a separate document where `currentColor` resolves to black\n * — invisible on dark themes and unreachable from app CSS. A component is\n * rendered inline, so it inherits the app's theme colors and the host's sizing\n * classes. Register a static color logo as a file and a theme-aware mark here.\n *\n * The host passes only `className` (sizing plus the provider's color class);\n * the component must render an inline SVG (or other inline markup) and must\n * not fetch. One registration per provider id per plugin; when two plugins\n * claim the same provider id the host keeps the first by plugin id and warns.\n */\ninterface PluginProviderIconRegistration {\n /**\n * The provider this mark is for — the id bb knows the provider by (the\n * provider declaration's id, e.g. `codex` or `acp-cursor`), not the plugin\n * id. Letters, digits, `-`, `_`.\n */\n providerId: string;\n /** Inline, theme-aware mark. Receives the host's sizing/color className. */\n icon: ComponentType<{\n className?: string;\n }>;\n}\ninterface PluginAppSlots {\n homepageSection(registration: PluginHomepageSectionRegistration): void;\n settingsSection(registration: PluginSettingsSectionRegistration): void;\n navPanel(registration: PluginNavPanelRegistration): void;\n /**\n * Add an action to an existing thread's panel launcher. This slot is\n * thread-only; use `experimental_newThreadPanelAction` for root compose.\n */\n threadPanelAction(registration: PluginThreadPanelActionRegistration): void;\n /**\n * Add an action to the root New thread screen's panel launcher (see\n * {@link PluginNewThreadPanelActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_newThreadPanelAction(registration: PluginNewThreadPanelActionRegistration): void;\n pendingInteraction(registration: PluginPendingInteractionRegistration): void;\n sidebarFooterAction(registration: PluginSidebarFooterActionRegistration): void;\n /**\n * Replace the sidebar's thread list (see\n * {@link PluginThreadListRegistration}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_threadList(registration: PluginThreadListRegistration): void;\n /**\n * Render a component in the thread header's action row (see\n * {@link PluginThreadHeaderActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_threadHeaderAction(registration: PluginThreadHeaderActionRegistration): void;\n fileOpener(registration: PluginFileOpenerRegistration): void;\n messageDirective(registration: PluginMessageDirectiveRegistration): void;\n messageAction(registration: PluginMessageActionRegistration): void;\n /**\n * Draw one agent provider's icon with an inline React component instead of\n * its ``-rendered logo file (see\n * {@link PluginProviderIconRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_providerIcon(registration: PluginProviderIconRegistration): void;\n}\ninterface PluginAppComposer {\n customize(registration: ComposerCustomization): void;\n}\n/** Stable lifecycle values for one content-script instance in one bb client. */\ninterface PluginContentScriptContext {\n /** The id of the plugin that owns this script. */\n readonly pluginId: string;\n /** Monotonic per-client generation, starting at 1. */\n readonly generation: number;\n /** Aborted before cleanup begins on replacement, deactivation, or teardown. */\n readonly signal: AbortSignal;\n /**\n * Persistently decorate any thread row for this plugin generation.\n *\n * The status is owned by the frontend generation and therefore survives\n * route changes. Passing `null` clears the plugin's status for that thread.\n * The host clears every remaining status when the frontend generation\n * deactivates.\n *\n * Optional so bundles can feature-detect support while this experimental\n * surface rolls out across 0.x clients.\n */\n readonly experimental_setThreadRowStatus?: (threadId: string, status: PluginComposerThreadRowStatus | null) => void;\n}\n/** Cleanup returned by a frontend content script. */\ntype PluginContentScriptDisposer = () => void | Promise;\n/**\n * Trusted same-origin JavaScript/TypeScript mounted once per active frontend\n * generation in each bb app window or browser tab.\n */\ninterface PluginContentScriptRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Install behavior into the bb app shell. The host awaits a returned\n * promise, contains failures, and calls the returned disposer exactly once.\n */\n mount(context: PluginContentScriptContext): void | PluginContentScriptDisposer | Promise;\n}\n/** Lifecycle surface for trusted frontend content scripts. */\ninterface PluginAppContentScripts {\n register(registration: PluginContentScriptRegistration): void;\n}\ninterface PluginAppBuilder {\n slots: PluginAppSlots;\n composer: PluginAppComposer;\n contentScripts: PluginAppContentScripts;\n}\ntype PluginAppSetup = (app: PluginAppBuilder) => void;\n/**\n * The opaque product of `definePluginApp` — a plugin's `app.tsx` default\n * export. The host re-runs `setup` against a fresh collector on every\n * (re)interpretation, replacing that plugin's registrations wholesale.\n */\ninterface PluginAppDefinition {\n /** Brand the host checks before interpreting a bundle's default export. */\n readonly __bbPluginApp: true;\n readonly setup: PluginAppSetup;\n}\ninterface PluginRpcClient {\n /**\n * Invoke one of the plugin's `bb.rpc` methods (POST\n * /api/v1/plugins/<id>/rpc/<method>). Resolves with the method's\n * inferred output; rejects with an `Error` carrying the server's message,\n * stable `code`, and validation `issues` when present.\n */\n call>(method: Method, ...args: PluginRpcCallArgs): Promise>;\n}\ninterface PluginSettingsState {\n /**\n * Effective non-secret setting values (secret settings are excluded —\n * read them server-side). Undefined while loading or unavailable.\n */\n values: Record | undefined;\n isLoading: boolean;\n}\n/** State of the app's shared realtime connection to the bb server. */\ntype PluginRealtimeConnectionState = \"connected\" | \"connecting\" | \"reconnecting\";\n/** Where `useComposer()` writes. */\ntype PluginComposerScope = {\n kind: \"thread\";\n threadId: string;\n} | {\n kind: \"queued-message\";\n threadId: string;\n queuedMessageId: string;\n} | {\n kind: \"side-chat\";\n projectId: string;\n parentThreadId: string;\n tabId: string;\n childThreadId: string | null;\n} | {\n kind: \"new-thread\";\n /** Root compose's effective selected project; null only while unresolved. */\n projectId: string | null;\n};\n/** One plugin-owned composer customization registration. */\ninterface ComposerCustomization {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Composer kinds where this customization is active; omit for all kinds. */\n scopes?: readonly PluginComposerScope[\"kind\"][];\n actions?: readonly {\n id: string;\n component: ComponentType;\n }[];\n banners?: readonly {\n id: string;\n /** Host chrome around the banner. Defaults to `\"card\"`. */\n chrome?: \"bare\" | \"card\";\n component: ComponentType;\n }[];\n plusMenu?: readonly ComposerPlusMenuItem[];\n richText?: ComposerRichTextSpec;\n}\n/** Host-rendered menu row in the composer's `+` menu. */\ninterface ComposerPlusMenuItem {\n id: string;\n label: string;\n /** BB icon name; unknown names fall back to the generic plugin icon. */\n icon?: string;\n /** Accessible description for the host-rendered row. */\n description?: string;\n disabled?: boolean | ((view: ComposerView) => boolean);\n run(context: {\n composer: PluginComposerApi;\n view: ComposerView;\n }): void | Promise;\n}\n/** Reactive read-side of the composer a plugin surface is mounted in. */\ninterface ComposerView {\n scope: PluginComposerScope;\n layout: \"compact\" | \"expanded\" | \"zen\";\n draft: {\n text: string;\n isEmpty: boolean;\n attachmentCount: number;\n };\n run: {\n isRunning: boolean;\n isSubmitting: boolean;\n };\n}\ninterface ComposerRichTextSpec {\n /** Content-derived paint: match ranges receive `className`; text is never mutated. */\n effects?: readonly {\n id: string;\n /** Plain-text offsets into the current structured draft. */\n match(text: string): readonly {\n from: number;\n to: number;\n }[];\n className: string;\n }[];\n /** Debounced, read-only observation of the structured draft. */\n onDraftChange?(draft: ComposerStructuredDraft, view: ComposerView): void;\n}\ninterface ComposerStructuredDraft {\n text: string;\n mentions: readonly {\n from: number;\n to: number;\n provider: string;\n id: string;\n label: string;\n }[];\n}\n/** Host-rendered paint applied to the editable composer text. */\ninterface PluginComposerTextEffect {\n className: string;\n}\n/** Host-rendered status that temporarily replaces a thread's draft glyph. */\ninterface PluginComposerThreadRowStatus {\n /** BB icon-name hint; unknown names fall back to the generic plugin icon. */\n icon: string;\n /** Accessible label for the status glyph. */\n label: string;\n /**\n * Semantic host treatment for the status glyph. `running` automatically\n * shimmers; terminal `success` and `error` tones are static. Defaults to the\n * neutral tone.\n */\n tone?: \"default\" | \"error\" | \"running\" | \"success\";\n}\n/** An @-mention pill bound to one of the calling plugin's mention providers. */\ninterface PluginComposerMention {\n /** Mention provider id registered by THIS plugin via `bb.ui.registerMentionProvider`. */\n provider: string;\n /** Item id your provider's `resolve` will receive at send time. */\n id: string;\n /** Pill text shown in the composer. */\n label: string;\n}\n/**\n * Programmatic access to the chat composer draft — the same shared draft the\n * built-in \"Add to chat\" affordances (file preview, diff, terminal selections)\n * write to. While a queued message is being edited, writes land in that\n * message's inline editor. In a side chat, writes land in the visible side-chat\n * draft. Otherwise, inside a thread context writes land in that thread's draft;\n * anywhere else (nav panel, homepage section) they seed the new-thread composer\n * draft, which persists until the user sends or clears it.\n */\ninterface PluginComposerApi {\n scope: PluginComposerScope;\n /** Current plain text for this composer scope. */\n readonly text: string;\n /**\n * Replace the draft's plain text. Attachments are preserved. Inline mentions\n * outside the changed range are preserved and rebased; mentions overlapped\n * by the replacement are removed because their text representation changed.\n */\n setText(next: string): void;\n /**\n * Replace the draft's plain text from the latest committed value. Uses the\n * same structured-state reconciliation as `setText`.\n */\n updateText(updater: (current: string) => string): void;\n /** Clear plain text without clearing independently attached files. */\n clear(): void;\n /**\n * Apply a host-rendered effect to this composer's editable text, or clear it.\n * Effects are scoped to the calling plugin and automatically clear when the\n * slot unmounts or its composer scope changes.\n */\n setTextEffect(effect: PluginComposerTextEffect | null): void;\n /**\n * Lock or unlock editing for this composer. Locks are scoped to the calling\n * plugin and automatically release when the slot unmounts or its composer\n * scope changes.\n */\n setInputLock(locked: boolean): void;\n /**\n * Append text to the draft as a `> ` blockquote block and focus the\n * composer. Blank text is a no-op. This is the \"reference this selection\n * in chat\" primitive.\n */\n addQuote(text: string): void;\n /**\n * Insert an @-mention pill that resolves through this plugin's mention\n * provider at send time — the durable way to reference an entity whose\n * content should be fetched fresh when the message is sent.\n */\n insertMention(mention: PluginComposerMention): void;\n /** Focus the composer caret at the end of the draft. */\n focus(): void;\n}\n/**\n * A consumer-supplied action on the messages of one `ThreadChat` instance,\n * rendered in the embedded timeline's per-message action bar alongside the\n * native and slot-registered actions. Unlike the `messageAction` slot this is\n * scoped to the rendering component, not registered globally.\n */\ninterface ThreadChatMessageAction {\n /** Unique within this ThreadChat instance; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Message roles the action applies to. Omitted = both user and assistant\n * messages.\n */\n roles?: readonly (\"assistant\" | \"user\")[];\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(message: ThreadChatMessageReference): void | Promise;\n}\n/**\n * Props of the host-owned `ThreadChat` component — one thread's chat\n * (timeline, and for the composer variants the full send/queue/draft\n * engine), rendered by the BB app inside a plugin slot. This is the\n * deliberate exception to the no-host-components rule (§5.5): a stable\n * product capability, not a UI kit. Versioned additive like slot props;\n * internal timeline rows, query hooks, and prompt-box configuration are\n * deliberately not exposed.\n */\ninterface ThreadChatProps {\n threadId: string;\n /**\n * \"full\" (default) is the page presentation (centered reading width);\n * \"compact\" is the side-panel presentation; \"timeline\" renders the\n * transcript without a composer.\n */\n variant?: \"compact\" | \"full\" | \"timeline\";\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the composer (ignored by `variant: \"timeline\"`). */\n focusRequest?: number;\n /**\n * Who controls the permission mode sends run with. \"inherit\" (default)\n * pins every send to the thread's own resolved default and renders the\n * picker as a dimmed label — a plugin surface can never widen it.\n * \"editable\" gives this chat its own picker, so the user can raise or\n * lower permissions for this thread independently of the thread it was\n * forked from. Ignored by `variant: \"timeline\"` (no composer).\n */\n permissionPolicy?: \"editable\" | \"inherit\";\n className?: string;\n /** Rendered above the conversation, scrolling with it. */\n leadingContent?: ReactNode;\n /**\n * Actions rendered in this instance's per-message action bar (see\n * {@link ThreadChatMessageAction}).\n */\n messageActions?: readonly ThreadChatMessageAction[];\n}\n/**\n * Every selection the composer resolved, JSON-serializable so a plugin can\n * forward it to its own backend rpc verbatim and hand it straight to\n * `bb.sdk.threads.spawn`.\n *\n * The split is deliberate: the composer owns *user selections*, the plugin\n * owns *filing and attribution*. `bb.sdk.threads.spawn` auto-fills\n * `origin: \"plugin\"` and `originPluginId`, so a thread created this way stays\n * attributed to the plugin — which it would not be if the component created\n * the thread itself. The plugin adds `sectionId`, `parentThreadId`, `title`,\n * and `visibility` to the request on its own; they are deliberately not\n * composer props.\n */\ninterface NewThreadRequest {\n /**\n * The selected project id. Choosing \"Don't work in a project\" submits BB's\n * personal-project id (not `null`) together with a `personal` workspace\n * environment. Forward those fields unchanged to `threads.spawn`; if the\n * plugin needs project metadata, request it from the plugin backend with\n * `bb.sdk.projects.list({ includePersonal: true })`.\n */\n projectId: string;\n providerId: string;\n model: string;\n reasoningLevel: ReasoningLevel;\n permissionMode: PermissionMode;\n /** Omitted when the selected provider has no service tiers. */\n serviceTier?: ServiceTier;\n /**\n * Per-field provenance (caller-explicit vs. default) for the execution\n * options above, forwarded to `spawn` so the server records what the user\n * actually chose.\n */\n executionInputSources: CreateExecutionInputSources;\n environment: CreateThreadEnvironmentArgs;\n input: PromptInput[];\n}\n/**\n * Props of the host-owned `experimental_NewThreadComposer` component — bb's\n * full new-thread compose surface (prompt editor with @-mentions and expand,\n * attachments, provider/model/reasoning picker, voice, submit, and the row\n * beneath with project, environment, branch-from, and permission mode),\n * rendered by the BB app inside a plugin slot.\n *\n * It is the create-side counterpart to `ThreadChat`: same deliberate\n * exception to the no-host-components rule (§5.5), same additive versioning.\n */\ninterface NewThreadComposerProps {\n /**\n * Seeds the project picker. The user can change it, including choosing\n * \"Don't work in a project\"; see {@link NewThreadRequest.projectId} for the\n * submitted projectless shape.\n */\n defaultProjectId?: string;\n /**\n * Seeds the provider picker. Like every `default*` prop this is a SEED, not\n * a controlled value: the composer stays uncontrolled, the user can change\n * it, and when omitted the composer falls back to the project's remembered\n * execution defaults exactly as before. When provided it takes precedence\n * over those project defaults.\n *\n * Re-seeding: the `default*` props are value-compared each render. When any\n * of them changes after mount, the composer re-seeds EVERY execution and\n * environment selection from the new props — including selections the user\n * had already touched — so switching between two saved records in the same\n * mounted composer reloads that record's values (the same rule\n * `defaultProjectId` already follows).\n *\n * Every seeded field is reported as caller-explicit in the submitted\n * request's `executionInputSources`. That is what makes the seed survive\n * `threads.spawn`: the server drops a requested `providerId`/`model` that\n * carries no provenance source and re-derives it from the project's stored\n * defaults, which would silently undo the seed.\n */\n defaultProviderId?: string;\n /** Seeds the model picker. Same seed semantics as {@link defaultProviderId}. */\n defaultModel?: string;\n /**\n * Seeds the reasoning-level picker. Same seed semantics as\n * {@link defaultProviderId}. If the seeded model does not support this\n * level, the composer reconciles to the closest supported one.\n */\n defaultReasoningLevel?: ReasoningLevel;\n /**\n * Seeds the service-tier picker. Same seed semantics as\n * {@link defaultProviderId}. Ignored (and omitted from the submitted\n * request) when the selected provider has no service tiers.\n */\n defaultServiceTier?: ServiceTier;\n /** Seeds the permission-mode picker. Same seed semantics as {@link defaultProviderId}. */\n defaultPermissionMode?: PermissionMode;\n /**\n * Seeds the environment and branch pickers from a previously submitted\n * `NewThreadRequest.environment`. Same seed semantics as\n * {@link defaultProviderId}: a seed the user can change, taking precedence\n * over the composer's own environment default when provided.\n *\n * Round trip: feeding a submitted request's `environment` back in and\n * resubmitting untouched reproduces an equivalent environment, with these\n * documented limits — the composer cannot represent every args variant:\n *\n * - `{ type: \"project-default\" }` seeds nothing; the composer resolves its\n * own default and submits that concrete environment instead.\n * - A `host` environment whose host no longer exists (or whose project has\n * no source on it) falls back to the composer's default host, exactly as\n * the primary compose surface would.\n * - A `reuse` environment whose worktree no longer has unarchived threads\n * falls back the same way.\n * - An `unmanaged` workspace's `path` has no composer control; the seeded\n * selection submits `path: null` (the host's configured checkout). The\n * composer itself never produces a non-null `path`, so real round trips\n * are unaffected.\n * - A `managed-worktree` with `baseBranch: { kind: \"default\" }` leaves the\n * branch picker on its default, which may resolve to a named base branch\n * when the project configures a dedicated worktree base — the same branch\n * the original `default` submission would have created from.\n */\n defaultEnvironment?: CreateThreadEnvironmentArgs;\n /** Seeds the draft, only while the draft is still empty. */\n initialPrompt?: string;\n placeholder?: string;\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the editor. */\n focusRequest?: number;\n className?: string;\n /**\n * Where the draft persists. Drafts survive reloads and are shared by every\n * composer using the same key; defaults to a key scoped to this plugin.\n */\n draftKey?: string;\n /**\n * Fires on submit with every selection resolved. The draft clears when this\n * resolves and is KEPT if it throws, so a failed create never loses what the\n * user typed.\n */\n onSubmit: (request: NewThreadRequest) => void | Promise;\n}\n/**\n * Props of the host-owned `Markdown` component — bb's chat message renderer\n * (the same typography, spacing, and code styling as timeline messages).\n * Use it wherever plugin UI quotes or previews message content so it reads\n * like the rest of the chat. Like `ThreadChat`, this is a stable product\n * capability, not a UI kit; renderer internals stay private.\n */\ninterface MarkdownProps {\n /** Markdown source, rendered exactly like a chat message body. */\n content: string;\n className?: string;\n}\n/** Current app selection, derived from the route. */\ninterface BbContext {\n projectId: string | null;\n threadId: string | null;\n}\ninterface BbNavigate {\n toThread(threadId: string): void;\n toProject(projectId: string): void;\n /**\n * Navigate to one of this plugin's own nav panels by its `path`.\n * `subPath` targets a location inside the panel (the component's\n * `subPath` prop); `replace` swaps the current history entry instead of\n * pushing — use it for redirects so back does not bounce.\n */\n toPluginPanel(path: string, options?: {\n subPath?: string;\n replace?: boolean;\n }): void;\n /**\n * Navigate to the root compose surface (the new-thread screen). Pass\n * `initialPrompt` to seed the composer draft and `focusPrompt` to focus the\n * composer on arrival — the pairing behind \"Create via chat\" style entry\n * points that drop the user into chat with a prefilled prompt.\n */\n toCompose(options?: {\n initialPrompt?: string;\n focusPrompt?: boolean;\n }): void;\n /**\n * Open one of this plugin's registered thread-panel actions in the current\n * thread surface. Returns false when the surface has no thread side panel or\n * the action is unavailable.\n */\n openThreadPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * Everything `@get-bb/plugin-sdk/app` resolves to at runtime. The BB app builds\n * the real implementation and `satisfies` this interface; `bb plugin build`\n * shims the specifier to that object on `globalThis.__bbPluginRuntime`.\n */\ninterface PluginSdkApp {\n definePluginApp(setup: PluginAppSetup): PluginAppDefinition;\n useRpc(): PluginRpcClient;\n useRealtime(channel: string, handler: (payload: unknown) => void): void;\n /**\n * Observe the same shared connection that delivers `useRealtime` signals.\n * Use a subsequent transition to `connected` to reconcile server state that\n * may have changed while ephemeral signals could not be delivered. The first\n * connection can transition from `connecting` and is not a reconnection.\n */\n useRealtimeConnectionState(): PluginRealtimeConnectionState;\n useSettings(): PluginSettingsState;\n useBbContext(): BbContext;\n useBbNavigate(): BbNavigate;\n useComposer(): PluginComposerApi;\n /**\n * The sidebar's live thread view (see {@link PluginSidebarThreadsState}).\n * Reads the host's own cache and realtime subscriptions, so it costs no\n * extra request and updates exactly when the built-in sidebar does.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreads(): PluginSidebarThreadsState;\n /**\n * Thread actions bound to the host's mutations (see\n * {@link PluginSidebarThreadActions}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_useSidebarThreadActions(): PluginSidebarThreadActions;\n /**\n * The pull request for one thread's branch (see\n * {@link PluginSidebarThreadPullRequestState}).\n *\n * Per row and opt-in, because it costs a git-host lookup: it is NOT on the\n * thread payload every sidebar loads. Threads sharing an environment share\n * one query, and the host owns the polling and staleness rules — an open PR\n * with pending checks refreshes, a merged one does not.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadPullRequest(threadId: string): PluginSidebarThreadPullRequestState;\n /**\n * Per-row drag-to-split support (see {@link PluginSidebarThreadSplit}).\n * Call it once per rendered row, like the built-in sidebar does.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadSplit(threadId: string): PluginSidebarThreadSplit;\n /**\n * The host-owned chat component (see {@link ThreadChatProps}). Together\n * with `Markdown`, the only components the SDK ships — everything else\n * stays vendored per §5.5.\n */\n ThreadChat: ComponentType;\n /**\n * The host-owned chat-message markdown renderer (see\n * {@link MarkdownProps}).\n */\n Markdown: ComponentType;\n /**\n * The host-owned new-thread compose surface (see\n * {@link NewThreadComposerProps}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_NewThreadComposer: ComponentType;\n useComposerView(): ComposerView;\n}\n\ndeclare const definePluginApp: (setup: PluginAppSetup) => PluginAppDefinition;\ndeclare const ThreadChat: react.ComponentType;\ndeclare const Markdown: react.ComponentType;\ndeclare const experimental_NewThreadComposer: react.ComponentType;\ndeclare const useRpc: , StandardSchemaV1>>>>() => PluginRpcClient;\ndeclare const useRealtime: (channel: string, handler: (payload: unknown) => void) => void;\ndeclare const useRealtimeConnectionState: () => PluginRealtimeConnectionState;\ndeclare const useSettings: () => PluginSettingsState;\ndeclare const useBbContext: () => BbContext;\ndeclare const useBbNavigate: () => BbNavigate;\ndeclare const useComposer: () => PluginComposerApi;\ndeclare const useComposerView: () => ComposerView;\ndeclare const experimental_useSidebarThreads: () => PluginSidebarThreadsState;\ndeclare const experimental_useSidebarThreadActions: () => PluginSidebarThreadActions;\ndeclare const experimental_useSidebarThreadPullRequest: (threadId: string) => PluginSidebarThreadPullRequestState;\ndeclare const experimental_useSidebarThreadSplit: (threadId: string) => PluginSidebarThreadSplit;\n\nexport { Markdown, ThreadChat, definePluginApp, experimental_NewThreadComposer, experimental_useSidebarThreadActions, experimental_useSidebarThreadPullRequest, experimental_useSidebarThreadSplit, experimental_useSidebarThreads, useBbContext, useBbNavigate, useComposer, useComposerView, useRealtime, useRealtimeConnectionState, useRpc, useSettings };\nexport type { BbContext, BbNavigate, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, JsonValue, MarkdownProps, NewThreadComposerProps, NewThreadRequest, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderIconRegistration, PluginRealtimeConnectionState, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginTargetedPanelActionOpenOptions, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps };\n"; +export const PLUGIN_SDK_APP_DTS = "// Portable type declarations for `@get-bb/plugin-sdk`. Unpublished BB\n// workspace contracts are flattened; public subpaths may reuse the\n// package root without requiring any other @bb/* package.\n//\n// Confused by the API, or need a symbol that isn't here? Clone the BB repo\n// and read the real source: https://github.com/get-bb/bb\n\nimport * as react from 'react';\nimport { ComponentType, ReactNode } from 'react';\nimport { z } from 'zod';\n\n/** A JSON-safe path segment reported by a Standard Schema validation issue. */\ntype PluginRpcIssuePathSegment = string | number;\n/** Validator-neutral validation detail carried by an RPC error envelope. */\ninterface PluginRpcValidationIssue {\n message: string;\n path?: PluginRpcIssuePathSegment[];\n}\n/** Stable wire error categories for plugin RPC. */\ntype PluginRpcErrorCode = \"handler_error\" | \"invalid_input\" | \"invalid_json\" | \"invalid_output\" | \"non_json_result\" | \"unknown_method\";\n/** Structured RPC failure returned as `{ ok: false, error }`. */\ninterface PluginRpcError {\n code: PluginRpcErrorCode;\n message: string;\n issues?: PluginRpcValidationIssue[];\n}\n/**\n * The validator-neutral subset of Standard Schema v1 used by plugin RPC.\n * Zod 4 schemas implement this interface directly; other validators can do\n * the same without becoming part of BB's public protocol.\n */\ninterface StandardSchemaV1 {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardSchemaV1Result | Promise>;\n readonly types?: {\n readonly input: Input;\n readonly output: Output;\n };\n };\n}\ntype StandardSchemaV1Result = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: readonly StandardSchemaV1Issue[];\n};\ninterface StandardSchemaV1Issue {\n readonly message: string;\n readonly path?: PropertyKey | readonly (PropertyKey | {\n readonly key: PropertyKey;\n })[];\n}\ntype StandardSchemaV1InferInput = NonNullable[\"input\"];\ntype StandardSchemaV1InferOutput = NonNullable[\"output\"];\ninterface PluginRpcMethodContract {\n readonly input: InputSchema;\n readonly output: OutputSchema;\n}\ntype PluginRpcContract = Readonly>;\ntype PluginRpcHandlers = {\n [Method in keyof Contract]: (input: StandardSchemaV1InferOutput) => StandardSchemaV1InferInput | Promise>;\n};\ntype PluginRpcCallInput = StandardSchemaV1InferInput;\ntype PluginRpcCallArgs = null extends PluginRpcCallInput ? [input?: PluginRpcCallInput] : [input: PluginRpcCallInput];\ntype PluginRpcResult = StandardSchemaV1InferOutput;\n\ndeclare const reasoningLevelSchema: z.ZodEnum<{\n high: \"high\";\n low: \"low\";\n max: \"max\";\n medium: \"medium\";\n none: \"none\";\n ultra: \"ultra\";\n ultracode: \"ultracode\";\n xhigh: \"xhigh\";\n}>;\ntype ReasoningLevel = z.infer;\ndeclare const serviceTierSchema: z.ZodEnum<{\n default: \"default\";\n fast: \"fast\";\n}>;\ntype ServiceTier = z.infer;\ndeclare const permissionModeSchema: z.ZodEnum<{\n \"accept-edits\": \"accept-edits\";\n auto: \"auto\";\n full: \"full\";\n}>;\ntype PermissionMode = z.infer;\ndeclare const promptInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{\n mentions: z.ZodDefault, z.ZodDiscriminatedUnion<[z.ZodObject<{\n kind: z.ZodLiteral<\"thread\">;\n label: z.ZodString;\n projectId: z.ZodOptional;\n threadId: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n kind: z.ZodLiteral<\"project\">;\n label: z.ZodString;\n projectId: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n kind: z.ZodLiteral<\"section\">;\n label: z.ZodString;\n sectionId: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n entryKind: z.ZodEnum<{\n directory: \"directory\";\n file: \"file\";\n }>;\n kind: z.ZodLiteral<\"path\">;\n label: z.ZodString;\n path: z.ZodString;\n source: z.ZodEnum<{\n \"thread-storage\": \"thread-storage\";\n workspace: \"workspace\";\n }>;\n }, z.core.$strip>, z.ZodObject<{\n argumentHint: z.ZodNullable;\n kind: z.ZodLiteral<\"command\">;\n label: z.ZodString;\n name: z.ZodString;\n origin: z.ZodEnum<{\n builtin: \"builtin\";\n project: \"project\";\n user: \"user\";\n }>;\n source: z.ZodEnum<{\n command: \"command\";\n skill: \"skill\";\n }>;\n trigger: z.ZodEnum<{\n \"/\": \"/\";\n }>;\n }, z.core.$strip>, z.ZodObject<{\n icon: z.ZodOptional>;\n itemId: z.ZodString;\n kind: z.ZodLiteral<\"plugin\">;\n label: z.ZodString;\n pluginId: z.ZodString;\n }, z.core.$strip>], \"kind\">>;\n start: z.ZodNumber;\n }, z.core.$strip>>>;\n text: z.ZodString;\n type: z.ZodLiteral<\"text\">;\n visibility: z.ZodOptional>;\n}, z.core.$strip>, z.ZodObject<{\n type: z.ZodLiteral<\"image\">;\n url: z.ZodString;\n visibility: z.ZodOptional>;\n}, z.core.$strip>, z.ZodObject<{\n path: z.ZodString;\n type: z.ZodLiteral<\"localImage\">;\n visibility: z.ZodOptional>;\n}, z.core.$strip>, z.ZodObject<{\n mimeType: z.ZodOptional;\n name: z.ZodOptional;\n path: z.ZodString;\n sizeBytes: z.ZodOptional;\n type: z.ZodLiteral<\"localFile\">;\n visibility: z.ZodOptional>;\n}, z.core.$strip>], \"type\">;\ntype PromptInput = z.infer;\n\ndeclare const createThreadEnvironmentArgsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{\n environmentId: z.ZodString;\n type: z.ZodLiteral<\"reuse\">;\n}, z.core.$strip>, z.ZodObject<{\n hostId: z.ZodOptional;\n type: z.ZodLiteral<\"host\">;\n workspace: z.ZodDiscriminatedUnion<[z.ZodObject<{\n branch: z.ZodOptional;\n name: z.ZodString;\n }, z.core.$strict>, z.ZodObject<{\n baseBranch: z.ZodString;\n kind: z.ZodLiteral<\"new\">;\n }, z.core.$strict>], \"kind\">>;\n path: z.ZodNullable;\n type: z.ZodLiteral<\"unmanaged\">;\n }, z.core.$strip>, z.ZodObject<{\n baseBranch: z.ZodDiscriminatedUnion<[z.ZodObject<{\n kind: z.ZodLiteral<\"named\">;\n name: z.ZodString;\n }, z.core.$strip>, z.ZodObject<{\n kind: z.ZodLiteral<\"default\">;\n }, z.core.$strip>], \"kind\">;\n type: z.ZodLiteral<\"managed-worktree\">;\n }, z.core.$strip>, z.ZodObject<{\n type: z.ZodLiteral<\"personal\">;\n }, z.core.$strip>], \"type\">;\n}, z.core.$strip>, z.ZodObject<{\n type: z.ZodLiteral<\"project-default\">;\n}, z.core.$strip>], \"type\">;\ntype CreateThreadEnvironmentArgs = z.infer;\n\ndeclare const createExecutionInputSourcesSchema: z.ZodObject<{\n model: z.ZodOptional>;\n permissionMode: z.ZodOptional>;\n providerId: z.ZodOptional>;\n reasoningLevel: z.ZodOptional>;\n serviceTier: z.ZodOptional>;\n}, z.core.$strict>;\ntype CreateExecutionInputSources = z.infer;\n\n/**\n * A value that survives a JSON round trip without coercion or data loss.\n *\n * Host boundaries still validate values at runtime because TypeScript cannot\n * exclude non-finite numbers and plugin bundles can bypass static types.\n */\ntype JsonValue = string | number | boolean | null | JsonValue[] | {\n [key: string]: JsonValue;\n};\n\n/**\n * The `@get-bb/plugin-sdk/app` contract (plugin design §5.2) — pure types with no\n * side effects. The BB app imports these to keep its real implementation in\n * sync (`satisfies PluginSdkApp`). Plugin authors import the same shapes through\n * `@get-bb/plugin-sdk/app`.\n *\n * Per-slot props are versioned contracts: additive-only within an SDK major.\n */\n/** Props passed to a `homepageSection` component. */\ninterface PluginHomepageSectionProps {\n /** Project in view on the compose surface; null when none is selected. */\n projectId: string | null;\n}\n/**\n * Props passed to a `settingsSection` component.\n *\n * Deliberately empty in V1; versioned additive like the other slot props.\n */\ninterface PluginSettingsSectionProps {\n}\n/** Props passed to a `navPanel` component (it owns its whole route). */\ninterface PluginNavPanelProps {\n /**\n * The route remainder after the panel root, \"\" at the root. The panel's\n * route is `/plugins///*`, so a deep link like\n * `/plugins/notes/notes/work/ideas.md` renders the panel with\n * `subPath: \"work/ideas.md\"`. Navigate within the panel via\n * `useBbNavigate().toPluginPanel(path, { subPath })` — browser\n * back/forward then walks panel-internal history.\n */\n subPath: string;\n}\n/**\n * Props passed to a panel tab opened by a `threadPanelAction`.\n *\n * This slot is rendered only for an existing thread. Use\n * `experimental_newThreadPanelAction` for the root New thread screen.\n */\ninterface PluginThreadPanelProps {\n threadId: string;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\n/** Props passed to a panel tab opened by `experimental_newThreadPanelAction`. */\ninterface PluginNewThreadPanelProps {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * The JSON value the action's `openPanel` call passed (round-tripped\n * through persistence, so the tab restores across reloads); null when the\n * action opened the panel without params.\n */\n params: JsonValue | null;\n}\ninterface PluginPendingInteractionView {\n id: string;\n threadId: string;\n title: string;\n payload: JsonValue;\n createdAt: number;\n expiresAt: number | null;\n}\ninterface PluginPendingInteractionProps {\n interaction: PluginPendingInteractionView;\n submit(value: JsonValue): Promise;\n cancel(): Promise;\n}\n/**\n * Props for a `sidebarFooterAction` — host-rendered (no plugin component).\n * Deliberately empty; the registration's `run` carries the behavior.\n */\ninterface PluginSidebarFooterActionProps {\n}\n/**\n * Props passed to an `experimental_threadList` component — the sidebar's\n * scrolling thread area, replaced wholesale by one plugin.\n */\ninterface PluginThreadListProps {\n /** The thread the route currently shows; null on non-thread routes. */\n activeThreadId: string | null;\n /** The project the route currently shows; null when none is selected. */\n activeProjectId: string | null;\n /** True on phone-width viewports and coarse pointers. */\n isCompactViewport: boolean;\n /**\n * Call after the user opens a thread. It closes the mobile sidebar drawer,\n * and it clears the host search field on every viewport. Always call it, or\n * the sidebar stays in search mode after the thread opens.\n */\n onNavigate: () => void;\n /**\n * The host search field's current text, or \"\" when the field is closed.\n * The host owns that field, so a plugin list filters by this rather than\n * shipping a second search box.\n */\n searchQuery: string;\n /**\n * BB's thread list, bound to this sidebar instance. Render it to delegate\n * conditionally without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Props passed to an `experimental_threadHeaderAction` component, rendered in\n * the thread header's action row.\n */\ninterface PluginThreadHeaderActionProps {\n /**\n * The thread this header belongs to. Never null: the slot is not rendered\n * on the compose screen or other non-thread routes. A split layout renders\n * one header per pane, so the component mounts once per visible thread,\n * each with its own id — keep per-thread state in the component, never in a\n * module-level singleton.\n */\n threadId: string;\n projectId: string;\n /**\n * True on phone-width viewports and coarse pointers. Collapse to an\n * icon-sized control when it is true — the row is short.\n */\n isCompactViewport: boolean;\n}\n/**\n * Where a file being opened by a `fileOpener` lives. `path` semantics follow\n * the source: workspace paths are relative to the environment's worktree,\n * thread-storage paths are relative to the thread's storage root, host paths\n * are absolute on the thread's host.\n */\ninterface PluginFileOpenerSource {\n kind: \"host\" | \"thread-storage\" | \"workspace\";\n threadId: string | null;\n environmentId: string | null;\n projectId: string | null;\n}\n/** Props passed to a `fileOpener` component (rendered as a panel file tab). */\ninterface PluginFileOpenerProps {\n path: string;\n source: PluginFileOpenerSource;\n /**\n * BB's file preview, bound to this file. Render it to delegate conditionally\n * without re-entering plugin replacement resolution.\n *\n * @experimental Audit before relying on this as a stable contract.\n */\n experimental_Original: ComponentType;\n}\n/**\n * Message context passed to a `messageDirective` component — the assistant\n * (or nested agent) message that contained the directive.\n */\ninterface PluginMessageDirectiveMessage {\n id: string;\n threadId: string;\n turnId: string | null;\n projectId: string | null;\n}\n/**\n * Open a worktree-relative file in the host's workspace file viewer. Returns\n * true when the host accepted the path; false when the path is invalid or the\n * viewer declined it.\n */\ntype PluginMessageDirectiveOpenWorkspaceFile = (path: string) => boolean;\n/**\n * Props passed to a `messageDirective` component. Attributes are untrusted\n * strings parsed from the directive; the plugin validates its own fields.\n */\ninterface PluginMessageDirectiveProps {\n /** Parsed, untrusted directive attributes (e.g. `{ file: \"demo.html\" }`). */\n attributes: Readonly>;\n /** Original directive source text (useful for diagnostics / crash fallback). */\n source: string;\n message: PluginMessageDirectiveMessage;\n /**\n * Opens a worktree-relative file in the host's workspace file viewer. Null\n * when the message surface has no workspace viewer available.\n */\n openWorkspaceFile: PluginMessageDirectiveOpenWorkspaceFile | null;\n}\ninterface PluginHomepageSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n component: ComponentType;\n}\ninterface PluginSettingsSectionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Optional host-rendered section heading. */\n title?: string;\n /**\n * Optional one-line host-rendered subheading under `title`, in the built-in\n * SettingsSection idiom (ignored when `title` is absent).\n */\n description?: string;\n component: ComponentType;\n}\ninterface PluginNavPanelRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /** URL segment under `/plugins//`; letters, digits, `-`, `_`. */\n path: string;\n component: ComponentType;\n /**\n * Ordered, non-closable tabs shown in this page's host-owned right panel.\n * BB owns selection and persistence and always includes its native Browser\n * and Terminal tools beside them. Components mount only while their tab is\n * active and the panel is open, and receive the same `subPath` as the page\n * component.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_fixedTabs?: readonly {\n /** Unique within this nav panel; letters, digits, `-`, `_`. */\n id: string;\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n component: ComponentType;\n /** `flush` lets the component own padding and scrolling. */\n layout?: \"flush\" | \"padded\";\n }[];\n /**\n * Optional presentational component rendered at the trailing edge of this\n * panel's sidebar row. It receives no props so it can own a narrow live\n * value through the ordinary SDK hooks without coupling that state to the\n * host sidebar. The host does not mount it on compact viewports and clips it\n * to a small, single-line box on wider viewports. It shares the trailing\n * action column, fading out for the host's options button on hover or focus;\n * do not render controls or rely on unbounded content here.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_sidebarAccessory?: ComponentType;\n /**\n * Optional component rendered on the right side of the shared title bar\n * (e.g. a sync button or a count). Contained separately from the body: a\n * throwing headerContent is hidden without breaking the title bar.\n */\n headerContent?: ComponentType;\n}\n/**\n * What a plugin action passes when it asks the host to open one of its panel\n * tabs. Shared by every `openPanel` entry point so a plugin registering more\n * than one kind of action can write a single open routine;\n * `PluginTargetedPanelActionOpenOptions` adds the `actionId` a caller\n * outside a panel action must pass to name the panel it wants.\n */\ninterface PluginPanelActionOpenOptions {\n /** Tab label. Default: the action's `title`. */\n title?: string;\n /**\n * Persisted with the tab and handed to the component as its `params` prop.\n * Must be a JSON value; anything else is a declined open.\n */\n params?: JsonValue;\n}\n/**\n * Context handed to a `threadPanelAction`'s `run`.\n *\n * The action is thread-only and is never offered on the root New thread\n * screen, so `threadId` is always present.\n */\ninterface PluginThreadPanelActionContext {\n /** The thread whose panel launcher invoked the action. */\n threadId: string;\n /**\n * Open a tab in the thread's side panel rendering this action's\n * `component`. `title` labels the tab (default: the action's `title`);\n * `params` must be JSON-serializable — it is persisted with the tab and\n * reaches the component as its `params` prop. Opening with params\n * identical to an already-open tab of this action focuses that tab\n * (updating its title) instead of duplicating it. May be called more than\n * once (different params ⇒ multiple tabs) or not at all.\n *\n * Returns true when the host accepted the open; false when it declined —\n * from this launcher, only a `params` that is not a JSON value. The true /\n * false contract is shared with `messageAction`'s `openPanel` and\n * `useBbNavigate().openThreadPanel` (which decline for more reasons) so one\n * open routine can serve every action kind. A decline is never thrown: the\n * host logs it and reports it here.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\ninterface PluginThreadPanelActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /**\n * Icon hint (BB icon name) used when the plugin ships no logo; the\n * launcher row and opened tabs prefer the plugin's logo.\n */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /**\n * How the host frames the tab content. \"padded\" (default) wraps the\n * component in the panel's scroll container with standard padding —\n * right for document-like content. \"flush\" gives the component the full\n * tab area (no padding, definite height, no host scrolling) — right for\n * app-like content that manages its own layout, such as\n * `ThreadChat`.\n */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action: call your RPC methods, show a\n * toast, and/or open panel tabs via `context.openPanel`. Omitted =\n * immediately open a panel tab with defaults. Errors (sync or async) are\n * contained and logged; they never break the launcher.\n */\n run?(context: PluginThreadPanelActionContext): void | Promise;\n}\n/** Context handed to an `experimental_newThreadPanelAction`'s `run`. */\ninterface PluginNewThreadPanelActionContext {\n /** Project selected in the root composer; null in projectless compose. */\n projectId: string | null;\n /**\n * Open a tab in the root New thread screen's side panel rendering this\n * action's `component`. The title, params, deduplication, return value, and\n * error semantics match `threadPanelAction`.\n */\n openPanel(options?: PluginPanelActionOpenOptions): boolean;\n}\n/** Registration for the root New thread screen's panel Actions list. */\ninterface PluginNewThreadPanelActionRegistration {\n /** Unique within this slot for the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label of the action row in the panel's new-tab launcher. */\n title: string;\n /** Icon hint (BB icon name) used when the plugin ships no logo. */\n icon?: string;\n /** Rendered inside every panel tab this action opens. */\n component: ComponentType;\n /** Host framing; matches `threadPanelAction`. */\n layout?: \"flush\" | \"padded\";\n /**\n * Runs when the user activates the action. Omitted = immediately open a\n * panel tab with defaults. Errors are contained and logged.\n */\n run?(context: PluginNewThreadPanelActionContext): void | Promise;\n}\ninterface PluginPendingInteractionRegistration {\n /** Matches `rendererId` passed to `bb.ui.requestInput`. */\n id: string;\n component: ComponentType;\n}\n/** Context handed to a `sidebarFooterAction`'s `run`. */\ninterface PluginSidebarFooterActionContext {\n /**\n * Navigate to this plugin's detail page in Tools, where declarative settings\n * and `settingsSection` slots render.\n */\n openSettings(): void;\n}\n/**\n * An icon button in the app sidebar footer (next to Settings / bug report).\n * Host-rendered for consistent chrome — plugins supply icon, label, and\n * `run` behavior only.\n */\ninterface PluginSidebarFooterActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip and accessible label for the icon button. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon: string;\n /**\n * Runs when the user activates the action (e.g. call `openSettings()`,\n * open a panel via other surfaces, toast). Errors (sync or async) are\n * contained and logged; they never break the sidebar.\n */\n run(context: PluginSidebarFooterActionContext): void | Promise;\n}\n/**\n * The one status bb would paint for a thread, already resolved through the\n * host's precedence (attention before work; plan and goal before the generic\n * spinner). Draw your own glyph for it — the SDK ships no status component.\n *\n * Treat an unrecognized value as \"none\": bb adds kinds over time, and an\n * older plugin must degrade to drawing nothing rather than throwing.\n *\n * \"draft\" and \"working-draft\" are never reported here: an unsubmitted composer\n * draft is per-client state the host reads per row, which an array-wide view\n * cannot. A thread holding a draft reports whatever it would report without\n * one.\n */\ntype PluginSidebarThreadIndicator = \"background-agent\" | \"background-command\" | \"draft\" | \"goal\" | \"none\" | \"plan-mode\" | \"runtime\" | \"unread-error\" | \"unread-success\" | \"waiting-for-input\" | \"workflow\" | \"working-draft\";\n/**\n * How a thread's environment presents its workspace: a worktree bb manages,\n * a worktree the user manages, or anything else (a plain checkout).\n */\ntype PluginSidebarWorkspaceKind = \"managed-worktree\" | \"other\" | \"unmanaged-worktree\";\n/** Live work counts on a thread. All zero means nothing is running. */\ninterface PluginSidebarThreadActivity {\n workflows: number;\n backgroundAgents: number;\n backgroundCommands: number;\n planMode: number;\n goals: number;\n}\n/**\n * One thread in the sidebar's live view.\n *\n * A deliberate copy of the fields a sidebar needs — not a re-export of the\n * host's internal thread row type, which changes whenever the app needs a\n * field. Timestamps are epoch milliseconds.\n */\ninterface PluginSidebarThread {\n id: string;\n projectId: string;\n /** Null while a thread is still unnamed; pair with `titleFallback`. */\n title: string | null;\n titleFallback: string | null;\n /** The thread this one was forked from or spawned under; null at the root. */\n parentThreadId: string | null;\n sectionId: string | null;\n /** How this thread came to exist under its parent; null for root threads. */\n originKind: \"fork\" | null;\n /** The plugin that spawned it, or null for non-plugin origins. */\n originPluginId: string | null;\n /** The agent provider this thread runs on, e.g. \"codex\", \"claude-code\". */\n providerId: string;\n /** The agent is blocked on the user: an approval or a question. */\n hasPendingInteraction: boolean;\n activity: PluginSidebarThreadActivity;\n indicator: PluginSidebarThreadIndicator;\n /**\n * The host's accessible label for `indicator`, e.g. \"Thread needs user\n * input\"; null when the indicator is \"none\". Use it for `aria-label` so\n * screen-reader text stays consistent across sidebars.\n */\n indicatorLabel: string | null;\n isUnread: boolean;\n isPinned: boolean;\n isArchived: boolean;\n environment: {\n id: string | null;\n name: string | null;\n branchName: string | null;\n workspaceDisplayKind: PluginSidebarWorkspaceKind;\n } | null;\n /**\n * The machine this thread's work runs on, with the name resolved for you.\n * Null when the thread has no environment yet, or when its host is not in\n * the known-hosts list. Useful where a thread has no branch to show — a\n * personal-project thread has a machine but no worktree.\n */\n host: {\n id: string;\n name: string;\n } | null;\n createdAt: number;\n updatedAt: number;\n lastReadAt: number | null;\n latestAttentionAt: number;\n}\n/**\n * The pull request for a thread's branch, narrowed to what a sidebar row\n * needs. `attention` is bb's rolled-up \"does this need you\" signal, so a row\n * can colour a badge without reading checks, review, and mergeability itself.\n */\ninterface PluginSidebarPullRequest {\n number: number;\n title: string;\n url: string;\n state: \"closed\" | \"draft\" | \"merged\" | \"open\";\n attention: \"blocked\" | \"changes_requested\" | \"checks_failed\" | \"checks_pending\" | \"closed\" | \"conflicts\" | \"draft\" | \"merged\" | \"none\" | \"ready_to_merge\" | \"review_requested\";\n}\ninterface PluginSidebarThreadPullRequestState {\n /** True while the first lookup for this thread's environment is in flight. */\n isLoading: boolean;\n /**\n * The pull request, or null when the branch has none, the thread has no\n * environment, or the lookup could not run (a git-host hiccup). A row should\n * treat null as \"nothing to show\", never as an error.\n */\n pullRequest: PluginSidebarPullRequest | null;\n}\n/** One project in the sidebar's live view. */\ninterface PluginSidebarProject {\n id: string;\n name: string;\n /** True for the implicit personal project. */\n isPersonal: boolean;\n}\ninterface PluginSidebarThreadsState {\n status: \"error\" | \"loading\" | \"ready\";\n threads: readonly PluginSidebarThread[];\n projects: readonly PluginSidebarProject[];\n}\n/**\n * Act on threads from a plugin surface. Every method routes to the host's own\n * flow, so optimistic updates, toasts, dialogs, pane closing, and route repair\n * behave exactly as they do in the built-in sidebar. Unknown thread ids are\n * ignored by `open` and rejected by the rest.\n */\ninterface PluginSidebarThreadActions {\n /**\n * Navigate to a thread. `split: true` applies bb's split placement rules —\n * a right split by default, focus when the thread is already open, replace\n * at the pane cap — and falls back to plain navigation where splits are off.\n */\n open(threadId: string, options?: {\n split?: boolean;\n }): void;\n /**\n * Go to the new-thread screen. Passing `projectId` also makes that project\n * the composer's selection, so the thread is created where you asked.\n */\n openNewThread(options?: {\n projectId?: string;\n focusPrompt?: boolean;\n }): void;\n setPinned(threadId: string, pinned: boolean): Promise;\n setRead(threadId: string, read: boolean): Promise;\n /** Silent rename — no dialog. For inline editing in your own row. */\n rename(threadId: string, title: string): Promise;\n /** Archives the thread AND its children, closing any panes showing them. */\n archive(threadId: string): void;\n /**\n * Opens bb's delete confirmation, which counts child threads first. Deletion\n * is destructive and recursive, so the host owns the confirmation: there is\n * deliberately no silent `delete`.\n */\n requestDelete(threadId: string): void;\n}\n/**\n * Render a plugin component in the thread header's action row.\n *\n * The frontend sibling of the backend `bb.ui.registerThreadAction`, which\n * renders a host-owned button and runs server-side. Use that one for \"do a\n * thing\"; use this one when the control must draw live state.\n *\n * The host places it at the left end of the action row, before the workspace\n * button, git actions, the panel toggle, maximize, and close. That row is a\n * 48px chrome row with 28px controls: render one inline control that fits, and\n * put anything taller in a portalled popover.\n */\ninterface PluginThreadHeaderActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Names the region the host wraps around your component (a labelled group).\n * It does NOT label your control: an icon-only button still needs its own\n * accessible name.\n */\n title: string;\n component: ComponentType;\n}\n/** One pane's place in the split layout, as fractions of the split area. */\ninterface PluginSidebarSplitPane {\n paneId: string;\n rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n /** This pane holds the thread the row represents. */\n isMe: boolean;\n isFocused: boolean;\n}\n/**\n * Drag-to-split support for one row, plus where that thread currently sits in\n * the split layout.\n */\ninterface PluginSidebarThreadSplit {\n /**\n * Spread onto the row's interactive element. Carries the pointer handler\n * that starts a split drag; empty when splits are unavailable, so spreading\n * it is always safe.\n *\n * The host owns every rule: the gesture engages only once the pointer leaves\n * the sidebar toward the main area (so a list with its own drag-to-reorder\n * keeps working), an edge drop splits, a center drop replaces, an\n * already-open thread focuses its pane, and the pane cap coerces a split\n * into a replace.\n */\n splitProps: {\n onPointerDown?: (event: react.PointerEvent) => void;\n };\n /**\n * False on compact viewports, when the user disabled splits, and for an\n * unknown thread id. Gate any \"open in split\" affordance you draw on it.\n */\n isAvailable: boolean;\n /**\n * Where this thread sits in the split layout, or null when it is not open in\n * one (including single-pane layouts). Draw a mini-map, a tint, or nothing.\n */\n layout: {\n panes: readonly PluginSidebarSplitPane[];\n } | null;\n}\n/**\n * Replace the sidebar's thread list with a plugin component.\n *\n * Unlike every other slot, this one is EXCLUSIVE: two lists cannot share one\n * scroll area. Registering activates the replacement while the plugin is\n * enabled. If multiple plugins register one, the first in deterministic slot\n * order is active by default; removing it reveals the next. The user can pin\n * BB's list or a specific provider under Settings → Appearance. A plugin can\n * also use its own setting and render `experimental_Original` conditionally.\n * An absent or crashing replacement falls back to BB's list rather than\n * leaving the user with no sidebar.\n *\n * The plugin gets the scrolling list and nothing else. The New-thread button,\n * the search field, the plugin nav rows, and the footer stay host-rendered in\n * every sidebar — they are shared surfaces (other plugins live in two of\n * them), and a replaced list must not be able to remove them.\n */\ninterface PluginThreadListRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label shown in Settings → Appearance and capability details. */\n title: string;\n /** Optional one-line description shown with the provider choice. */\n description?: string;\n component: ComponentType;\n}\n/**\n * Register this plugin as a viewer/editor for file extensions. By default,\n * matching files render the first applicable opener in deterministic slot\n * order. The user can pin BB's preview or a specific opener per extension\n * under Settings → Files. The file tab's \"Open with\" menu can override that\n * choice for one open. A plugin can also use its own setting and render\n * `experimental_Original` conditionally. Applies to working-tree, host, and\n * thread-storage files — never to git-ref snapshots (diff views always use\n * BB's preview).\n */\ninterface PluginFileOpenerRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Label in the \"Open with\" menu (e.g. \"Notes editor\"). */\n title: string;\n /** Lowercase extensions without the dot (e.g. [\"md\", \"mdx\"]). */\n extensions: readonly string[];\n component: ComponentType;\n}\n/**\n * Register a leaf message directive rendered inside assistant (and nested\n * agent) message Markdown. `id` is the directive name: `inline-vis` matches\n * `::inline-vis{file=\"demo.html\"}`.\n */\ninterface PluginMessageDirectiveRegistration {\n /**\n * The directive name. Lowercase kebab-case beginning with a letter.\n */\n id: string;\n component: ComponentType;\n}\n/**\n * A narrow, stable reference to one rendered chat message — NOT an internal\n * timeline row. `sourceSeqEnd` is the last source event sequence the message\n * covers, the anchor the server accepts for provider-history forks.\n */\ninterface ThreadChatMessageReference {\n id: string;\n threadId: string;\n role: \"assistant\" | \"user\";\n /** Visible text of the message. */\n text: string;\n sourceSeqEnd: number;\n}\n/**\n * What a caller that is *not* itself a panel action passes to open one — a\n * `messageAction`'s `run`, or any component via `useBbNavigate()`. A panel\n * action opening its own tab is already the target, so it passes the bare\n * {@link PluginPanelActionOpenOptions} instead.\n */\ninterface PluginTargetedPanelActionOpenOptions extends PluginPanelActionOpenOptions {\n /** A `threadPanelAction` id registered by this same plugin. */\n actionId: string;\n}\n/** Context handed to a `messageAction`'s `run`. */\ninterface PluginMessageActionContext {\n /** The thread whose timeline surfaced the action. */\n threadId: string;\n message: ThreadChatMessageReference;\n /**\n * Present only when the action was invoked from the text-selection menu;\n * the exact text the user highlighted inside `message`.\n */\n selectedText?: string;\n /**\n * Open one of this plugin's `threadPanelAction` components in the current\n * thread's side panel — the registration-callback equivalent of\n * `useBbNavigate().openThreadPanel`.\n *\n * Returns true when the host accepted the open; false when it declined —\n * `params` was not a JSON value, the action id names no `threadPanelAction`\n * of this plugin, or the surface has no side panel (only the main thread\n * view does; a `ThreadChat` embedded in a plugin panel does not). A decline\n * is never thrown: the host logs it and reports it here.\n */\n openPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * An action on chat messages: an icon button in the per-message action bar\n * (user and assistant messages) and an entry in the assistant-message\n * text-selection menu. Host-rendered chrome — the plugin supplies title,\n * icon hint, and `run` behavior only.\n */\ninterface PluginMessageActionRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(context: PluginMessageActionContext): void | Promise;\n}\n/**\n * Supply the inline React mark bb draws for one agent provider.\n *\n * A manifest `branding.icon` (or a provider's `logoUrl`) is fetched and drawn\n * through ``, a separate document where `currentColor` resolves to black\n * — invisible on dark themes and unreachable from app CSS. A component is\n * rendered inline, so it inherits the app's theme colors and the host's sizing\n * classes. Register a static color logo as a file and a theme-aware mark here.\n *\n * The host passes only `className` (sizing plus the provider's color class);\n * the component must render an inline SVG (or other inline markup) and must\n * not fetch. One registration per provider id per plugin; when two plugins\n * claim the same provider id the host keeps the first by plugin id and warns.\n */\ninterface PluginProviderIconRegistration {\n /**\n * The provider this mark is for — the id bb knows the provider by (the\n * provider declaration's id, e.g. `codex` or `acp-cursor`), not the plugin\n * id. Letters, digits, `-`, `_`.\n */\n providerId: string;\n /** Inline, theme-aware mark. Receives the host's sizing/color className. */\n icon: ComponentType<{\n className?: string;\n }>;\n}\ninterface PluginAppSlots {\n homepageSection(registration: PluginHomepageSectionRegistration): void;\n settingsSection(registration: PluginSettingsSectionRegistration): void;\n navPanel(registration: PluginNavPanelRegistration): void;\n /**\n * Add an action to an existing thread's panel launcher. This slot is\n * thread-only; use `experimental_newThreadPanelAction` for root compose.\n */\n threadPanelAction(registration: PluginThreadPanelActionRegistration): void;\n /**\n * Add an action to the root New thread screen's panel launcher (see\n * {@link PluginNewThreadPanelActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_newThreadPanelAction(registration: PluginNewThreadPanelActionRegistration): void;\n pendingInteraction(registration: PluginPendingInteractionRegistration): void;\n sidebarFooterAction(registration: PluginSidebarFooterActionRegistration): void;\n /**\n * Replace the sidebar's thread list (see\n * {@link PluginThreadListRegistration}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_threadList(registration: PluginThreadListRegistration): void;\n /**\n * Render a component in the thread header's action row (see\n * {@link PluginThreadHeaderActionRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_threadHeaderAction(registration: PluginThreadHeaderActionRegistration): void;\n fileOpener(registration: PluginFileOpenerRegistration): void;\n messageDirective(registration: PluginMessageDirectiveRegistration): void;\n messageAction(registration: PluginMessageActionRegistration): void;\n /**\n * Draw one agent provider's icon with an inline React component instead of\n * its ``-rendered logo file (see\n * {@link PluginProviderIconRegistration}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_providerIcon(registration: PluginProviderIconRegistration): void;\n}\ninterface PluginAppComposer {\n customize(registration: ComposerCustomization): void;\n}\n/** Stable lifecycle values for one content-script instance in one bb client. */\ninterface PluginContentScriptContext {\n /** The id of the plugin that owns this script. */\n readonly pluginId: string;\n /** Monotonic per-client generation, starting at 1. */\n readonly generation: number;\n /** Aborted before cleanup begins on replacement, deactivation, or teardown. */\n readonly signal: AbortSignal;\n /**\n * Persistently decorate any thread row for this plugin generation.\n *\n * The status is owned by the frontend generation and therefore survives\n * route changes. Passing `null` clears the plugin's status for that thread.\n * The host clears every remaining status when the frontend generation\n * deactivates.\n *\n * Optional so bundles can feature-detect support while this experimental\n * surface rolls out across 0.x clients.\n */\n readonly experimental_setThreadRowStatus?: (threadId: string, status: PluginComposerThreadRowStatus | null) => void;\n}\n/** Cleanup returned by a frontend content script. */\ntype PluginContentScriptDisposer = () => void | Promise;\n/**\n * Trusted same-origin JavaScript/TypeScript mounted once per active frontend\n * generation in each bb app window or browser tab.\n */\ninterface PluginContentScriptRegistration {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /**\n * Install behavior into the bb app shell. The host awaits a returned\n * promise, contains failures, and calls the returned disposer exactly once.\n */\n mount(context: PluginContentScriptContext): void | PluginContentScriptDisposer | Promise;\n}\n/** Lifecycle surface for trusted frontend content scripts. */\ninterface PluginAppContentScripts {\n register(registration: PluginContentScriptRegistration): void;\n}\ninterface PluginAppBuilder {\n slots: PluginAppSlots;\n composer: PluginAppComposer;\n contentScripts: PluginAppContentScripts;\n}\ntype PluginAppSetup = (app: PluginAppBuilder) => void;\n/**\n * The opaque product of `definePluginApp` — a plugin's `app.tsx` default\n * export. The host re-runs `setup` against a fresh collector on every\n * (re)interpretation, replacing that plugin's registrations wholesale.\n */\ninterface PluginAppDefinition {\n /** Brand the host checks before interpreting a bundle's default export. */\n readonly __bbPluginApp: true;\n readonly setup: PluginAppSetup;\n}\ninterface PluginRpcClient {\n /**\n * Invoke one of the plugin's `bb.rpc` methods (POST\n * /api/v1/plugins/<id>/rpc/<method>). Resolves with the method's\n * inferred output; rejects with an `Error` carrying the server's message,\n * stable `code`, and validation `issues` when present.\n */\n call>(method: Method, ...args: PluginRpcCallArgs): Promise>;\n}\ninterface PluginSettingsState {\n /**\n * Effective non-secret setting values (secret settings are excluded —\n * read them server-side). Undefined while loading or unavailable.\n */\n values: Record | undefined;\n isLoading: boolean;\n}\n/** State of the app's shared realtime connection to the bb server. */\ntype PluginRealtimeConnectionState = \"connected\" | \"connecting\" | \"reconnecting\";\n/** Where `useComposer()` writes. */\ntype PluginComposerScope = {\n kind: \"thread\";\n threadId: string;\n} | {\n kind: \"queued-message\";\n threadId: string;\n queuedMessageId: string;\n} | {\n kind: \"side-chat\";\n projectId: string;\n parentThreadId: string;\n tabId: string;\n childThreadId: string | null;\n} | {\n kind: \"new-thread\";\n /** Root compose's effective selected project; null only while unresolved. */\n projectId: string | null;\n};\n/** One plugin-owned composer customization registration. */\ninterface ComposerCustomization {\n /** Unique within the plugin; letters, digits, `-`, `_`. */\n id: string;\n /** Composer kinds where this customization is active; omit for all kinds. */\n scopes?: readonly PluginComposerScope[\"kind\"][];\n actions?: readonly {\n id: string;\n component: ComponentType;\n }[];\n banners?: readonly {\n id: string;\n /** Host chrome around the banner. Defaults to `\"card\"`. */\n chrome?: \"bare\" | \"card\";\n component: ComponentType;\n }[];\n plusMenu?: readonly ComposerPlusMenuItem[];\n richText?: ComposerRichTextSpec;\n}\n/** Host-rendered menu row in the composer's `+` menu. */\ninterface ComposerPlusMenuItem {\n id: string;\n label: string;\n /** BB icon name; unknown names fall back to the generic plugin icon. */\n icon?: string;\n /** Accessible description for the host-rendered row. */\n description?: string;\n disabled?: boolean | ((view: ComposerView) => boolean);\n run(context: {\n composer: PluginComposerApi;\n view: ComposerView;\n }): void | Promise;\n}\n/** Reactive read-side of the composer a plugin surface is mounted in. */\ninterface ComposerView {\n scope: PluginComposerScope;\n layout: \"compact\" | \"expanded\" | \"zen\";\n draft: {\n text: string;\n isEmpty: boolean;\n attachmentCount: number;\n };\n run: {\n isRunning: boolean;\n isSubmitting: boolean;\n };\n}\ninterface ComposerRichTextSpec {\n /** Content-derived paint: match ranges receive `className`; text is never mutated. */\n effects?: readonly {\n id: string;\n /** Plain-text offsets into the current structured draft. */\n match(text: string): readonly {\n from: number;\n to: number;\n }[];\n className: string;\n }[];\n /** Debounced, read-only observation of the structured draft. */\n onDraftChange?(draft: ComposerStructuredDraft, view: ComposerView): void;\n}\ninterface ComposerStructuredDraft {\n text: string;\n mentions: readonly {\n from: number;\n to: number;\n provider: string;\n id: string;\n label: string;\n }[];\n}\n/** Host-rendered paint applied to the editable composer text. */\ninterface PluginComposerTextEffect {\n className: string;\n}\n/** Host-rendered status that temporarily replaces a thread's draft glyph. */\ninterface PluginComposerThreadRowStatus {\n /** BB icon-name hint; unknown names fall back to the generic plugin icon. */\n icon: string;\n /** Accessible label for the status glyph. */\n label: string;\n /**\n * Semantic host treatment for the status glyph. `running` automatically\n * shimmers; terminal `success` and `error` tones are static. Defaults to the\n * neutral tone.\n */\n tone?: \"default\" | \"error\" | \"running\" | \"success\";\n}\n/** An @-mention pill bound to one of the calling plugin's mention providers. */\ninterface PluginComposerMention {\n /** Mention provider id registered by THIS plugin via `bb.ui.registerMentionProvider`. */\n provider: string;\n /** Item id your provider's `resolve` will receive at send time. */\n id: string;\n /** Pill text shown in the composer. */\n label: string;\n}\n/**\n * Programmatic access to the chat composer draft — the same shared draft the\n * built-in \"Add to chat\" affordances (file preview, diff, terminal selections)\n * write to. While a queued message is being edited, writes land in that\n * message's inline editor. In a side chat, writes land in the visible side-chat\n * draft. Otherwise, inside a thread context writes land in that thread's draft;\n * anywhere else (nav panel, homepage section) they seed the new-thread composer\n * draft, which persists until the user sends or clears it.\n */\ninterface PluginComposerApi {\n scope: PluginComposerScope;\n /** Current plain text for this composer scope. */\n readonly text: string;\n /**\n * Replace the draft's plain text. Attachments are preserved. Inline mentions\n * outside the changed range are preserved and rebased; mentions overlapped\n * by the replacement are removed because their text representation changed.\n */\n setText(next: string): void;\n /**\n * Replace the draft's plain text from the latest committed value. Uses the\n * same structured-state reconciliation as `setText`.\n */\n updateText(updater: (current: string) => string): void;\n /** Clear plain text without clearing independently attached files. */\n clear(): void;\n /**\n * Apply a host-rendered effect to this composer's editable text, or clear it.\n * Effects are scoped to the calling plugin and automatically clear when the\n * slot unmounts or its composer scope changes.\n */\n setTextEffect(effect: PluginComposerTextEffect | null): void;\n /**\n * Lock or unlock editing for this composer. Locks are scoped to the calling\n * plugin and automatically release when the slot unmounts or its composer\n * scope changes.\n */\n setInputLock(locked: boolean): void;\n /**\n * Append text to the draft as a `> ` blockquote block and focus the\n * composer. Blank text is a no-op. This is the \"reference this selection\n * in chat\" primitive.\n */\n addQuote(text: string): void;\n /**\n * Insert an @-mention pill that resolves through this plugin's mention\n * provider at send time — the durable way to reference an entity whose\n * content should be fetched fresh when the message is sent.\n */\n insertMention(mention: PluginComposerMention): void;\n /** Focus the composer caret at the end of the draft. */\n focus(): void;\n}\n/**\n * A consumer-supplied action on the messages of one `ThreadChat` instance,\n * rendered in the embedded timeline's per-message action bar alongside the\n * native and slot-registered actions. Unlike the `messageAction` slot this is\n * scoped to the rendering component, not registered globally.\n */\ninterface ThreadChatMessageAction {\n /** Unique within this ThreadChat instance; letters, digits, `-`, `_`. */\n id: string;\n /** Tooltip / menu label for the action. */\n title: string;\n /** Icon hint (BB icon name); unknown names fall back to a generic icon. */\n icon?: string;\n /**\n * Message roles the action applies to. Omitted = both user and assistant\n * messages.\n */\n roles?: readonly (\"assistant\" | \"user\")[];\n /**\n * Runs when the user activates the action. Errors (sync or async) are\n * contained and logged; they never break the timeline.\n */\n run(message: ThreadChatMessageReference): void | Promise;\n}\n/**\n * Props of the host-owned `ThreadChat` component — one thread's chat\n * (timeline, and for the composer variants the full send/queue/draft\n * engine), rendered by the BB app inside a plugin slot. This is the\n * deliberate exception to the no-host-components rule (§5.5): a stable\n * product capability, not a UI kit. Versioned additive like slot props;\n * internal timeline rows, query hooks, and prompt-box configuration are\n * deliberately not exposed.\n */\ninterface ThreadChatProps {\n threadId: string;\n /**\n * \"full\" (default) is the page presentation (centered reading width);\n * \"compact\" is the side-panel presentation; \"timeline\" renders the\n * transcript without a composer.\n */\n variant?: \"compact\" | \"full\" | \"timeline\";\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the composer (ignored by `variant: \"timeline\"`). */\n focusRequest?: number;\n /**\n * Who controls the permission mode sends run with. \"inherit\" (default)\n * pins every send to the thread's own resolved default and renders the\n * picker as a dimmed label — a plugin surface can never widen it.\n * \"editable\" gives this chat its own picker, so the user can raise or\n * lower permissions for this thread independently of the thread it was\n * forked from. Ignored by `variant: \"timeline\"` (no composer).\n */\n permissionPolicy?: \"editable\" | \"inherit\";\n className?: string;\n /** Rendered above the conversation, scrolling with it. */\n leadingContent?: ReactNode;\n /**\n * Actions rendered in this instance's per-message action bar (see\n * {@link ThreadChatMessageAction}).\n */\n messageActions?: readonly ThreadChatMessageAction[];\n}\n/**\n * Every selection the composer resolved, JSON-serializable so a plugin can\n * forward it to its own backend rpc verbatim and hand it straight to\n * `bb.sdk.threads.spawn`.\n *\n * The split is deliberate: the composer owns *user selections*, the plugin\n * owns *filing and attribution*. `bb.sdk.threads.spawn` auto-fills\n * `origin: \"plugin\"` and `originPluginId`, so a thread created this way stays\n * attributed to the plugin — which it would not be if the component created\n * the thread itself. The plugin adds `sectionId`, `parentThreadId`, `title`,\n * and `visibility` to the request on its own; they are deliberately not\n * composer props.\n */\ninterface NewThreadRequest {\n /**\n * The selected project id. Choosing \"Don't work in a project\" submits BB's\n * personal-project id (not `null`) together with a `personal` workspace\n * environment. Forward those fields unchanged to `threads.spawn`; if the\n * plugin needs project metadata, request it from the plugin backend with\n * `bb.sdk.projects.list({ includePersonal: true })`.\n */\n projectId: string;\n providerId: string;\n model: string;\n reasoningLevel: ReasoningLevel;\n permissionMode: PermissionMode;\n /** Omitted when the selected provider has no service tiers. */\n serviceTier?: ServiceTier;\n /**\n * Per-field provenance (caller-explicit vs. default) for the execution\n * options above, forwarded to `spawn` so the server records what the user\n * actually chose.\n */\n executionInputSources: CreateExecutionInputSources;\n environment: CreateThreadEnvironmentArgs;\n input: PromptInput[];\n}\n/**\n * Props of the host-owned `experimental_NewThreadComposer` component — bb's\n * full new-thread compose surface (prompt editor with @-mentions and expand,\n * attachments, provider/model/reasoning picker, voice, submit, and the row\n * beneath with project, environment, branch-from, and permission mode),\n * rendered by the BB app inside a plugin slot.\n *\n * It is the create-side counterpart to `ThreadChat`: same deliberate\n * exception to the no-host-components rule (§5.5), same additive versioning.\n */\ninterface NewThreadComposerProps {\n /**\n * Seeds the project picker. The user can change it, including choosing\n * \"Don't work in a project\"; see {@link NewThreadRequest.projectId} for the\n * submitted projectless shape.\n */\n defaultProjectId?: string;\n /**\n * Seeds the provider picker. Like every `default*` prop this is a SEED, not\n * a controlled value: the composer stays uncontrolled, the user can change\n * it, and when omitted the composer falls back to the project's remembered\n * execution defaults exactly as before. When provided it takes precedence\n * over those project defaults.\n *\n * Re-seeding: the `default*` props are value-compared each render. When any\n * of them changes after mount, the composer re-seeds EVERY execution and\n * environment selection from the new props — including selections the user\n * had already touched — so switching between two saved records in the same\n * mounted composer reloads that record's values (the same rule\n * `defaultProjectId` already follows).\n *\n * Every seeded field is reported as caller-explicit in the submitted\n * request's `executionInputSources`. That is what makes the seed survive\n * `threads.spawn`: the server drops a requested `providerId`/`model` that\n * carries no provenance source and re-derives it from the project's stored\n * defaults, which would silently undo the seed.\n */\n defaultProviderId?: string;\n /** Seeds the model picker. Same seed semantics as {@link defaultProviderId}. */\n defaultModel?: string;\n /**\n * Seeds the reasoning-level picker. Same seed semantics as\n * {@link defaultProviderId}. If the seeded model does not support this\n * level, the composer reconciles to the closest supported one.\n */\n defaultReasoningLevel?: ReasoningLevel;\n /**\n * Seeds the service-tier picker. Same seed semantics as\n * {@link defaultProviderId}. Ignored (and omitted from the submitted\n * request) when the selected provider has no service tiers.\n */\n defaultServiceTier?: ServiceTier;\n /** Seeds the permission-mode picker. Same seed semantics as {@link defaultProviderId}. */\n defaultPermissionMode?: PermissionMode;\n /**\n * Seeds the environment and branch pickers from a previously submitted\n * `NewThreadRequest.environment`. Same seed semantics as\n * {@link defaultProviderId}: a seed the user can change, taking precedence\n * over the composer's own environment default when provided.\n *\n * Round trip: feeding a submitted request's `environment` back in and\n * resubmitting untouched reproduces an equivalent environment, with these\n * documented limits — the composer cannot represent every args variant:\n *\n * - `{ type: \"project-default\" }` seeds nothing; the composer resolves its\n * own default and submits that concrete environment instead.\n * - A `host` environment whose host no longer exists (or whose project has\n * no source on it) falls back to the composer's default host, exactly as\n * the primary compose surface would.\n * - A `reuse` environment whose worktree no longer has unarchived threads\n * falls back the same way.\n * - An `unmanaged` workspace's `path` has no composer control; the seeded\n * selection submits `path: null` (the host's configured checkout). The\n * composer itself never produces a non-null `path`, so real round trips\n * are unaffected.\n * - A `managed-worktree` with `baseBranch: { kind: \"default\" }` leaves the\n * branch picker on its default, which may resolve to a named base branch\n * when the project configures a dedicated worktree base — the same branch\n * the original `default` submission would have created from.\n */\n defaultEnvironment?: CreateThreadEnvironmentArgs;\n /** Seeds the draft, only while the draft is still empty. */\n initialPrompt?: string;\n placeholder?: string;\n /**\n * \"contained\" (default) fills and scrolls inside a bounded parent;\n * \"document\" grows with its content and defers scrolling to the page.\n */\n layout?: \"contained\" | \"document\";\n /** Bump to focus the editor. */\n focusRequest?: number;\n className?: string;\n /**\n * Where the draft persists. Drafts survive reloads and are shared by every\n * composer using the same key; defaults to a key scoped to this plugin.\n */\n draftKey?: string;\n /**\n * Fires on submit with every selection resolved. The draft clears when this\n * resolves and is KEPT if it throws, so a failed create never loses what the\n * user typed.\n */\n onSubmit: (request: NewThreadRequest) => void | Promise;\n}\n/**\n * Props of the host-owned `Markdown` component — bb's chat message renderer\n * (the same typography, spacing, and code styling as timeline messages).\n * Use it wherever plugin UI quotes or previews message content so it reads\n * like the rest of the chat. Like `ThreadChat`, this is a stable product\n * capability, not a UI kit; renderer internals stay private.\n */\ninterface MarkdownProps {\n /** Markdown source, rendered exactly like a chat message body. */\n content: string;\n className?: string;\n}\n/** Current app selection, derived from the route. */\ninterface BbContext {\n projectId: string | null;\n threadId: string | null;\n}\ninterface BbNavigate {\n toThread(threadId: string): void;\n toProject(projectId: string): void;\n /**\n * Navigate to one of this plugin's own nav panels by its `path`.\n * `subPath` targets a location inside the panel (the component's\n * `subPath` prop); `replace` swaps the current history entry instead of\n * pushing — use it for redirects so back does not bounce.\n */\n toPluginPanel(path: string, options?: {\n subPath?: string;\n replace?: boolean;\n }): void;\n /**\n * Navigate to the root compose surface (the new-thread screen). Pass\n * `initialPrompt` to seed the composer draft and `focusPrompt` to focus the\n * composer on arrival — the pairing behind \"Create via chat\" style entry\n * points that drop the user into chat with a prefilled prompt.\n */\n toCompose(options?: {\n initialPrompt?: string;\n focusPrompt?: boolean;\n }): void;\n /**\n * Open one of this plugin's registered thread-panel actions in the current\n * thread surface. Returns false when the surface has no thread side panel or\n * the action is unavailable.\n */\n openThreadPanel(options: PluginTargetedPanelActionOpenOptions): boolean;\n}\n/**\n * Everything `@get-bb/plugin-sdk/app` resolves to at runtime. The BB app builds\n * the real implementation and `satisfies` this interface; `bb plugin build`\n * shims the specifier to that object on `globalThis.__bbPluginRuntime`.\n */\ninterface PluginSdkApp {\n definePluginApp(setup: PluginAppSetup): PluginAppDefinition;\n useRpc(): PluginRpcClient;\n useRealtime(channel: string, handler: (payload: unknown) => void): void;\n /**\n * Observe the same shared connection that delivers `useRealtime` signals.\n * Use a subsequent transition to `connected` to reconcile server state that\n * may have changed while ephemeral signals could not be delivered. The first\n * connection can transition from `connecting` and is not a reconnection.\n */\n useRealtimeConnectionState(): PluginRealtimeConnectionState;\n useSettings(): PluginSettingsState;\n useBbContext(): BbContext;\n useBbNavigate(): BbNavigate;\n useComposer(): PluginComposerApi;\n /**\n * The sidebar's live thread view (see {@link PluginSidebarThreadsState}).\n * Reads the host's own cache and realtime subscriptions, so it costs no\n * extra request and updates exactly when the built-in sidebar does.\n *\n * `threads` is one array of every visible thread and is not capped. Thread\n * objects keep their identity across updates while the underlying entry is\n * unchanged, so a memoized row re-renders only when its own thread changed;\n * the array itself is new on every update. Window your rows (render only\n * what is on screen) as the built-in sidebar does — a list that mounts one\n * row per thread is slow on phones with many threads.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreads(): PluginSidebarThreadsState;\n /**\n * Thread actions bound to the host's mutations (see\n * {@link PluginSidebarThreadActions}). Experimental: see\n * docs/api_to_audit.md.\n */\n experimental_useSidebarThreadActions(): PluginSidebarThreadActions;\n /**\n * The pull request for one thread's branch (see\n * {@link PluginSidebarThreadPullRequestState}).\n *\n * Per row and opt-in, because it costs a git-host lookup: it is NOT on the\n * thread payload every sidebar loads. Threads sharing an environment share\n * one query, and the host owns the polling and staleness rules — an open PR\n * with pending checks refreshes, a merged one does not.\n *\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadPullRequest(threadId: string): PluginSidebarThreadPullRequestState;\n /**\n * Per-row drag-to-split support (see {@link PluginSidebarThreadSplit}).\n * Call it once per rendered row, like the built-in sidebar does.\n * Experimental: see docs/api_to_audit.md.\n */\n experimental_useSidebarThreadSplit(threadId: string): PluginSidebarThreadSplit;\n /**\n * The host-owned chat component (see {@link ThreadChatProps}). Together\n * with `Markdown`, the only components the SDK ships — everything else\n * stays vendored per §5.5.\n */\n ThreadChat: ComponentType;\n /**\n * The host-owned chat-message markdown renderer (see\n * {@link MarkdownProps}).\n */\n Markdown: ComponentType;\n /**\n * The host-owned new-thread compose surface (see\n * {@link NewThreadComposerProps}). Experimental: see\n * docs/api_to_audit.md for what to audit before the prefix drops.\n */\n experimental_NewThreadComposer: ComponentType;\n useComposerView(): ComposerView;\n}\n\ndeclare const definePluginApp: (setup: PluginAppSetup) => PluginAppDefinition;\ndeclare const ThreadChat: react.ComponentType;\ndeclare const Markdown: react.ComponentType;\ndeclare const experimental_NewThreadComposer: react.ComponentType;\ndeclare const useRpc: , StandardSchemaV1>>>>() => PluginRpcClient;\ndeclare const useRealtime: (channel: string, handler: (payload: unknown) => void) => void;\ndeclare const useRealtimeConnectionState: () => PluginRealtimeConnectionState;\ndeclare const useSettings: () => PluginSettingsState;\ndeclare const useBbContext: () => BbContext;\ndeclare const useBbNavigate: () => BbNavigate;\ndeclare const useComposer: () => PluginComposerApi;\ndeclare const useComposerView: () => ComposerView;\ndeclare const experimental_useSidebarThreads: () => PluginSidebarThreadsState;\ndeclare const experimental_useSidebarThreadActions: () => PluginSidebarThreadActions;\ndeclare const experimental_useSidebarThreadPullRequest: (threadId: string) => PluginSidebarThreadPullRequestState;\ndeclare const experimental_useSidebarThreadSplit: (threadId: string) => PluginSidebarThreadSplit;\n\nexport { Markdown, ThreadChat, definePluginApp, experimental_NewThreadComposer, experimental_useSidebarThreadActions, experimental_useSidebarThreadPullRequest, experimental_useSidebarThreadSplit, experimental_useSidebarThreads, useBbContext, useBbNavigate, useComposer, useComposerView, useRealtime, useRealtimeConnectionState, useRpc, useSettings };\nexport type { BbContext, BbNavigate, ComposerCustomization, ComposerPlusMenuItem, ComposerRichTextSpec, ComposerStructuredDraft, ComposerView, JsonValue, MarkdownProps, NewThreadComposerProps, NewThreadRequest, PluginAppBuilder, PluginAppComposer, PluginAppContentScripts, PluginAppDefinition, PluginAppSetup, PluginAppSlots, PluginComposerApi, PluginComposerMention, PluginComposerScope, PluginComposerTextEffect, PluginComposerThreadRowStatus, PluginContentScriptContext, PluginContentScriptDisposer, PluginContentScriptRegistration, PluginFileOpenerProps, PluginFileOpenerRegistration, PluginFileOpenerSource, PluginHomepageSectionProps, PluginHomepageSectionRegistration, PluginMessageActionContext, PluginMessageActionRegistration, PluginMessageDirectiveMessage, PluginMessageDirectiveOpenWorkspaceFile, PluginMessageDirectiveProps, PluginMessageDirectiveRegistration, PluginNavPanelProps, PluginNavPanelRegistration, PluginNewThreadPanelActionContext, PluginNewThreadPanelActionRegistration, PluginNewThreadPanelProps, PluginPanelActionOpenOptions, PluginPendingInteractionProps, PluginPendingInteractionRegistration, PluginPendingInteractionView, PluginProviderIconRegistration, PluginRealtimeConnectionState, PluginRpcCallArgs, PluginRpcClient, PluginRpcContract, PluginRpcError, PluginRpcErrorCode, PluginRpcHandlers, PluginRpcIssuePathSegment, PluginRpcMethodContract, PluginRpcResult, PluginRpcValidationIssue, PluginSdkApp, PluginSettingsSectionProps, PluginSettingsSectionRegistration, PluginSettingsState, PluginSidebarFooterActionContext, PluginSidebarFooterActionProps, PluginSidebarFooterActionRegistration, PluginSidebarProject, PluginSidebarPullRequest, PluginSidebarSplitPane, PluginSidebarThread, PluginSidebarThreadActions, PluginSidebarThreadActivity, PluginSidebarThreadIndicator, PluginSidebarThreadPullRequestState, PluginSidebarThreadSplit, PluginSidebarThreadsState, PluginSidebarWorkspaceKind, PluginTargetedPanelActionOpenOptions, PluginThreadHeaderActionProps, PluginThreadHeaderActionRegistration, PluginThreadListProps, PluginThreadListRegistration, PluginThreadPanelActionContext, PluginThreadPanelActionRegistration, PluginThreadPanelProps, StandardSchemaV1, StandardSchemaV1InferInput, StandardSchemaV1InferOutput, StandardSchemaV1Issue, StandardSchemaV1Result, ThreadChatMessageAction, ThreadChatMessageReference, ThreadChatProps };\n";