Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@
-keep class com.google.android.material.** { *; }
-keep class io.noties.markwon.** { *; }
-keep class com.google.gson.** { *; }
-keep class org.snakeyaml.engine.** { *; }

-keep class com.google.firebase.** { *; }
-keep class com.google.android.gms.** { *; }
Expand Down
39 changes: 37 additions & 2 deletions docs/PLUGIN_API_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,41 @@ need a source change, a recompile, or both · `tooling` = API-stability
milestone. **[verified]** = read from the checked-in ABI dump. **[reconstructed]**
= diffed from `plugin-api/src` history (predates the dump; symbol-accurate).

### 26.40 — unreleased
### 26.41 — unreleased
- **added — The AI prompt config engine and settings-pane helpers** _(ADFA-6281)_ **[verified]**
Every AI plugin carried its own copy of the code that reads and renders its prompt
config, and the credential screens their own copy of the reveal toggle and pane
styling, so a fix had to be repeated per plugin and a missed copy made the plugins
drift. The host now ships one copy.
`com.itsaky.androidide.plugins.ai.prompt`: `PromptTemplateEngine` and `PromptText`
(the `{{NAME}}` / `{{#NAME}}` / `{{^NAME}}` renderer; names may be in any case and hold
dots, e.g. `{{fileName}}` or `{{item.name}}`, `{{{{` writes a literal `{{`, and config text keeps its whitespace as YAML
parsed it); `PromptConfigLoader.load(source,
parser)`, which reads `agent.yml` and its `include` list off the main thread;
`PromptConfigDocument` and `PromptConfigObject`, the strict key-by-key reader a parser
maps the merged YAML through; `PromptConfigSource` / `AssetPromptConfigSource`;
`PromptConfigException`; and `PromptConfigStore<T>`, the per-activation cache, behind
`PromptConfigProvider<T>`. Loader and store are generic over the plugin's config type:
a plugin supplies only a `PromptConfigParser<T>` and keeps one store, e.g.
`val shared = PromptConfigStore(MyParser)`, and calls `shared.reload(source, onLoaded, onFailed)`
from `activate()` and `shared.clear()` from `deactivate()`. The YAML library (snakeyaml-engine 2.10)
is on the host side, so a plugin using the loader no longer bundles it.
`com.itsaky.androidide.plugins.ai.ui`: `SecretRevealController`, whose two states are
each a `RevealToggle` (icon and content description), and
`View.applyPaneStyling(PaneStyle, outlinedButtonIds)`, with `PaneStyle` grouping a
`ButtonColors` per emphasis and a `FieldColors`. Both take the plugin's own resource ids
rather than shipping any: they resolve against the view's context, which carries the
plugin's resources, not the host's.
Additive to the ABI (185 added lines in the dump, none removed), but no longer unused:
AI-Core and the Gemini, Local and OpenAI agents now load and render their prompt config
through `ai.prompt` and drop their private copies, and the Gemini, OpenAI and MCP
settings screens use `ai.ui`. `LlmInferenceService.WebSearchBackend` (`canSearchWeb()`)
lets a backend say whether a `web_search` request would be searched now; ai-core forces
and offers its `web_search` tool only when it does. The `extraParams` keys both sides
read are defined once, as `WebSearchBackend.EXTRA_PARAM_WEB_SEARCH` and
`ToolCallingBackend.EXTRA_PARAM_REQUIRED_TOOL`. Floor
`plugin.min_ide_version` at `26.41` to use any of it; an older IDE has none of these
classes, and the plugin fails with `NoClassDefFoundError` on first use.
- **added — Read-only App Logs and IDE Logs** _(ADFA-6267)_ **[verified]**
Plugins could read build output (`IdeBuildService.getBuildOutput()`) but not the App Logs
or IDE Logs tabs, so an agent diagnosing a runtime crash had to ask the user to paste them.
Expand All @@ -50,7 +84,8 @@ milestone. **[verified]** = read from the checked-in ABI dump. **[reconstructed]
`LogReadResult.EMPTY`, never a throw. The service has no clear or write method, and needs
no permission: plugins run in-process under the IDE's uid, so a gate would disclose log
access, not enforce it. Purely additive (the ABI dump diff is additions only). Floor
`plugin.min_ide_version` at `26.40` to use it; an older IDE has no such service.
`plugin.min_ide_version` at `26.41` to use it; an older IDE has no such service.
### 26.40 — 2026-09-29
- **added — An embedding capability a backend can declare** _(ADFA-6053)_ **[verified]**
A backend that has an embedding model can now say so. The only embedding entry point
before this was `LlmInferenceService.getEmbeddings(String, String)`, which addresses a
Expand Down
2 changes: 1 addition & 1 deletion docs/plugin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The surface a plugin binds to is broader than one module. All of the following a
- Extension interfaces plugins **implement**: `UIExtension`, `EditorExtension`, `EditorTabExtension`, `DocumentationExtension`, `BuildActionExtension`, `SnippetExtension`, `ProjectExtension`, `FileOpenExtension`, `SettingsExtension`.
- IDE service interfaces plugins **call** (via `ServiceRegistry.get(X::class.java)`): `IdeProjectService`, `IdeEditorService`, `IdeFileService`, `IdeEnvironmentService`, `IdeArchiveService`, `IdeBuildService`, `IdeLogService`, `IdeUIService`, `IdeEditorTabService`, `IdeTooltipService`, `IdeThemeService`, `IdeFeatureFlagService`, `IdeCommandService`, `IdeTemplateService`, `IdeSnippetService`, `IdeSidebarService`.
- Cross-plugin service interfaces, where **one plugin implements what another calls** (via `SharedServices`): `LlmInferenceService` — implemented by ai-core, called by every AI plugin — together with the types nested in it that a *backend* plugin implements (`LlmBackend`, `HistoryCapableBackend`, `ToolCallingBackend`, `CancellableBackend`, `ConfigurableBackend`, `EmbeddingBackend`) and the value types either side constructs (`ChatMessage`, `LlmConfig`, `LlmResponse`, `SystemPromptRequest`, `ToolDefinition`, `ToolCallRequest`). Also `ToolSourceRegistry` — implemented by ai-core, called by any plugin contributing tools to the agent — with `ToolSource` and `ToolSpec`, which a *contributing* plugin implements, `ToolInvocation`, which ai-core constructs and passes to `ToolSource.invoke`, and `ToolOutcome`, which the source returns.
- Utility classes plugins **instantiate**: `KeystoreSecretStore` (AES/GCM over the Android Keystore, alias supplied by the caller). Host-side implementation rather than an interface, so plugins share one copy in the process instead of compiling their own.
- Utility classes plugins **instantiate**: `KeystoreSecretStore` (AES/GCM over the Android Keystore, alias supplied by the caller); the AI prompt config engine in `ai.prompt` (`PromptTemplateEngine`, `PromptConfigLoader`, `PromptConfigStore`, `PromptConfigDocument`, `PromptConfigObject`, `AssetPromptConfigSource`), generic over a plugin's own config type through `PromptConfigParser` and `PromptConfigProvider`, which a plugin implements; and the settings-pane helpers in `ai.ui` (`SecretRevealController` with `RevealToggle`, `applyPaneStyling` with `PaneStyle`, `ButtonColors` and `FieldColors`). Host-side implementations rather than interfaces, so plugins share one copy in the process instead of compiling their own.
- Data classes plugins **construct** (e.g. `MenuItem`, `TabItem`, `EditorTabItem`, `NavigationItem`, `ToolbarAction`, `FabAction`, `PluginBuildAction`, `SnippetContribution`, `PluginTooltipEntry`, `PluginSettingsEntry`).
- Enums / sealed types plugins **reference**: `PluginPermission`, `ShowAsAction`, `ArchiveFormat`, `BuildActionCategory`, `ToolbarActionIds`, `CommandSpec`, `CommandResult`, `ExtractResult`, `KeystoreSecretStore.Stored`. Sealed, so a plugin `when`s over the cases exhaustively — adding one is a **breaking** change, not an additive one.
- **Wire/format contracts outside the module:**
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ tooling-agp = { module = "com.android.tools.build:gradle", version.ref = "agp-to
tooling-builderModel = { module = "com.android.tools.build:builder-model", version.ref = "agp-tooling" }
tooling-gradleApi = { module = "com.itsaky.androidide.gradle:gradle-tooling-api", version.ref = "gradle-tooling" }
tooling-slf4j = { module = "org.slf4j:slf4j-api", version = "2.0.12" }
# 2.x targets Java 8; 3.x needs 11. Match the AI plugins' copy, which the app shadows parent-first.
snakeyaml-engine = { module = "org.snakeyaml:snakeyaml-engine", version = "2.10" }

# Classpaths
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }
Expand Down
Loading
Loading