Skip to content

Commit 2ce4fd4

Browse files
authored
feat(cli): ov cli grep with --exclude-uri/ -x option (#1174)
* feat: add ov grep cli exclude uri args * feat: grep with exclude uri * feat: add sdk document and grep method() args
1 parent c92b72d commit 2ce4fd4

File tree

17 files changed

+210
-17
lines changed

17 files changed

+210
-17
lines changed

bot/vikingbot/openviking_mount/ov_server.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,21 @@ async def search_memory(
334334
"agent_memory": agent_memory.memories if hasattr(agent_memory, "memories") else [],
335335
}
336336

337-
async def grep(self, uri: str, pattern: str, case_insensitive: bool = False) -> Dict[str, Any]:
337+
async def grep(
338+
self,
339+
uri: str,
340+
pattern: str,
341+
case_insensitive: bool = False,
342+
node_limit: Optional[int] = 10,
343+
exclude_uri: Optional[str] = None,
344+
) -> Dict[str, Any]:
338345
"""通过模式(正则表达式)搜索内容"""
339346
return await self.client.grep(
340-
uri, pattern, case_insensitive=case_insensitive, node_limit=10
347+
uri,
348+
pattern,
349+
case_insensitive=case_insensitive,
350+
node_limit=node_limit,
351+
exclude_uri=exclude_uri,
341352
)
342353

343354
async def glob(self, pattern: str, uri: Optional[str] = None) -> Dict[str, Any]:

crates/ov_cli/src/client.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,12 +514,14 @@ impl HttpClient {
514514
pub async fn grep(
515515
&self,
516516
uri: &str,
517+
exclude_uri: Option<String>,
517518
pattern: &str,
518519
ignore_case: bool,
519520
node_limit: i32,
520521
) -> Result<serde_json::Value> {
521522
let body = serde_json::json!({
522523
"uri": uri,
524+
"exclude_uri": exclude_uri,
523525
"pattern": pattern,
524526
"case_insensitive": ignore_case,
525527
"node_limit": node_limit,

crates/ov_cli/src/commands/search.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ pub async fn search(
4444
pub async fn grep(
4545
client: &HttpClient,
4646
uri: &str,
47+
exclude_uri: Option<String>,
4748
pattern: &str,
4849
ignore_case: bool,
4950
node_limit: i32,
5051
output_format: OutputFormat,
5152
compact: bool,
5253
) -> Result<()> {
53-
let result = client.grep(uri, pattern, ignore_case, node_limit).await?;
54+
let result = client
55+
.grep(uri, exclude_uri, pattern, ignore_case, node_limit)
56+
.await?;
5457
output_success(&result, output_format, compact);
5558
Ok(())
5659
}

crates/ov_cli/src/main.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ enum Commands {
405405
/// Target URI
406406
#[arg(short, long, default_value = "viking://")]
407407
uri: String,
408+
/// Excluded URI range. Any entry whose URI falls under this URI prefix is skipped
409+
#[arg(short = 'x', long = "exclude-uri")]
410+
exclude_uri: Option<String>,
408411
/// Search pattern
409412
pattern: String,
410413
/// Case insensitive
@@ -801,10 +804,11 @@ async fn main() {
801804
} => handle_search(query, uri, session_id, node_limit, threshold, ctx).await,
802805
Commands::Grep {
803806
uri,
807+
exclude_uri,
804808
pattern,
805809
ignore_case,
806810
node_limit,
807-
} => handle_grep(uri, pattern, ignore_case, node_limit, ctx).await,
811+
} => handle_grep(uri, exclude_uri, pattern, ignore_case, node_limit, ctx).await,
808812

809813
Commands::Glob {
810814
pattern,
@@ -1425,12 +1429,16 @@ async fn handle_stat(uri: String, ctx: CliContext) -> Result<()> {
14251429

14261430
async fn handle_grep(
14271431
uri: String,
1432+
exclude_uri: Option<String>,
14281433
pattern: String,
14291434
ignore_case: bool,
14301435
node_limit: i32,
14311436
ctx: CliContext,
14321437
) -> Result<()> {
14331438
let mut params = vec![format!("--uri={}", uri), format!("-n {}", node_limit)];
1439+
if let Some(excluded) = &exclude_uri {
1440+
params.push(format!("-x {}", excluded));
1441+
}
14341442
if ignore_case {
14351443
params.push("-i".to_string());
14361444
}
@@ -1440,6 +1448,7 @@ async fn handle_grep(
14401448
commands::search::grep(
14411449
&client,
14421450
&uri,
1451+
exclude_uri,
14431452
&pattern,
14441453
ignore_case,
14451454
node_limit,

docs/en/api/06-retrieval.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ Search content by pattern (regex).
299299
| uri | str | Yes | - | Viking URI to search in |
300300
| pattern | str | Yes | - | Search pattern (regex) |
301301
| case_insensitive | bool | No | False | Ignore case |
302+
| node_limit | int | No | None | Maximum number of nodes to search |
303+
| exclude_uri | str | No | None | URI prefix to exclude from search |
302304

303305
**Python SDK (Embedded / HTTP)**
304306

docs/zh/api/06-retrieval.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ curl -X POST http://localhost:1933/api/v1/search/search \
299299
| uri | str || - | 要搜索的 Viking URI |
300300
| pattern | str || - | 搜索模式(正则表达式) |
301301
| case_insensitive | bool || False | 忽略大小写 |
302+
| node_limit | int || None | 最大搜索节点数 |
303+
| exclude_uri | str || None | 要排除在搜索之外的 URI 前缀 |
302304

303305
**Python SDK (Embedded / HTTP)**
304306

openviking/async_client.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,23 @@ async def rm(self, uri: str, recursive: bool = False) -> None:
422422
await self._ensure_initialized()
423423
await self._client.rm(uri, recursive=recursive)
424424

425-
async def grep(self, uri: str, pattern: str, case_insensitive: bool = False) -> Dict:
425+
async def grep(
426+
self,
427+
uri: str,
428+
pattern: str,
429+
case_insensitive: bool = False,
430+
node_limit: Optional[int] = None,
431+
exclude_uri: Optional[str] = None,
432+
) -> Dict:
426433
"""Content search"""
427434
await self._ensure_initialized()
428-
return await self._client.grep(uri, pattern, case_insensitive=case_insensitive)
435+
return await self._client.grep(
436+
uri,
437+
pattern,
438+
case_insensitive=case_insensitive,
439+
node_limit=node_limit,
440+
exclude_uri=exclude_uri,
441+
)
429442

430443
async def glob(self, pattern: str, uri: str = "viking://") -> Dict:
431444
"""File pattern matching"""

openviking/client/local.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,22 @@ async def _search():
320320
execution.telemetry,
321321
)
322322

323-
async def grep(self, uri: str, pattern: str, case_insensitive: bool = False) -> Dict[str, Any]:
323+
async def grep(
324+
self,
325+
uri: str,
326+
pattern: str,
327+
case_insensitive: bool = False,
328+
node_limit: Optional[int] = None,
329+
exclude_uri: Optional[str] = None,
330+
) -> Dict[str, Any]:
324331
"""Content search with pattern."""
325332
return await self._service.fs.grep(
326-
uri, pattern, ctx=self._ctx, case_insensitive=case_insensitive
333+
uri,
334+
pattern,
335+
ctx=self._ctx,
336+
case_insensitive=case_insensitive,
337+
node_limit=node_limit,
338+
exclude_uri=exclude_uri,
327339
)
328340

329341
async def glob(self, pattern: str, uri: str = "viking://") -> Dict[str, Any]:

openviking/server/routers/search.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class GrepRequest(BaseModel):
6363
"""Request model for grep."""
6464

6565
uri: str
66+
exclude_uri: Optional[str] = None
6667
pattern: str
6768
case_insensitive: bool = False
6869
node_limit: Optional[int] = None
@@ -158,6 +159,7 @@ async def grep(
158159
request.uri,
159160
request.pattern,
160161
ctx=_ctx,
162+
exclude_uri=request.exclude_uri,
161163
case_insensitive=request.case_insensitive,
162164
node_limit=request.node_limit,
163165
)

openviking/service/fs_service.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,19 @@ async def grep(
162162
uri: str,
163163
pattern: str,
164164
ctx: RequestContext,
165+
exclude_uri: Optional[str] = None,
165166
case_insensitive: bool = False,
166167
node_limit: Optional[int] = None,
167168
) -> Dict:
168169
"""Content search."""
169170
viking_fs = self._ensure_initialized()
170171
return await viking_fs.grep(
171-
uri, pattern, case_insensitive=case_insensitive, node_limit=node_limit, ctx=ctx
172+
uri,
173+
pattern,
174+
exclude_uri=exclude_uri,
175+
case_insensitive=case_insensitive,
176+
node_limit=node_limit,
177+
ctx=ctx,
172178
)
173179

174180
async def glob(

0 commit comments

Comments
 (0)