// Verstak Plugin SDK — bundled frontend plugin API contract. // // The desktop host creates the real API with createPluginAPI(pluginId) inside // VerstakPluginAPI.js and passes it to bundled plugin components at mount time. // This SDK file intentionally exposes the TypeScript contract only; it is not // a standalone security boundary or RPC client. import type { CapabilityEntry, FileBytes, FileEntry, FileMetadata, MovePathOptions, OpenResourceRequest, OpenResourceResult, PluginSettings, RegisteredContributionPoints, RestoreTrashOptions, TrashEntry, TrashResult, WriteTextOptions, } from './types'; export type PluginCommandArgs = Record; export type PluginDataJSON = Record; export type PluginCommandHandler = ( args: PluginCommandArgs, declaration: PluginCommandDeclaration ) => unknown | Promise; export type Unsubscribe = () => void; export interface PluginCommandDeclaration { status: 'declared'; pluginId: string; commandId: string; handler?: string; args?: PluginCommandArgs; } export interface PluginCommandResult { status: 'handled'; pluginId: string; commandId: string; result: unknown; } export interface PluginEvent> { name: string; pluginId: string; payload: TPayload; timestamp: string; } export interface SyncStatus { configured: boolean; serverUrl: string; deviceId: string; deviceName: string; connected: boolean; revoked: boolean; tokenStored: boolean; unpushedOps: number; lastSyncAt: string; syncInterval: number; lastError: string; statusLabel: string; } export interface SyncConflict { op_id?: string; opId?: string; entity_type?: string; entityType?: string; entity_id?: string; entityId?: string; path?: string; reason?: string; message?: string; [key: string]: unknown; } export interface SyncNowResult { pushed: number; pulled: number; serverSequence: number; conflicts?: SyncConflict[]; applyErrors?: string[]; } export interface VerstakPluginAPI { readonly pluginId: string; settings: { read(): Promise; read(key: string): Promise; write(key: string, value: unknown): Promise; writeAll(settings: PluginSettings): Promise; }; storage: { data: { read(name: string): Promise; write(name: string, data: PluginDataJSON): Promise; }; }; capabilities: { has(capability: string): Promise; get(capability: string): Promise<{ available: boolean; name?: string; pluginId?: string; status?: string }>; list(): Promise; }; commands: { register(commandId: string, handler: PluginCommandHandler): Promise; execute(commandId: string, args?: PluginCommandArgs): Promise; executeFor(targetPluginId: string, commandId: string, args?: PluginCommandArgs): Promise; }; contributions: { list(): Promise; list( point: K ): Promise>; }; events: { publish(eventName: string, payload?: Record): Promise; subscribe>( eventName: string, handler: (event: PluginEvent) => void ): Promise; }; files: { /** * Files API uses canonical vault-relative slash paths. Backslashes, * Windows/UNC absolute paths, traversal, null bytes, `.verstak` variants, * and symlink read/write/move/trash operations are rejected by the host. */ list(relativeDir?: string): Promise; metadata(relativePath: string): Promise; readText(relativePath: string): Promise; readBytes(relativePath: string): Promise; writeText(relativePath: string, content: string, options?: WriteTextOptions): Promise; createFolder(relativePath: string): Promise; move(fromRelativePath: string, toRelativePath: string, options?: MovePathOptions): Promise; trash(relativePath: string): Promise; listTrash(): Promise; restoreTrash(trashId: string, options?: RestoreTrashOptions): Promise; openExternal(relativePath: string): Promise; showInFolder(relativePath: string): Promise; }; workbench: { openResource(request: OpenResourceRequest): Promise; editResource(request: OpenResourceRequest): Promise; }; sync: { status(): Promise; configure(serverUrl: string, username: string, password: string): Promise; disconnect(): Promise; testConnection(serverUrl: string, username: string, password: string): Promise; setInterval(minutes: number): Promise; resetKey(): Promise; now(): Promise; }; dispose?: () => void; } export function createPluginAPI(_pluginId: string): VerstakPluginAPI { throw new Error('createPluginAPI is provided by Verstak Desktop at plugin runtime'); }