mirror of
https://github.com/stablyai/orca.git
synced 2026-11-14 01:47:24 +00:00
* plugins: editor.save.before hook (format on save, or refuse the save) Explicit saves of text files from an editor tab run plugins' editor.save.before in main before the write (local, SSH, WSL and folder workspaces all save through that one renderer path). A plugin can return changed text or deny with a reason, shown in the save error. The buffer takes the hook's text only if it is unchanged since the hook started; edits made meanwhile stay dirty. Autosave, restart saves and bytes documents are not hooked, and with no live plugin listing the hook the save path adds no await. Co-Authored-By: Claude <noreply@anthropic.com> * test(plugins): editor.save.before text reaches the visible Monaco model The hook writes its text into the tab's draft, which reaches the model through the same content-sync bridge as Reload from disk. A model-level test covers the formatted text showing, the next keystroke editing it, and edits typed during the hook staying in the model. Co-Authored-By: Claude <noreply@anthropic.com> * plugins: editor.save.before review fixes: flush held typing, update the surviving view, keep the denial - After the hook answers, pending view text (rich Markdown's serialize timer) is flushed before deciding whether the buffer still holds the hook's input. - The hook's text goes to whichever view of the buffer record is still open, so closing the saving view keeps a sibling view in step with disk. - The save-request bridge passes Errors through whole, so the toast shows the plugin and its reason instead of a generic failure. Co-Authored-By: Claude <noreply@anthropic.com> * chore(plugins): regenerate after rebasing the save hook on main --------- Co-authored-by: Claude <noreply@anthropic.com>
121 lines
4.3 KiB
TypeScript
121 lines
4.3 KiB
TypeScript
import type { PluginCatalogType } from './catalog/plugin-catalog-types'
|
|
import type { PluginExecutionProfile } from './contributions/plugin-execution-profile'
|
|
import type { PluginHostImages } from './images/plugin-image-url'
|
|
import type { PluginStatusBarItemContribution } from './contributions/plugin-status-bar-item-contribution'
|
|
|
|
/** One installed plugin as main projects it for every client (preload IPC and the `plugins.list`
|
|
* RPC). Optional fields are absent on older hosts, so paired clients must tolerate them. */
|
|
|
|
export type PluginHostPanel = {
|
|
id: string
|
|
title: string
|
|
/** Lucide icon name declared in the plugin manifest. */
|
|
icon?: string
|
|
tabKey: `plugin:${string}`
|
|
}
|
|
|
|
/** pending awaits consent; idle defers worker startup; errored exhausted retries or failed startup. */
|
|
export type PluginHostStatus =
|
|
| 'running'
|
|
| 'restarting'
|
|
| 'idle'
|
|
| 'pending'
|
|
| 'disabled'
|
|
| 'errored'
|
|
| 'invalid'
|
|
|
|
export type PluginHostCustomEditor = {
|
|
id: string
|
|
title: string
|
|
extensions: string[]
|
|
filenames: string[]
|
|
priority: 'default' | 'option'
|
|
/** Absent on hosts that predate byte editors: text. */
|
|
contentKind?: 'text' | 'bytes'
|
|
/** Absent on hosts that predate the field: `any`. */
|
|
frame?: 'any' | 'isolated'
|
|
/** orca-plugin-image URL of the editor's tab icon; absent when it declares none. */
|
|
icon?: string
|
|
}
|
|
|
|
export type PluginHostNewFile = {
|
|
id: string
|
|
title: string
|
|
/** Suffix, with the dot, of the untitled file it creates. */
|
|
extension: string
|
|
/** orca-plugin-image URL; absent when it declares none. */
|
|
icon?: string
|
|
}
|
|
|
|
export type PluginHostListEntry = {
|
|
pluginKey: string
|
|
consentFingerprint: string | null
|
|
name: string
|
|
version: string
|
|
publisher: string
|
|
description?: string
|
|
/** The verified execution profile from the installed manifest; absent for invalid entries and
|
|
* on hosts that predate it. Never infer it from the plugin's contents. */
|
|
execution?: PluginExecutionProfile
|
|
/** What the installed manifest contributes; absent on hosts that predate it. */
|
|
types?: readonly PluginCatalogType[]
|
|
/** Declared images (format 2 manifests), as orca-plugin-image URLs main serves. */
|
|
images?: PluginHostImages
|
|
/** SPDX license expression from the manifest. */
|
|
license?: string
|
|
homepage?: string
|
|
repository?: string
|
|
status: PluginHostStatus
|
|
needsReconsent: boolean
|
|
error?: string
|
|
isDev: boolean
|
|
/** Dev folders: file changes the host had seen when it last loaded the folder, so a client can
|
|
* tell a reload happened. Absent on older hosts and installed plugins. */
|
|
devChangeCount?: number
|
|
official: boolean
|
|
bundled: boolean
|
|
capabilities: { kind: string; description: string }[]
|
|
panels: PluginHostPanel[]
|
|
/** Absent on hosts that predate custom editors. */
|
|
customEditors?: PluginHostCustomEditor[]
|
|
/** Absent on hosts that predate new-file templates. */
|
|
newFiles?: PluginHostNewFile[]
|
|
commands: {
|
|
id: string
|
|
title: string
|
|
// Why `worktree`: hosts from before the rename to `workspace` still send it.
|
|
context: 'global' | 'workspace' | 'worktree'
|
|
handler: { type: 'built-in'; action: string } | { type: 'worker' }
|
|
keybindings: { key: string; when: 'global' | 'workspace' | 'worktree' }[]
|
|
/** The built-in action it runs in place of; absent on older hosts. */
|
|
replaces?: string
|
|
/** Another plugin, installed earlier, replaces the same action, so this one does not. */
|
|
replacedBy?: string
|
|
}[]
|
|
/** The manifest's status bar items; a worker's changes arrive separately. Absent on older hosts. */
|
|
statusBarItems?: PluginStatusBarItemContribution[]
|
|
/** The hooks its manifest lists, so a window can skip asking when none applies. Absent on older
|
|
* hosts. */
|
|
hooks?: string[]
|
|
hasWorker: boolean
|
|
vmRecipes?: {
|
|
id: string
|
|
name: string
|
|
description?: string
|
|
commands: {
|
|
phase: 'create' | 'suspend' | 'resume' | 'destroy'
|
|
command: string
|
|
}[]
|
|
}[]
|
|
restarts: number
|
|
blockedByKillList?: { reason: string; advisoryUrl?: string }
|
|
source?: {
|
|
kind: 'local-path' | 'git' | 'marketplace' | 'bundled'
|
|
reference: string
|
|
resolvedCommit: string | null
|
|
contentHash: string
|
|
/** `ref` is the catalog's ref, so a client can join to the exact catalog source. */
|
|
marketplace?: { reference: string; ref?: string; resolvedCommit: string }
|
|
}
|
|
}
|