mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-14 13:22:37 +00:00
* feat(plugins): contribute settings screens and shared controls * fix(plugins): localize settings and verify shared UI consumers * test(composer): unmount draft test roots after each case * test(app): keep launch terminals alive until cleanup The fixed ten-second profile lifetime could expire before a busy CI browser attached or finished revisiting the composer. Keep the real process waiting for input until project teardown terminates it. * test(server): await the initial snapshot before a buffered ref event Watcher setup can read checkout facts before the initial refresh publishes a snapshot. Wait for publication before injecting the event so the test consistently exercises a second refresh.
339 lines
9.9 KiB
TypeScript
339 lines
9.9 KiB
TypeScript
import type { ComponentType } from "react";
|
|
import type { PaseoApi } from "@getpaseo/client";
|
|
import type { AgentTimelineItem, JsonValue } from "@getpaseo/protocol/agent-types";
|
|
import type { ZodType, input as ZodInput, output as ZodOutput } from "zod";
|
|
import type { PluginRpcContract } from "./rpc.js";
|
|
import type { ProviderRegistration } from "./provider.js";
|
|
|
|
export interface PluginTheme {
|
|
readonly colors: {
|
|
readonly surface0: string;
|
|
readonly surface1: string;
|
|
readonly surface2: string;
|
|
readonly border: string;
|
|
readonly foreground: string;
|
|
readonly foregroundMuted: string;
|
|
readonly accent: string;
|
|
readonly accentForeground: string;
|
|
readonly statusSuccess: string;
|
|
readonly statusWarning: string;
|
|
readonly statusDanger: string;
|
|
};
|
|
}
|
|
|
|
export interface PluginHostProps {
|
|
theme: PluginTheme;
|
|
host: {
|
|
id: string;
|
|
label: string;
|
|
};
|
|
layout: {
|
|
compact: boolean;
|
|
platform: "ios" | "android" | "web";
|
|
};
|
|
}
|
|
|
|
interface PluginNavigableHostProps extends PluginHostProps {
|
|
/** Client-owned navigation. Undefined on older hosts; hide dependent affordances when absent. */
|
|
readonly navigation?: {
|
|
readonly openAgent: (input: { readonly agentId: string }) => void;
|
|
readonly openWorkspace: (input: { readonly workspaceId: string }) => void;
|
|
};
|
|
}
|
|
|
|
export interface PluginSurfaceProps extends PluginNavigableHostProps {}
|
|
|
|
export interface PluginIconProps {
|
|
name: string;
|
|
size?: number;
|
|
color?: string;
|
|
}
|
|
|
|
export interface PluginWorkspaceSnapshot {
|
|
readonly id: string;
|
|
readonly projectId: string;
|
|
readonly projectDisplayName: string;
|
|
readonly projectRootPath: string;
|
|
readonly directory: string;
|
|
readonly projectKind: "git" | "non_git" | "directory";
|
|
readonly kind: "directory" | "local_checkout" | "checkout" | "worktree";
|
|
readonly name: string;
|
|
readonly title: string | null;
|
|
readonly status: "needs_input" | "failed" | "running" | "attention" | "done";
|
|
readonly statusEnteredAt: string | null;
|
|
readonly archivingAt: string | null;
|
|
readonly diffStat: { readonly additions: number; readonly deletions: number } | null;
|
|
}
|
|
|
|
export interface PluginAgentSnapshot {
|
|
readonly id: string;
|
|
readonly workspaceId: string;
|
|
readonly provider: string;
|
|
readonly status: "initializing" | "idle" | "running" | "error" | "closed";
|
|
readonly createdAt: string;
|
|
readonly updatedAt: string;
|
|
readonly lastActivityAt: string;
|
|
readonly title: string | null;
|
|
readonly cwd: string;
|
|
readonly model: string | null;
|
|
readonly currentModeId: string | null;
|
|
readonly thinkingOptionId: string | null;
|
|
readonly requiresAttention: boolean;
|
|
readonly attentionReason: "finished" | "error" | "permission" | null;
|
|
readonly parentAgentId: string | null;
|
|
readonly labels: Readonly<Record<string, string>>;
|
|
}
|
|
|
|
export type PluginPanelLocation = "workspace" | "explorer";
|
|
|
|
export interface PluginOpenPanelOptions {
|
|
location?: PluginPanelLocation;
|
|
}
|
|
|
|
interface PluginWorkspacePanelBase {
|
|
id: string;
|
|
title: string;
|
|
icon: string;
|
|
locations?: readonly PluginPanelLocation[];
|
|
}
|
|
|
|
export interface PluginWorkspacePanelProps extends PluginNavigableHostProps {
|
|
context: "workspace";
|
|
workspaceId: string;
|
|
}
|
|
|
|
export interface PluginAgentPanelProps extends PluginNavigableHostProps {
|
|
context: "agent";
|
|
workspaceId: string;
|
|
agentId: string;
|
|
}
|
|
|
|
export interface PluginComposerPillProps extends PluginHostProps {
|
|
workspaceId: string;
|
|
agentId: string;
|
|
}
|
|
|
|
export interface PluginComposerPillContribution {
|
|
id: string;
|
|
title: string;
|
|
workspaceId: string;
|
|
agentId: string;
|
|
Component: ComponentType<PluginComposerPillProps>;
|
|
onPress(): void | Promise<void>;
|
|
}
|
|
|
|
export interface PluginClientOpenPanelOptions extends PluginOpenPanelOptions {
|
|
workspaceId: string;
|
|
agentId?: string;
|
|
}
|
|
|
|
export interface PluginClientContext extends PluginCommandCapabilities {
|
|
addSettingsScreen(contribution: PluginSettingsScreenContribution): PluginCleanup;
|
|
addSurface(id: string, Component: ComponentType<PluginSurfaceProps>): PluginCleanup;
|
|
addSidebarItem(contribution: PluginSidebarContribution): PluginCleanup;
|
|
addWorkspacePanel(contribution: PluginWorkspacePanelContribution): PluginCleanup;
|
|
addCommandCenterItem(contribution: PluginCommandCenterItemContribution): PluginCleanup;
|
|
addSlashCommand(contribution: PluginClientSlashCommandContribution): PluginCleanup;
|
|
addComposerPill(contribution: PluginComposerPillContribution): PluginCleanup;
|
|
addAttachmentSource(contribution: PluginAttachmentSourceContribution): PluginCleanup;
|
|
addTheme(contribution: PluginThemeContribution): PluginCleanup;
|
|
addTimelineTransformer<ItemType extends AgentTimelineItem["type"]>(
|
|
contribution: PluginTimelineTransformerContribution<ItemType>,
|
|
): PluginCleanup;
|
|
addTimelineRenderer<Schema extends ZodType>(
|
|
contribution: PluginTimelineRendererContribution<Schema>,
|
|
): PluginCleanup;
|
|
openPanel(id: string, options: PluginClientOpenPanelOptions): void;
|
|
}
|
|
|
|
export type PluginClientContribution = (client: PluginClientContext) => PluginCleanup;
|
|
|
|
export type PluginWorkspacePanelContribution =
|
|
| (PluginWorkspacePanelBase & {
|
|
context: "workspace";
|
|
Component: ComponentType<PluginWorkspacePanelProps>;
|
|
})
|
|
| (PluginWorkspacePanelBase & {
|
|
context: "agent";
|
|
Component: ComponentType<PluginAgentPanelProps>;
|
|
});
|
|
|
|
export interface PluginSettingsScreenContribution {
|
|
id: string;
|
|
title: string;
|
|
icon: string;
|
|
Component: ComponentType<PluginSurfaceProps>;
|
|
}
|
|
|
|
export interface PluginSurfaceContribution {
|
|
id: string;
|
|
Component: ComponentType<PluginSurfaceProps>;
|
|
}
|
|
|
|
export interface PluginSidebarContribution {
|
|
id: string;
|
|
title: string;
|
|
icon: string;
|
|
surface: string;
|
|
}
|
|
|
|
export interface PluginThemeColors {
|
|
background: string;
|
|
foreground: string;
|
|
raised: string;
|
|
control: string;
|
|
border: string;
|
|
accent?: string;
|
|
mutedForeground: string;
|
|
ring: string;
|
|
}
|
|
|
|
export interface PluginThemeContribution {
|
|
id: string;
|
|
name: string;
|
|
appearance: "light" | "dark";
|
|
colors: PluginThemeColors;
|
|
}
|
|
|
|
export interface PluginAttachmentSourceContribution {
|
|
id: string;
|
|
title: string;
|
|
icon: string;
|
|
pickerTitle: string;
|
|
searchPlaceholder: string;
|
|
search: PluginRpcContract;
|
|
}
|
|
|
|
export type PluginTimelineData = JsonValue;
|
|
|
|
export interface PluginTimelineItem {
|
|
type: "plugin";
|
|
id?: string;
|
|
kind: string;
|
|
version: number;
|
|
data: PluginTimelineData;
|
|
}
|
|
|
|
export interface PluginTimelineTransformResult {
|
|
items: PluginTimelineItem[];
|
|
}
|
|
|
|
export type PluginTimelineTransformerContribution<
|
|
ItemType extends AgentTimelineItem["type"] = AgentTimelineItem["type"],
|
|
> = ItemType extends AgentTimelineItem["type"]
|
|
? {
|
|
id: string;
|
|
query: {
|
|
itemType: ItemType;
|
|
};
|
|
transform(input: {
|
|
item: Extract<AgentTimelineItem, { type: ItemType }>;
|
|
phase: "streaming" | "complete";
|
|
}): PluginTimelineTransformResult | undefined;
|
|
}
|
|
: never;
|
|
|
|
export interface PluginTimelineItemProps<Data = unknown> extends PluginHostProps {
|
|
agentId: string;
|
|
item: {
|
|
type: "plugin";
|
|
kind: string;
|
|
version: number;
|
|
data: Data;
|
|
};
|
|
timestamp: Date;
|
|
}
|
|
|
|
export interface PluginTimelineRendererContribution<Schema extends ZodType = ZodType> {
|
|
kind: string;
|
|
version: number;
|
|
schema: Schema;
|
|
Component: ComponentType<PluginTimelineItemProps<ZodOutput<Schema>>>;
|
|
}
|
|
|
|
export interface PluginCommandCapabilities {
|
|
paseo: PaseoApi;
|
|
rpc<InputSchema extends ZodType, OutputSchema extends ZodType>(
|
|
contract: PluginRpcContract<InputSchema, OutputSchema>,
|
|
input: ZodInput<InputSchema>,
|
|
): Promise<ZodOutput<OutputSchema>>;
|
|
openSurface(id: string): void;
|
|
openSettings(id: string): void;
|
|
}
|
|
|
|
export interface PluginGlobalCommandContext extends PluginCommandCapabilities {
|
|
context: "global";
|
|
}
|
|
|
|
export interface PluginWorkspaceCommandContext extends PluginCommandCapabilities {
|
|
context: "workspace";
|
|
workspace: PluginWorkspaceSnapshot;
|
|
openPanel(id: string, options?: PluginOpenPanelOptions): void;
|
|
}
|
|
|
|
export interface PluginAgentCommandContext extends PluginCommandCapabilities {
|
|
context: "agent";
|
|
workspace: PluginWorkspaceSnapshot;
|
|
agent: PluginAgentSnapshot;
|
|
openPanel(id: string, options?: PluginOpenPanelOptions): void;
|
|
}
|
|
|
|
interface PluginCommandCenterItemBase {
|
|
id: string;
|
|
title: string;
|
|
icon: string;
|
|
keywords?: readonly string[];
|
|
}
|
|
|
|
export type PluginCommandCenterItemContribution =
|
|
| (PluginCommandCenterItemBase & {
|
|
context: "global";
|
|
onSelect(context: PluginGlobalCommandContext): void | Promise<void>;
|
|
})
|
|
| (PluginCommandCenterItemBase & {
|
|
context: "workspace";
|
|
onSelect(context: PluginWorkspaceCommandContext): void | Promise<void>;
|
|
})
|
|
| (PluginCommandCenterItemBase & {
|
|
context: "agent";
|
|
onSelect(context: PluginAgentCommandContext): void | Promise<void>;
|
|
});
|
|
|
|
interface PluginClientSlashCommandBase {
|
|
name: string;
|
|
description: string;
|
|
argumentHint: string;
|
|
}
|
|
|
|
export type PluginClientSlashCommandContribution =
|
|
| (PluginClientSlashCommandBase & {
|
|
context: "workspace";
|
|
onSubmit(context: PluginWorkspaceCommandContext & { args: string }): void | Promise<void>;
|
|
})
|
|
| (PluginClientSlashCommandBase & {
|
|
context: "agent";
|
|
onSubmit(context: PluginAgentCommandContext & { args: string }): void | Promise<void>;
|
|
});
|
|
|
|
export interface PluginHandlerContext {
|
|
paseo: PaseoApi;
|
|
}
|
|
|
|
export interface PluginServerContext {
|
|
registerSettings<Schema extends ZodType>(
|
|
definition: import("./settings.js").SettingsDefinition<Schema>,
|
|
): void;
|
|
handle<InputSchema extends ZodType, OutputSchema extends ZodType>(
|
|
contract: PluginRpcContract<InputSchema, OutputSchema>,
|
|
handler: (
|
|
input: ZodOutput<InputSchema>,
|
|
context: PluginHandlerContext,
|
|
) => ZodInput<OutputSchema> | Promise<ZodInput<OutputSchema>>,
|
|
): void;
|
|
registerProvider(provider: ProviderRegistration): void;
|
|
}
|
|
|
|
export type PluginCleanup = () => void | Promise<void>;
|
|
|
|
export type PluginServerContribution = (server: PluginServerContext) => PluginCleanup;
|