* feat: add compound tag filtering via tag_groups
Adds tag_groups to RecallRequest and ReflectRequest to express arbitrary
boolean tag predicates: leaf {tags, match}, and/or/not compounds.
Top-level groups are AND-ed. Existing tags/tags_match unchanged.
Examples:
Step filter AND user scope:
tag_groups: [{tags: ["step:5","step:8"], match: "any_strict"},
{tags: ["user:alice"], match: "all_strict"}]
Exclusion:
tag_groups: [{tags: ["user:alice"], match: "all_strict"},
{not: {tags: ["archived"], match: "any_strict"}}]
- Recursive SQL builder (build_tag_groups_where_clause) threads through
all 4 retrieval strategies (semantic/BM25, temporal, graph, MPFP)
- Python-side filter (filter_results_by_tag_groups) for post-traversal
- 22 new unit tests
- OpenAPI spec + all clients regenerated (Rust, Python, TypeScript, Go)
* fix: add tag_groups: None to Rust CLI struct initializers
* fix: add tag_groups: None to Rust client test RecallRequest initializer
* feat: reject tags+tag_groups together, add tag_groups integration tests
- Add model_validator to RecallRequest and ReflectRequest that returns 422
when both `tags` and `tag_groups` are set (mutually exclusive)
- Add 5 integration tests for tag_groups compound filtering:
* validation: 422 when both fields are set
* AND filter: two leaf groups (step scope AND user scope)
* OR compound: user:alice OR user:bob
* NOT compound: user:alice AND NOT archived
* Nested: user:alice AND (step:5 OR step:8)
* ci: trigger CI run
|
||
|---|---|---|
| .. | ||
| src | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| INTEGRATION.md | ||
| README.md | ||
Hindsight Rust Client
Auto-generated Rust client library for the Hindsight semantic memory system API.
Features
- 🦀 Fully typed - Complete type safety with Rust's type system
- 🔄 Auto-generated - Stays in sync with the OpenAPI spec automatically
- ⚡ Async/await - Built on tokio and reqwest for modern async Rust
- 📦 Standalone - Can be published to crates.io independently
Installation
Add to your Cargo.toml:
[dependencies]
hindsight-client = "0.1.0"
tokio = { version = "1", features = ["full"] }
Quick Start
use hindsight_client::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a client
let client = Client::new("http://localhost:8888");
// List all agents
let agents = client.list_agents().await?;
for agent in agents {
println!("Agent: {} - {}", agent.agent_id, agent.name);
}
// Get agent profile
let profile = client.get_agent_profile("my-agent").await?;
println!("Background: {}", profile.background);
// Search memories
let search_request = hindsight_client::types::SearchRequest {
query: "What did I learn today?".to_string(),
fact_type: None,
thinking_budget: Some(100),
max_tokens: Some(4096),
trace: Some(false),
};
let results = client.search_memories("my-agent", &search_request).await?;
for result in results.results {
println!("- {}", result.text);
}
// Store a memory
let memory_request = hindsight_client::types::BatchMemoryRequest {
items: vec![
hindsight_client::types::MemoryItem {
content: "I learned about Rust today".to_string(),
context: Some("Daily learning".to_string()),
}
],
document_id: Some("my-doc".to_string()),
};
client.batch_put_memories("my-agent", &memory_request).await?;
Ok(())
}
How It Works
This library uses progenitor to generate the client code from the OpenAPI specification at build time.
The generation happens automatically when you run cargo build, so the client always stays in sync with the API schema.
Build Process
build.rsreads the OpenAPI spec from../../openapi.json- Converts OpenAPI 3.1 → 3.0 (for progenitor compatibility)
- Generates Rust client code using progenitor
- Code is included in the library via
include!()macro
API Methods
All API endpoints are available as async methods on the Client struct:
Agent Management
list_agents()- List all agentscreate_or_update_agent()- Create or update an agentget_agent_profile()- Get agent profile with personalityupdate_agent_personality()- Update agent personality traitsadd_agent_background()- Add/merge agent backgroundget_agent_stats()- Get memory statistics
Memory Operations
search_memories()- Semantic search across memoriesthink()- Generate contextual answers using agent identitybatch_put_memories()- Store multiple memoriesbatch_put_async()- Queue memories for background processinglist_memories()- List memory units with paginationdelete_memory_unit()- Delete a specific memoryclear_agent_memories()- Clear all or filtered memories
Document Management
list_documents()- List documents with optional searchget_document()- Get document details and contentdelete_document()- Delete document and its memories
Operations (Async Tasks)
list_operations()- List async operationscancel_operation()- Cancel a pending operation
Visualization
get_graph()- Get memory graph data for visualization
Error Handling
The client uses progenitor_client::Error for all errors:
match client.get_agent_profile("my-agent").await {
Ok(profile) => println!("Got profile: {}", profile.name),
Err(progenitor_client::Error::ErrorResponse(resp)) => {
println!("API error: {} - {}", resp.status, resp.body);
}
Err(e) => println!("Other error: {}", e),
}
Development
Building
cargo build
The OpenAPI spec is automatically converted and the client is generated during build.
Testing
cargo test
Releasing
This client can be published to crates.io independently of the CLI:
cargo publish
Architecture
hindsight-clients/rust/
├── Cargo.toml # Package definition
├── build.rs # Build script (generates client)
├── src/
│ └── lib.rs # Library entry point
└── target/
└── debug/build/
└── hindsight-client-.../out/
└── hindsight_client_generated.rs # Generated code
License
MIT