feat: add Google code retrieval across desktop CLI and MCP
Core CI / core (macos-latest) (push) Canceled after 0s
Core CI / core (windows-latest) (push) Canceled after 0s
Core CI / desktop (macos-latest) (push) Canceled after 0s
Core CI / desktop (ubuntu-latest) (push) Canceled after 0s
Core CI / desktop (windows-latest) (push) Canceled after 0s
Core CI / core (ubuntu-latest) (push) Canceled after 2m23s
Core CI / core (macos-latest) (push) Canceled after 0s
Core CI / core (windows-latest) (push) Canceled after 0s
Core CI / desktop (macos-latest) (push) Canceled after 0s
Core CI / desktop (ubuntu-latest) (push) Canceled after 0s
Core CI / desktop (windows-latest) (push) Canceled after 0s
Core CI / core (ubuntu-latest) (push) Canceled after 2m23s
This commit is contained in:
1 parent
8b9b079469
commit
81846b3e98
32 files changed
+1303
-59
No files matched your search
@@ -68,6 +68,9 @@ enum Command {
|
||||
/// Restrict results to this folder and descendants.
|
||||
#[arg(long)]
|
||||
folder: Option<PathBuf>,
|
||||
/// Search indexed source-code files only; supports symbols and semantic code queries.
|
||||
#[arg(long)]
|
||||
code_only: bool,
|
||||
/// File extension, with or without the leading dot.
|
||||
#[arg(long)]
|
||||
extension: Option<String>,
|
||||
@@ -166,6 +169,7 @@ fn main() -> Result<()> {
|
||||
performance,
|
||||
debug_performance,
|
||||
folder,
|
||||
code_only,
|
||||
extension,
|
||||
min_size,
|
||||
max_size,
|
||||
@@ -183,6 +187,7 @@ fn main() -> Result<()> {
|
||||
require_existing_index(&db)?;
|
||||
let options = SearchOptions {
|
||||
folder,
|
||||
code_only,
|
||||
extension,
|
||||
min_size,
|
||||
max_size,
|
||||
|
||||
@@ -38,6 +38,9 @@ struct SearchInput {
|
||||
limit: u16,
|
||||
|
||||
folder: Option<String>,
|
||||
/// Restrict all retrieval lanes to indexed source-code files.
|
||||
#[serde(default)]
|
||||
code_only: bool,
|
||||
|
||||
extension: Option<String>,
|
||||
|
||||
@@ -168,6 +171,7 @@ impl AgentServer {
|
||||
let options = SearchOptions {
|
||||
|
||||
folder: input.folder.map(PathBuf::from),
|
||||
code_only: input.code_only,
|
||||
|
||||
extension: input.extension,
|
||||
|
||||
@@ -272,6 +276,7 @@ impl AgentServer {
|
||||
Ok(json!({
|
||||
|
||||
"mode": mode,
|
||||
"code_only": input.code_only,
|
||||
|
||||
"semantic_available": mode == "hybrid",
|
||||
|
||||
|
||||
@@ -157,3 +157,55 @@ fn exclusions_and_filters_change_real_results() {
|
||||
let stats: serde_json::Value = serde_json::from_slice(&stats.stdout).unwrap();
|
||||
assert_eq!(stats["files"], 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn code_only_filters_real_results_and_finds_exact_symbols() {
|
||||
let fixture = Fixture::new();
|
||||
fs::create_dir(fixture.0.join("code")).unwrap();
|
||||
fs::write(
|
||||
fixture.0.join("code/retry.rs"),
|
||||
"pub fn refreshAccessToken() { /* retry failed requests with backoff */ }",
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(
|
||||
fixture.0.join("code/notes.txt"),
|
||||
"refreshAccessToken retry failed requests with backoff",
|
||||
)
|
||||
.unwrap();
|
||||
let indexed = fixture.run(&["index", "--db", "index.db", "--root", "code"]);
|
||||
assert!(
|
||||
indexed.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&indexed.stderr)
|
||||
);
|
||||
let all = fixture.run(&["search", "--db", "index.db", "refreshAccessToken", "--json"]);
|
||||
assert_eq!(
|
||||
serde_json::from_slice::<serde_json::Value>(&all.stdout)
|
||||
.unwrap()
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.len(),
|
||||
2
|
||||
);
|
||||
let code = fixture.run(&[
|
||||
"search",
|
||||
"--db",
|
||||
"index.db",
|
||||
"refreshAccessToken",
|
||||
"--code-only",
|
||||
"--json",
|
||||
]);
|
||||
assert!(
|
||||
code.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&code.stderr)
|
||||
);
|
||||
let results: serde_json::Value = serde_json::from_slice(&code.stdout).unwrap();
|
||||
assert_eq!(results.as_array().unwrap().len(), 1);
|
||||
assert_eq!(results[0]["filename"], "retry.rs");
|
||||
assert!(results[0]["snippet"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.contains("refreshAccessToken"));
|
||||
assert_eq!(results[0]["source"]["kind"], "line");
|
||||
}
|
||||
@@ -75,6 +75,16 @@ fn actual_mcp_handshake_search_and_guarded_sources() {
|
||||
"Termination clause: sixty days written notice to end the supplier partnership.",
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(
|
||||
folder.join("retry.rs"),
|
||||
"pub fn refreshAccessToken() { /* retry requests */ }",
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(
|
||||
folder.join("symbol-note.txt"),
|
||||
"refreshAccessToken retry requests",
|
||||
)
|
||||
.unwrap();
|
||||
let db = fixture.path().join("index.sqlite");
|
||||
let indexed = Command::new(env!("CARGO_BIN_EXE_searchi"))
|
||||
.args(["index", "--db"])
|
||||
@@ -154,6 +164,21 @@ fn actual_mcp_handshake_search_and_guarded_sources() {
|
||||
.unwrap()
|
||||
.contains("local path"));
|
||||
}
|
||||
let code = server.request(
|
||||
40,
|
||||
"tools/call",
|
||||
json!({"name":"search","arguments":{"query":"refreshAccessToken","code_only":true}}),
|
||||
);
|
||||
let code_results = code["result"]["structuredContent"]["results"]
|
||||
.as_array()
|
||||
.unwrap();
|
||||
assert_eq!(code_results.len(), 1);
|
||||
assert_eq!(code_results[0]["filename"], "retry.rs");
|
||||
assert_eq!(code_results[0]["source"]["kind"], "line");
|
||||
assert!(code_results[0]["snippet"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.contains("refreshAccessToken"));
|
||||
let mutation = server.request(7, "tools/call", json!({"name":"index","arguments":{}}));
|
||||
assert!(mutation["error"].is_object());
|
||||
std::fs::write(
|
||||
|
||||
Reference in new issue
Block a user