|
1 | 1 | #include <iostream> |
2 | | -#include <optional> |
3 | 2 | #include <string> |
4 | | -#include "person_support.hpp" |
5 | | -#include "priority_support.hpp" |
| 3 | + |
| 4 | +#include <filesystem_tools.hpp> |
6 | 5 | #include <json_invoke/json_invoke.hpp> |
7 | 6 |
|
| 7 | +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(NumberedLine, line_number, content); |
| 8 | +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(FileEntry, name, type, size_bytes, last_modified); |
| 9 | +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SearchMatch, path, line_number, line); |
| 10 | +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(FileInfo, path, type, size_bytes, last_modified, exists); |
| 11 | + |
8 | 12 | int main() |
9 | 13 | { |
10 | 14 | json_invoke::JsonInvokeAdapterThreadSafe adapter; |
11 | 15 |
|
12 | | - adapter.registerFunction("add", json_invoke::readOnly([](int x, int y) { return x + y; }), "Add two integers."); |
13 | | - adapter.registerFunction("getPerson", json_invoke::readOnly(getPerson), "Construct one person."); |
14 | | - adapter.registerFunction( |
15 | | - "describePerson", |
16 | | - json_invoke::readOnly(&Person::describe), |
17 | | - json_invoke::FunctionMetadata{{"person"}, "Call Person::describe() for one person."}); |
18 | 16 | adapter.registerFunction( |
19 | | - "countPeopleAtLeastAge", |
20 | | - json_invoke::readOnly(countPeopleAtLeastAge), |
21 | | - json_invoke::FunctionMetadata{{"people", "minimum_age"}, "Count how many people in a JSON roster meet a minimum age."}); |
| 17 | + "write_file", |
| 18 | + json_invoke::mutating(writeFile), |
| 19 | + json_invoke::FunctionMetadata{{"path", "content", "overwrite"}, "Write text content to a file."}); |
22 | 20 | adapter.registerFunction( |
23 | | - "countPeopleAtLeastAgeByTeam", |
24 | | - json_invoke::readOnly(countPeopleAtLeastAgeByTeam), |
25 | | - json_invoke::FunctionMetadata{ |
26 | | - {"team_rosters", "minimum_age"}, |
27 | | - "Count how many people in each team roster meet a minimum age."}); |
| 21 | + "read_file", |
| 22 | + json_invoke::readOnly(readFile), |
| 23 | + json_invoke::FunctionMetadata{{"path"}, "Read the full text content of a file."}); |
28 | 24 | adapter.registerFunction( |
29 | | - "oldestPersonByQueue", |
30 | | - json_invoke::readOnly(oldestPersonByQueue), |
31 | | - json_invoke::FunctionMetadata{ |
32 | | - {"queue_rosters"}, |
33 | | - "Find the oldest person in each support queue."}); |
| 25 | + "get_file_info", |
| 26 | + json_invoke::readOnly(getFileInfo), |
| 27 | + json_invoke::FunctionMetadata{{"path"}, "Return metadata for one path."}); |
34 | 28 | adapter.registerFunction( |
35 | | - "displayNickname", |
36 | | - json_invoke::readOnly([](std::optional<std::string> nickname) { |
37 | | - return nickname.value_or("anonymous"); |
38 | | - }), |
39 | | - json_invoke::FunctionMetadata{{"nickname"}, "Return the nickname or a default when omitted."}); |
| 29 | + "list_directory", |
| 30 | + json_invoke::readOnly(listDirectory), |
| 31 | + json_invoke::FunctionMetadata{{"path"}, "List immediate directory entries."}); |
40 | 32 | adapter.registerFunction( |
41 | | - "recommendIncidentPriority", |
42 | | - json_invoke::readOnly(recommendIncidentPriority), |
43 | | - json_invoke::FunctionMetadata{ |
44 | | - {"requested_priority", "customer_blocked", "production_impact", "affected_users"}, |
45 | | - "Recommend an incident priority from request urgency and customer impact."}); |
46 | | - |
47 | | - //#1 |
48 | | - std::cout << "--- Invoke add as int ---" << std::endl; |
49 | | - int sum = adapter.invoke({ |
50 | | - {"name", "add"}, |
51 | | - {"args", {8, 13}}, |
52 | | - }); |
53 | | - std::cout << sum << std::endl; |
| 33 | + "search_files", |
| 34 | + json_invoke::readOnly(searchFiles), |
| 35 | + json_invoke::FunctionMetadata{{"directory", "pattern", "recursive"}, "Search text files for a literal pattern."}); |
54 | 36 |
|
55 | | - //#2 |
56 | | - std::cout << "\n--- Invoke LLM-style payload as int ---" << std::endl; |
57 | | - json_invoke::json llm_tool_call_request = { |
58 | | - {"type", "function"}, |
59 | | - {"function", { |
60 | | - {"name", "add"}, |
61 | | - {"arguments", R"({"arg0":21,"arg1":9})"}, |
| 37 | + std::cout << "--- 1) write_file (JSON request -> typed return) ---" << std::endl; |
| 38 | + std::string write_result = adapter.invoke({ |
| 39 | + {"name", "write_file"}, |
| 40 | + {"args", { |
| 41 | + {"path", "build/_json_invoke_scratch.txt"}, |
| 42 | + {"content", "alpha\nbeta\ngamma\n"}, |
| 43 | + {"overwrite", true}, |
62 | 44 | }}, |
63 | | - }; |
64 | | - int llm_sum = adapter.invoke(llm_tool_call_request); |
65 | | - std::cout << llm_sum << std::endl; |
66 | | - |
67 | | - //#3 |
68 | | - std::cout << "\n--- Invoke getPerson get Person object ---" << std::endl; |
69 | | - Person person = adapter.invoke({ |
70 | | - {"name", "getPerson"}, |
71 | 45 | }); |
72 | | - std::cout << person.describe() << std::endl; |
| 46 | + std::cout << write_result << std::endl; |
73 | 47 |
|
74 | | - //#4 |
75 | | - std::cout << "\n--- Invoke describePerson get std::string ---" << std::endl; |
76 | | - std::string description = adapter.invoke({ |
77 | | - {"name", "describePerson"}, |
78 | | - {"args", {person}}, |
| 48 | + std::cout << "\n--- 2) read_file (JSON request -> typed string) ---" << std::endl; |
| 49 | + std::string content = adapter.invoke({ |
| 50 | + {"name", "read_file"}, |
| 51 | + {"args", {{"path", "build/_json_invoke_scratch.txt"}}}, |
79 | 52 | }); |
80 | | - std::cout << description << std::endl; |
| 53 | + std::cout << content; |
81 | 54 |
|
82 | | - //#5 |
83 | | - std::cout << "\n--- Invoke getPerson get Person as Json ---" << std::endl; |
84 | | - json_invoke::json personJson = adapter.invoke({ |
85 | | - {"name", "getPerson"}, |
| 55 | + std::cout << "\n--- 3) get_file_info (as JSON) ---" << std::endl; |
| 56 | + json_invoke::json info_json = adapter.invoke({ |
| 57 | + {"name", "get_file_info"}, |
| 58 | + {"args", {{"path", "build/_json_invoke_scratch.txt"}}}, |
86 | 59 | }); |
87 | | - std::cout << personJson.dump(2) << std::endl; |
88 | | - |
89 | | - //#6 |
90 | | - std::cout << "\n--- Invoke describePerson using json object ---" << std::endl; |
91 | | - json_invoke::json descriptionRequest = { |
92 | | - {"name", "describePerson"}, |
93 | | - {"args", {personJson}}, |
94 | | - }; |
95 | | - json_invoke::json descriptionJson = adapter.invoke(descriptionRequest); |
96 | | - std::cout << descriptionJson.dump(2) << std::endl; |
97 | | - |
98 | | - std::cout << "\n--- Count people from array of JSON objects ---" << std::endl; |
99 | | - json_invoke::json rosterRequest = { |
100 | | - {"name", "countPeopleAtLeastAge"}, |
101 | | - {"args", { |
102 | | - {"people", json_invoke::json::array({ |
103 | | - personJson, |
104 | | - json_invoke::json{{"name", "Bob"}, {"age", 17}}, |
105 | | - json_invoke::json{{"name", "Cara"}, {"age", 41}}, |
106 | | - })}, |
107 | | - {"minimum_age", 21}, |
108 | | - }}, |
109 | | - }; |
110 | | - int adultCount = adapter.invoke(rosterRequest); |
111 | | - std::cout << adultCount << std::endl; |
| 60 | + std::cout << info_json.dump(2) << std::endl; |
112 | 61 |
|
113 | | - std::cout << "\n--- Count people by team from dictionary of rosters ---" << std::endl; |
114 | | - json_invoke::json teamRosterRequest = { |
115 | | - {"name", "countPeopleAtLeastAgeByTeam"}, |
116 | | - {"args", { |
117 | | - {"team_rosters", { |
118 | | - {"support", json_invoke::json::array({ |
119 | | - personJson, |
120 | | - json_invoke::json{{"name", "Bob"}, {"age", 17}}, |
121 | | - })}, |
122 | | - {"platform", json_invoke::json::array({ |
123 | | - json_invoke::json{{"name", "Cara"}, {"age", 41}}, |
124 | | - json_invoke::json{{"name", "Dylan"}, {"age", 29}}, |
125 | | - json_invoke::json{{"name", "Eva"}, {"age", 18}}, |
126 | | - })}, |
127 | | - }}, |
128 | | - {"minimum_age", 21}, |
| 62 | + std::cout << "\n--- 4) list_directory (LLM-style payload) ---" << std::endl; |
| 63 | + json_invoke::json llm_tool_call_request = { |
| 64 | + {"type", "function"}, |
| 65 | + {"function", { |
| 66 | + {"name", "list_directory"}, |
| 67 | + {"arguments", R"({"path":"build"})"}, |
129 | 68 | }}, |
130 | 69 | }; |
131 | | - json_invoke::json teamCounts = adapter.invoke(teamRosterRequest); |
132 | | - std::cout << teamCounts.dump(2) << std::endl; |
| 70 | + json_invoke::json entries_json = adapter.invoke(llm_tool_call_request); |
| 71 | + std::cout << entries_json.dump(2) << std::endl; |
133 | 72 |
|
134 | | - std::cout << "\n--- Find oldest person by queue from unordered dictionary ---" << std::endl; |
135 | | - json_invoke::json queueRequest = { |
136 | | - {"name", "oldestPersonByQueue"}, |
| 73 | + std::cout << "\n--- 5) search_files (as JSON) ---" << std::endl; |
| 74 | + json_invoke::json matches_json = adapter.invoke({ |
| 75 | + {"name", "search_files"}, |
137 | 76 | {"args", { |
138 | | - {"queue_rosters", { |
139 | | - {"billing", json_invoke::json::array({ |
140 | | - json_invoke::json{{"name", "Mia"}, {"age", 26}}, |
141 | | - json_invoke::json{{"name", "Noah"}, {"age", 31}}, |
142 | | - })}, |
143 | | - {"vip", json_invoke::json::array({ |
144 | | - personJson, |
145 | | - json_invoke::json{{"name", "Olivia"}, {"age", 45}}, |
146 | | - })}, |
147 | | - }}, |
| 77 | + {"directory", "build"}, |
| 78 | + {"pattern", "beta"}, |
| 79 | + {"recursive", false}, |
148 | 80 | }}, |
149 | | - }; |
150 | | - json_invoke::json oldestByQueue = adapter.invoke(queueRequest); |
151 | | - std::cout << oldestByQueue.dump(2) << std::endl; |
152 | | - |
153 | | - std::cout << "\n--- Invoke displayNickname without optional arg ---" << std::endl; |
154 | | - std::string nickname = adapter.invoke({ |
155 | | - {"name", "displayNickname"}, |
156 | | - {"args", json_invoke::json::object()}, |
157 | | - }); |
158 | | - std::cout << nickname << std::endl; |
159 | | - |
160 | | - std::cout << "\n--- Invoke displayNickname with optional arg ---" << std::endl; |
161 | | - std::string nicknameWithArg = adapter.invoke({ |
162 | | - {"name", "displayNickname"}, |
163 | | - {"args", {"tom"}}, |
164 | 81 | }); |
165 | | - std::cout << nicknameWithArg << std::endl; |
166 | | - |
167 | | - std::cout << "\n--- Recommend incident priority from named JSON args ---" << std::endl; |
168 | | - json_invoke::json recommendedPriorityJson = adapter.invoke({ |
169 | | - {"name", "recommendIncidentPriority"}, |
170 | | - {"args", { |
171 | | - {"requested_priority", "low"}, |
172 | | - {"customer_blocked", true}, |
173 | | - {"production_impact", false}, |
174 | | - {"affected_users", 120}, |
175 | | - }}, |
176 | | - }); |
177 | | - std::cout << recommendedPriorityJson.dump(2) << std::endl; |
178 | | - |
179 | | - std::cout << "\n--- Recommend incident priority as typed enum ---" << std::endl; |
180 | | - Priority recommendedPriority = adapter.invoke({ |
181 | | - {"name", "recommendIncidentPriority"}, |
182 | | - {"args", { |
183 | | - {"requested_priority", "normal"}, |
184 | | - {"customer_blocked", true}, |
185 | | - {"production_impact", true}, |
186 | | - {"affected_users", 320}, |
187 | | - }}, |
188 | | - }); |
189 | | - std::cout << func_registry::enum_name(recommendedPriority) << std::endl; |
190 | | - |
191 | | - //std::cout << "\n--- Tool summaries JSON ---" << std::endl; |
192 | | - //std::cout << adapter.getAllToolSummariesJson().dump(2) << std::endl; |
| 82 | + std::cout << "matches: " << matches_json.size() << std::endl; |
| 83 | + if (!matches_json.empty()) |
| 84 | + { |
| 85 | + std::cout << "first match: " << matches_json.front().dump() << std::endl; |
| 86 | + } |
193 | 87 |
|
194 | 88 | std::cout << "\n--- Tool schemas JSON ---" << std::endl; |
195 | 89 | std::cout << adapter.getAllToolSchemasJson().dump(2) << std::endl; |
|
0 commit comments