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"
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) {
41 if (docs_result.ok()) {
45 data_dir_ = std::filesystem::current_path() /
"agent";
55 const std::filesystem::path& data_dir)
56 : data_dir_(data_dir),
57 prefs_file_(data_dir /
"preferences.json"),
58 patterns_file_(data_dir /
"patterns.json"),
59 projects_file_(data_dir /
"projects.json"),
60 memories_file_(data_dir /
"memories.json") {}
64 return absl::OkStatus();
80 return absl::OkStatus();
100 return absl::OkStatus();
106 const std::string& value) {
108 return absl::FailedPreconditionError(
"Service not initialized");
116 const std::string& key)
const {
131 return absl::FailedPreconditionError(
"Service not initialized");
141 const std::string& rom_hash,
142 const std::string& data,
145 return absl::FailedPreconditionError(
"Service not initialized");
160std::vector<LearnedKnowledgeService::ROMPattern>
162 const std::string& rom_hash)
const {
163 std::vector<ROMPattern> results;
166 bool type_match = type.empty() || pattern.pattern_type == type;
167 bool hash_match = rom_hash.empty() || pattern.rom_hash == rom_hash;
169 if (type_match && hash_match) {
170 results.push_back(pattern);
178 const std::string& type,
const std::string& rom_hash,
179 float new_confidence) {
183 if (pattern.pattern_type == type && pattern.rom_hash == rom_hash) {
184 pattern.confidence = new_confidence;
185 pattern.access_count++;
191 return absl::NotFoundError(
"Pattern not found");
200 const std::string& project_name,
const std::string& rom_hash,
201 const std::string& context) {
203 return absl::FailedPreconditionError(
"Service not initialized");
209 if (project.project_name == project_name) {
210 project.rom_hash = rom_hash;
211 project.context_data = context;
212 project.last_accessed = CurrentTimestamp();
230std::optional<LearnedKnowledgeService::ProjectContext>
232 const std::string& project_name)
const {
234 if (project.project_name == project_name) {
241std::vector<LearnedKnowledgeService::ProjectContext>
249 const std::string& topic,
const std::string& summary,
250 const std::vector<std::string>& key_facts) {
252 return absl::FailedPreconditionError(
"Service not initialized");
256 memory.
id = GenerateRandomID();
257 memory.
topic = topic;
273std::vector<LearnedKnowledgeService::ConversationMemory>
275 std::vector<ConversationMemory> results;
277 std::string query_lower = query;
278 std::transform(query_lower.begin(), query_lower.end(), query_lower.begin(),
282 std::string topic_lower = memory.topic;
283 std::string summary_lower = memory.summary;
284 std::transform(topic_lower.begin(), topic_lower.end(), topic_lower.begin(),
286 std::transform(summary_lower.begin(), summary_lower.end(),
287 summary_lower.begin(), ::tolower);
289 if (topic_lower.find(query_lower) != std::string::npos ||
290 summary_lower.find(query_lower) != std::string::npos) {
291 results.push_back(memory);
298std::vector<LearnedKnowledgeService::ConversationMemory>
300 std::vector<ConversationMemory> recent =
memories_;
303 std::sort(recent.begin(), recent.end(),
305 return a.created_at > b.created_at;
308 if (recent.size() >
static_cast<size_t>(limit)) {
309 recent.resize(limit);
319 nlohmann::json export_data;
325 export_data[
"patterns"] = nlohmann::json::array();
328 p[
"type"] = pattern.pattern_type;
329 p[
"rom_hash"] = pattern.rom_hash;
330 p[
"data"] = pattern.pattern_data;
331 p[
"confidence"] = pattern.confidence;
332 p[
"learned_at"] = pattern.learned_at;
333 p[
"access_count"] = pattern.access_count;
334 export_data[
"patterns"].push_back(p);
338 export_data[
"projects"] = nlohmann::json::array();
341 p[
"name"] = project.project_name;
342 p[
"rom_hash"] = project.rom_hash;
343 p[
"context"] = project.context_data;
344 p[
"last_accessed"] = project.last_accessed;
345 export_data[
"projects"].push_back(p);
349 export_data[
"memories"] = nlohmann::json::array();
353 m[
"topic"] = memory.topic;
354 m[
"summary"] = memory.summary;
355 m[
"key_facts"] = memory.key_facts;
356 m[
"created_at"] = memory.created_at;
357 m[
"access_count"] = memory.access_count;
358 export_data[
"memories"].push_back(m);
361 return export_data.dump(2);
365 const std::string& json_data) {
367 auto data = nlohmann::json::parse(json_data);
370 if (data.contains(
"preferences")) {
371 for (
const auto& [key, value] : data[
"preferences"].items()) {
377 if (data.contains(
"patterns")) {
378 for (
const auto& p : data[
"patterns"]) {
380 pattern.pattern_type = p[
"type"];
381 pattern.rom_hash = p[
"rom_hash"];
382 pattern.pattern_data = p[
"data"];
383 pattern.confidence = p[
"confidence"];
384 pattern.learned_at = p[
"learned_at"];
385 pattern.access_count = p[
"access_count"];
391 if (data.contains(
"projects")) {
392 for (
const auto& p : data[
"projects"]) {
393 ProjectContext project;
394 project.project_name = p[
"name"];
395 project.rom_hash = p[
"rom_hash"];
396 project.context_data = p[
"context"];
397 project.last_accessed = p[
"last_accessed"];
403 if (data.contains(
"memories")) {
404 for (
const auto& m : data[
"memories"]) {
405 ConversationMemory memory;
407 memory.topic = m[
"topic"];
408 memory.summary = m[
"summary"];
409 memory.key_facts = m[
"key_facts"].get<std::vector<std::string>>();
410 memory.created_at = m[
"created_at"];
411 memory.access_count = m[
"access_count"];
417 }
catch (
const std::exception& e) {
418 return absl::InternalError(absl::StrCat(
"JSON parse error: ", e.what()));
423 return absl::UnimplementedError(
424 "JSON support not enabled. Build with -DYAZE_WITH_JSON=ON");
428 return absl::UnimplementedError(
429 "JSON support not enabled. Build with -DYAZE_WITH_JSON=ON");
451 int64_t earliest = CurrentTimestamp();
453 if (pattern.learned_at < earliest) {
454 earliest = pattern.learned_at;
458 if (memory.created_at < earliest) {
459 earliest = memory.created_at;
475 return absl::OkStatus();
480 if (!file.is_open()) {
481 return absl::InternalError(
"Failed to open preferences file");
487 for (
const auto& [key, value] : data.items()) {
491 return absl::OkStatus();
492 }
catch (
const std::exception& e) {
493 return absl::InternalError(
494 absl::StrCat(
"Failed to load preferences: ", e.what()));
503 if (!file.is_open()) {
504 return absl::InternalError(
"Failed to open preferences file for writing");
507 file << data.dump(2);
508 return absl::OkStatus();
509 }
catch (
const std::exception& e) {
510 return absl::InternalError(
511 absl::StrCat(
"Failed to save preferences: ", e.what()));
517 return absl::OkStatus();
525 for (
const auto& p : data) {
527 pattern.pattern_type = p[
"type"];
528 pattern.rom_hash = p[
"rom_hash"];
529 pattern.pattern_data = p[
"data"];
530 pattern.confidence = p[
"confidence"];
531 pattern.learned_at = p[
"learned_at"];
532 pattern.access_count = p.value(
"access_count", 0);
536 return absl::OkStatus();
537 }
catch (
const std::exception& e) {
538 return absl::InternalError(
539 absl::StrCat(
"Failed to load patterns: ", e.what()));
545 nlohmann::json data = nlohmann::json::array();
549 p[
"type"] = pattern.pattern_type;
550 p[
"rom_hash"] = pattern.rom_hash;
551 p[
"data"] = pattern.pattern_data;
552 p[
"confidence"] = pattern.confidence;
553 p[
"learned_at"] = pattern.learned_at;
554 p[
"access_count"] = pattern.access_count;
559 file << data.dump(2);
560 return absl::OkStatus();
561 }
catch (
const std::exception& e) {
562 return absl::InternalError(
563 absl::StrCat(
"Failed to save patterns: ", e.what()));
569 return absl::OkStatus();
577 for (
const auto& p : data) {
578 ProjectContext project;
579 project.project_name = p[
"name"];
580 project.rom_hash = p[
"rom_hash"];
581 project.context_data = p[
"context"];
582 project.last_accessed = p[
"last_accessed"];
586 return absl::OkStatus();
587 }
catch (
const std::exception& e) {
588 return absl::InternalError(
589 absl::StrCat(
"Failed to load projects: ", e.what()));
595 nlohmann::json data = nlohmann::json::array();
599 p[
"name"] = project.project_name;
600 p[
"rom_hash"] = project.rom_hash;
601 p[
"context"] = project.context_data;
602 p[
"last_accessed"] = project.last_accessed;
607 file << data.dump(2);
608 return absl::OkStatus();
609 }
catch (
const std::exception& e) {
610 return absl::InternalError(
611 absl::StrCat(
"Failed to save projects: ", e.what()));
617 nlohmann::json data = nlohmann::json::array();
622 m[
"topic"] = memory.topic;
623 m[
"summary"] = memory.summary;
624 m[
"key_facts"] = memory.key_facts;
625 m[
"created_at"] = memory.created_at;
626 m[
"access_count"] = memory.access_count;
631 file << data.dump(2);
632 return absl::OkStatus();
633 }
catch (
const std::exception& e) {
634 return absl::InternalError(
635 absl::StrCat(
"Failed to save memories: ", e.what()));
641 return absl::OkStatus();
649 for (
const auto& m : data) {
650 ConversationMemory memory;
652 memory.topic = m[
"topic"];
653 memory.summary = m[
"summary"];
654 memory.key_facts = m[
"key_facts"].get<std::vector<std::string>>();
655 memory.created_at = m[
"created_at"];
656 memory.access_count = m.value(
"access_count", 0);
660 return absl::OkStatus();
661 }
catch (
const std::exception& e) {
662 return absl::InternalError(
663 absl::StrCat(
"Failed to load memories: ", e.what()));
670 return absl::OkStatus();
673 return absl::UnimplementedError(
"JSON support required");
676 return absl::OkStatus();
679 return absl::UnimplementedError(
"JSON support required");
682 return absl::OkStatus();
685 return absl::UnimplementedError(
"JSON support required");
688 return absl::OkStatus();
691 return absl::UnimplementedError(
"JSON support required");
696 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()
int64_t CurrentTimestamp()
std::vector< std::string > key_facts