Archived
feat: add public plugin workspace capabilities
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { customElement, query, state } from "lit/decorators.js";
|
||||
import { configApi, piWebApi, terminalsApi, type Machine, type MachineHealth, type PiWebConfigValues, type PiWebShortcutConfig, type Project, type RealtimeEvent, type SessionInfo, type TerminalCommandRun, type TerminalUiEvent, type ThinkingLevel, type Workspace } from "../api";
|
||||
import { configApi, piWebApi, terminalsApi, workspacesApi, type Machine, type MachineHealth, type PiWebConfigValues, type PiWebShortcutConfig, type Project, type RealtimeEvent, type SessionInfo, type TerminalCommandRun, type TerminalUiEvent, type ThinkingLevel, type Workspace } from "../api";
|
||||
import type { AppAction } from "../actions";
|
||||
import { initialAppState, type AppState } from "../appState";
|
||||
import { isSessionActive } from "../../../shared/activity";
|
||||
@@ -17,7 +17,7 @@ import { InMemoryTerminalSelectionMemory } from "../controllers/terminalSelectio
|
||||
import { KeyboardShortcutDispatcher } from "../keyboardShortcuts";
|
||||
import { selectedMachineId } from "../controllers/types";
|
||||
import { RealtimeSocket } from "../sessionSocket";
|
||||
import type { QualifiedContributionId, QualifiedThemeContribution, QualifiedThemePairContribution, QualifiedWorkspacePanelContribution, PluginRuntimeContext, TerminalCommandRunsInternalRuntime, WorkspacePanelContext } from "../plugins/types";
|
||||
import type { PluginMachine, QualifiedContributionId, QualifiedThemeContribution, QualifiedThemePairContribution, QualifiedWorkspacePanelContribution, PluginRuntimeContext, TerminalCommandRunsInternalRuntime, WorkspacePanelContext } from "../plugins/types";
|
||||
import { CLASSIC_THEME_ID, DEFAULT_THEME_PREFERENCE, applyPiWebTheme, findThemePairForTheme, readStoredThemePreference, resolveThemePreference, writeStoredThemePreference, type ThemePreference, type ThemePreferenceResolution } from "../theme";
|
||||
import { corePlugin } from "../plugins/core";
|
||||
import { themePackPlugin } from "../plugins/themes";
|
||||
@@ -828,7 +828,8 @@ export class PiWebApp extends LitElement {
|
||||
private visibleWorkspacePanels(): QualifiedWorkspacePanelContribution[] {
|
||||
const workspace = this.state.selectedWorkspace;
|
||||
if (workspace === undefined) return [];
|
||||
return this.plugins.getWorkspacePanels().filter((panel) => panel.visible?.({ workspace, state: this.state }) ?? true);
|
||||
const context = this.createWorkspacePanelContext(workspace);
|
||||
return this.plugins.getWorkspacePanels().filter((panel) => panel.visible?.(context) ?? true);
|
||||
}
|
||||
|
||||
private workspacePanelEmptyState(): WorkspacePanelEmptyState {
|
||||
@@ -892,31 +893,45 @@ export class PiWebApp extends LitElement {
|
||||
}
|
||||
|
||||
private createWorkspacePanelContext(workspace: Workspace): WorkspacePanelContext {
|
||||
const createContext = (origin: string): WorkspacePanelContext => installWorkspacePanelScope({
|
||||
workspace,
|
||||
state: this.state,
|
||||
piWebInternal: { terminalCommandRuns: this.terminalCommandRunsForOrigin(origin) },
|
||||
fileTree: this.state.fileTree,
|
||||
expandedDirs: this.state.expandedDirs,
|
||||
selectedFilePath: this.state.selectedFilePath,
|
||||
selectedFileContent: this.state.selectedFileContent,
|
||||
fileTreeStale: this.state.fileTreeStale,
|
||||
gitStatus: this.state.gitStatus,
|
||||
selectedDiffPath: this.state.selectedDiffPath,
|
||||
selectedDiff: this.state.selectedDiff,
|
||||
selectedStagedDiff: this.state.selectedStagedDiff,
|
||||
gitStale: this.state.gitStale,
|
||||
activeTerminalCount: this.state.activeTerminalCount,
|
||||
selectedTerminalId: this.state.selectedTerminalId,
|
||||
terminalAutoStart: this.terminalAutoStartWorkspaceId === workspace.id,
|
||||
openTerminal: (options) => { this.openTerminal(options); },
|
||||
onRefreshFiles: () => { void this.files.refreshFiles(); },
|
||||
onExpandDir: (path: string) => { void this.files.expandDir(path); },
|
||||
onSelectFile: (path: string) => { void this.files.selectFile(path); },
|
||||
onRefreshGit: () => { void this.git.refreshGit(); },
|
||||
onSelectDiff: (path: string) => { void this.git.selectDiff(path); },
|
||||
onSelectTerminal: (terminalId: string | undefined, options?: { replace?: boolean | undefined }) => { this.selectTerminal(terminalId, options); },
|
||||
}, createContext);
|
||||
const machine = pluginMachineFromState(this.state);
|
||||
const machineId = machine.id;
|
||||
const createContext = (origin: string): WorkspacePanelContext => {
|
||||
const terminalCommandRuns = this.terminalCommandRunsForOrigin(origin, machineId);
|
||||
return installWorkspacePanelScope({
|
||||
machine,
|
||||
workspace,
|
||||
state: this.state,
|
||||
files: {
|
||||
readFile: (path: string) => workspacesApi.workspaceFile(workspace.projectId, workspace.id, path, machineId),
|
||||
},
|
||||
terminal: {
|
||||
open: (options) => { void this.openRuntimeTerminal(machineId, workspace, options); },
|
||||
runCommand: (input) => terminalCommandRuns.runCommand({ ...input, workspace }),
|
||||
},
|
||||
requestRender: () => { this.requestUpdate(); },
|
||||
piWebUnstable: { terminalCommandRuns },
|
||||
fileTree: this.state.fileTree,
|
||||
expandedDirs: this.state.expandedDirs,
|
||||
selectedFilePath: this.state.selectedFilePath,
|
||||
selectedFileContent: this.state.selectedFileContent,
|
||||
fileTreeStale: this.state.fileTreeStale,
|
||||
gitStatus: this.state.gitStatus,
|
||||
selectedDiffPath: this.state.selectedDiffPath,
|
||||
selectedDiff: this.state.selectedDiff,
|
||||
selectedStagedDiff: this.state.selectedStagedDiff,
|
||||
gitStale: this.state.gitStale,
|
||||
activeTerminalCount: this.state.activeTerminalCount,
|
||||
selectedTerminalId: this.state.selectedTerminalId,
|
||||
terminalAutoStart: this.terminalAutoStartWorkspaceId === workspace.id,
|
||||
openTerminal: (options) => { this.openTerminal(options); },
|
||||
onRefreshFiles: () => { void this.files.refreshFiles(); },
|
||||
onExpandDir: (path: string) => { void this.files.expandDir(path); },
|
||||
onSelectFile: (path: string) => { void this.files.selectFile(path); },
|
||||
onRefreshGit: () => { void this.git.refreshGit(); },
|
||||
onSelectDiff: (path: string) => { void this.git.selectDiff(path); },
|
||||
onSelectTerminal: (terminalId: string | undefined, options?: { replace?: boolean | undefined }) => { this.selectTerminal(terminalId, options); },
|
||||
}, createContext);
|
||||
};
|
||||
return createContext("core");
|
||||
}
|
||||
|
||||
@@ -944,7 +959,7 @@ export class PiWebApp extends LitElement {
|
||||
private createPluginRuntimeContext(): PluginRuntimeContext {
|
||||
const createContext = (origin: string): PluginRuntimeContext => installPluginRuntimeScope({
|
||||
state: this.state,
|
||||
piWebInternal: {
|
||||
piWebUnstable: {
|
||||
terminalCommandRuns: this.terminalCommandRunsForOrigin(origin),
|
||||
openSettings: (section) => { this.openSettings(section); },
|
||||
},
|
||||
@@ -1343,6 +1358,12 @@ function createPluginRegistry(): PluginRegistry {
|
||||
return registry;
|
||||
}
|
||||
|
||||
function pluginMachineFromState(state: Pick<AppState, "selectedMachine">): PluginMachine {
|
||||
const machine = state.selectedMachine;
|
||||
if (machine !== undefined) return { id: machine.id, name: machine.name, kind: machine.kind };
|
||||
return { id: "local", name: "local", kind: "local" };
|
||||
}
|
||||
|
||||
function machineActivitySubscriptionInputsChanged(previous: AppState, next: AppState): boolean {
|
||||
return previous.machines !== next.machines
|
||||
|| previous.machineStatuses !== next.machineStatuses
|
||||
|
||||
@@ -85,7 +85,7 @@ export function createCoreActions(): PluginAction[] {
|
||||
description: "Manage PI WEB configuration and keyboard shortcuts",
|
||||
shortcut: "mod+,",
|
||||
group: "Preferences",
|
||||
run: (context) => { context.piWebInternal?.openSettings?.(); },
|
||||
run: (context) => { context.piWebUnstable?.openSettings?.(); },
|
||||
},
|
||||
{
|
||||
id: "app.refresh-data",
|
||||
|
||||
@@ -86,7 +86,7 @@ function renderImageViewer(context: WorkspacePanelContext, file: FileContentResp
|
||||
<p class="muted">Image too large to preview: ${formatFileSize(file.size)} · limit ${MAX_IMAGE_PREVIEW_LABEL}</p>
|
||||
`;
|
||||
}
|
||||
const src = workspaceImagePreviewUrl(context.workspace.projectId, context.workspace.id, file.path, { modifiedAt: file.modifiedAt, machineId: context.state.selectedMachine?.id ?? "local" });
|
||||
const src = workspaceImagePreviewUrl(context.workspace.projectId, context.workspace.id, file.path, { modifiedAt: file.modifiedAt, machineId: context.machine.id });
|
||||
return html`
|
||||
<div class="viewer-header"><strong>${file.path}</strong><small>${metadata}</small></div>
|
||||
<div class="image-preview">
|
||||
@@ -97,7 +97,7 @@ function renderImageViewer(context: WorkspacePanelContext, file: FileContentResp
|
||||
|
||||
function renderTerminal(context: WorkspacePanelContext): TemplateResult {
|
||||
loadTerminalPanel();
|
||||
return html`<terminal-panel .workspace=${context.workspace} .machineId=${context.state.selectedMachine?.id ?? "local"} .selectedTerminalId=${context.selectedTerminalId} .autoStart=${context.terminalAutoStart} .onSelectTerminal=${context.onSelectTerminal}></terminal-panel>`;
|
||||
return html`<terminal-panel .workspace=${context.workspace} .machineId=${context.machine.id} .selectedTerminalId=${context.selectedTerminalId} .autoStart=${context.terminalAutoStart} .onSelectTerminal=${context.onSelectTerminal}></terminal-panel>`;
|
||||
}
|
||||
|
||||
function renderGit(context: WorkspacePanelContext): TemplateResult {
|
||||
|
||||
@@ -11,7 +11,7 @@ function createContext(statePatch: Partial<AppState> = {}) {
|
||||
const calls: string[] = [];
|
||||
const context: PluginRuntimeContext = {
|
||||
state: { ...initialAppState(), ...statePatch },
|
||||
piWebInternal: {
|
||||
piWebUnstable: {
|
||||
terminalCommandRuns: {
|
||||
runCommand: vi.fn(),
|
||||
listCommandRuns: vi.fn(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { html, svg } from "lit";
|
||||
import type { AppState } from "../appState";
|
||||
import type { Workspace } from "../api";
|
||||
import type { PiWebPluginRegistration, PluginAction, PluginRuntimeContext, QualifiedContributionId, QualifiedPluginAction, QualifiedThemeContribution, QualifiedThemePairContribution, QualifiedWorkspaceLabelContribution, QualifiedWorkspacePanelContribution, ThemeContribution, ThemePairContribution, WorkspaceLabelContribution, WorkspaceLabelItem, WorkspacePanelContext, WorkspacePanelContribution } from "./types";
|
||||
import type { PiWebPluginRegistration, PluginAction, PluginMachine, PluginRuntimeContext, QualifiedContributionId, QualifiedPluginAction, QualifiedThemeContribution, QualifiedThemePairContribution, QualifiedWorkspaceLabelContribution, QualifiedWorkspacePanelContribution, ThemeContribution, ThemePairContribution, WorkspaceLabelContribution, WorkspaceLabelItem, WorkspacePanelContext, WorkspacePanelContribution } from "./types";
|
||||
|
||||
const idPattern = /^[a-z][a-z0-9.-]*$/u;
|
||||
const localIdPattern = /^[a-z][a-z0-9.-]*$/u;
|
||||
@@ -72,7 +72,7 @@ export class PluginRegistry {
|
||||
}
|
||||
|
||||
getWorkspaceLabelItems(state: AppState, workspace: Workspace): WorkspaceLabelItem[] {
|
||||
const context = { state, workspace };
|
||||
const context = { machine: pluginMachineFromState(state), state, workspace };
|
||||
return [...this.workspaceLabels]
|
||||
.sort((left, right) => (left.order ?? 1000) - (right.order ?? 1000) || left.id.localeCompare(right.id))
|
||||
.flatMap((contribution) => {
|
||||
@@ -89,11 +89,13 @@ export class PluginRegistry {
|
||||
private qualifyWorkspacePanel(pluginId: string, panel: WorkspacePanelContribution): QualifiedWorkspacePanelContribution {
|
||||
const id = this.qualify(pluginId, panel.id);
|
||||
const badge = panel.badge;
|
||||
const visible = panel.visible;
|
||||
return {
|
||||
...panel,
|
||||
id,
|
||||
pluginId,
|
||||
localId: panel.id,
|
||||
...(visible === undefined ? {} : { visible: (context: WorkspacePanelContext) => visible(workspacePanelContextFor(context, pluginId)) }),
|
||||
...(badge === undefined ? {} : { badge: (context: WorkspacePanelContext) => badge(workspacePanelContextFor(context, pluginId)) }),
|
||||
render: (context: WorkspacePanelContext) => panel.render(workspacePanelContextFor(context, pluginId)),
|
||||
};
|
||||
@@ -160,3 +162,9 @@ export function installWorkspacePanelScope(context: WorkspacePanelContext, scope
|
||||
workspacePanelScopes.set(context, scope);
|
||||
return context;
|
||||
}
|
||||
|
||||
function pluginMachineFromState(state: Pick<AppState, "selectedMachine">): PluginMachine {
|
||||
const machine = state.selectedMachine;
|
||||
if (machine !== undefined) return { id: machine.id, name: machine.name, kind: machine.kind };
|
||||
return { id: "local", name: "local", kind: "local" };
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { TemplateResult } from "lit";
|
||||
import type { AppAction } from "../actions";
|
||||
import type { FileContentResponse, FileTreeEntry, GitDiffResponse, GitStatusResponse, RunTerminalCommandInput, TerminalCommandRun, TerminalCommandRunFilter, TerminalCommandRunHandle, Workspace } from "../api";
|
||||
import type { FileContentResponse, FileTreeEntry, GitDiffResponse, GitStatusResponse, Machine, RunTerminalCommandInput, TerminalCommandRun, TerminalCommandRunFilter, TerminalCommandRunHandle, Workspace } from "../api";
|
||||
import type { AppState } from "../appState";
|
||||
import type { SettingsSection } from "../settingsRoute";
|
||||
import type { LocalContributionId, PluginId, QualifiedContributionId } from "./ids";
|
||||
@@ -39,7 +39,24 @@ export interface PluginContributions {
|
||||
themePairs?: ThemePairContribution[];
|
||||
}
|
||||
|
||||
export interface PiWebInternalRuntimeContext {
|
||||
export interface PluginMachine {
|
||||
id: string;
|
||||
name: string;
|
||||
kind: Machine["kind"];
|
||||
}
|
||||
|
||||
export interface WorkspacePanelFiles {
|
||||
readFile(path: string): Promise<FileContentResponse>;
|
||||
}
|
||||
|
||||
export type WorkspaceTerminalCommandInput = Omit<RunTerminalCommandInput, "workspace">;
|
||||
|
||||
export interface WorkspacePanelTerminal {
|
||||
open(options?: { terminalId?: string | undefined }): void;
|
||||
runCommand(input: WorkspaceTerminalCommandInput): Promise<TerminalCommandRunHandle>;
|
||||
}
|
||||
|
||||
export interface PiWebUnstableRuntimeContext {
|
||||
terminalCommandRuns: TerminalCommandRunsInternalRuntime;
|
||||
openSettings?: (section?: SettingsSection) => void;
|
||||
}
|
||||
@@ -53,7 +70,7 @@ export interface TerminalCommandRunsInternalRuntime {
|
||||
|
||||
export interface PluginRuntimeContext {
|
||||
state: AppState;
|
||||
piWebInternal?: PiWebInternalRuntimeContext;
|
||||
piWebUnstable?: PiWebUnstableRuntimeContext;
|
||||
openActionPalette: () => void;
|
||||
focusPrompt: () => void;
|
||||
addProject: () => void | Promise<void>;
|
||||
@@ -93,15 +110,14 @@ export interface QualifiedPluginAction extends AppAction {
|
||||
localId: LocalContributionId;
|
||||
}
|
||||
|
||||
export interface WorkspacePanelVisibilityContext {
|
||||
workspace: Workspace;
|
||||
state: AppState;
|
||||
}
|
||||
|
||||
export interface WorkspacePanelContext {
|
||||
machine: PluginMachine;
|
||||
workspace: Workspace;
|
||||
state: AppState;
|
||||
piWebInternal?: PiWebInternalRuntimeContext;
|
||||
files: WorkspacePanelFiles;
|
||||
terminal: WorkspacePanelTerminal;
|
||||
requestRender: () => void;
|
||||
piWebUnstable?: Pick<PiWebUnstableRuntimeContext, "terminalCommandRuns">;
|
||||
fileTree: FileTreeEntry[];
|
||||
expandedDirs: Record<string, FileTreeEntry[]>;
|
||||
selectedFilePath: string | undefined;
|
||||
@@ -131,7 +147,7 @@ export interface WorkspacePanelContribution {
|
||||
title: string;
|
||||
icon?: WorkspacePanelIcon;
|
||||
order?: number;
|
||||
visible?: (context: WorkspacePanelVisibilityContext) => boolean;
|
||||
visible?: (context: WorkspacePanelContext) => boolean;
|
||||
badge?: (context: WorkspacePanelContext) => string | number | TemplateResult | undefined;
|
||||
render: (context: WorkspacePanelContext) => TemplateResult;
|
||||
}
|
||||
@@ -143,6 +159,7 @@ export interface QualifiedWorkspacePanelContribution extends WorkspacePanelContr
|
||||
}
|
||||
|
||||
export interface WorkspaceLabelContext {
|
||||
machine: PluginMachine;
|
||||
workspace: Workspace;
|
||||
state: AppState;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
import type { TemplateResult } from "lit";
|
||||
import type { FileContentResponse, MachineKind, PiWebStatusResponse, TerminalCommandRunHandle } from "./shared/apiTypes.js";
|
||||
|
||||
export type {
|
||||
FileContentMediaType,
|
||||
FileContentResponse,
|
||||
FileTreeEntry,
|
||||
FileTreeResponse,
|
||||
MachineKind,
|
||||
PiWebComponentStatus,
|
||||
PiWebInstallationInfo,
|
||||
PiWebInstallationKind,
|
||||
PiWebReleaseStatus,
|
||||
PiWebServiceComponent,
|
||||
PiWebStatusMessage,
|
||||
PiWebStatusResponse,
|
||||
PiWebStatusSeverity,
|
||||
PiWebVersionResponse,
|
||||
TerminalCommandRun,
|
||||
TerminalCommandRunFilter,
|
||||
TerminalCommandRunHandle,
|
||||
TerminalCommandRunStatus,
|
||||
} from "./shared/apiTypes.js";
|
||||
|
||||
export type PluginId = string;
|
||||
export type LocalContributionId = string;
|
||||
export type QualifiedContributionId = string;
|
||||
export type HtmlTemplateTag = (strings: TemplateStringsArray, ...values: unknown[]) => TemplateResult;
|
||||
export type SvgTemplateTag = (strings: TemplateStringsArray, ...values: unknown[]) => TemplateResult;
|
||||
|
||||
export interface PiWebPlugin {
|
||||
apiVersion: 1;
|
||||
name: string;
|
||||
activate: (context: PluginActivationContext) => PluginActivationResult;
|
||||
}
|
||||
|
||||
export interface PluginActivationContext {
|
||||
apiVersion: 1;
|
||||
pluginId: PluginId;
|
||||
html: HtmlTemplateTag;
|
||||
svg: SvgTemplateTag;
|
||||
}
|
||||
|
||||
export interface PluginActivationResult {
|
||||
contributions: PluginContributions;
|
||||
}
|
||||
|
||||
export interface PluginContributions {
|
||||
actions?: PluginAction[];
|
||||
workspacePanels?: WorkspacePanelContribution[];
|
||||
workspaceLabels?: WorkspaceLabelContribution[];
|
||||
themes?: ThemeContribution[];
|
||||
themePairs?: ThemePairContribution[];
|
||||
}
|
||||
|
||||
export interface PluginMachine {
|
||||
id: string;
|
||||
name: string;
|
||||
kind: MachineKind;
|
||||
}
|
||||
|
||||
export interface PluginRuntimeState {
|
||||
selectedWorkspace?: Workspace;
|
||||
selectedSession?: unknown;
|
||||
workspaceTool?: string;
|
||||
mainView?: string;
|
||||
piWebStatus?: PiWebStatusResponse;
|
||||
}
|
||||
|
||||
export interface PluginRuntimeContext {
|
||||
state: PluginRuntimeState;
|
||||
openActionPalette: () => void;
|
||||
focusPrompt: () => void;
|
||||
addProject: () => void | Promise<void>;
|
||||
configureAuth: () => void | Promise<void>;
|
||||
logoutAuth: () => void | Promise<void>;
|
||||
openThemePicker: () => void;
|
||||
selectMainView: (view: string) => void;
|
||||
selectWorkspaceTool: (tool: QualifiedContributionId) => void;
|
||||
openTerminal: (options?: { terminalId?: string | undefined }) => void;
|
||||
refreshFiles: () => void | Promise<void>;
|
||||
refreshGit: () => void | Promise<void>;
|
||||
refreshAppData: () => void | Promise<void>;
|
||||
reloadPage: () => void;
|
||||
startSession: () => void | Promise<void>;
|
||||
archiveSession: () => void | Promise<void>;
|
||||
stopActiveWork: () => void | Promise<void>;
|
||||
}
|
||||
|
||||
export interface PluginAction {
|
||||
id: LocalContributionId;
|
||||
title: string;
|
||||
description?: string;
|
||||
shortcut?: string;
|
||||
group?: string;
|
||||
enabled?: (context: PluginRuntimeContext) => boolean;
|
||||
run: (context: PluginRuntimeContext) => void | Promise<void>;
|
||||
}
|
||||
|
||||
export interface Workspace {
|
||||
id: string;
|
||||
projectId: string;
|
||||
path: string;
|
||||
label: string;
|
||||
branch?: string;
|
||||
isMain: boolean;
|
||||
isGitRepo: boolean;
|
||||
isGitWorktree: boolean;
|
||||
}
|
||||
|
||||
export interface WorkspacePanelFiles {
|
||||
readFile(path: string): Promise<FileContentResponse>;
|
||||
}
|
||||
|
||||
export interface WorkspaceTerminalCommandInput {
|
||||
title: string;
|
||||
command: string;
|
||||
metadata?: Record<string, string>;
|
||||
open?: boolean;
|
||||
}
|
||||
|
||||
export interface WorkspacePanelTerminal {
|
||||
open(options?: { terminalId?: string | undefined }): void;
|
||||
runCommand(input: WorkspaceTerminalCommandInput): Promise<TerminalCommandRunHandle>;
|
||||
}
|
||||
|
||||
export interface WorkspacePanelContext {
|
||||
machine: PluginMachine;
|
||||
workspace: Workspace;
|
||||
state?: PluginRuntimeState;
|
||||
files: WorkspacePanelFiles;
|
||||
terminal: WorkspacePanelTerminal;
|
||||
requestRender: () => void;
|
||||
openTerminal: (options?: { terminalId?: string | undefined }) => void;
|
||||
}
|
||||
|
||||
export type WorkspacePanelIcon = TemplateResult;
|
||||
|
||||
export interface WorkspacePanelContribution {
|
||||
id: LocalContributionId;
|
||||
title: string;
|
||||
icon?: WorkspacePanelIcon;
|
||||
order?: number;
|
||||
visible?: (context: WorkspacePanelContext) => boolean;
|
||||
badge?: (context: WorkspacePanelContext) => string | number | TemplateResult | undefined;
|
||||
render: (context: WorkspacePanelContext) => TemplateResult;
|
||||
}
|
||||
|
||||
export interface WorkspaceLabelContext {
|
||||
machine: PluginMachine;
|
||||
workspace: Workspace;
|
||||
state?: PluginRuntimeState;
|
||||
}
|
||||
|
||||
export type WorkspaceLabelItem = WorkspaceLabelTextItem | WorkspaceLabelLinkItem | WorkspaceLabelRenderItem;
|
||||
|
||||
export interface WorkspaceLabelTextItem {
|
||||
type: "text";
|
||||
text: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceLabelLinkItem {
|
||||
type: "link";
|
||||
text: string;
|
||||
href: string;
|
||||
title?: string;
|
||||
target?: "_blank" | "_self";
|
||||
}
|
||||
|
||||
export interface WorkspaceLabelRenderItem {
|
||||
type: "render";
|
||||
render: () => TemplateResult;
|
||||
}
|
||||
|
||||
export interface WorkspaceLabelContribution {
|
||||
id: LocalContributionId;
|
||||
order?: number;
|
||||
visible?: (context: WorkspaceLabelContext) => boolean;
|
||||
items: (context: WorkspaceLabelContext) => WorkspaceLabelItem[];
|
||||
}
|
||||
|
||||
export type ThemeColorScheme = "dark" | "light";
|
||||
export type ThemeTokens = Record<string, string>;
|
||||
|
||||
export interface ThemeContribution {
|
||||
id: LocalContributionId;
|
||||
name: string;
|
||||
description?: string;
|
||||
order?: number;
|
||||
colorScheme: ThemeColorScheme;
|
||||
tokens: ThemeTokens;
|
||||
}
|
||||
|
||||
export interface ThemePairContribution {
|
||||
id: LocalContributionId;
|
||||
name: string;
|
||||
description?: string;
|
||||
order?: number;
|
||||
light: LocalContributionId;
|
||||
dark: LocalContributionId;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { TerminalCommandRun, TerminalCommandRunFilter, TerminalCommandRunHandle, Workspace, WorkspaceTerminalCommandInput } from "../plugin-api.js";
|
||||
|
||||
export interface UnstableRunTerminalCommandInput extends WorkspaceTerminalCommandInput {
|
||||
workspace: Workspace;
|
||||
}
|
||||
|
||||
export interface UnstableTerminalCommandRunsRuntime {
|
||||
runCommand(input: UnstableRunTerminalCommandInput): Promise<TerminalCommandRunHandle>;
|
||||
listCommandRuns(filter?: TerminalCommandRunFilter): Promise<TerminalCommandRun[]>;
|
||||
getCommandRun(runId: string): Promise<TerminalCommandRun | undefined>;
|
||||
open(options?: { terminalId?: string | undefined }): void;
|
||||
}
|
||||
|
||||
export interface UnstableRuntimeCapabilities {
|
||||
terminalCommandRuns: UnstableTerminalCommandRunsRuntime;
|
||||
openSettings?: (section?: string) => void;
|
||||
}
|
||||
|
||||
export interface UnstablePluginRuntimeContext {
|
||||
piWebUnstable?: UnstableRuntimeCapabilities;
|
||||
}
|
||||
|
||||
export interface UnstableWorkspacePanelContext {
|
||||
piWebUnstable?: Pick<UnstableRuntimeCapabilities, "terminalCommandRuns">;
|
||||
}
|
||||
Reference in New Issue
Block a user