9#include "absl/strings/str_cat.h"
10#include "absl/strings/str_format.h"
11#include "absl/time/clock.h"
12#include "absl/time/time.h"
13#include "nlohmann/json.hpp"
22int64_t CurrentTimestamp() {
23 return absl::ToUnixMillis(absl::Now());
27 static int counter = 0;
28 auto now = std::chrono::system_clock::now().time_since_epoch().count();
29 return absl::StrFormat(
"%lld_%d", now, counter++);
32bool FileExists(
const std::filesystem::path& path) {
40 if (data_result.ok()) {
44 if (temp_result.ok()) {
48 data_dir_ = std::filesystem::current_path() /
"agent";
59 const std::filesystem::path& data_dir)
60 : data_dir_(data_dir),
61 prefs_file_(data_dir /
"preferences.json"),
62 patterns_file_(data_dir /
"patterns.json"),
63 projects_file_(data_dir /
"projects.json"),
64 memories_file_(data_dir /
"memories.json") {}
68 return absl::OkStatus();
84 return absl::OkStatus();
104 return absl::OkStatus();
110 const std::string& value) {
112 return absl::FailedPreconditionError(
"Service not initialized");
120 const std::string& key)
const {
135 return absl::FailedPreconditionError(
"Service not initialized");
145 const std::string& rom_hash,
146 const std::string& data,
149 return absl::FailedPreconditionError(
"Service not initialized");
164std::vector<LearnedKnowledgeService::ROMPattern>
166 const std::string& rom_hash)
const {
167 std::vector<ROMPattern> results;
170 bool type_match = type.empty() || pattern.pattern_type == type;
171 bool hash_match = rom_hash.empty() || pattern.rom_hash == rom_hash;
173 if (type_match && hash_match) {
174 results.push_back(pattern);
182 const std::string& type,
const std::string& rom_hash,
183 float new_confidence) {
187 if (pattern.pattern_type == type && pattern.rom_hash == rom_hash) {
188 pattern.confidence = new_confidence;
189 pattern.access_count++;
195 return absl::NotFoundError(
"Pattern not found");
204 const std::string& project_name,
const std::string& rom_hash,
205 const std::string& context) {
207 return absl::FailedPreconditionError(
"Service not initialized");
213 if (project.project_name == project_name) {
214 project.rom_hash = rom_hash;
215 project.context_data = context;
216 project.last_accessed = CurrentTimestamp();
234std::optional<LearnedKnowledgeService::ProjectContext>
236 const std::string& project_name)
const {
238 if (project.project_name == project_name) {
245std::vector<LearnedKnowledgeService::ProjectContext>
253 const std::string& topic,
const std::string& summary,
254 const std::vector<std::string>& key_facts) {
256 return absl::FailedPreconditionError(
"Service not initialized");
260 memory.
id = GenerateRandomID();
261 memory.
topic = topic;
277std::vector<LearnedKnowledgeService::ConversationMemory>
279 std::vector<ConversationMemory> results;
281 std::string query_lower = query;
282 std::transform(query_lower.begin(), query_lower.end(), query_lower.begin(),
286 std::string topic_lower = memory.topic;
287 std::string summary_lower = memory.summary;
288 std::transform(topic_lower.begin(), topic_lower.end(), topic_lower.begin(),
290 std::transform(summary_lower.begin(), summary_lower.end(),
291 summary_lower.begin(), ::tolower);
293 if (topic_lower.find(query_lower) != std::string::npos ||
294 summary_lower.find(query_lower) != std::string::npos) {
295 results.push_back(memory);
302std::vector<LearnedKnowledgeService::ConversationMemory>
304 std::vector<ConversationMemory> recent =
memories_;
307 std::sort(recent.begin(), recent.end(),
309 return a.created_at > b.created_at;
312 if (recent.size() >
static_cast<size_t>(limit)) {
313 recent.resize(limit);
323 nlohmann::json export_data;
329 export_data[
"patterns"] = nlohmann::json::array();
332 p[
"type"] = pattern.pattern_type;
333 p[
"rom_hash"] = pattern.rom_hash;
334 p[
"data"] = pattern.pattern_data;
335 p[
"confidence"] = pattern.confidence;
336 p[
"learned_at"] = pattern.learned_at;
337 p[
"access_count"] = pattern.access_count;
338 export_data[
"patterns"].push_back(p);
342 export_data[
"projects"] = nlohmann::json::array();
345 p[
"name"] = project.project_name;
346 p[
"rom_hash"] = project.rom_hash;
347 p[
"context"] = project.context_data;
348 p[
"last_accessed"] = project.last_accessed;
349 export_data[
"projects"].push_back(p);
353 export_data[
"memories"] = nlohmann::json::array();
357 m[
"topic"] = memory.topic;
358 m[
"summary"] = memory.summary;
359 m[
"key_facts"] = memory.key_facts;
360 m[
"created_at"] = memory.created_at;
361 m[
"access_count"] = memory.access_count;
362 export_data[
"memories"].push_back(m);
365 return export_data.dump(2);
369 const std::string& json_data) {
371 auto data = nlohmann::json::parse(json_data);
374 if (data.contains(
"preferences")) {
375 for (
const auto& [key, value] : data[
"preferences"].items()) {
381 if (data.contains(
"patterns")) {
382 for (
const auto& p : data[
"patterns"]) {
384 pattern.pattern_type = p[
"type"];
385 pattern.rom_hash = p[
"rom_hash"];
386 pattern.pattern_data = p[
"data"];
387 pattern.confidence = p[
"confidence"];
388 pattern.learned_at = p[
"learned_at"];
389 pattern.access_count = p[
"access_count"];
395 if (data.contains(
"projects")) {
396 for (
const auto& p : data[
"projects"]) {
397 ProjectContext project;
398 project.project_name = p[
"name"];
399 project.rom_hash = p[
"rom_hash"];
400 project.context_data = p[
"context"];
401 project.last_accessed = p[
"last_accessed"];
407 if (data.contains(
"memories")) {
408 for (
const auto& m : data[
"memories"]) {
409 ConversationMemory memory;
411 memory.topic = m[
"topic"];
412 memory.summary = m[
"summary"];
413 memory.key_facts = m[
"key_facts"].get<std::vector<std::string>>();
414 memory.created_at = m[
"created_at"];
415 memory.access_count = m[
"access_count"];
421 }
catch (
const std::exception& e) {
422 return absl::InternalError(absl::StrCat(
"JSON parse error: ", e.what()));
427 return absl::UnimplementedError(
428 "JSON support not enabled. Build with -DYAZE_WITH_JSON=ON");
432 return absl::UnimplementedError(
433 "JSON support not enabled. Build with -DYAZE_WITH_JSON=ON");
455 int64_t earliest = CurrentTimestamp();
457 if (pattern.learned_at < earliest) {
458 earliest = pattern.learned_at;
462 if (memory.created_at < earliest) {
463 earliest = memory.created_at;
479 return absl::OkStatus();
484 if (!file.is_open()) {
485 return absl::InternalError(
"Failed to open preferences file");
491 for (
const auto& [key, value] : data.items()) {
495 return absl::OkStatus();
496 }
catch (
const std::exception& e) {
497 return absl::InternalError(
498 absl::StrCat(
"Failed to load preferences: ", e.what()));
507 if (!file.is_open()) {
508 return absl::InternalError(
"Failed to open preferences file for writing");
511 file << data.dump(2);
512 return absl::OkStatus();
513 }
catch (
const std::exception& e) {
514 return absl::InternalError(
515 absl::StrCat(
"Failed to save preferences: ", e.what()));
521 return absl::OkStatus();
529 for (
const auto& p : data) {
531 pattern.pattern_type = p[
"type"];
532 pattern.rom_hash = p[
"rom_hash"];
533 pattern.pattern_data = p[
"data"];
534 pattern.confidence = p[
"confidence"];
535 pattern.learned_at = p[
"learned_at"];
536 pattern.access_count = p.value(
"access_count", 0);
540 return absl::OkStatus();
541 }
catch (
const std::exception& e) {
542 return absl::InternalError(
543 absl::StrCat(
"Failed to load patterns: ", e.what()));
549 nlohmann::json data = nlohmann::json::array();
553 p[
"type"] = pattern.pattern_type;
554 p[
"rom_hash"] = pattern.rom_hash;
555 p[
"data"] = pattern.pattern_data;
556 p[
"confidence"] = pattern.confidence;
557 p[
"learned_at"] = pattern.learned_at;
558 p[
"access_count"] = pattern.access_count;
563 file << data.dump(2);
564 return absl::OkStatus();
565 }
catch (
const std::exception& e) {
566 return absl::InternalError(
567 absl::StrCat(
"Failed to save patterns: ", e.what()));
573 return absl::OkStatus();
581 for (
const auto& p : data) {
582 ProjectContext project;
583 project.project_name = p[
"name"];
584 project.rom_hash = p[
"rom_hash"];
585 project.context_data = p[
"context"];
586 project.last_accessed = p[
"last_accessed"];
590 return absl::OkStatus();
591 }
catch (
const std::exception& e) {
592 return absl::InternalError(
593 absl::StrCat(
"Failed to load projects: ", e.what()));
599 nlohmann::json data = nlohmann::json::array();
603 p[
"name"] = project.project_name;
604 p[
"rom_hash"] = project.rom_hash;
605 p[
"context"] = project.context_data;
606 p[
"last_accessed"] = project.last_accessed;
611 file << data.dump(2);
612 return absl::OkStatus();
613 }
catch (
const std::exception& e) {
614 return absl::InternalError(
615 absl::StrCat(
"Failed to save projects: ", e.what()));
621 nlohmann::json data = nlohmann::json::array();
626 m[
"topic"] = memory.topic;
627 m[
"summary"] = memory.summary;
628 m[
"key_facts"] = memory.key_facts;
629 m[
"created_at"] = memory.created_at;
630 m[
"access_count"] = memory.access_count;
635 file << data.dump(2);
636 return absl::OkStatus();
637 }
catch (
const std::exception& e) {
638 return absl::InternalError(
639 absl::StrCat(
"Failed to save memories: ", e.what()));
645 return absl::OkStatus();
653 for (
const auto& m : data) {
654 ConversationMemory memory;
656 memory.topic = m[
"topic"];
657 memory.summary = m[
"summary"];
658 memory.key_facts = m[
"key_facts"].get<std::vector<std::string>>();
659 memory.created_at = m[
"created_at"];
660 memory.access_count = m.value(
"access_count", 0);
664 return absl::OkStatus();
665 }
catch (
const std::exception& e) {
666 return absl::InternalError(
667 absl::StrCat(
"Failed to load memories: ", e.what()));
674 return absl::OkStatus();
677 return absl::UnimplementedError(
"JSON support required");
680 return absl::OkStatus();
683 return absl::UnimplementedError(
"JSON support required");
686 return absl::OkStatus();
689 return absl::UnimplementedError(
"JSON support required");
692 return absl::OkStatus();
695 return absl::UnimplementedError(
"JSON support required");
700 return GenerateRandomID();
std::optional< std::string > GetPreference(const std::string &key) const
absl::Status SaveMemories()
absl::Status StoreConversationSummary(const std::string &topic, const std::string &summary, const std::vector< std::string > &key_facts)
std::vector< ProjectContext > GetAllProjects() const
std::vector< ConversationMemory > GetRecentMemories(int limit=10) const
std::vector< ConversationMemory > memories_
std::filesystem::path prefs_file_
std::vector< ProjectContext > projects_
std::string GenerateID() const
absl::Status RemovePreference(const std::string &key)
std::vector< ConversationMemory > SearchMemories(const std::string &query) const
LearnedKnowledgeService()
std::vector< ROMPattern > QueryPatterns(const std::string &type, const std::string &rom_hash="") const
absl::Status LoadPreferences()
absl::Status ImportFromJSON(const std::string &json_data)
absl::Status SavePatterns()
std::filesystem::path memories_file_
std::filesystem::path data_dir_
absl::Status SaveProjects()
absl::Status UpdatePatternConfidence(const std::string &type, const std::string &rom_hash, float new_confidence)
std::map< std::string, std::string > preferences_
absl::Status Initialize()
std::optional< ProjectContext > GetProjectContext(const std::string &project_name) const
absl::Status SetPreference(const std::string &key, const std::string &value)
absl::Status SavePreferences()
absl::Status LoadPatterns()
absl::StatusOr< std::string > ExportToJSON() const
absl::Status SaveProjectContext(const std::string &project_name, const std::string &rom_hash, const std::string &context)
std::filesystem::path patterns_file_
std::vector< ROMPattern > patterns_
absl::Status LearnPattern(const std::string &type, const std::string &rom_hash, const std::string &data, float confidence=1.0f)
std::map< std::string, std::string > GetAllPreferences() const
absl::Status LoadProjects()
std::filesystem::path projects_file_
absl::Status LoadMemories()
bool FileExists(const std::string &path)
std::string GenerateRandomID()
std::vector< std::string > key_facts