From c8899e688027cdf927a0f644eb481bbede3d2862 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 15:50:51 +0800 Subject: [PATCH 1/2] fix(code-intelligence): prepare cold workspace symbol queries --- .../src/code_intelligence/language_runtime.rs | 12 +++++ .../code_intelligence/workspace_runtime.rs | 19 ++++++++ .../workspace_runtime/integration_tests.rs | 47 +++++++++++++++++++ .../fixtures/code_intelligence_fake_lsp.rs | 12 +++++ 4 files changed, 90 insertions(+) diff --git a/core/src/code_intelligence/language_runtime.rs b/core/src/code_intelligence/language_runtime.rs index 44bc02fe..d6a34166 100644 --- a/core/src/code_intelligence/language_runtime.rs +++ b/core/src/code_intelligence/language_runtime.rs @@ -257,6 +257,18 @@ impl LanguageRuntime { self.initialized.capabilities } + pub(crate) async fn prepare_saved_document( + &self, + path: &WorkspacePath, + saved_content: &str, + cancellation: &CancellationToken, + ) -> Result<(), LanguageRuntimeError> { + self.require_path(path)?; + self.sync_saved_document(path, saved_content, cancellation) + .await?; + ensure_not_cancelled(cancellation) + } + pub(crate) async fn document_symbols( &self, path: &WorkspacePath, diff --git a/core/src/code_intelligence/workspace_runtime.rs b/core/src/code_intelligence/workspace_runtime.rs index 455c98ff..4b6f6f89 100644 --- a/core/src/code_intelligence/workspace_runtime.rs +++ b/core/src/code_intelligence/workspace_runtime.rs @@ -346,15 +346,34 @@ impl WorkspaceRuntime { return Ok(self.workspace_result(Vec::new(), false)); } + let source_paths = tokio::select! { + _ = cancellation.cancelled() => return Err(CodeIntelligenceError::Cancelled), + paths = self.source_paths.read() => paths.clone(), + }; let mut queries = FuturesUnordered::new(); for slot in self .slots .iter() .filter(|slot| slot.relevant.load(Ordering::Acquire)) { + let anchor = source_paths + .iter() + .find(|path| slot.profile.supports_path(Path::new(path.as_str()))) + .cloned(); let cancellation = cancellation.clone(); queries.push(async move { + let anchor = anchor.ok_or_else(|| CodeIntelligenceError::Unavailable { + message: format!( + "no saved source file can prepare the {} language runtime", + profile_language(slot.profile.id()) + ), + })?; let runtime = self.ensure_runtime(slot, &cancellation).await?; + let content = self.read_saved(&anchor, &cancellation).await?; + runtime + .prepare_saved_document(&anchor, &content, &cancellation) + .await + .map_err(|error| map_language_error(slot.profile.id(), error))?; runtime .search_symbols(query, limit, cancellation) .await diff --git a/core/src/code_intelligence/workspace_runtime/integration_tests.rs b/core/src/code_intelligence/workspace_runtime/integration_tests.rs index bc441854..3cdf4279 100644 --- a/core/src/code_intelligence/workspace_runtime/integration_tests.rs +++ b/core/src/code_intelligence/workspace_runtime/integration_tests.rs @@ -150,6 +150,53 @@ fn test_runtime_with_file_system( ) } +#[tokio::test] +async fn first_workspace_symbol_query_opens_a_saved_source_document() { + let workspace = tempfile::tempdir().unwrap(); + write_workspace_files( + workspace.path(), + &[ + ("package.json", "{}\n"), + ( + "src/main.ts", + "export function answer(): number { return 42; }\n", + ), + ], + ); + let root = std::fs::canonicalize(workspace.path()).unwrap(); + let snapshot = snapshot(&root, &["package.json", "src/main.ts"]); + let server_dir = tempfile::tempdir().unwrap(); + let server = server_dir.path().join(if cfg!(windows) { + "requires-open-fake-lsp.exe" + } else { + "requires-open-fake-lsp" + }); + compile_fake_server(&server); + let runtime = test_runtime( + &root, + &snapshot, + vec![LanguageServerProfile::typescript_javascript(&server)], + ); + + let result = runtime + .search_symbols("answer", 10, CancellationToken::new()) + .await + .expect("the first workspace symbol query must prepare a language project"); + + assert_eq!(result.items.len(), 1); + assert_eq!(result.items[0].name, "answer"); + assert_eq!(result.items[0].location.path.as_str(), "src/main.ts"); + let log = std::fs::read_to_string(server.with_extension("log")).unwrap(); + let did_open = log.find("\"method\":\"textDocument/didOpen\"").unwrap(); + let workspace_symbol = log.find("\"method\":\"workspace/symbol\"").unwrap(); + assert!( + did_open < workspace_symbol, + "the saved source must be opened before workspace symbol search: {log}" + ); + + runtime.shutdown().await; +} + #[tokio::test] async fn abandoned_caller_does_not_restart_an_in_flight_language_runtime() { let workspace = tempfile::tempdir().unwrap(); diff --git a/core/tests/fixtures/code_intelligence_fake_lsp.rs b/core/tests/fixtures/code_intelligence_fake_lsp.rs index eea17a59..ea4b0fa8 100644 --- a/core/tests/fixtures/code_intelligence_fake_lsp.rs +++ b/core/tests/fixtures/code_intelligence_fake_lsp.rs @@ -63,6 +63,18 @@ fn main() -> io::Result<()> { } continue; }; + if executable_name.contains("requires-open") + && method == "workspace/symbol" + && document_uri.is_none() + { + write_message( + &mut output, + &format!( + "{{\"jsonrpc\":\"2.0\",\"id\":{id},\"error\":{{\"code\":1,\"message\":\"No Project.\"}}}}" + ), + )?; + continue; + } if is_navigation_method(&method) { navigation_requests += 1; } From 2de08cbde14d61f862a9e3bfda58db2032c5779d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 16:08:40 +0800 Subject: [PATCH 2/2] release: prepare a3s-code 5.3.4 --- .github/workflows/release.yml | 4 ++-- CHANGELOG.md | 8 ++++++++ Cargo.lock | 2 +- core/Cargo.toml | 2 +- scripts/check_semver.sh | 5 ++++- sdk/node/Cargo.lock | 4 ++-- sdk/node/Cargo.toml | 4 ++-- sdk/node/examples/package-lock.json | 14 +++++++------- sdk/node/package-lock.json | 16 ++++++++-------- sdk/node/package.json | 14 +++++++------- sdk/python-bootstrap/pyproject.toml | 2 +- sdk/python-bootstrap/src/a3s_code/_bootstrap.py | 2 +- sdk/python/CHANGELOG.md | 7 +++++++ sdk/python/Cargo.lock | 4 ++-- sdk/python/Cargo.toml | 4 ++-- sdk/python/pyproject.toml | 2 +- 16 files changed, 56 insertions(+), 38 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 964d2309..d5ecac80 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,10 +55,10 @@ jobs: test -n "$VERSION" bash check-version.sh "$VERSION" - - name: Check public API compatibility with v5.3.2 + - name: Check public API compatibility with v5.3.3 run: | cargo install cargo-semver-checks --version 0.48.0 --locked - bash scripts/check_semver.sh 5.3.2 + bash scripts/check_semver.sh 5.3.3 - name: Check SDK protocol and API alignment run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a5fefb7..bd8837d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [5.3.4] - 2026-07-16 + +### Fixed + +- Prepared one saved source document per active language before a cold + workspace-symbol search, so language servers that load projects on document + open can serve the first semantic query instead of returning `No Project`. + ## [5.3.3] - 2026-07-16 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 823fcb3c..14ae86d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,7 @@ source = "git+https://github.com/A3S-Lab/ACL.git?rev=6e2a6469edc0f4c61b1e588d0ac [[package]] name = "a3s-code-core" -version = "5.3.3" +version = "5.3.4" dependencies = [ "a3s-acl 0.2.1 (git+https://github.com/A3S-Lab/ACL.git?rev=6e2a6469edc0f4c61b1e588d0ace873aaf15ce22)", "a3s-common", diff --git a/core/Cargo.toml b/core/Cargo.toml index d8ef2efa..9395be30 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-code-core" -version = "5.3.3" +version = "5.3.4" edition = "2021" authors = ["A3S Lab Team"] license = "MIT" diff --git a/scripts/check_semver.sh b/scripts/check_semver.sh index de17a17a..ffec4cd6 100644 --- a/scripts/check_semver.sh +++ b/scripts/check_semver.sh @@ -3,10 +3,13 @@ set -euo pipefail -BASELINE_VERSION="${1:-5.3.2}" +BASELINE_VERSION="${1:-5.3.3}" PACKAGE="a3s-code-core" case "$BASELINE_VERSION" in + 5.3.3) + BASELINE_SHA256="5ed95dff8354578962130615e36654f7107c7bd9a0b862fe8e9e6ae1ed1676f9" + ;; 5.3.2) BASELINE_SHA256="da8f43aa04ca80edbc543575a5b2bfc9e1cf48e76aecf74a61f67d536f8172c2" ;; diff --git a/sdk/node/Cargo.lock b/sdk/node/Cargo.lock index 458c11be..b947c2c2 100644 --- a/sdk/node/Cargo.lock +++ b/sdk/node/Cargo.lock @@ -15,7 +15,7 @@ source = "git+https://github.com/A3S-Lab/ACL.git?rev=6e2a6469edc0f4c61b1e588d0ac [[package]] name = "a3s-code-core" -version = "5.3.3" +version = "5.3.4" dependencies = [ "a3s-acl 0.2.1 (git+https://github.com/A3S-Lab/ACL.git?rev=6e2a6469edc0f4c61b1e588d0ace873aaf15ce22)", "a3s-common", @@ -76,7 +76,7 @@ dependencies = [ [[package]] name = "a3s-code-node" -version = "5.3.3" +version = "5.3.4" dependencies = [ "a3s-code-core", "anyhow", diff --git a/sdk/node/Cargo.toml b/sdk/node/Cargo.toml index 029e6a02..44944972 100644 --- a/sdk/node/Cargo.toml +++ b/sdk/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-code-node" -version = "5.3.3" +version = "5.3.4" edition = "2021" authors = ["A3S Lab Team"] license = "MIT" @@ -11,7 +11,7 @@ description = "A3S Code Node.js bindings - Native addon via napi-rs" crate-type = ["cdylib"] [dependencies] -a3s-code-core = { version = "5.3.3", path = "../../core", features = ["s3", "serve"] } +a3s-code-core = { version = "5.3.4", path = "../../core", features = ["s3", "serve"] } napi = { version = "2", features = ["async", "napi6", "serde-json"] } napi-derive = "2" tokio = { version = "1.35", features = ["full"] } diff --git a/sdk/node/examples/package-lock.json b/sdk/node/examples/package-lock.json index c2beba2d..09b8c6b2 100644 --- a/sdk/node/examples/package-lock.json +++ b/sdk/node/examples/package-lock.json @@ -18,7 +18,7 @@ }, "..": { "name": "@a3s-lab/code", - "version": "5.3.3", + "version": "5.3.4", "license": "MIT", "devDependencies": { "@napi-rs/cli": "^2", @@ -27,12 +27,12 @@ "typescript": "^5.9.3" }, "optionalDependencies": { - "@a3s-lab/code-darwin-arm64": "5.3.3", - "@a3s-lab/code-linux-arm64-gnu": "5.3.3", - "@a3s-lab/code-linux-arm64-musl": "5.3.3", - "@a3s-lab/code-linux-x64-gnu": "5.3.3", - "@a3s-lab/code-linux-x64-musl": "5.3.3", - "@a3s-lab/code-win32-x64-msvc": "5.3.3" + "@a3s-lab/code-darwin-arm64": "5.3.4", + "@a3s-lab/code-linux-arm64-gnu": "5.3.4", + "@a3s-lab/code-linux-arm64-musl": "5.3.4", + "@a3s-lab/code-linux-x64-gnu": "5.3.4", + "@a3s-lab/code-linux-x64-musl": "5.3.4", + "@a3s-lab/code-win32-x64-msvc": "5.3.4" } }, "node_modules/@a3s-lab/code": { diff --git a/sdk/node/package-lock.json b/sdk/node/package-lock.json index 57423bfa..37f83d8a 100644 --- a/sdk/node/package-lock.json +++ b/sdk/node/package-lock.json @@ -1,12 +1,12 @@ { "name": "@a3s-lab/code", - "version": "5.3.3", + "version": "5.3.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@a3s-lab/code", - "version": "5.3.3", + "version": "5.3.4", "license": "MIT", "devDependencies": { "@napi-rs/cli": "^2", @@ -15,12 +15,12 @@ "typescript": "^5.9.3" }, "optionalDependencies": { - "@a3s-lab/code-darwin-arm64": "5.3.3", - "@a3s-lab/code-linux-arm64-gnu": "5.3.3", - "@a3s-lab/code-linux-arm64-musl": "5.3.3", - "@a3s-lab/code-linux-x64-gnu": "5.3.3", - "@a3s-lab/code-linux-x64-musl": "5.3.3", - "@a3s-lab/code-win32-x64-msvc": "5.3.3" + "@a3s-lab/code-darwin-arm64": "5.3.4", + "@a3s-lab/code-linux-arm64-gnu": "5.3.4", + "@a3s-lab/code-linux-arm64-musl": "5.3.4", + "@a3s-lab/code-linux-x64-gnu": "5.3.4", + "@a3s-lab/code-linux-x64-musl": "5.3.4", + "@a3s-lab/code-win32-x64-msvc": "5.3.4" } }, "node_modules/@a3s-lab/code-darwin-arm64": { diff --git a/sdk/node/package.json b/sdk/node/package.json index cd948dec..f2c45765 100644 --- a/sdk/node/package.json +++ b/sdk/node/package.json @@ -1,6 +1,6 @@ { "name": "@a3s-lab/code", - "version": "5.3.3", + "version": "5.3.4", "description": "A3S Code - Native Node.js bindings for the coding-agent runtime", "main": "index.js", "types": "index.d.ts", @@ -44,11 +44,11 @@ "test:helpers": "node test-helpers.mjs" }, "optionalDependencies": { - "@a3s-lab/code-darwin-arm64": "5.3.3", - "@a3s-lab/code-linux-x64-gnu": "5.3.3", - "@a3s-lab/code-linux-x64-musl": "5.3.3", - "@a3s-lab/code-linux-arm64-gnu": "5.3.3", - "@a3s-lab/code-linux-arm64-musl": "5.3.3", - "@a3s-lab/code-win32-x64-msvc": "5.3.3" + "@a3s-lab/code-darwin-arm64": "5.3.4", + "@a3s-lab/code-linux-x64-gnu": "5.3.4", + "@a3s-lab/code-linux-x64-musl": "5.3.4", + "@a3s-lab/code-linux-arm64-gnu": "5.3.4", + "@a3s-lab/code-linux-arm64-musl": "5.3.4", + "@a3s-lab/code-win32-x64-msvc": "5.3.4" } } diff --git a/sdk/python-bootstrap/pyproject.toml b/sdk/python-bootstrap/pyproject.toml index 4cc0efb7..a48f0b41 100644 --- a/sdk/python-bootstrap/pyproject.toml +++ b/sdk/python-bootstrap/pyproject.toml @@ -7,7 +7,7 @@ name = "a3s-code" # Keep in sync with crates/code core release. The bootstrap loader fetches # the matching native wheel from `https://github.com/AI45Lab/Code/releases/tag/v` # at import time. -version = "5.3.3" +version = "5.3.4" description = "A3S Code Python SDK — pure-Python bootstrap that fetches the native wheel from GitHub Releases" readme = "README.md" license = {text = "MIT"} diff --git a/sdk/python-bootstrap/src/a3s_code/_bootstrap.py b/sdk/python-bootstrap/src/a3s_code/_bootstrap.py index ae2c6352..a4d57713 100644 --- a/sdk/python-bootstrap/src/a3s_code/_bootstrap.py +++ b/sdk/python-bootstrap/src/a3s_code/_bootstrap.py @@ -31,7 +31,7 @@ # Version is the bootstrap's own version, which equals the matching native # wheel version on GH Releases. Bumped by the release workflow. -__version__ = "5.3.3" +__version__ = "5.3.4" _DEFAULT_BASE_URL = "https://github.com/A3S-Lab/Code/releases/download" _REQUEST_TIMEOUT_S = 120 diff --git a/sdk/python/CHANGELOG.md b/sdk/python/CHANGELOG.md index 4eacad44..5189f11c 100644 --- a/sdk/python/CHANGELOG.md +++ b/sdk/python/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to the A3S Code Python SDK will be documented in this file. ## [Unreleased] +## [5.3.4] - 2026-07-16 + +### Fixed + +- Updated the bundled Core so a cold workspace-symbol query prepares a saved + source document before asking the language server to search its projects. + ## [5.3.3] - 2026-07-16 ### Fixed diff --git a/sdk/python/Cargo.lock b/sdk/python/Cargo.lock index 995d105f..21e5a5e4 100644 --- a/sdk/python/Cargo.lock +++ b/sdk/python/Cargo.lock @@ -15,7 +15,7 @@ source = "git+https://github.com/A3S-Lab/ACL.git?rev=6e2a6469edc0f4c61b1e588d0ac [[package]] name = "a3s-code-core" -version = "5.3.3" +version = "5.3.4" dependencies = [ "a3s-acl 0.2.1 (git+https://github.com/A3S-Lab/ACL.git?rev=6e2a6469edc0f4c61b1e588d0ace873aaf15ce22)", "a3s-common", @@ -76,7 +76,7 @@ dependencies = [ [[package]] name = "a3s-code-py" -version = "5.3.3" +version = "5.3.4" dependencies = [ "a3s-code-core", "anyhow", diff --git a/sdk/python/Cargo.toml b/sdk/python/Cargo.toml index fd2824a1..eb3b424b 100644 --- a/sdk/python/Cargo.toml +++ b/sdk/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-code-py" -version = "5.3.3" +version = "5.3.4" edition = "2021" authors = ["A3S Lab Team"] license = "MIT" @@ -12,7 +12,7 @@ name = "a3s_code" crate-type = ["cdylib"] [dependencies] -a3s-code-core = { version = "5.3.3", path = "../../core", features = ["s3", "serve"] } +a3s-code-core = { version = "5.3.4", path = "../../core", features = ["s3", "serve"] } pyo3 = { version = "0.23", features = ["multiple-pymethods"] } tokio = { version = "1.35", features = ["full"] } serde_json = "1.0" diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index 40f1a2b0..f5c57ec2 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "a3s-code" -version = "5.3.3" +version = "5.3.4" description = "A3S Code - Native Python bindings for the coding-agent runtime" readme = "README.md" license = {text = "MIT"}