-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathmemory_write_tool.cpp
More file actions
124 lines (111 loc) · 4.57 KB
/
Copy pathmemory_write_tool.cpp
File metadata and controls
124 lines (111 loc) · 4.57 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
#include "memory_write_tool.hpp"
#include "../memory/memory_paths.hpp"
#include "../memory/memory_registry.hpp"
#include "../memory/memory_types.hpp"
#include "../utils/logger.hpp"
#include "../utils/utf8_path.hpp"
#include <nlohmann/json.hpp>
namespace acecode {
namespace {
MemoryWriteMode parse_mode(const std::string& s) {
if (s == "create") return MemoryWriteMode::Create;
if (s == "update") return MemoryWriteMode::Update;
return MemoryWriteMode::Upsert;
}
} // namespace
ToolImpl create_memory_write_tool(MemoryRegistry& registry) {
ToolDef def;
def.name = "memory_write";
def.description =
"Persist a memory entry under ~/.acecode/memory/<name>.md. Writes are "
"atomic and the MEMORY.md index is updated automatically. 'name' is "
"sanitized to [A-Za-z0-9_-] (1-64 chars). 'type' must be one of "
"user|feedback|project|reference. 'mode' defaults to 'upsert' (also "
"'create' or 'update'). The tool always writes inside "
"~/.acecode/memory/ — other paths are rejected.";
def.parameters = nlohmann::json({
{"type", "object"},
{"properties", {
{"name", {
{"type", "string"},
{"description", "File-stem identifier ([A-Za-z0-9_-]{1,64})."}
}},
{"type", {
{"type", "string"},
{"enum", nlohmann::json::array({"user", "feedback", "project", "reference"})},
{"description", "Category of the memory."}
}},
{"description", {
{"type", "string"},
{"description", "Short one-line description used in MEMORY.md index."}
}},
{"body", {
{"type", "string"},
{"description", "Markdown body of the memory entry."}
}},
{"mode", {
{"type", "string"},
{"enum", nlohmann::json::array({"create", "update", "upsert"})},
{"description", "Write semantics. Default 'upsert' (create-or-replace)."}
}}
}},
{"required", nlohmann::json::array({"name", "type", "description", "body"})}
});
auto execute = [®istry](const std::string& arguments_json,
const ToolContext& /*ctx*/) -> ToolResult {
std::string name, type_str, description, body, mode_str;
try {
if (arguments_json.empty()) {
return ToolResult{"[Error] memory_write requires arguments.", false};
}
auto args = nlohmann::json::parse(arguments_json);
name = args.value("name", "");
type_str = args.value("type", "");
description = args.value("description", "");
body = args.value("body", "");
mode_str = args.value("mode", "upsert");
} catch (...) {
return ToolResult{"[Error] Failed to parse tool arguments.", false};
}
std::string name_err = validate_memory_name(name);
if (!name_err.empty()) {
nlohmann::json err;
err["success"] = false;
err["error"] = name_err;
return ToolResult{err.dump(), false};
}
auto parsed_type = parse_memory_type(type_str);
if (!parsed_type.has_value()) {
nlohmann::json err;
err["success"] = false;
err["error"] = "invalid type: " + type_str +
" (allowed: user|feedback|project|reference)";
return ToolResult{err.dump(), false};
}
if (description.empty()) {
nlohmann::json err;
err["success"] = false;
err["error"] = "description must not be empty";
return ToolResult{err.dump(), false};
}
std::string err_msg;
auto written = registry.upsert(name, *parsed_type, description, body,
parse_mode(mode_str), err_msg);
if (!written) {
nlohmann::json err;
err["success"] = false;
err["error"] = err_msg;
return ToolResult{err.dump(), false};
}
nlohmann::json out;
out["success"] = true;
out["name"] = written->name;
out["description"] = written->description;
out["type"] = memory_type_to_string(written->type);
out["path"] = path_to_utf8_generic(written->path);
LOG_INFO("[memory_write] persisted " + path_to_utf8_generic(written->path));
return ToolResult{out.dump(), true};
};
return ToolImpl{def, execute, /*is_read_only=*/false};
}
} // namespace acecode