This repository has been archived on 2026-08-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
pi-web/src/shared/apiTypes.ts
T

565 lines
15 KiB
TypeScript

export type MachineKind = "local" | "remote";
export type MachineStatus = "unknown" | "online" | "offline" | "error";
export const PI_WEB_CAPABILITIES = {
sessionsDeleteArchived: "sessions.deleteArchived",
sessionsReload: "sessions.reload",
promptAttachments: "prompt.attachments",
workspaceFileSuggestions: "workspace.fileSuggestions",
} as const;
export type PiWebCapability = typeof PI_WEB_CAPABILITIES[keyof typeof PI_WEB_CAPABILITIES];
export interface Machine {
id: string;
name: string;
kind: MachineKind;
baseUrl?: string;
createdAt: string;
updatedAt: string;
status?: MachineStatus;
statusMessage?: string;
}
export interface MachineHealth {
machineId: string;
ok: boolean;
checkedAt: string;
status?: MachineStatus;
web?: PiWebComponentStatus;
sessiond?: PiWebComponentStatus;
error?: string;
}
export interface MachineRuntime {
machineId: string;
ok: boolean;
checkedAt: string;
packageName?: string;
generatedAt?: string;
components?: PiWebRuntimeResponse["components"];
capabilities?: PiWebCapability[];
error?: string;
}
export type PiWebShortcutConfig = Record<string, string | null>;
export type PiWebPluginSettings = Record<string, unknown>;
export type PiWebPluginConfigMap = Record<string, PiWebPluginConfig>;
export interface PiWebPluginConfig {
enabled?: boolean;
settings?: PiWebPluginSettings;
[key: string]: unknown;
}
export interface PiWebPathAccessConfig {
allowedPaths?: string[];
}
export interface PiWebUploadsConfig {
defaultFolder?: string;
}
export interface PiWebConfigValues {
host?: string;
port?: number;
allowedHosts?: string[] | true;
shortcuts?: PiWebShortcutConfig;
plugins?: PiWebPluginConfigMap;
/** External filesystem roots PI WEB may expose outside a workspace. */
pathAccess?: PiWebPathAccessConfig;
/** Workspace-relative defaults for manual file uploads. */
uploads?: PiWebUploadsConfig;
/** Maximum accepted HTTP request body size in bytes (uploads/attachments). */
maxUploadBytes?: number;
/** When true, LLMs can start new sessions via the spawn_session tool. */
spawnSessions?: boolean;
/**
* Beta: when true, LLMs can start tracked child sessions via the
* spawn_subsession / list_subsessions / check_subsession / read_subsession
* tools. Off by default
* while the capability stabilizes. Requires spawnSessions to be enabled.
*/
subsessions?: boolean;
}
export type PiWebPluginScope = "bundled" | "local" | "user" | "project";
export interface PiWebPluginInfo {
id: string;
module: string;
source: string;
scope: PiWebPluginScope;
machineSpecific: boolean;
enabled: boolean;
}
export interface PiWebPluginsResponse {
plugins: PiWebPluginInfo[];
}
export interface PiWebConfigEnvOverrides {
host: boolean;
port: boolean;
allowedHosts: boolean;
spawnSessions: boolean;
subsessions: boolean;
}
export interface PiWebConfigResponse {
path: string;
exists: boolean;
config: PiWebConfigValues;
effectiveConfig: PiWebConfigValues;
envOverrides: PiWebConfigEnvOverrides;
}
export interface Project {
id: string;
name: string;
path: string;
createdAt: string;
}
export interface WorkspaceEffectiveConfig {
uploads?: PiWebUploadsConfig;
}
export interface Workspace {
id: string;
projectId: string;
path: string;
label: string;
branch?: string;
isMain: boolean;
isGitRepo: boolean;
isGitWorktree: boolean;
/** Workspace-effective project/global settings needed by workspace UI features. */
effectiveConfig?: WorkspaceEffectiveConfig;
}
export interface SessionRef {
id: string;
cwd: string;
}
export interface SessionInfo extends SessionRef {
path: string;
name?: string;
created: string;
modified: string;
messageCount: number;
firstMessage: string;
parentSessionPath?: string;
archived?: boolean;
archivedAt?: string;
}
export interface ArchiveSessionsResponse {
archived: true;
sessionIds?: string[];
archivedCount?: number;
skippedAlreadyArchivedCount?: number;
}
export interface SessionActivity {
sessionId: string;
phase: "active" | "idle" | "error";
label: string;
detail?: string;
at: string;
}
export interface QueuedSessionMessage {
kind: "steer" | "followUp";
text: string;
}
/**
* A binary attachment carried with a prompt. The wire format mirrors pi's own
* `ImageContent` shape (`{ type: "image", data, mimeType }`) so attachments are
* fully compatible with the underlying pi coding agent.
*/
export interface PromptAttachment {
/** Kind of attachment. Only images are supported by pi today. */
kind: "image";
/** IANA mime type (for example "image/png"). */
mimeType: string;
/** Base64-encoded binary payload (no data: URL prefix). */
data: string;
/** Optional original filename, used for previews and folder-mode filenames. */
name?: string;
}
/**
* How prompt attachments should be delivered to the session.
* - "inline": send the binary to pi as native image content (multimodal input).
* - "folder": save the file into the workspace and reference it from the prompt
* text so the agent reads it with its own tools.
*/
export type PromptAttachmentDelivery = "inline" | "folder";
export interface SavedPromptAttachment {
/** Workspace-relative path the attachment was written to. */
path: string;
mimeType: string;
size: number;
}
export interface SessionModel {
provider?: string;
id?: string;
name?: string;
contextWindow?: number;
reasoning?: unknown;
}
// Domain type is owned by pi and re-exported from the shared thinking-levels
// module. Wire/data fields below intentionally use `string` so an unknown level
// from a newer pi runtime parses and renders gracefully instead of failing.
export type { ThinkingLevel } from "./thinkingLevels.js";
export type AuthType = "oauth" | "api_key";
export type AuthStatusSource = "stored" | "runtime" | "environment" | "fallback" | "models_json_key" | "models_json_command";
export interface AuthProviderStatus {
configured: boolean;
source?: AuthStatusSource;
label?: string;
}
export interface AuthProviderOption {
id: string;
name: string;
authType: AuthType;
status: AuthProviderStatus;
}
export interface AuthProvidersResponse {
providers: AuthProviderOption[];
}
export interface OAuthFlowState {
flowId: string;
providerId: string;
providerName: string;
status: "running" | "complete" | "error" | "cancelled";
auth?: { url: string; instructions?: string };
prompt?: { requestId: string; message: string; placeholder?: string; allowEmpty?: boolean; kind: "prompt" | "manual" };
select?: { requestId: string; message: string; options: CommandOption[] };
progress: string[];
error?: string;
}
export interface ModelSelectionResponse {
models: SessionModel[];
}
export interface ThinkingLevelsResponse {
levels: string[];
}
export interface SessionStatus {
sessionId: string;
model?: SessionModel;
thinkingLevel?: string;
isStreaming: boolean;
isCompacting: boolean;
isBashRunning: boolean;
pendingMessageCount: number;
queuedMessages: QueuedSessionMessage[];
messageCount?: number;
tokens: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number };
cost: number;
contextUsage?: { tokens: number | null; contextWindow: number; percent: number | null };
}
export interface WorkspaceActivity {
cwd: string;
hasSessionActivity: boolean;
hasTerminalActivity: boolean;
updatedAt: string;
}
export interface WorkspaceActivityResponse {
workspaces: WorkspaceActivity[];
generatedAt: string;
}
export interface SlashCommand {
name: string;
description?: string;
source: "extension" | "prompt" | "skill" | "builtin";
}
export interface FileSuggestion {
path: string;
kind: "tracked" | "untracked" | "other";
}
export interface FileTreeEntry {
name: string;
path: string;
type: "file" | "directory" | "symlink";
size?: number;
modifiedAt?: string;
}
export interface FileTreeResponse {
path: string;
entries: FileTreeEntry[];
scannedAt: string;
truncated: boolean;
}
export type FileContentMediaType = "image";
export interface FileContentResponse {
path: string;
language?: string;
mediaType?: FileContentMediaType;
mimeType?: string;
encoding: "utf8";
size: number;
modifiedAt: string;
content: string;
truncated: boolean;
binary: boolean;
}
export interface WriteWorkspaceFileOptions {
createDirs?: boolean; // default: true — mkdir -p equivalent
overwrite?: boolean; // default: true — throw if false and file exists
}
export interface WriteWorkspaceFileResponse {
path: string;
size: number;
modifiedAt: string;
created: boolean; // true if file was created, false if overwritten
}
export interface DeleteWorkspaceFileResponse {
path: string;
existed: boolean; // true if file existed and was deleted, false if file did not exist
}
export interface MoveWorkspaceFileOptions {
createDirs?: boolean; // default: true — mkdir -p equivalent for target parent directory
overwrite?: boolean; // default: false — throw if target exists (safer default than writeFile)
}
export interface MoveWorkspaceFileResponse {
fromPath: string;
toPath: string;
size: number;
modifiedAt: string;
}
export type GitFileState = "unmodified" | "modified" | "added" | "deleted" | "renamed" | "copied" | "untracked" | "ignored" | "conflicted";
export interface GitStatusFile {
path: string;
oldPath?: string;
index: GitFileState;
workingTree: GitFileState;
}
export interface GitStatusResponse {
isGitRepo: boolean;
hash: string;
branch?: string;
upstream?: string;
ahead?: number;
behind?: number;
files: GitStatusFile[];
}
export interface GitDiffResponse {
path?: string;
staged: boolean;
hash: string;
diff: string;
truncated: boolean;
}
export interface TerminalInfo {
id: string;
cwd: string;
name: string;
createdAt: string;
exited: boolean;
exitCode?: number;
commandRunId?: string;
}
export type TerminalCommandRunStatus = "queued" | "running" | "succeeded" | "failed";
export interface TerminalCommandRun {
id: string;
origin: string;
projectId: string;
workspaceId: string;
terminalId: string;
title: string;
command: string;
status: TerminalCommandRunStatus;
exitCode?: number;
createdAt: string;
startedAt?: string;
completedAt?: string;
metadata: Record<string, string>;
}
export interface RunTerminalCommandInput {
workspace: Workspace;
title: string;
command: string;
metadata?: Record<string, string>;
open?: boolean;
}
export interface TerminalCommandRunHandle {
run: TerminalCommandRun;
completed: Promise<TerminalCommandRun>;
}
export interface TerminalCommandRunFilter {
projectId?: string;
workspaceId?: string;
terminalId?: string;
statuses?: TerminalCommandRunStatus[];
metadata?: Record<string, string>;
}
export type PiWebServiceComponent = "web" | "sessiond";
export type PiWebStatusSeverity = "info" | "warning" | "error";
export type PiWebInstallationKind = "pi-package" | "npm-global" | "local" | "unknown";
export interface PiWebInstallationInfo {
kind: PiWebInstallationKind;
path?: string;
source?: string;
scope?: "user" | "project";
npmRoot?: string;
}
export interface PiWebComponentStatus {
component: PiWebServiceComponent;
label: string;
runtimeVersion?: string;
installedVersion?: string;
stale: boolean;
available: boolean;
installation?: PiWebInstallationInfo;
error?: string;
}
export interface PiWebRuntimeComponent {
component: PiWebServiceComponent;
label: string;
runtimeVersion?: string;
available: boolean;
capabilities: PiWebCapability[];
error?: string;
}
export interface PiWebReleaseStatus {
packageName: string;
latestVersion?: string;
updateAvailable: boolean;
checkedAt?: string;
skipped?: boolean;
error?: string;
}
export interface PiWebStatusMessage {
id: string;
severity: PiWebStatusSeverity;
title: string;
body: string;
command?: string;
}
export interface PiWebVersionResponse {
packageName: string;
generatedAt: string;
components: {
web: PiWebComponentStatus;
sessiond: PiWebComponentStatus;
};
}
export interface PiWebRuntimeResponse {
packageName: string;
generatedAt: string;
components: {
web: PiWebRuntimeComponent;
sessiond: PiWebRuntimeComponent;
};
capabilities: PiWebCapability[];
}
export interface PiWebStatusResponse extends PiWebVersionResponse {
release: PiWebReleaseStatus;
commands: {
update?: string;
restart?: string;
restartWeb?: string;
restartSessiond?: string;
status?: string;
};
messages: PiWebStatusMessage[];
}
export type TerminalUiEvent =
| { type: "terminal.created"; terminal: TerminalInfo }
| { type: "terminal.exited"; terminal: TerminalInfo }
| { type: "terminal.closed"; terminalId: string; cwd: string };
export interface WorkspaceActivityUiEvent {
type: "workspace.activity";
activity: WorkspaceActivity;
}
export interface CommandOption {
value: string;
label: string;
description?: string;
}
export interface MessagePage {
messages: unknown[];
start: number;
total: number;
}
export type CommandResult =
| { type: "done"; message?: string; session?: SessionInfo; promptDraft?: string }
| { type: "select"; requestId: string; title: string; options: CommandOption[] }
| { type: "unsupported"; message: string };
export type SessionUiEvent =
| { type: "message.append"; message: unknown }
| { type: "assistant.delta"; text: string }
| { type: "assistant.thinking.delta"; text: string }
| { type: "tool.start"; toolName: string; toolCallId: string; summary: string; args?: unknown }
| { type: "tool.update"; toolName: string; toolCallId: string; text: string; content?: unknown; details?: unknown }
| { type: "tool.end"; toolName: string; toolCallId: string; text: string; isError: boolean; content?: unknown; details?: unknown }
| { type: "shell.start"; command: string; excludeFromContext?: boolean }
| { type: "shell.chunk"; chunk: string }
| { type: "shell.end"; output?: string; exitCode?: number | null; cancelled?: boolean; truncated?: boolean; fullOutputPath?: string; isError?: boolean }
| { type: "agent.start" }
| { type: "agent.end" }
| { type: "message.end"; message?: unknown }
| { type: "status.update"; status: SessionStatus }
| { type: "activity.update"; activity: SessionActivity }
| { type: "command.output"; level: "info" | "success" | "error"; message: string }
| { type: "session.error"; message: string }
| { type: "session.name"; sessionId: string; name?: string }
| { type: "session.created"; session: SessionInfo }
| { type: "pi.event"; eventType: string };
export type GlobalSessionEvent = Extract<SessionUiEvent, { type: "status.update" | "activity.update" | "session.name" | "session.created" }>;
export type RealtimeEvent = GlobalSessionEvent | TerminalUiEvent | WorkspaceActivityUiEvent;