diff --git a/.github/buildcheck/tests/test_versions.py b/.github/buildcheck/tests/test_versions.py
index b2f03ca0a..3504e2538 100644
--- a/.github/buildcheck/tests/test_versions.py
+++ b/.github/buildcheck/tests/test_versions.py
@@ -4,6 +4,7 @@
import io
import os
+import tempfile
import unittest
from unittest import mock
@@ -62,6 +63,33 @@ def test_only_coordinates_both_use_and_only_differences(self):
["s:p is 2 here and 9 in r1: bump it in every repository"])
+class GradleKotlinTest(unittest.TestCase):
+
+ def test_plugins_are_read_from_every_kts_file_outside_build_output(self):
+ with tempfile.TemporaryDirectory() as root:
+ os.makedirs(os.path.join(root, "app", "build"))
+ with open(os.path.join(root, "app", "build.gradle.kts"), "w", encoding="utf-8") as f:
+ f.write('plugins {\n id("com.android.application") version "9.4.0"\n'
+ ' id("org.jetbrains.kotlin.plugin.compose") version "2.4.20"\n'
+ ' kotlin("jvm") version "2.4.21"\n}\n')
+ with open(os.path.join(root, "app", "build", "stale.gradle.kts"), "w", encoding="utf-8") as f:
+ f.write('kotlin("jvm") version "1.0.0"\n')
+ self.assertEqual(versions.gradle_kotlin_plugins(root), [
+ ("app/build.gradle.kts", "org.jetbrains.kotlin.plugin.compose", "2.4.20"),
+ ("app/build.gradle.kts", "org.jetbrains.kotlin.jvm", "2.4.21"),
+ ])
+
+ def test_a_plugin_behind_the_poms_kotlin_is_a_warning_and_nothing_else_is(self):
+ own = {"org.jetbrains.kotlin:kotlin-stdlib": {"2.4.21"}, "org.jetbrains.kotlinx:kotlinx-coroutines-core": {"1.11.0"}}
+ plugins = [("app/build.gradle.kts", "org.jetbrains.kotlin.plugin.compose", "2.4.20"),
+ ("app/build.gradle.kts", "org.jetbrains.kotlin.jvm", "2.4.21")]
+ self.assertEqual(versions.compare_gradle_kotlin(own, plugins), [
+ "org.jetbrains.kotlin.plugin.compose is 2.4.20 in app/build.gradle.kts and the POMs use Kotlin 2.4.21: "
+ "Dependabot bumps only the POMs, bump the Gradle plugin with them"])
+ self.assertEqual(versions.compare_gradle_kotlin({"a:b": {"1"}}, plugins), [])
+ self.assertEqual(versions.compare_gradle_kotlin(own, []), [])
+
+
class MainTest(unittest.TestCase):
def run_main(self, siblings):
@@ -87,6 +115,19 @@ def test_differences_are_warnings_and_never_fail(self):
self.assertNotIn("BitcoinAddressFinder:", err)
self.assertIn("1 version differences", out)
+ def test_a_gradle_kotlin_plugin_behind_the_poms_is_reported_with_the_other_warnings(self):
+ kotlin = pom('org.jetbrains.kotlin'
+ 'kotlin-stdlib2.4.21')
+ out, err = io.StringIO(), io.StringIO()
+ with mock.patch.object(versions, "current_repo", return_value="java-llama.cpp"), \
+ mock.patch.object(versions, "read_local", return_value=[kotlin]), \
+ mock.patch.object(versions, "gradle_kotlin_plugins", return_value=[
+ ("android-llmservice/app/build.gradle.kts", "org.jetbrains.kotlin.plugin.compose", "2.4.20")]):
+ self.assertEqual(versions.main(["x"], "/nowhere", lambda repo, path: kotlin, out, err), 0)
+ self.assertIn("::warning::org.jetbrains.kotlin.plugin.compose is 2.4.20 in android-llmservice/app/build.gradle.kts "
+ "and the POMs use Kotlin 2.4.21", err.getvalue())
+ self.assertIn("1 version differences", out.getvalue())
+
def test_a_missing_pom_skips_that_file_not_the_repository(self):
out, err = io.StringIO(), io.StringIO()
bumped = pom('org.junit.jupiter'
diff --git a/.github/buildcheck/versions.py b/.github/buildcheck/versions.py
index 2935a7614..7b1270d83 100644
--- a/.github/buildcheck/versions.py
+++ b/.github/buildcheck/versions.py
@@ -12,12 +12,17 @@
`${property}` references resolved -- not property
names, which differ between repositories and include values that must differ (the Java release).
+It also compares the Kotlin the POMs use with every Kotlin Gradle plugin a `*.gradle.kts` of the
+repository pins: Dependabot's maven ecosystem bumps `kotlin.version` and never sees the Gradle files,
+which is how a Compose compiler plugin stayed one patch release behind the POMs.
+
Warnings, never failures: a bump lands in four pull requests, and the first one merged would
otherwise turn the other three repositories red. The repository's own artifacts
(`net.ladenthin:*`) are left out: a sibling depends on the last RELEASE of java-llama.cpp while
java-llama.cpp itself is at the next snapshot.
"""
+import os
import re
import sys
import urllib.request
@@ -28,7 +33,7 @@
NS = "{http://maven.apache.org/POM/4.0.0}"
POMS = {
"java-llama.cpp": ("pom.xml", "llama/pom.xml", "llama-langchain4j/pom.xml", "llama-kotlin/pom.xml",
- "llama-platform/pom.xml", "llama-atmosphere-agent/pom.xml"),
+ "llama-platform/pom.xml", "llama-atmosphere-agent/pom.xml", "examples/server/pom.xml"),
"BitcoinAddressFinder": ("pom.xml",),
"srcmorph": ("pom.xml", "srcmorph/pom.xml", "srcmorph-cli/pom.xml", "srcmorph-maven-plugin/pom.xml"),
"streambuffer": ("pom.xml",),
@@ -42,6 +47,11 @@
CONFIGURED = {"palantirJavaFormat": "com.palantir.javaformat:palantir-java-format"}
RAW_URL = "https://raw.githubusercontent.com/{owner}/{repo}/HEAD/{path}"
PROPERTY = re.compile(r"\$\{([^}]+)\}")
+KOTLIN_GROUP = "org.jetbrains.kotlin"
+# `id("org.jetbrains.kotlin.plugin.compose") version "2.4.21"` and `kotlin("jvm") version "2.4.21"`
+GRADLE_KOTLIN = re.compile(
+ r'(?:id\("(org\.jetbrains\.kotlin(?:\.[A-Za-z.]+)?)"\)|kotlin\("([A-Za-z.]+)"\))\s+version\s+"([^"]+)"')
+SKIPPED_DIRS = {".git", ".gradle", ".idea", "build", "node_modules", "target"}
def coordinates(pom_texts):
@@ -94,6 +104,38 @@ def compare(own, others):
return warnings
+def gradle_kotlin_plugins(root):
+ """(path, plugin id, version) for every Kotlin Gradle plugin a `*.gradle.kts` below root pins, in
+ path order; build output and the tools' own directories are not searched."""
+ found = []
+ for dirpath, dirnames, filenames in os.walk(root):
+ dirnames[:] = sorted(d for d in dirnames if d not in SKIPPED_DIRS)
+ for name in sorted(filenames):
+ if not name.endswith(".gradle.kts"):
+ continue
+ path = os.path.join(dirpath, name)
+ with open(path, encoding="utf-8") as f:
+ text = f.read()
+ for match in GRADLE_KOTLIN.finditer(text):
+ plugin = match.group(1) or f"{KOTLIN_GROUP}.{match.group(2)}"
+ found.append((os.path.relpath(path, root).replace(os.sep, "/"), plugin, match.group(3)))
+ return found
+
+
+def compare_gradle_kotlin(own, plugins):
+ """Warnings for every Kotlin Gradle plugin whose version is not one the POMs use for
+ `org.jetbrains.kotlin:*`; nothing when the POMs use no Kotlin or no Gradle file pins a plugin."""
+ maven = set()
+ for coordinate, used in own.items():
+ if coordinate.startswith(KOTLIN_GROUP + ":"):
+ maven |= used
+ if not maven:
+ return []
+ return [f"{plugin} is {version} in {path} and the POMs use Kotlin {', '.join(sorted(maven))}: "
+ f"Dependabot bumps only the POMs, bump the Gradle plugin with them"
+ for path, plugin, version in plugins if version not in maven]
+
+
def fetch(repo, path):
with urllib.request.urlopen(RAW_URL.format(owner=OWNER, repo=repo, path=path), timeout=20) as response:
return response.read().decode("utf-8")
@@ -129,7 +171,7 @@ def main(argv, root, fetcher=fetch, out=sys.stdout, err=sys.stderr):
print(f"::warning::could not read {sibling}'s {path}: {e}", file=err)
if texts:
others[sibling] = coordinates(texts)
- warnings = compare(own, others)
+ warnings = compare(own, others) + compare_gradle_kotlin(own, gradle_kotlin_plugins(root))
for warning in warnings:
print(f"::warning::{warning}", file=err)
shared = set(own).intersection(*others.values()) if others else set()
diff --git a/.github/shared-files.sha256 b/.github/shared-files.sha256
index e8e1e8d2f..2d0fa4df2 100644
--- a/.github/shared-files.sha256
+++ b/.github/shared-files.sha256
@@ -22,13 +22,14 @@ cbe504ad081ba31ec16e11c11f879c64179ca7741bf0b1d1318a7fc969ed67dd .github/buildc
fe36042fbd5444f0b454ad1304cdafde901dd8cec57cfaba7c7086d996dfee27 .github/buildcheck/tests/test_sharedfiles.py
7fe208dd33184b4543328f97b339c95e23c408b120e6bfa6095de4182aeb9a19 .github/check-release-gate.py
1604ccdea83998814a3c1f98f746272222039867b0c7d692355e61495c1c648b .github/check-shared-files.py
-e5f1679dc7151b2676b2f587860bbaa17e1b89b44a5a4e9703eb3499248c4a06 .github/buildcheck/versions.py
-d454d33b61089b5f7bd6d439e3e5b58e01e7b01eeba6b4c2f7ed3360bbb158f0 .github/buildcheck/tests/test_versions.py
+74b4b18af6c5be2af54048de408ec6e138f37f85b9f9ed2fdef258e270a7c90c .github/buildcheck/versions.py
+de437064302f9314028afff00e17fc995e48869e07ee402206d23708c7ed355a .github/buildcheck/tests/test_versions.py
0c78f43dd181f079d35edde7cbf25bb22eac92c907845d8dc8eec78e812aa097 .github/check-versions.py
33c70847b6568604e8725d167a9b1d5910cc2a1a5b01fec7362be31b488ddb02 .github/buildcheck/runscripts.py
c4967e3011d474ec43dbc797d113685c0a8a01b7cc52e910a1356273e6a67dc9 .github/buildcheck/tests/test_runscripts.py
7ad8f7258c983c91e67db695e5ab6ea0f9279af007a6aa815f92f0d8a74c2ae4 .github/check-run-scripts.py
7da53fdb9537ccf7d3f3740be31f295bacb914fe186304b9ed8a65fd3d3d413e .github/print-crash-logs.sh
+fa1469664cb632e210ff3aa0669f15219d160ef13b486abeb978efade55f330b .github/print-host-info.sh
c8c02dc39aeacc154fad74071443c6513666aa94ca9f9c5fab49c5f39dea7ee6 .github/verify-signing-key.sh
e0b2a4f331eae326b61c71f78d6272d06d99140a85dedb7710f93402de862466 .github/verify-bytecode-version.sh
ab45f5c102b47dd16c325d4d9c283d158ba90c05f484eac45b2767885c4462f9 .github/signing-selftest/build.gradle.kts
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40052827c..23b26b8fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -142,6 +142,23 @@ from version 5.0.0 onward. Pre-fork releases (`1.x`–`4.2.0`) were authored by
core's; `check-natives.py` fails when they differ.
### Changed
+- **The local agent speaks ACP through SDK 0.80.0** (`com.agentclientprotocol:acp-core` +
+ `acp-json-jackson2`, from 0.18.0 -- upstream's binary-incompatible release of 2026-10-08). The wire
+ format is unchanged, so `AcpServerTest`, which drives the server with plain JSON, is unchanged too; the
+ port is mechanical: session updates go out through `sendSessionUpdate` without the discriminator
+ argument the records now write themselves, `session/request_permission` is a call on the prompt
+ context's `client()`, `awaitTermination()` replaces `await()`, and the constructors that gained the
+ protocol's new tool-call `name` carry the agent's tool name there (`read_file`, `shell`, ...), so an
+ editor can show it next to the title.
+- **Build tooling in step with the sibling repositories:** Spotless 3.10.4, Checker Framework 4.3.1,
+ `exec-maven-plugin` 3.6.4 in `examples/server/pom.xml` -- which `check-versions.py` reads now, so the
+ drift it had (3.6.2 against the reactor's 3.6.4) can no longer go unseen -- and the Compose compiler
+ plugin 2.4.21, the Kotlin the POMs already used. `check-versions.py` compares the Kotlin Gradle
+ plugins of every `*.gradle.kts` with the POMs' Kotlin from now on: Dependabot bumps `kotlin.version`
+ and never sees the Gradle files.
+- **`print-host-info.sh` is a shared file** (`.github/shared-files.sha256`, in all four repositories):
+ the runner's CPU at the top of every test job, which is how a chosen CPU module or a timing is read
+ against the hardware the job drew.
- **Upgraded the pinned llama.cpp from b11538 to b11556**, one reviewed step (18 commits, 96 files, no
`tools/ui` change, so the WebUI is unchanged). All twelve patches apply unchanged and every drop-check
still finds its defect. In the range: a request pinned to a **busy** slot (`id_slot`,
diff --git a/CLAUDE.md b/CLAUDE.md
index 06b158cec..dd3983bc1 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -342,7 +342,12 @@ resolved) with the siblings' default branches and **warns** per difference. Warn
bump lands in four pull requests and the first one merged must not turn the other three red; the
repos' own artifacts (`net.ladenthin:*`) are left out. It compares what is used, not property names:
those differ between repos and include values that must differ (`maven.compiler.release`). The POM
-list per repo is `versions.POMS` -- a new module's POM goes there, in all four copies.
+list per repo is `versions.POMS` -- a new module's POM goes there, in all four copies (here also
+`examples/server/pom.xml`, whose `exec-maven-plugin` sat two patch releases behind the reactor's unseen
+until it was listed). It also compares the Kotlin Gradle plugins of every `*.gradle.kts` with the Kotlin
+the POMs use (`org.jetbrains.kotlin:*`): Dependabot's maven ecosystem bumps `kotlin.version` and never
+sees the Gradle files, which is how the Compose compiler plugin stayed at 2.4.20 while the POMs went to
+2.4.21.
**Run scripts parse (`check-run-scripts.py`).** A cleanup once lost the trailing ` \` of six continued
lines in `publish.yml` -- each left a line starting with `||`/`&&`, a syntax error in a step only a
@@ -357,7 +362,8 @@ file line), folded and plain values as YAML folds them, `${{ ... }}` becomes a w
`workflow.py` it reads the two-space layout these workflows use, not general YAML.
Shared today: the `buildcheck` modules above marked shared in
-`__init__.py` (+ their tests and CLIs), `print-crash-logs.sh`, `verify-signing-key.sh`,
+`__init__.py` (+ their tests and CLIs), `print-crash-logs.sh`, `print-host-info.sh` (the runner's CPU at the top of every
+test job, so a timing or a chosen CPU module can be read against the hardware), `verify-signing-key.sh`,
`verify-bytecode-version.sh`, `smoke-fatjar-cli.sh` (BAF + srcmorph; `sign-fatjars.sh` is srcmorph's
alone since jllama ships no fat jar), the signing self-test, `lombok.config`, the issue/PR templates, `CODE_OF_CONDUCT.md`,
`claude.yml`, `claude-code-review.yml`, `codeql.yml`, `scorecard.yml`, `reuse.yml`, `osv-scanner.yml`,
diff --git a/android-llmservice/CLAUDE.md b/android-llmservice/CLAUDE.md
index 851e3799d..62febc185 100644
--- a/android-llmservice/CLAUDE.md
+++ b/android-llmservice/CLAUDE.md
@@ -22,7 +22,7 @@ domain is the only string that must be globally unique.
Structure (mirrors the consumer-test's plumbing):
- **`settings.gradle.kts`** — `rootProject.name = "android-llmservice"`; pins AGP `9.4.0` + the
- Compose compiler plugin (`2.4.20`); `mavenLocal()` first so the freshly-built AAR + façade
+ Compose compiler plugin (`2.4.21`); `mavenLocal()` first so the freshly-built AAR + façade
resolve there in CI (Maven Central for real users). Stay at `>= 9.2.1`: `9.2.1` (not `9.2.0`)
first fixed a real R8 regression (`ClassNotFoundException` on `com.android.tools.r8.RecordTag`
after upgrading Gradle to 9.x with AGP 9.2.0) that hits this project directly since
@@ -34,7 +34,7 @@ Structure (mirrors the consumer-test's plumbing):
Kotlin Gradle plugin 2.2.10+), so the standalone `org.jetbrains.kotlin.android` plugin is no longer
applied — applying it now fails the build with "no longer required for Kotlin support since
AGP 9.0" (`app/build.gradle.kts` line 7). The Compose compiler plugin still applies
- separately and its 2.4.20 pin exceeds AGP's 2.2.10 floor, so no other version changed.
+ separately and its 2.4.21 pin exceeds AGP's 2.2.10 floor, so no other version changed.
- **`app/build.gradle.kts`** — `namespace`/`applicationId` `net.ladenthin.android.llmservice`,
`minSdk 28` (AAR floor), `compileSdk 37` (raised from 35 — Compose/lifecycle/activity AAR
metadata now requires it), `targetSdk 35`, Jetpack Compose, `androidx.appcompat` (only for
diff --git a/android-llmservice/README.md b/android-llmservice/README.md
index 65d8e0a8f..0ae994480 100644
--- a/android-llmservice/README.md
+++ b/android-llmservice/README.md
@@ -199,7 +199,7 @@ gradle -p android-llmservice connectedDebugAndroidTest -PjllamaVersion="$VERSION
```
android-llmservice/
-├── settings.gradle.kts # AGP 9.4.0 (built-in Kotlin) + Compose plugin 2.4.20, mavenLocal first
+├── settings.gradle.kts # AGP 9.4.0 (built-in Kotlin) + Compose plugin 2.4.21, mavenLocal first
├── gradle.properties
├── requirements.md # spec of record: every feature the app implements today (no unit tests)
├── TODO.md # roadmap: not-yet-built features
diff --git a/android-llmservice/settings.gradle.kts b/android-llmservice/settings.gradle.kts
index 841b400a8..c920c14c6 100644
--- a/android-llmservice/settings.gradle.kts
+++ b/android-llmservice/settings.gradle.kts
@@ -23,11 +23,11 @@ pluginManagement {
// AGP 9.0+ has built-in Kotlin support (runtime dependency on Kotlin Gradle plugin
// 2.2.10+), so the standalone org.jetbrains.kotlin.android plugin is no longer
// applied/needed — see https://developer.android.com/build/migrate-to-built-in-kotlin.
- // The Compose compiler plugin (2.4.20) still applies separately and exceeds AGP's
+ // The Compose compiler plugin (2.4.21) still applies separately and exceeds AGP's
// 2.2.10 floor.
plugins {
id("com.android.application") version "9.4.0"
- id("org.jetbrains.kotlin.plugin.compose") version "2.4.20"
+ id("org.jetbrains.kotlin.plugin.compose") version "2.4.21"
}
}
diff --git a/examples/server/pom.xml b/examples/server/pom.xml
index 85b47ac1e..44f477961 100644
--- a/examples/server/pom.xml
+++ b/examples/server/pom.xml
@@ -57,7 +57,7 @@ SPDX-License-Identifier: MIT
org.codehaus.mojo
exec-maven-plugin
- 3.6.2
+ 3.6.4
${llama.main}
diff --git a/llama-atmosphere-agent/CLAUDE.md b/llama-atmosphere-agent/CLAUDE.md
index e18c387ca..5029213c9 100644
--- a/llama-atmosphere-agent/CLAUDE.md
+++ b/llama-atmosphere-agent/CLAUDE.md
@@ -855,7 +855,10 @@ object before `buildAsync`**, or the handshake message races the listener into a
`request(1)` is never called — a flaky test that looked like a server bug.
**`--acp` (`AcpServer`, `AcpFrontend`).** The ACP Java SDK (`com.agentclientprotocol:acp-core` +
-`acp-json-jackson2`, 0.18.0) over `StdioAcpAgentTransport`. Its sync handlers run on the SDK's own pool,
+`acp-json-jackson2`, 0.80.0 -- binary-incompatible with 0.18.0, ported 2026-10-11: session updates go out
+through `sendSessionUpdate` without the discriminator argument the records write themselves,
+`session/request_permission` is a call on `context.client()`, `awaitTermination()` replaces `await()`, and
+the tool-call `name` the protocol added carries the agent's tool name) over `StdioAcpAgentTransport`. Its sync handlers run on the SDK's own pool,
so a blocking `session/prompt` does not block `session/cancel` or the answer to a permission request.
One `AgentSession` per ACP session, built for the editor's `cwd` (`AgentOptions.withWorkspace`); the
model endpoint is opened once per process. **stdout is the protocol**: `run()` keeps the real stdout for
diff --git a/llama-atmosphere-agent/pom.xml b/llama-atmosphere-agent/pom.xml
index fec2085e5..30bb12f68 100644
--- a/llama-atmosphere-agent/pom.xml
+++ b/llama-atmosphere-agent/pom.xml
@@ -70,7 +70,7 @@ SPDX-License-Identifier: MIT
4.0.72
4.4.7
12.1.14
- 0.18.0
+ 0.80.0
2.0.20
1.0.1
6.1.3
@@ -84,7 +84,7 @@ SPDX-License-Identifier: MIT
3.2.8
0.11.0
3.6.4
- 3.10.3
+ 3.10.4
2.102.0
net.ladenthin.llama.atmosphere.LocalAgent
diff --git a/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpFrontend.java b/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpFrontend.java
index 54db13779..7d1f44f90 100644
--- a/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpFrontend.java
+++ b/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpFrontend.java
@@ -146,19 +146,18 @@ private synchronized void toolStarted(String tool, @Nullable Map
String id = "call_" + toolCounter.incrementAndGet();
openTools.addLast(new String[] {id, tool});
output.clear();
- context.sendUpdate(
- sessionId,
- new AcpSchema.ToolCall(
- "tool_call",
- id,
- title(tool, arguments),
- kind(tool),
- AcpSchema.ToolCallStatus.IN_PROGRESS,
- null,
- locations(arguments),
- arguments,
- null,
- null));
+ context.sendSessionUpdate(new AcpSchema.ToolCall(
+ "tool_call",
+ id,
+ title(tool, arguments),
+ tool,
+ kind(tool),
+ AcpSchema.ToolCallStatus.IN_PROGRESS,
+ null,
+ locations(arguments),
+ arguments,
+ null,
+ null));
}
private synchronized void toolEnded(String tool, String result, AcpSchema.ToolCallStatus status) {
@@ -166,10 +165,8 @@ private synchronized void toolEnded(String tool, String result, AcpSchema.ToolCa
if (id == null) {
return;
}
- context.sendUpdate(
- sessionId,
- new AcpSchema.ToolCallUpdateNotification(
- "tool_call_update", id, null, null, status, text(cut(result)), null, null, result, null));
+ context.sendSessionUpdate(new AcpSchema.ToolCallUpdateNotification(
+ "tool_call_update", id, null, null, null, status, text(cut(result)), null, null, result, null));
}
private @Nullable String takeOpen(String tool) {
@@ -217,25 +214,29 @@ private ApprovalResolution askEditor(PendingApproval approval) {
AcpSchema.ToolCallUpdate call = new AcpSchema.ToolCallUpdate(
id != null ? id : "call_" + toolCounter.incrementAndGet(),
title(approval.toolName(), approval.arguments()),
+ approval.toolName(),
kind(approval.toolName()),
AcpSchema.ToolCallStatus.PENDING,
null,
locations(approval.arguments()),
approval.arguments(),
+ null,
null);
AcpSchema.RequestPermissionResponse answer;
try {
- answer = context.requestPermission(new AcpSchema.RequestPermissionRequest(
- sessionId,
- call,
- List.of(
- new AcpSchema.PermissionOption("allow", "Allow", AcpSchema.PermissionOptionKind.ALLOW_ONCE),
- new AcpSchema.PermissionOption(
- "always",
- "Allow all (switch to auto mode)",
- AcpSchema.PermissionOptionKind.ALLOW_ALWAYS),
- new AcpSchema.PermissionOption(
- "reject", "Reject", AcpSchema.PermissionOptionKind.REJECT_ONCE))));
+ answer = context.client()
+ .requestPermission(new AcpSchema.RequestPermissionRequest(
+ sessionId,
+ call,
+ List.of(
+ new AcpSchema.PermissionOption(
+ "allow", "Allow", AcpSchema.PermissionOptionKind.ALLOW_ONCE),
+ new AcpSchema.PermissionOption(
+ "always",
+ "Allow all (switch to auto mode)",
+ AcpSchema.PermissionOptionKind.ALLOW_ALWAYS),
+ new AcpSchema.PermissionOption(
+ "reject", "Reject", AcpSchema.PermissionOptionKind.REJECT_ONCE))));
} catch (RuntimeException e) {
// no answer (the editor went away, or the request timed out): the same as nobody to ask
return ApprovalResolution.deny();
@@ -247,9 +248,7 @@ private ApprovalResolution askEditor(PendingApproval approval) {
case "allow" -> ApprovalResolution.approve();
case "always" -> {
agent.mode(ApprovalMode.AUTO);
- context.sendUpdate(
- sessionId,
- new AcpSchema.CurrentModeUpdate("current_mode_update", AcpServer.modeId(ApprovalMode.AUTO)));
+ context.sendSessionUpdate(new AcpSchema.CurrentModeUpdate(AcpServer.modeId(ApprovalMode.AUTO)));
yield ApprovalResolution.approve();
}
default -> ApprovalResolution.deny();
@@ -274,19 +273,18 @@ public synchronized void commandOutput(String line) {
return;
}
lastOutputPush = now;
- context.sendUpdate(
- sessionId,
- new AcpSchema.ToolCallUpdateNotification(
- "tool_call_update",
- id,
- null,
- null,
- AcpSchema.ToolCallStatus.IN_PROGRESS,
- text(String.join("\n", output)),
- null,
- null,
- null,
- null));
+ context.sendSessionUpdate(new AcpSchema.ToolCallUpdateNotification(
+ "tool_call_update",
+ id,
+ null,
+ null,
+ null,
+ AcpSchema.ToolCallStatus.IN_PROGRESS,
+ text(String.join("\n", output)),
+ null,
+ null,
+ null,
+ null));
}
private static List text(String value) {
diff --git a/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpServer.java b/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpServer.java
index 6d74c1d59..0fa8fa5ad 100644
--- a/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpServer.java
+++ b/llama-atmosphere-agent/src/main/java/net/ladenthin/llama/atmosphere/AcpServer.java
@@ -69,7 +69,7 @@ private AcpServer(Function sessionFactory, InputStream in, O
AgentSession session = sessionFactory.apply(Path.of(request.cwd()));
sessions.put(id, session);
announceCommandsSoon(self[0], id);
- return new AcpSchema.NewSessionResponse(id, modes(session.mode()), null);
+ return new AcpSchema.NewSessionResponse(id, modes(session.mode()));
})
.promptHandler(this::prompt)
.setSessionModeHandler(request -> {
@@ -126,7 +126,7 @@ static int run(AgentOptions options, PrintStream err) throws Exception {
AcpServer.class.getPackage().getImplementationVersion() == null
? "dev"
: AcpServer.class.getPackage().getImplementationVersion())) {
- server.agent.await();
+ server.agent.awaitTermination();
}
}
return 0;
@@ -145,9 +145,7 @@ private AcpSchema.PromptResponse prompt(AcpSchema.PromptRequest request, SyncPro
return new AcpSchema.PromptResponse(AcpSchema.StopReason.CANCELLED);
}
if (session.mode() != before) {
- context.sendUpdate(
- request.sessionId(),
- new AcpSchema.CurrentModeUpdate("current_mode_update", modeId(session.mode())));
+ context.sendSessionUpdate(new AcpSchema.CurrentModeUpdate(modeId(session.mode())));
}
return new AcpSchema.PromptResponse(
session.stopRequested() ? AcpSchema.StopReason.CANCELLED : AcpSchema.StopReason.END_TURN);
@@ -245,8 +243,7 @@ private static void announceCommandsSoon(AcpSyncAgent agent, String sessionId) {
// The session id reaches the editor with the response to session/new; an update that
// arrives before it names a session the editor does not know yet.
Thread.sleep(100);
- agent.sendSessionUpdate(
- sessionId, new AcpSchema.AvailableCommandsUpdate("available_commands_update", commands()));
+ agent.sendSessionUpdate(sessionId, new AcpSchema.AvailableCommandsUpdate(commands()));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (RuntimeException e) {
diff --git a/llama/pom.xml b/llama/pom.xml
index a8a1291fd..6b50b452c 100644
--- a/llama/pom.xml
+++ b/llama/pom.xml
@@ -61,7 +61,7 @@ SPDX-License-Identifier: MIT
- 4.3.0
+ 4.3.1
3.8.7
2.0.20
@@ -99,7 +99,7 @@ SPDX-License-Identifier: MIT
4.10.4.1
7.7.4
1.14.0
- 3.10.3
+ 3.10.4
2.102.0
UTF-8
2026-09-01T07:57:45Z