forked from 0xeb/copilot-sdk-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresume_with_tools.cpp
More file actions
191 lines (165 loc) · 6.4 KB
/
Copy pathresume_with_tools.cpp
File metadata and controls
191 lines (165 loc) · 6.4 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
// Copyright (c) 2025 Elias Bachaalany
// SPDX-License-Identifier: MIT
/// @file resume_with_tools.cpp
/// @brief Example demonstrating resuming a session with custom tools
///
/// This example shows how to:
/// 1. Create an initial session
/// 2. Save the session ID
/// 3. Resume the session later with new custom tools
/// 4. Use the tools in the resumed session
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <copilot/copilot.hpp>
#include <iostream>
#include <mutex>
#include <string>
/// Custom tool handler - returns secret values
copilot::ToolResultObject secret_handler(const copilot::ToolInvocation& invocation)
{
copilot::ToolResultObject result;
try
{
auto& args = invocation.arguments.value();
std::string key = args["key"].get<std::string>();
// Simulated secret store
std::map<std::string, std::string> secrets = {
{"API_KEY", "example-api-key"},
{"DB_PASSWORD", "example-db-password"},
{"ENCRYPTION_KEY", "example-encryption-key"}
};
auto it = secrets.find(key);
if (it != secrets.end())
{
result.text_result_for_llm = "Secret value for '" + key + "': " + it->second;
result.result_type = copilot::ToolResultType::Success;
}
else
{
result.text_result_for_llm = "No secret found for key: " + key;
result.result_type = copilot::ToolResultType::Failure;
result.error = "Key not found";
}
}
catch (const std::exception& e)
{
result.text_result_for_llm = "Error retrieving secret";
result.result_type = copilot::ToolResultType::Failure;
result.error = e.what();
}
return result;
}
int main()
{
try
{
// Create client
copilot::ClientOptions options;
options.log_level = copilot::LogLevel::Info;
copilot::Client client(options);
std::cout << "=== Phase 1: Create Initial Session ===\n\n";
client.start().get();
auto session1 = client.create_session().get();
std::string session_id = session1->session_id();
std::cout << "Created session: " << session_id << "\n";
// Synchronization
std::mutex mtx;
std::condition_variable cv;
std::atomic<bool> idle{false};
auto sub1 = session1->on(
[&](const copilot::SessionEvent& event)
{
if (event.type == copilot::SessionEventType::AssistantMessage)
{
auto& data = event.as<copilot::AssistantMessageData>();
std::cout << "Assistant: " << data.content << "\n";
}
else if (event.type == copilot::SessionEventType::SessionIdle)
{
idle = true;
cv.notify_one();
}
}
);
// Send initial message (no tools available yet)
copilot::MessageOptions opts;
opts.prompt = "Hello! Remember that my favorite color is blue.";
session1->send(opts).get();
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait_for(lock, std::chrono::seconds(30), [&]() { return idle.load(); });
}
std::cout << "\n=== Phase 2: Stop and Resume with Tools ===\n\n";
// Stop the client (but don't destroy the session)
client.stop().get();
// Define our custom tool
copilot::Tool secret_tool;
secret_tool.name = "get_secret";
secret_tool.description = "Retrieve a secret value from the secure store. "
"Available keys: API_KEY, DB_PASSWORD, ENCRYPTION_KEY";
secret_tool.parameters_schema = copilot::json{
{"type", "object"},
{"properties",
{{"key",
{{"type", "string"},
{"description", "The key to look up (e.g., 'API_KEY', 'DB_PASSWORD')"}}}}},
{"required", {"key"}}
};
secret_tool.handler = secret_handler;
// Restart client and resume session WITH the tool
client.start().get();
copilot::ResumeSessionConfig resume_config;
resume_config.tools = {secret_tool};
auto session2 = client.resume_session(session_id, resume_config).get();
std::cout << "Resumed session: " << session2->session_id() << "\n";
std::cout << "Custom tool 'get_secret' is now available!\n\n";
// Reset for next message
idle = false;
auto sub2 = session2->on(
[&](const copilot::SessionEvent& event)
{
if (event.type == copilot::SessionEventType::AssistantMessage)
{
auto& data = event.as<copilot::AssistantMessageData>();
std::cout << "Assistant: " << data.content << "\n";
}
else if (event.type == copilot::SessionEventType::ToolExecutionStart)
{
auto& data = event.as<copilot::ToolExecutionStartData>();
std::cout << "\n[Tool: " << data.tool_name << "] Starting...\n";
}
else if (event.type == copilot::SessionEventType::ToolExecutionComplete)
{
auto& data = event.as<copilot::ToolExecutionCompleteData>();
std::cout << "[Tool: " << data.tool_call_id << "] Complete\n";
if (data.result.has_value())
std::cout << " Result: " << data.result->content << "\n\n";
}
else if (event.type == copilot::SessionEventType::SessionIdle)
{
idle = true;
cv.notify_one();
}
}
);
// Ask about both the remembered info AND use the new tool
opts.prompt = "First, what's my favorite color? Then, use the get_secret tool to "
"retrieve the API_KEY for me.";
session2->send(opts).get();
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait_for(lock, std::chrono::seconds(60), [&]() { return idle.load(); });
}
std::cout << "\n=== Cleanup ===\n";
session2->destroy().get();
client.force_stop();
std::cout << "Done!\n";
}
catch (const std::exception& e)
{
std::cerr << "Error: " << e.what() << "\n";
return 1;
}
return 0;
}