Skip to content

Commit 898f0b1

Browse files
RoyLinRoyLin
authored andcommitted
feat(code): add optional DocumentParserRegistry for agentic_search
- Make document parsing optional (not required by default) - Add DocumentParserRegistry to SessionOptions - Expose DocumentParserRegistry to Python and Node.js SDKs - AgenticSearchTool accepts optional parser registry - Update documentation with configuration examples - Maintain minimal core + tool bootstrapping principle Breaking changes: None (backward compatible)
1 parent 43ffb03 commit 898f0b1

20 files changed

Lines changed: 1839 additions & 28 deletions

DOCUMENT_PARSER_SDK_INTEGRATION.md

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# Document Parser API - SDK Integration Complete ✅
2+
3+
## 完成状态
4+
5+
文档解析扩展已完全同步到 Python 和 Node.js SDK。
6+
7+
## 实现内容
8+
9+
### 1. Rust Core
10+
11+
**SessionOptions 扩展**
12+
- 添加 `document_parser_registry: Option<Arc<DocumentParserRegistry>>` 字段
13+
- 在创建 session 时,如果提供了 registry,自动重新注册 `AgenticSearchTool`
14+
15+
**公开 API**
16+
- 导出 `AgenticSearchTool` 到公共 API
17+
- 导出 `DocumentParserRegistry``DocumentParser` trait
18+
19+
### 2. Node.js SDK
20+
21+
**DocumentParserRegistry 类**
22+
```typescript
23+
import { Agent, DocumentParserRegistry } from '@a3s-lab/code';
24+
25+
const agent = await Agent.create('agent.hcl');
26+
27+
// 使用文档解析器
28+
const session = agent.session('.', {
29+
documentParserRegistry: new DocumentParserRegistry()
30+
});
31+
```
32+
33+
**SessionOptions 字段**
34+
- 添加 `document_parser_registry?: DocumentParserRegistry`
35+
- 自动转换为 Rust `DocumentParserRegistry::new()`
36+
37+
### 3. Python SDK
38+
39+
**DocumentParserRegistry 类**
40+
```python
41+
from a3s_code import Agent, SessionOptions, DocumentParserRegistry
42+
43+
agent = Agent("agent.hcl")
44+
45+
# 使用文档解析器
46+
opts = SessionOptions()
47+
opts.document_parser_registry = DocumentParserRegistry()
48+
session = agent.session(".", opts)
49+
```
50+
51+
**SessionOptions 属性**
52+
- 添加 `document_parser_registry` 属性(getter/setter)
53+
- 自动转换为 Rust `DocumentParserRegistry::new()`
54+
55+
## 使用示例
56+
57+
### Node.js
58+
59+
```typescript
60+
import { Agent, DocumentParserRegistry } from '@a3s-lab/code';
61+
62+
const agent = await Agent.create('agent.hcl');
63+
64+
// 方式 1:默认(纯文本搜索)
65+
const session1 = agent.session('.');
66+
67+
// 方式 2:启用文档解析器(当前包含 PlainTextParser)
68+
const session2 = agent.session('.', {
69+
documentParserRegistry: new DocumentParserRegistry()
70+
});
71+
72+
// 使用 agentic_search
73+
const result = await session2.send('Find authentication code');
74+
```
75+
76+
### Python
77+
78+
```python
79+
from a3s_code import Agent, SessionOptions, DocumentParserRegistry
80+
81+
agent = Agent("agent.hcl")
82+
83+
# 方式 1:默认(纯文本搜索)
84+
session1 = agent.session(".")
85+
86+
# 方式 2:启用文档解析器(当前包含 PlainTextParser)
87+
opts = SessionOptions()
88+
opts.document_parser_registry = DocumentParserRegistry()
89+
session2 = agent.session(".", opts)
90+
91+
# 使用 agentic_search
92+
result = session2.send("Find authentication code")
93+
```
94+
95+
### Rust
96+
97+
```rust
98+
use a3s_code_core::{Agent, SessionOptions};
99+
use a3s_code_core::tools::document_parser::{DocumentParser, DocumentParserRegistry};
100+
101+
// 实现自定义解析器
102+
struct PdfParser;
103+
impl DocumentParser for PdfParser {
104+
fn name(&self) -> &str { "pdf" }
105+
fn supported_extensions(&self) -> &[&str] { &["pdf"] }
106+
fn parse(&self, path: &Path) -> anyhow::Result<String> {
107+
// 使用 pdf-extract 或类似库
108+
todo!()
109+
}
110+
}
111+
112+
// 注册自定义解析器
113+
let mut registry = DocumentParserRegistry::new();
114+
registry.register(Arc::new(PdfParser));
115+
116+
// 创建 session
117+
let opts = SessionOptions::new()
118+
.with_document_parser_registry(Arc::new(registry));
119+
let session = agent.session(".", opts)?;
120+
```
121+
122+
## 当前功能
123+
124+
| 功能 | Rust | Node.js | Python |
125+
|------|------|---------|--------|
126+
| `DocumentParserRegistry`||||
127+
| `PlainTextParser`(默认) ||||
128+
| 自定义解析器(通过 trait) ||||
129+
| SessionOptions 配置 ||||
130+
131+
## 未来扩展
132+
133+
### 内置解析器(计划中)
134+
135+
可以通过 Cargo features 添加更多内置解析器:
136+
137+
```toml
138+
[features]
139+
pdf = ["pdf-extract"]
140+
excel = ["calamine"]
141+
word = ["docx-rs"]
142+
```
143+
144+
然后在 SDK 中暴露:
145+
146+
```typescript
147+
// 未来 API(尚未实现)
148+
const registry = new DocumentParserRegistry()
149+
.enablePdf()
150+
.enableExcel()
151+
.enableWord();
152+
```
153+
154+
### 回调机制(可选)
155+
156+
允许 SDK 用户通过回调函数实现自定义解析器:
157+
158+
```typescript
159+
// 未来 API(尚未实现)
160+
const registry = new DocumentParserRegistry()
161+
.registerParser({
162+
name: 'custom',
163+
extensions: ['custom'],
164+
parse: async (path) => {
165+
// 用户自定义解析逻辑
166+
return extractedText;
167+
}
168+
});
169+
```
170+
171+
## 测试
172+
173+
### Rust Core
174+
```bash
175+
cargo test --lib
176+
# ✅ 1477 passed
177+
```
178+
179+
### Node.js SDK
180+
```bash
181+
cd sdk/node/examples
182+
node test-agentic-search-sdk.js
183+
# ✅ All tests passed
184+
```
185+
186+
### Python SDK
187+
```bash
188+
cd sdk/python/examples
189+
python test_agentic_search_sdk.py
190+
# ✅ All tests passed
191+
```
192+
193+
## 总结
194+
195+
**API 已完全同步**
196+
- Rust core 支持 `DocumentParserRegistry` 配置
197+
- Node.js SDK 暴露 `DocumentParserRegistry`
198+
- Python SDK 暴露 `DocumentParserRegistry`
199+
- 所有 SDK 都可以通过 `SessionOptions` 配置
200+
201+
**向后兼容**
202+
- 默认行为不变(纯文本搜索)
203+
- 文档解析器是可选的
204+
205+
**可扩展**
206+
- Rust 用户可以实现自定义解析器
207+
- 未来可以添加更多内置解析器
208+
- SDK 用户可以选择启用文档解析
209+
210+
**结论**:文档解析扩展已完全对 Python 和 Node.js SDK 开放,用户可以通过 `SessionOptions` 配置 `DocumentParserRegistry`

README.md

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
[![Crates.io](https://img.shields.io/crates/v/a3s-code-core.svg)](https://crates.io/crates/a3s-code-core)
66
[![Documentation](https://docs.rs/a3s-code-core/badge.svg)](https://docs.rs/a3s-code-core)
77
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
8-
[![Tests](https://img.shields.io/badge/tests-1471%20passing-brightgreen.svg)](./core/tests)
8+
[![Tests](https://img.shields.io/badge/tests-1477%20passing-brightgreen.svg)](./core/tests)
99

1010
---
1111

1212
## Why A3S Code?
1313

1414
- **Embeddable** — Rust library, not a service. Node.js and Python bindings included. CLI for terminal use.
1515
- **Safe by Default** — Permission system, HITL confirmation, skill-based tool restrictions, and error recovery (parse retries, tool timeout, circuit breaker).
16-
- **Extensible**19 trait-based extension points, all with working defaults. Slash commands, tool search, and multi-agent teams.
16+
- **Extensible**20 trait-based extension points, all with working defaults. Slash commands, tool search, and multi-agent teams.
1717
- **Scalable** — Lane-based priority queue with multi-machine task distribution.
1818

1919
---
@@ -657,7 +657,7 @@ Switch a lane to External mode via `session.set_lane_handler(SessionLane::Execut
657657

658658
---
659659

660-
### 🔌 Extensibility (19 Extension Points)
660+
### 🔌 Extensibility (20 Extension Points)
661661

662662
All policies are replaceable via traits with working defaults:
663663

@@ -680,14 +680,38 @@ All policies are replaceable via traits with working defaults:
680680
| BashSandbox | Shell execution isolation | LocalBashExecutor |
681681
| SkillValidator | Skill activation logic | DefaultSkillValidator |
682682
| SkillScorer | Skill relevance ranking | DefaultSkillScorer |
683+
| DocumentParser | Custom file format parsing for agentic_search | None (plain text only) |
683684

684685
Implement any trait and inject via `SessionOptions` builder methods (e.g., `with_security_provider`, `with_permission_checker`, `with_session_store`).
685686

687+
### 📄 Document Parser Extension
688+
689+
`agentic_search` works with plain text by default. To enable PDF, Excel, Word, or other binary formats, implement the `DocumentParser` trait and register it:
690+
691+
```rust
692+
use a3s_code_core::tools::document_parser::{DocumentParser, DocumentParserRegistry};
693+
694+
struct PdfParser;
695+
696+
impl DocumentParser for PdfParser {
697+
fn name(&self) -> &str { "pdf" }
698+
fn supported_extensions(&self) -> &[&str] { &["pdf"] }
699+
fn parse(&self, path: &Path) -> anyhow::Result<String> {
700+
// use pdf-extract or similar
701+
todo!()
702+
}
703+
}
704+
705+
let mut registry = DocumentParserRegistry::new();
706+
registry.register(Arc::new(PdfParser));
707+
let tool = AgenticSearchTool::with_parser_registry(registry);
708+
```
709+
686710
---
687711

688712
## Architecture
689713

690-
5 core components (stable, not replaceable) + 19 extension points (replaceable via traits):
714+
5 core components (stable, not replaceable) + 20 extension points (replaceable via traits):
691715

692716
```
693717
Agent (config-driven)

core/src/agent_api.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ pub struct SessionOptions {
181181
/// dispatched locally. The executor is also propagated to sub-agents via
182182
/// the sentinel hook mechanism.
183183
pub hook_executor: Option<Arc<dyn crate::hooks::HookExecutor>>,
184+
/// Optional document parser registry for agentic_search tool.
185+
///
186+
/// When set, enables custom document format support (PDF, Excel, Word, etc.)
187+
/// for the agentic_search tool. If not set, only plain text files are searched.
188+
pub document_parser_registry: Option<Arc<crate::tools::document_parser::DocumentParserRegistry>>,
184189
}
185190

186191
impl std::fmt::Debug for SessionOptions {
@@ -1011,6 +1016,13 @@ impl Agent {
10111016
}
10121017
}
10131018

1019+
// Register custom agentic_search tool with document parser registry if provided
1020+
if let Some(ref registry) = opts.document_parser_registry {
1021+
use crate::tools::AgenticSearchTool;
1022+
let tool = AgenticSearchTool::with_parser_registry((**registry).clone());
1023+
tool_executor.register_dynamic_tool(Arc::new(tool));
1024+
}
1025+
10141026
let tool_defs = tool_executor.definitions();
10151027

10161028
// Build prompt slots: start from session options or agent-level config

0 commit comments

Comments
 (0)