Файли
openidea/wit/io.wit
T
l0ng-ai 047cac209b feat(plugins): plugin API 1.4 (#2207)
Plugin API 1.4: grants for unencrypted HTTP, local sockets, IDE commands and owned database sources; window status items, output channels, content tabs, editor selections, decorations, search, Problems and VCS reads; runs, keyed terminals with exit events, plugin run targets, dynamic run configurations and test parsers; language features, injections, snippets and menu locations; plugin MCP tools on the built-in server; four official API examples. Released 1.3 plugins keep working.
2026-11-09 08:40:40 +08:00

193 рядки
8.1 KiB
Plaintext
Неформатований Анотація Історія

Цей файл містить неоднозначні символи Юнікоду
Цей файл містить символи Юнікоду, які можна сплутати з іншими символами. Якщо ви вважаєте, що це зроблено навмисно, можете сміливо ігнорувати це попередження. Щоб показати їх, скористайтеся кнопкою Escape.
package openidea:[email protected];
/// Problems in files, shown in the editor and the Problems view.
interface diagnostics {
use types.{error, range, location};
/// Problems reported by a source for a file in this window's project.
record file-problems { path: string, source: string, diagnostics: list<diagnostic> }
/// Current Problems view snapshot, optionally filtered to a project file.
/// Requires project.read and an invoking window. Empty for remote projects.
problems: func(path: option<string>) -> result<list<file-problems>, error>;
enum severity {
error,
warning,
info,
hint,
}
/// Another place that explains a diagnostic (the earlier declaration, say).
record related-information {
location: location,
message: string,
}
record diagnostic {
range: range,
severity: severity,
message: string,
/// Rule or check id (`LineLength`).
code: option<string>,
/// The tool that found it, when not the plugin itself (`checkstyle`).
source: option<string>,
/// `unnecessary` (shown faded) and `deprecated` (struck through); unknown ones are ignored.
tags: list<string>,
related: list<related-information>,
}
/// Replaces the plugin's diagnostics for the file at `path` (absolute, in
/// an open project); an empty list clears them. Requires `project.read`.
publish: func(path: string, diagnostics: list<diagnostic>) -> result<_, error>;
}
/// HTTPS with `net:<host>`; unencrypted HTTP with `net.http:<host>`.
interface net {
use types.{error};
record header {
name: string,
value: string,
}
record request {
method: string,
/// `https://…` requires `net:<host>`. Plain `http://…` requires
/// `net.http:<host>` (API 1.4), except loopback, which uses `net:<host>`.
url: string,
/// `{{secret:<name>}}` in a value is replaced by the plugin's secret
/// `name` on the way out (requires `secrets`); the plugin never sees it.
headers: list<header>,
body: option<list<u8>>,
/// Default 30 s; the call's own budget applies too.
timeout-ms: option<u32>,
}
record response {
status: u16,
headers: list<header>,
/// At most 8 MiB.
body: list<u8>,
}
/// Fails with `denied` for a host the plugin may not reach, `cancelled`
/// when a newer request replaced the call or the user cancelled.
fetch: func(req: request) -> result<response, error>;
}
/// Secrets the user stored for the plugin (Settings › Plugins, kept in the
/// OS keychain). Plugins only use them through `{{secret:<name>}}` in
/// `net` requests. Requires `secrets`.
interface secrets {
use types.{error};
/// Stores a declared secret without ever exposing it back to plugin code (API 1.4).
set: func(name: string, value: string) -> result<_, error>;
/// Deletes a declared secret (API 1.4).
delete: func(name: string) -> result<_, error>;
is-set: func(name: string) -> bool;
}
/// Runs of programs granted with `process:<program>` (the file the user
/// approved, checked before every run): once and awaited with `run`, once
/// with an environment with `run-command`, or kept running behind a `child`
/// handle started with `start`.
interface process {
use types.{error};
use workspace.{project};
record output {
/// `none` when killed by a signal.
status: option<s32>,
/// At most 4 MiB each (the rest is dropped).
stdout: string,
stderr: string,
}
/// What to run (API 1.3). `env` only adds variables: an existing name in
/// the prepared child environment (including the login-shell PATH) is an
/// error naming that key; nothing is replaced or removed. Names compare
/// case-insensitively on Windows. At most 64 entries, nonempty names of
/// at most 256 bytes without '=' or NUL, values at most 4 KiB without NUL.
record command {
program: string,
args: list<string>,
env: list<tuple<string, string>>,
}
/// What a kept-running program printed since the last call, and its exit
/// code once it ended (`none` while it still runs).
record chunk {
/// Up to 1 MiB per stream; unpolled output keeps the last 1 MiB.
/// `poll` takes up to `max-bytes`, or one whole character when that
/// limit is smaller. Incomplete characters wait for the next read.
stdout: string,
stderr: string,
status: option<s32>,
}
/// A program left running. Dropping the handle kills it if it still
/// runs, so a plugin cannot leak one; a plugin has at most 8 at a time
/// (the ninth `start` is `invalid`). They also end with the plugin:
/// stopping, disabling or reclaiming it kills what it started.
resource child {
/// What it printed since the last call, and its status once it ends.
poll: func(max-bytes: u32) -> result<chunk, error>;
/// Waits up to `timeout-ms` for it to end (0 only checks), then
/// reports what it printed since the last call.
wait: func(timeout-ms: u32) -> result<chunk, error>;
/// Writes to its stdin; fails once it ended or stdin was closed.
write: func(text: string) -> result<_, error>;
/// Closes stdin; fails once the program ended.
close-stdin: func() -> result<_, error>;
/// Kills it and reaps it, so its status is available afterwards.
kill: func() -> result<_, error>;
}
/// Runs `program` with `args` in `cwd`'s root (else the plugin's data
/// directory) and waits; cancelled with the task or call. Call it inside
/// a task for anything slow.
run: func(program: string, args: list<string>, cwd: option<borrow<project>>, stdin: option<string>) -> result<output, error>;
/// The same as `run`, with append-only environment variables (API 1.3).
run-command: func(cmd: command, cwd: option<borrow<project>>, stdin: option<string>) -> result<output, error>;
/// Starts `cmd` with piped stdin and stdout/stderr, and returns the
/// handle to it without waiting (API 1.3). Closing the invoking window
/// also ends its processes.
start: func(cmd: command, cwd: option<borrow<project>>) -> result<child, error>;
}
/// Local sockets on the project machine, including the server for remote projects.
/// Requires `ipc:<path>`; host-expanded `~/`, `$TMPDIR/`, `$XDG_RUNTIME_DIR/`
/// and Windows `\\.\pipe\name` are accepted. API 1.4.
interface ipc {
use types.{error};
/// A byte stream. At most eight per plugin; dropping closes it, as does stopping the plugin.
resource connection {
/// Writes up to 1 MiB, subject to the current call's budget and cancellation.
write: func(bytes: list<u8>) -> result<_, error>;
/// Reads up to 1 MiB; empty on EOF or timeout. Zero timeout only checks.
read: func(max-bytes: u32, timeout-ms: u32) -> result<list<u8>, error>;
/// Closes the stream; subsequent reads and writes fail.
close: func() -> result<_, error>;
}
/// Connects to an absolute Unix socket or Windows named pipe; never TCP.
connect: func(name: string) -> result<connection, error>;
}
/// OAuth browser redirects received on the desktop, even for remote projects (API 1.4).
/// No capability needed; only commands/events of a window may use this interface.
interface auth {
use types.{error};
/// A one-shot IPv4 loopback listener. At most two open per plugin.
resource loopback {
/// `http://127.0.0.1:<random-port>/<path>` for the authorization URL.
redirect-uri: func() -> string;
/// Returns the first matching request's raw query string, or none on timeout.
/// Waiting is excluded from the call budget. The listener serves a short
/// completion page and closes; resource drop and plugin stop also close it.
wait: func(timeout-ms: u32) -> result<option<string>, error>;
}
/// Binds 127.0.0.1 only. `path` has no query or fragment.
begin-loopback: func(path: string) -> result<loopback, error>;
}