Repository navigation
Expand file tree
/
Copy pathbackend.h
More file actions
216 lines (176 loc) · 9.96 KB
/
Copy pathbackend.h
File metadata and controls
216 lines (176 loc) · 9.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/**
* SQLite backend for memory storage
*
* Mirrors ragger_memory/sqlite_backend.py from the Python version.
*/
#pragma once
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "storage_types.h"
#include "storage_backend.h"
#include "nlohmann_json.hpp"
namespace ragger::sqlite {
using json = nlohmann::json;
using ragger::Embedder;
class Backend : public StorageBackend {
public:
Backend(Embedder& embedder, const std::string& db_path = "");
/// DB-only constructor — no embedder required.
/// readonly=true: opens with SQLITE_OPEN_READONLY, skips schema creation (for export).
/// readonly=false (default): opens read-write and creates users/settings tables.
explicit Backend(const std::string& db_path, bool readonly = false);
~Backend() override;
/// Path to the database file.
std::string db_path() const override;
/// Store text with metadata. Returns memory ID.
std::string store(const std::string& text, json metadata = {},
bool defer_embedding = false) override;
/// Store a Level 5 RAG document chunk.
int store_document(const DocumentChunk& chunk,
bool defer_embedding = false) override;
/// Store / finalize a raw L1 conversation turn (turns table).
int store_turn(const std::string& user_text,
const std::string& assistant_text,
const std::string& model_name = "",
bool defer_embedding = false,
const std::string& session_guid = "",
const std::string& source_timestamp = "",
const std::string& session_name = "",
const std::string& name_source = "") override;
std::vector<TurnRecord> turns_by_session(
const std::string& session_guid) override;
bool finalize_turn(int turn_id,
const std::string& assistant_text,
const std::string& model_name = "") override;
/// Write back a document's embedding (import path).
bool update_document_embedding(int document_id,
const std::vector<float>& emb) override;
/// Store a curated L6 decision/lesson. Returns decision_id.
int store_decision(const std::string& text,
const std::string& status = "current",
const std::string& tags = "",
const std::string& source_timestamp = "",
bool defer_embedding = false) override;
KnowledgeResult store_knowledge(const KnowledgeInput& in) override;
json find_document_source(const std::string& path) override;
json list_document_sources() override;
void invalidate_all_caches() override;
json delete_document_source(int document_source_id) override;
/// Agent API Phase 2 reads (see StorageBackend docs).
std::vector<AgentHit> agent_search(const AgentSearchQuery& q) override;
json agent_get(const AgentGetQuery& q) override;
/// Agent API Phase 4: timeline / curation / review (see StorageBackend docs).
json agent_timeline(const TimelineQuery& q) override;
json agent_update(const UpdateRequest& req) override;
json agent_review(const std::string& action,
const std::vector<std::string>& ids) override;
/// Near-duplicate decision hints for free text (Phase 3 note surface).
std::vector<std::pair<int,float>> possible_supersedes_for_text(
const std::string& text) override;
/// Write back a single row's embedding for any embedded context table.
bool update_decision_embedding(int decision_id,
const std::vector<float>& emb) override;
bool update_turn_embedding(int turn_id,
const std::vector<float>& emb) override;
bool note_exists_exact(const std::string& text,
const std::string& created_at) override;
bool decision_exists_exact(const std::string& text,
const std::string& created_at) override;
bool turn_exists_fuzzy(const std::string& user_text,
const std::string& ts,
int window_seconds) override;
std::optional<TurnRecord> find_turn_by_text(
const std::string& user_text) override;
bool update_turn_meta(int turn_id,
const std::string& timestamp = "",
const std::string& session_guid = "") override;
std::vector<std::string> current_decisions(int limit) override;
bool set_decision_status(int decision_id, const std::string& status) override;
std::vector<std::string> decisions_by_status(const std::string& status, int limit) override;
std::vector<TurnRecord> unsummarized_turns(int limit = 0) override;
// --- v0.12.0 turn_id-based turn-summary methods (schema migration) ---
bool turn_summary_exists(int turn_id) override;
bool finalize_turn_summary(int turn_id, const std::string& text,
const std::string& summary_model_name) override;
bool mark_turn_summarized(int turn_id, const std::string& model_name) override;
int reset_abandoned_turn_summaries(int limit = 0) override;
std::string last_episode_end(const std::string& session_guid) override;
std::vector<SummaryRecord> l2_summaries_since(
const std::string& session_guid, const std::string& since_ts) override;
std::vector<EpisodeCandidateTurn> episode_candidate_turns(
const std::string& session_guid, const std::string& since_ts) override;
int store_episode_close(const EpisodeClose& close) override;
std::vector<std::string> episodes_needing_close(int idle_minutes) override;
std::vector<TurnRecord> turns_by_session_desc(
const std::string& session_guid, int limit = 0) override;
std::vector<SummaryRecord> turn_summaries_by_session_desc(
const std::string& session_guid, int limit = 0) override;
std::vector<SummaryRecord> episodes_by_session_desc(
const std::string& session_guid, int limit = 0) override;
// PHASE8: update_text is gone (text is never rewritten in place).
/// Hybrid search across the four corpora: vector cosine blended with the
/// custom terms-index keyword relevance. (`collections` is currently a
/// no-op; kept for API compat.)
SearchResponse search(const std::string& query,
int limit = 5,
float min_score = 0.0f,
std::vector<std::string> collections = {}) override;
/// Text-only fallback: FTS5 keyword + phonetic scoring, no embeddings.
SearchResponse search_text_only(const std::string& query,
int limit = 5) override;
/// Number of stored memories.
int count() const override;
std::vector<std::pair<std::string, int64_t>> table_row_counts() const override;
/// True if any table holds a non-NULL embedding.
bool has_embeddings() const override;
/// Total rows across the four embedded tables (rebuild scope).
int count_embeddable_rows(const std::string& table = "all") const override;
/// Load all memories. Returns vector of SearchResult (score=0).
std::vector<SearchResult> load_all(const std::string& collection = "") override;
/// Rebuild embeddings for all stored documents. Returns doc count.
int rebuild_embeddings(Embedder& embedder, bool progress = true,
const std::string& table = "all") override;
void set_embedder(Embedder& embedder) override;
void set_vector_type(vector_codec::VectorType t) override;
int backfill_embeddings(Embedder& embedder,
const std::string& table = "all") override;
uint8_t embedding_version() const override;
uint8_t increment_embedding_version() override;
int reindex_table(const std::string& table, bool progress = false) override;
void reset_terms_table() override;
/// Get distinct collection names.
std::vector<std::string> collections() const override;
/// Delete a memory by ID. Returns true if deleted.
bool delete_memory(int memory_id) override;
/// Delete multiple memories by ID. Returns count deleted.
int delete_batch(const std::vector<int>& memory_ids) override;
/// Search by metadata field matching with optional temporal filtering. Returns vector of results.
std::vector<SearchResult> search_by_metadata(const json& metadata_filter, int limit = 0,
const std::string& after = "",
const std::string& before = "") override;
void close() override;
/// Delete old conversation entries older than specified hours. Returns count deleted.
int cleanup_old_conversations(float max_age_hours) override;
// --- Users / settings ---
std::optional<UserInfo> get_user_by_username(const std::string& username) override;
std::optional<std::string> get_user_password(const std::string& username) override;
void update_user_token(const std::string& username, const std::string& new_hash) override;
int create_user(const std::string& username, const std::string& token_hash) override;
bool delete_user(const std::string& username) override;
void set_user_password(const std::string& username, const std::string& password_hash) override;
std::optional<UserInfo> get_user_by_token_hash(const std::string& token_hash) override;
std::optional<std::string> get_setting(const std::string& key) override;
void set_setting(const std::string& key, const std::string& value) override;
// --- Schema introspection ---
std::vector<SchemaObject> list_schema_objects() override;
std::vector<std::string> table_column_names(const std::string& table) override;
void iterate_table_rows(const std::string& table,
const std::function<void(const ExportRow&)>& cb) override;
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
};
} // namespace ragger::sqlite