Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.11.102] - 2026-07-16

### Added

- **`RecalledMemory` gains optional `vector_score` and `text_score` fields** — Server v0.11.98
now surfaces hybrid sub-scores (vector similarity component and BM25 text component) alongside
`smart_score` on every recall result. Both fields are `Option<f32>` and absent when the server
did not emit them (e.g. vector-only or BM25-only queries). Additive — no ranking change.
([server PR#767](https://github.com/Dakera-AI/dakera/pull/767))

### Changed

- **Server sync v0.11.98** — syncs to server v0.11.98: WAL durability fix (data-loss off-by-one
LSN guard), unified-query pagination cursor now correct, bi-temporal `valid_from` field
now persisted, candle 0.10→0.11 upgrade, adaptive w_vec boost (CE-147), RocksDB opt-in
persistent hot tier, Phase-1 speed wave (7 latency fixes), graph handlers on `spawn_blocking`.

## [0.11.101] - 2026-07-05

### Changed
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dakera-client"
version = "0.11.101"
version = "0.11.102"
edition = "2021"
description = "Rust client SDK for Dakera AI Agent Memory Platform"
license = "MIT"
Expand Down
21 changes: 19 additions & 2 deletions src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,12 @@ pub struct RecalledMemory {
/// KG-3: hop depth at which this memory was found (only set on associated memories)
#[serde(skip_serializing_if = "Option::is_none")]
pub depth: Option<u8>,
/// Hybrid sub-score: vector similarity component (server v0.11.98+, absent when BM25-only)
#[serde(skip_serializing_if = "Option::is_none")]
pub vector_score: Option<f32>,
/// Hybrid sub-score: BM25 text component (server v0.11.98+, absent when vector-only)
#[serde(skip_serializing_if = "Option::is_none")]
pub text_score: Option<f32>,
}

impl<'de> serde::Deserialize<'de> for RecalledMemory {
Expand All @@ -471,8 +477,8 @@ impl<'de> serde::Deserialize<'de> for RecalledMemory {
use serde::de::Error as _;
let val = serde_json::Value::deserialize(deserializer)?;

// Server wraps recall results as {memory:{...}, score, weighted_score, smart_score}.
// smart_score is the actual ranking key (server sorts by it); prefer it.
// Server wraps recall results as {memory:{...}, score, weighted_score, smart_score,
// vector_score, text_score}. smart_score is the actual ranking key (server sorts by it).
// Fall back to flat format for direct memory-get responses.
let smart_score = val
.get("smart_score")
Expand All @@ -486,6 +492,15 @@ impl<'de> serde::Deserialize<'de> for RecalledMemory {
.or(weighted_score)
.or_else(|| val.get("score").and_then(|v| v.as_f64()).map(|v| v as f32))
.unwrap_or(0.0);
// Hybrid sub-scores (server v0.11.98+): surfaced at the top level alongside smart_score.
let vector_score = val
.get("vector_score")
.and_then(|v| v.as_f64())
.map(|v| v as f32);
let text_score = val
.get("text_score")
.and_then(|v| v.as_f64())
.map(|v| v as f32);

let mem = val.get("memory").unwrap_or(&val);

Expand Down Expand Up @@ -542,6 +557,8 @@ impl<'de> serde::Deserialize<'de> for RecalledMemory {
last_accessed_at,
access_count,
depth,
vector_score,
text_score,
})
}
}
Expand Down
Loading