diff --git a/Cargo.lock b/Cargo.lock index 8c6fa298f..f907ce3c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4180,7 +4180,7 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "ide-agent" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dunce", "encoding_rs", @@ -4204,7 +4204,7 @@ dependencies = [ [[package]] name = "ide-analysis" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ast-grep-core", "ide-core", @@ -4218,7 +4218,7 @@ dependencies = [ [[package]] name = "ide-android" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "serde", @@ -4229,7 +4229,7 @@ dependencies = [ [[package]] name = "ide-build" -version = "0.1.39" +version = "0.1.40" dependencies = [ "blake3", "dirs 6.0.0", @@ -4245,7 +4245,7 @@ dependencies = [ [[package]] name = "ide-cli" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dirs 6.0.0", "serde", @@ -4259,7 +4259,7 @@ dependencies = [ [[package]] name = "ide-clipboard" -version = "0.1.39" +version = "0.1.40" dependencies = [ "objc2 0.6.5", "objc2-app-kit 0.3.2", @@ -4268,7 +4268,7 @@ dependencies = [ [[package]] name = "ide-core" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dunce", "encoding_rs", @@ -4286,7 +4286,7 @@ dependencies = [ [[package]] name = "ide-coverage" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "ide-run", @@ -4300,7 +4300,7 @@ dependencies = [ [[package]] name = "ide-dap" -version = "0.1.39" +version = "0.1.40" dependencies = [ "futures", "ide-core", @@ -4323,7 +4323,7 @@ dependencies = [ [[package]] name = "ide-db" -version = "0.1.39" +version = "0.1.40" dependencies = [ "bb8", "blake3", @@ -4353,7 +4353,7 @@ dependencies = [ [[package]] name = "ide-docker" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "serde", @@ -4366,7 +4366,7 @@ dependencies = [ [[package]] name = "ide-extension" -version = "0.1.39" +version = "0.1.40" dependencies = [ "base64 0.22.1", "blake3", @@ -4386,7 +4386,7 @@ dependencies = [ [[package]] name = "ide-fonts" -version = "0.1.39" +version = "0.1.40" dependencies = [ "objc2-core-foundation", "objc2-core-text", @@ -4398,7 +4398,7 @@ dependencies = [ [[package]] name = "ide-github" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "ide-vcs", @@ -4411,7 +4411,7 @@ dependencies = [ [[package]] name = "ide-host" -version = "0.1.39" +version = "0.1.40" dependencies = [ "base64 0.22.1", "blake3", @@ -4478,7 +4478,7 @@ dependencies = [ [[package]] name = "ide-http" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "parking_lot", @@ -4496,7 +4496,7 @@ dependencies = [ [[package]] name = "ide-index" -version = "0.1.39" +version = "0.1.40" dependencies = [ "blake3", "criterion", @@ -4518,7 +4518,7 @@ dependencies = [ [[package]] name = "ide-jsonrpc" -version = "0.1.39" +version = "0.1.40" dependencies = [ "encoding_rs", "futures", @@ -4535,7 +4535,7 @@ dependencies = [ [[package]] name = "ide-language" -version = "0.1.39" +version = "0.1.40" dependencies = [ "blake3", "criterion", @@ -4591,7 +4591,7 @@ dependencies = [ [[package]] name = "ide-lsp" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dunce", "futures", @@ -4617,7 +4617,7 @@ dependencies = [ [[package]] name = "ide-mcp" -version = "0.1.39" +version = "0.1.40" dependencies = [ "bytes", "dunce", @@ -4636,7 +4636,7 @@ dependencies = [ [[package]] name = "ide-notebook" -version = "0.1.39" +version = "0.1.40" dependencies = [ "futures", "ide-core", @@ -4659,7 +4659,7 @@ dependencies = [ [[package]] name = "ide-plugin" -version = "0.1.39" +version = "0.1.40" dependencies = [ "blake3", "dunce", @@ -4682,7 +4682,7 @@ dependencies = [ [[package]] name = "ide-profiler" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "ide-run", @@ -4695,7 +4695,7 @@ dependencies = [ [[package]] name = "ide-remote" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dunce", "globset", @@ -4714,7 +4714,7 @@ dependencies = [ [[package]] name = "ide-run" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dunce", "encoding_rs", @@ -4738,7 +4738,7 @@ dependencies = [ [[package]] name = "ide-sdk" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dunce", "ide-core", @@ -4758,7 +4758,7 @@ dependencies = [ [[package]] name = "ide-search" -version = "0.1.39" +version = "0.1.40" dependencies = [ "criterion", "globset", @@ -4778,7 +4778,7 @@ dependencies = [ [[package]] name = "ide-spell" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "parking_lot", @@ -4791,7 +4791,7 @@ dependencies = [ [[package]] name = "ide-ssh" -version = "0.1.39" +version = "0.1.40" dependencies = [ "dirs 6.0.0", "flate2", @@ -4812,7 +4812,7 @@ dependencies = [ [[package]] name = "ide-syntax" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "ide-language", @@ -4827,7 +4827,7 @@ dependencies = [ [[package]] name = "ide-terminal" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "libc", @@ -4840,7 +4840,7 @@ dependencies = [ [[package]] name = "ide-text" -version = "0.1.39" +version = "0.1.40" dependencies = [ "criterion", "ide-core", @@ -4853,7 +4853,7 @@ dependencies = [ [[package]] name = "ide-tools" -version = "0.1.39" +version = "0.1.40" dependencies = [ "flate2", "hex", @@ -4874,7 +4874,7 @@ dependencies = [ [[package]] name = "ide-vcs" -version = "0.1.39" +version = "0.1.40" dependencies = [ "blake3", "dunce", @@ -4895,7 +4895,7 @@ dependencies = [ [[package]] name = "ide-vfs" -version = "0.1.39" +version = "0.1.40" dependencies = [ "chardetng", "dunce", @@ -4919,7 +4919,7 @@ dependencies = [ [[package]] name = "ide-web" -version = "0.1.39" +version = "0.1.40" dependencies = [ "ide-core", "open", @@ -4935,7 +4935,7 @@ dependencies = [ [[package]] name = "ide-workspace" -version = "0.1.39" +version = "0.1.40" dependencies = [ "blake3", "dunce", @@ -6522,7 +6522,7 @@ dependencies = [ [[package]] name = "openidea" -version = "0.1.39" +version = "0.1.40" dependencies = [ "base64 0.22.1", "blake3", diff --git a/Cargo.toml b/Cargo.toml index 8e2e0e3c6..197b46448 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = ["crates/*", "src-tauri"] exclude = ["sdk", "plugins"] [workspace.package] -version = "0.1.39" +version = "0.1.40" edition = "2024" rust-version = "1.96" license = "Apache-2.0" diff --git a/package.json b/package.json index e35520a11..1244e4e1d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "openidea", "private": true, "description": "An open-source IDE inspired by IntelliJ IDEA", - "version": "0.1.39", + "version": "0.1.40", "license": "Apache-2.0", "type": "module", "scripts": { diff --git a/sdk/rust/openidea-plugin/tests/api/released/commit.wit b/sdk/rust/openidea-plugin/tests/api/released/commit.wit index a70b889c1..91dbe0e28 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/commit.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/commit.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// The commit being prepared in the window the current command or event came /// from (the Commit tool window, or the Commit dialog while it is open): the diff --git a/sdk/rust/openidea-plugin/tests/api/released/database.wit b/sdk/rust/openidea-plugin/tests/api/released/database.wit new file mode 100644 index 000000000..4e77bd9c8 --- /dev/null +++ b/sdk/rust/openidea-plugin/tests/api/released/database.wit @@ -0,0 +1,34 @@ +package openidea:plugin@1.4.0; + +/// Plugin-owned project data sources. Requires database.sources and project trust. +/// Runs on the Database subsystem's host, including on remote project servers. +interface database { + use types.{error}; + use workspace.{project}; + /// Non-secret connection settings. Id is private to this plugin (1–128 bytes). + /// Drivers: sqlite, postgres, mysql, sqlServer, clickhouse, oracle. + /// SQLite uses database as its file path, or a sqlite: URL. Options are driver properties. + /// URLs and options must not contain passwords, tokens or other credentials. + record data-source { + id: string, + name: string, + driver: string, + host: option, + port: option, + database: option, + user: option, + url: option, + options: list>, + } + /// Creates or replaces only this plugin's source; unrelated file entries are preserved. + upsert-source: func(project: borrow, source: data-source) -> result<_, error>; + /// Removes an owned source and its credentials; not-found for every other id. + remove-source: func(project: borrow, id: string) -> result<_, error>; + /// Lists only this plugin's private ids, never connection settings or credentials. + sources: func(project: borrow) -> result, error>; + /// Writes an owned source's password directly to the Database secure store. Never readable. + set-credential: func(project: borrow, id: string, password: string) -> result<_, error>; + /// Requests the project's usual connection/introspection in the invoking window. + /// Invalid outside a command/event of that project's window. + connect: func(project: borrow, id: string) -> result<_, error>; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/decorations.wit b/sdk/rust/openidea-plugin/tests/api/released/decorations.wit new file mode 100644 index 000000000..1c5a033e6 --- /dev/null +++ b/sdk/rust/openidea-plugin/tests/api/released/decorations.wit @@ -0,0 +1,22 @@ +package openidea:plugin@1.4.0; + +/// Project-scoped decorations (API 1.4). Requires project.read; paths must be inside +/// an open project. Sets belong to the plugin and disappear when it stops. +/// Styles: highlight, search, added, modified, removed, warning, error, info, +/// underline, strikethrough, muted. Unknown styles are ignored. Theme tokens only. +interface decorations { + use types.{error, range}; + /// An editor annotation; after is plain text shown after the range. + record decoration { range: range, style: string, hover: option, after: option } + /// A project-tree annotation; badge is at most two Unicode characters. + record file-decoration { badge: option, style: string, tooltip: option } + /// Replace this set for a file. At most 10,000 items/file and 50 editor sets/plugin. + /// Metadata is bounded to 4 MiB per plugin. Unknown styles are ignored. + set: func(path: string, set-id: string, items: list) -> result<_, error>; + /// Remove this editor set from every file/project. + clear: func(set-id: string) -> result<_, error>; + /// Replace this set's tree annotation for a file; at most 50 tree sets/plugin. + set-file: func(path: string, set-id: string, item: file-decoration) -> result<_, error>; + /// Remove this tree set from every file/project. + clear-file: func(set-id: string) -> result<_, error>; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/details.wit b/sdk/rust/openidea-plugin/tests/api/released/details.wit index 9e889851a..f7342991d 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/details.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/details.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// What the pane beside the Services tree shows for a plugin's node. interface detail-types { diff --git a/sdk/rust/openidea-plugin/tests/api/released/diagnostics.wit b/sdk/rust/openidea-plugin/tests/api/released/diagnostics.wit index d5d62de72..499335fde 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/diagnostics.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/diagnostics.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Optional export (world `plugin-diagnostics`): problems in the current, /// possibly unsaved document, for the languages declared with the diff --git a/sdk/rust/openidea-plugin/tests/api/released/endpoints.wit b/sdk/rust/openidea-plugin/tests/api/released/endpoints.wit index 95302fcb0..f4a446fe0 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/endpoints.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/endpoints.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// HTTP endpoints found in a project (`[[contributes.endpoints]]`). interface endpoints-provider { diff --git a/sdk/rust/openidea-plugin/tests/api/released/events.wit b/sdk/rust/openidea-plugin/tests/api/released/events.wit index 8851d18a7..f52030971 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/events.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/events.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Workbench events, delivered in batches to `event-handler.handle`. interface events { @@ -29,6 +29,9 @@ interface events { /// Delivers `kind` events from now on, for the rest of the session (also /// across idle reclaim: an event activates the plugin again). Declare /// `activation = ["on-event:"]` to get them before first use. + /// API 1.4 also delivers `file-closed` (JSON path string), `settings-changed` + /// (JSON array of the plugin's changed setting keys), and `input-mode-changed` + /// (JSON {path, mode, sub}) through `other`. The last needs `events.input`. /// Kinds: `file-opened`, `file-saved`, `files-changed` (batched disk changes /// as `other`, with created/modified/removed path lists in JSON), `editor-focused` (the focused editor /// changed), `vcs-changed` (a repository's state changed: commit, diff --git a/sdk/rust/openidea-plugin/tests/api/released/exports.wit b/sdk/rust/openidea-plugin/tests/api/released/exports.wit index 67d7c6060..434b29ceb 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/exports.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/exports.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; interface lifecycle { use types.{context, error}; diff --git a/sdk/rust/openidea-plugin/tests/api/released/file-actions.wit b/sdk/rust/openidea-plugin/tests/api/released/file-actions.wit index 477809180..12b4aec17 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/file-actions.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/file-actions.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Optional export (world `plugin-file-actions`): quick fixes and /// refactorings that create, rename or delete files, next to the text edits diff --git a/sdk/rust/openidea-plugin/tests/api/released/fs.wit b/sdk/rust/openidea-plugin/tests/api/released/fs.wit index 7cd07fd71..c1a96cf83 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/fs.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/fs.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Files outside the open projects: the configuration of the program a /// plugin integrates with, a tool installed elsewhere, a licence file. diff --git a/sdk/rust/openidea-plugin/tests/api/released/host.wit b/sdk/rust/openidea-plugin/tests/api/released/host.wit index 91c3e12fc..c5ce20fbe 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/host.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/host.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Writes to the IDE log, tagged with the plugin id. interface log { @@ -53,6 +53,11 @@ interface ui { /// Shows or updates the plugin's status bar item `id` in every window. set-status-item: func(id: string, item: status-item); remove-status-item: func(id: string); + /// Overrides the global item in the invoking window only (API 1.4). + /// Invalid outside a command or event of a window; removed on window close or plugin stop. + set-window-status-item: func(id: string, item: status-item) -> result<_, error>; + /// Removes this window's override, falling back to the global item. + remove-window-status-item: func(id: string) -> result<_, error>; /// Sets the plugin's context key `key`, which `when` clauses test as /// `plugin..`, in the window the current command or event came /// from (every window when there is none). A window's value takes @@ -104,3 +109,23 @@ interface storage { /// Keys starting with `prefix`, sorted. keys: func(prefix: string) -> result, error>; } + +/// Executes stable IDE action ids or `plugin..` (API 1.4). +interface command-runner { + use types.{error}; + /// Only in commands/events of a window. Returns a plugin command's value, + /// or none for IDE actions; unknown ids are not-found. Nested calls are bounded. + /// Requires high-risk `ide.commands`, except for this plugin's own commands. + execute: func(id: string, arg: option) -> result, error>; +} + +/// Per-plugin named, read-only Output tabs (API 1.4), with a 1 MiB UTF-8 ring buffer. +interface output { + use types.{error}; + /// Appends text to a channel (at most 32 channels, names 1-128 bytes). + append: func(channel: string, text: string) -> result<_, error>; + /// Clears a channel's buffer. + clear: func(channel: string) -> result<_, error>; + /// Reveals the channel in the invoking window; only commands/events of a window. + reveal: func(channel: string) -> result<_, error>; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/hover.wit b/sdk/rust/openidea-plugin/tests/api/released/hover.wit index a95c22758..5ddde792e 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/hover.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/hover.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Optional export (world `plugin-hover`): Markdown added to the hover of /// documents of the languages declared with the `hover` provider kind, diff --git a/sdk/rust/openidea-plugin/tests/api/released/indexing.wit b/sdk/rust/openidea-plugin/tests/api/released/indexing.wit index 4ee08d64b..227aab726 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/indexing.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/indexing.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Cross-file associations a plugin publishes for the files it declares under /// `[[contributes.documentIndexers]]`. The host calls `index` in cancellable diff --git a/sdk/rust/openidea-plugin/tests/api/released/injections.wit b/sdk/rust/openidea-plugin/tests/api/released/injections.wit new file mode 100644 index 000000000..016e5b905 --- /dev/null +++ b/sdk/rust/openidea-plugin/tests/api/released/injections.wit @@ -0,0 +1,16 @@ +package openidea:plugin@1.4.0; + +/// Embedded languages. The host routes plugin providers and configured language +/// servers inside these ranges, preserving host-document UTF-16 coordinates. +/// Each LSP range gets its own masked, in-memory sibling document (at most 32 +/// per host document, documents over 2 MiB excluded). No file is written. +/// Formatting and rename continue to use the host language's server. +interface injections { + /// A versioned document snapshot. Coordinates are zero-based UTF-16. + record document { path: string, language: string, version: u64, text: string } + /// A host-document range containing the named language. + record injection { range: range, language: string } + use types.{range}; + /// Embedded ranges, refreshed after edits under the editor-provider budget. + injections: func(doc: document) -> list; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/inlay.wit b/sdk/rust/openidea-plugin/tests/api/released/inlay.wit index ab00b0c9b..1098869a5 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/inlay.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/inlay.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Optional export (world `plugin-inlay-hints`): inline hints in documents of /// the languages declared with the `inlay-hints` provider kind, including diff --git a/sdk/rust/openidea-plugin/tests/api/released/io.wit b/sdk/rust/openidea-plugin/tests/api/released/io.wit index cffd883be..b27e48d62 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/io.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/io.wit @@ -1,8 +1,13 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// 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 } + /// 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) -> result, error>; enum severity { error, @@ -35,7 +40,7 @@ interface diagnostics { publish: func(path: string, diagnostics: list) -> result<_, error>; } -/// HTTP(S) to the hosts granted with `net:`. +/// HTTPS with `net:`; unencrypted HTTP with `net.http:`. interface net { use types.{error}; @@ -46,7 +51,8 @@ interface net { record request { method: string, - /// `https://…`; plain `http://` only to `localhost` / `127.0.0.1`. + /// `https://…` requires `net:`. Plain `http://…` requires + /// `net.http:` (API 1.4), except loopback, which uses `net:`. url: string, /// `{{secret:}}` in a value is replaced by the plugin's secret /// `name` on the way out (requires `secrets`); the plugin never sees it. @@ -72,6 +78,11 @@ interface net { /// OS keychain). Plugins only use them through `{{secret:}}` 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; } @@ -144,3 +155,38 @@ interface process { /// also ends its processes. start: func(cmd: command, cwd: option>) -> result; } + +/// Local sockets on the project machine, including the server for remote projects. +/// Requires `ipc:`; 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) -> 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, 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; +} + +/// 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:/` 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, error>; + } + /// Binds 127.0.0.1 only. `path` has no query or fragment. + begin-loopback: func(path: string) -> result; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/language-features.wit b/sdk/rust/openidea-plugin/tests/api/released/language-features.wit new file mode 100644 index 000000000..c47c4b621 --- /dev/null +++ b/sdk/rust/openidea-plugin/tests/api/released/language-features.wit @@ -0,0 +1,114 @@ +package openidea:plugin@1.4.0; + +/// Additional language features, called only for declared API 1.4 provider kinds. +/// Editor calls have a 50 ms soft / 500 ms hard budget; formatting has 5 seconds. +interface language-features { + use types.{error, position, range, text-edit, location}; + /// A versioned document snapshot. Coordinates are zero-based UTF-16. + record document { + path: string, + language: string, + version: u64, + text: string, + } + /// A parameter label, either literal text or UTF-16 offsets within the signature label. + variant parameter-label { text(string), offsets(tuple) } + /// Indentation options selected by the editor. + record format-options { + tab-size: u32, + insert-spaces: bool, + } + /// One parameter, with optional Markdown documentation. + record parameter { + label: parameter-label, + documentation: option, + } + /// One callable signature; documentation is Markdown. + record signature { + label: string, + documentation: option, + parameters: list, + } + /// Callable signatures and zero-based active signature/parameter indices. + record signature-help-result { + signatures: list, + active-signature: u32, + active-parameter: u32, + } + /// An occurrence of the symbol. Kind: text, read or write; unknown is text. + record highlight { + range: range, + kind: string, + } + /// An absolute path, project-relative path or HTTP(S) URL to follow on click. + record document-link { + range: range, + target: string, + } + /// An inline action. Command must be this plugin's declared command id. + record code-lens { + range: range, + title: string, + command: string, + argument: option, + } + /// A multi-line fold. Kinds: region, comment or imports; unknown is region. + record fold-range { + start-line: u32, + end-line: u32, + kind: string, + } + /// A color literal. All channels are finite floats in the inclusive range 0–1. + record color-info { + range: range, + red: f32, + green: f32, + blue: f32, + alpha: f32, + } + /// An outline node. Parent indexes this list, precedes the child and contains it. + /// Kinds are LSP-style names (e.g. class, method, enum-member); unknown is neutral. + record document-symbol { + name: string, + detail: string, + kind: string, + range: range, + selection-range: range, + parent: option, + } + /// A line action for this plugin's own declared command. Icons follow line-marker + /// aliases, registered icon names or declared manifest marker SVG paths. + record gutter-action { + line: u32, + icon: option, + tooltip: string, + command: string, + argument: option, + } + /// Format the whole document or the selected range. + format: func(doc: document, range: option, options: format-options) -> result, error>; + /// Signature help when the language server has no signatures. + signature-help: func(doc: document, at: position) -> option; + /// Occurrences at the caret, appended to language-server highlights. + document-highlights: func(doc: document, at: position) -> list; + /// Navigable ranges, appended to language-server document links. + document-links: func(doc: document) -> list; + /// Clicks run only this plugin's declared commands. + code-lenses: func(doc: document) -> list; + /// Nested ranges, innermost to outermost. + selection-ranges: func(doc: document, at: position) -> list; + /// Folds to merge with tree-sitter, for any declared language. + folding: func(doc: document) -> list; + /// Color literals to show in the existing color-preview gutter and picker. + colors: func(doc: document) -> list; + /// Replacement strings for the selected color range. + color-presentations: func(doc: document, color: color-info) -> list; + /// Used only when no LSP document symbols are available. + document-symbols: func(doc: document) -> list; + /// Implementation locations, merged with language-server results. + implementation: func(doc: document, at: position) -> list; + /// Type-declaration locations, merged with language-server results. + type-definition: func(doc: document, at: position) -> list; + /// Clicks run only this plugin's declared commands. + gutter-actions: func(doc: document) -> list; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/mcp.wit b/sdk/rust/openidea-plugin/tests/api/released/mcp.wit new file mode 100644 index 000000000..e250f5496 --- /dev/null +++ b/sdk/rust/openidea-plugin/tests/api/released/mcp.wit @@ -0,0 +1,16 @@ +package openidea:plugin@1.4.0; + +/// Discovery of the IDE's built-in MCP server; never exposes its URL or token. +interface mcp { + /// Stdio bridge argv for the invoking project; none without a window/project or while off. + stdio-command: func() -> option>; +} + +/// Optional tools declared by contributes.mcpTools, under the plugin's grants and command budget. +interface mcp-provider { + use types.{error}; + use invocation.{invocation}; + /// Calls the declared local tool name with JSON arguments and the project's window context. + /// Returns text; tools may encode structured data as JSON text. + call: func(tool: string, arguments: string, ctx: borrow) -> result; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/plugin.wit b/sdk/rust/openidea-plugin/tests/api/released/plugin.wit index 8d1451ac3..04c707d20 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/plugin.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/plugin.wit @@ -8,7 +8,7 @@ /// `fs` and `workspace`, and everything else goes through the imports below, /// gated by the capabilities granted in `plugin.toml` (a missing one returns /// `error::denied`). -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; world plugin { import log; @@ -17,6 +17,7 @@ world plugin { import fs; import workspace; import editor; + import decorations; import invocation; import vcs; import commit; @@ -26,7 +27,15 @@ world plugin { import net; import secrets; import process; + import ipc; + import output; + import auth; + import command-runner; import views; + import run; + import run-targets; + import database; + import mcp; import settings; export lifecycle; @@ -168,3 +177,26 @@ world plugin-diagnostics { world editor-diagnostics { export diagnostics-provider; } + +/// A plugin that exports project run configurations. +world plugin-run-configurations { include plugin; export run-configurations; } +/// Export-only configurations world, composed with plugin by SDK macros. +world configurations-provider { export run-configurations; } +/// A plugin that parses its test output. +world plugin-test-results { include plugin; export test-results; } +/// Export-only test parser world, composed with plugin by SDK macros. +world test-results-provider { export test-results; } + +/// A plugin with additional API 1.4 language features. +world plugin-language-features { include plugin; export language-features; } +/// Export-only language features, composed with the base plugin world. +world editor-language-features { export language-features; } +/// A plugin that identifies embedded language ranges. +world plugin-injections { include plugin; export injections; } +/// Export-only injections, composed with the base plugin world. +world language-injections { export injections; } + +/// A plugin contributing tools to the built-in MCP server. +world plugin-mcp { include plugin; export mcp-provider; } +/// Export-only MCP tools, composed with the base plugin world. +world mcp-tools { export mcp-provider; } diff --git a/sdk/rust/openidea-plugin/tests/api/released/providers.wit b/sdk/rust/openidea-plugin/tests/api/released/providers.wit index 317eb81d1..8c0713ec6 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/providers.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/providers.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Editor features a plugin provides for the languages it declares under /// `[[contributes.providers]]` (the host calls only declared kinds). They run diff --git a/sdk/rust/openidea-plugin/tests/api/released/run-targets.wit b/sdk/rust/openidea-plugin/tests/api/released/run-targets.wit new file mode 100644 index 000000000..ee436a9a5 --- /dev/null +++ b/sdk/rust/openidea-plugin/tests/api/released/run-targets.wit @@ -0,0 +1,39 @@ +package openidea:plugin@1.4.0; + +/// Project-scoped targets owned by the registering plugin (API 1.4). +interface run-targets { + use types.{error}; + use workspace.{project}; + + /// An argv wrapper using a granted, pinned process program. No shell is used. + /// Normally: program + args + workdir-args + command + command arguments. + /// An override matches wrap::program_name(command) and replaces args AND command: + /// program + override + workdir-args + command arguments. + /// DDEV: program="ddev", args=["exec"], commands=[("composer", ["composer"])]: + /// `ddev exec php x.php` and `ddev composer install`. + /// Each workdir-args element may contain {cwd}, mapped under container-root. + /// All workdir-args are omitted without container-root or for cwd outside the project. + /// Without workdir-args the wrapper manages its container directory itself. + /// The wrapper always starts in the configuration's LOCAL working directory. + /// Environment reaches the wrapper; forwarding into a container depends on its conventions. + /// Registration never selects the target. Debugging requires container-root and an + /// explicitly supported language debugger placement. Connect-back adapters listen + /// on the host; the target must configure the debuggee to connect to that host. + /// Stdio adapters run inside the target and must be installed there. + record run-target { + id: string, + name: string, + program: string, + args: list, + workdir-args: list, + container-root: option, + commands: list>>, + } + + /// Registers/replaces this plugin's target in an open, trusted project. + /// Targets survive idle reclamation, and disappear on unregister or plugin stop. + /// Remote project registration and execution take place on the server. + register: func(project: borrow, target: run-target) -> result<_, error>; + /// Removes only this plugin's target from the project; missing ids are harmless. + unregister: func(project: borrow, id: string); +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/run.wit b/sdk/rust/openidea-plugin/tests/api/released/run.wit new file mode 100644 index 000000000..6c62534e2 --- /dev/null +++ b/sdk/rust/openidea-plugin/tests/api/released/run.wit @@ -0,0 +1,53 @@ +package openidea:plugin@1.4.0; + +/// Launches this plugin's configurations in the invoking window's Run tool window. +interface run { + use types.{error}; + /// Starts an owned configuration, appending args. Debug requires a debugger. + /// Only from a window command/event. The returned id receives run-exited. + start: func(config: string, args: list, debug: bool) -> result; +} + +/// Optional dynamic configurations, refreshed alongside run detectors. +interface run-configurations { + /// A configuration running an approved process in the project sandbox. + record run-configuration { + id: string, + name: string, + program: string, + args: list, + cwd: option, + test: bool, + framework: option, + } + /// Returns the complete set for this project root. + configurations: func(project-root: string) -> list; +} + +/// Optional parser for test configurations whose framework is plugin. +interface test-results { + use types.{location, extension}; + /// A suite or test; parents must precede children and ids remain stable for a run. + record test-start { id: string, parent: option, name: string, location: option } + /// A successful test and optional elapsed milliseconds. + record test-passed { id: string, duration-ms: option } + /// A failed test, comparison and optional declaration location. + record test-failed { + id: string, duration-ms: option, message: string, + expected: option, actual: option, location: option, + } + /// A skipped test and its explanation. + record test-skipped { id: string, reason: option } + /// Output attached to a test or suite. + record test-output { id: string, text: string } + /// Incremental updates to the IDE's test tree. Unknown extensions are ignored. + variant test-event { + suite-started(test-start), test-started(test-start), passed(test-passed), + failed(test-failed), skipped(test-skipped), output(test-output), other(extension), + } + /// Parses one bounded output batch; failures fall back to built-in parsers. + parse: func(config: string, chunk: string) -> list; + /// Selects test-tree name paths (parents then test), using the same config id as parse. + /// Returns the full replacement argument list, or none when filtering is unsupported. + select-tests: func(config: string, tests: list>) -> option>; +} diff --git a/sdk/rust/openidea-plugin/tests/api/released/semantic.wit b/sdk/rust/openidea-plugin/tests/api/released/semantic.wit index ec89fe405..586c324e6 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/semantic.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/semantic.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Optional export (world `plugin-semantic-tokens`): semantic colouring of /// documents of the languages declared with the `semantic-tokens` provider diff --git a/sdk/rust/openidea-plugin/tests/api/released/types.wit b/sdk/rust/openidea-plugin/tests/api/released/types.wit index 8114a2db0..4192e783c 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/types.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/types.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Shared types. Positions are 0-based lines and UTF-16 code unit columns, /// as in the editor and LSP. diff --git a/sdk/rust/openidea-plugin/tests/api/released/views.wit b/sdk/rust/openidea-plugin/tests/api/released/views.wit index 78da35354..a34be2d46 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/views.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/views.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; /// Declarative views: tool windows declared /// under `[[contributes.views]]` and custom editors under @@ -124,6 +124,31 @@ interface view-types { interface views { use types.{error}; use detail-types.{process-log}; + use process.{command}; + + /// An editor toolbar action; at most one action is the Save handler. + record content-action { id: string, label: string, icon: option, primary: bool, save: bool } + /// A plugin-owned content editor, scoped by key to the invoking window. + record content-tab { + key: string, title: string, file-name: option, language: option, + content: string, read-only: bool, actions: list, + } + /// A comparison opened by a content action reply. + record content-diff { left: string, right: string, left-label: option, right-label: option, title: option } + /// Optional updates to an outstanding action or Save request. + record content-tab-reply { + content: option, saved: option, read-only: option, + status: option, error: option, diff: option, + } + /// Opens or focuses a running session with this key; env is append-only. + /// Only from a window command/event; the id receives one terminal-exited. + open-terminal-session: func(key: string, title: string, cmd: command) -> result; + /// Writes to this plugin's running keyed terminal in the invoking window. + write-terminal: func(key: string, text: string) -> result<_, error>; + /// Opens the existing content editor protocol without a web view. + open-content-tab: func(tab: content-tab) -> result<_, error>; + /// Answers content-tab-action in its originating window. + reply-content-tab: func(request-id: string, reply: content-tab-reply) -> result<_, error>; /// The view (or every custom editor of that id) shows outdated content: /// the IDE renders it again. diff --git a/sdk/rust/openidea-plugin/tests/api/released/workspace.wit b/sdk/rust/openidea-plugin/tests/api/released/workspace.wit index 556dd0da8..7c1e9dd19 100644 --- a/sdk/rust/openidea-plugin/tests/api/released/workspace.wit +++ b/sdk/rust/openidea-plugin/tests/api/released/workspace.wit @@ -1,4 +1,4 @@ -package openidea:plugin@1.3.0; +package openidea:plugin@1.4.0; interface workspace { use types.{error, location}; @@ -39,10 +39,28 @@ interface workspace { location: location, } + /// Text search options. Include/exclude are project-relative globs, as in Find in Files. + record text-query { + pattern: string, + regex: bool, + case-sensitive: bool, + whole-word: bool, + %include: list, + exclude: list, + } + /// A match with zero-based lines and UTF-16 columns, and its displayed line. + record text-match { location: location, line: string } + /// Bounded search results; limit-hit says there may be more matches. + record text-search { matches: list, limit-hit: bool } + /// A project open in the IDE. resource project { /// Absolute path of the project root. Requires `project.read`. root: func() -> result; + /// Find in Files with unsaved documents and project excludes. Requires project.read. + /// Cancellable, at most 10,000 matches. Zero limit returns no matches. + /// Line previews are capped at 4096 UTF-8 bytes, results at 4 MiB (limit-hit). + search-text: func(query: text-query, limit: u32) -> result; /// Reads a UTF-8 text file inside the project (absolute, or relative /// to the root); paths leaving the root are refused. Unsaved editor /// contents win over the disk. A missing path is `not-found`. @@ -94,10 +112,22 @@ interface editor { text: string, } + /// An editor in the invoking window. + record open-editor { path: string, language: string, dirty: bool, active: bool } + /// Only from commands/events of a window. Requires editor.read. + open-editors: func() -> result, error>; + /// Open a project file (project.read) or a file in plugin-dir, selecting a range. + /// Only from commands/events of a window. Paths follow views.open-location. + open: func(path: string, selection: option) -> result<_, error>; + /// A file open in an editor. resource text-editor { /// Absolute path of the file. path: func() -> string; + /// Replace selections in this window's editor. No capability; commands/events only. + set-selections: func(selections: list) -> result<_, error>; + /// Scroll a range into view in this window's editor. No capability; commands/events only. + reveal: func(range: range) -> result<_, error>; /// Language id (`rust`, `solidity`, …). language: func() -> string; /// Current version and text. Requires `editor.read`. @@ -151,6 +181,22 @@ interface vcs { changed-files: u32, } + /// A commit in repository history; date is Unix seconds. + record commit-info { + id: string, short-id: string, author: string, author-email: string, + date: s64, subject: string, body: string, parents: list, + } + /// One zero-based document line's attribution; date is Unix seconds. + record blame-line { line: u32, commit: string, author: string, date: s64, summary: string } + /// Newest commits first, at most 1000. Trusted projects only; requires vcs.read. + log: func(project: borrow, path: option, limit: u32) -> result, error>; + /// Includes unsaved text, with changed lines attributed to uncommitted changes. + /// Trusted projects only; requires vcs.read. Paths must be inside the project. + blame: func(project: borrow, path: string) -> result, error>; + /// Working tree versus HEAD or against. None outside a repository. Disk text only. + /// Fails above 4 MiB. Trusted projects only; requires vcs.read. + diff: func(project: borrow, path: option, against: option) -> result, error>; + /// `none` when the project is not in a repository. Requires `vcs.read`. status: func(project: borrow) -> result, error>; /// Configured remotes (`name`, fetch `url`), in order. Requires `vcs.read`. diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c3d2d8b1d..8ff6039de 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "OpenIDEA", - "version": "0.1.39", + "version": "0.1.40", "identifier": "ai.l0ng.openidea", "build": { "beforeDevCommand": "pnpm dev",