forked from 0xeb/copilot-sdk-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompaction_events.cpp
More file actions
179 lines (155 loc) · 6.85 KB
/
Copy pathcompaction_events.cpp
File metadata and controls
179 lines (155 loc) · 6.85 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
// Copyright (c) 2025 Elias Bachaalany
// SPDX-License-Identifier: MIT
/// @file compaction_events.cpp
/// @brief Example demonstrating session compaction and usage monitoring
///
/// This example shows how to:
/// 1. Configure infinite sessions with a low compaction threshold
/// 2. Subscribe to SessionCompactionStart, SessionCompactionComplete events
/// 3. Monitor context usage via SessionUsageInfo events
/// 4. Track compaction progress in real-time
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <copilot/copilot.hpp>
#include <iostream>
#include <mutex>
#include <string>
int main()
{
try
{
copilot::ClientOptions options;
options.log_level = copilot::LogLevel::Info;
copilot::Client client(options);
std::cout << "=== Compaction Events Example ===\n\n";
std::cout << "This example monitors context compaction in real-time.\n";
std::cout << "When the context window fills up, the session automatically\n";
std::cout << "compacts (summarizes) older messages to free up space.\n\n";
client.start().get();
// Configure session with a low compaction threshold to trigger compaction sooner
copilot::SessionConfig config;
config.streaming = true;
copilot::InfiniteSessionConfig infinite_config;
infinite_config.enabled = true;
infinite_config.background_compaction_threshold = 0.10; // Trigger at 10% usage
config.infinite_sessions = infinite_config;
auto session = client.create_session(config).get();
std::cout << "Session created with low compaction threshold (10%)\n";
std::cout << "Compaction events will appear when context usage exceeds the threshold.\n\n";
// Synchronization
std::mutex mtx;
std::condition_variable cv;
std::atomic<bool> idle{false};
// Subscribe to all events, highlighting compaction-related ones
auto subscription = session->on(
[&](const copilot::SessionEvent& event)
{
if (auto* delta = event.try_as<copilot::AssistantMessageDeltaData>())
{
std::cout << delta->delta_content << std::flush;
}
else if (auto* msg = event.try_as<copilot::AssistantMessageData>())
{
// Final message in non-streaming mode
if (!msg->content.empty())
std::cout << "\nAssistant: " << msg->content << "\n";
}
else if (auto* usage = event.try_as<copilot::SessionUsageInfoData>())
{
// Context usage statistics
double pct = (usage->token_limit > 0)
? (usage->current_tokens / usage->token_limit * 100.0)
: 0.0;
std::cout << "\n[Usage] Tokens: "
<< static_cast<int>(usage->current_tokens)
<< "/" << static_cast<int>(usage->token_limit)
<< " (" << static_cast<int>(pct) << "%)"
<< " Messages: " << static_cast<int>(usage->messages_length)
<< "\n";
}
else if (event.try_as<copilot::SessionCompactionStartData>())
{
std::cout << "\n*** COMPACTION STARTED ***\n"
<< " Context is being summarized to free up space...\n";
}
else if (auto* complete = event.try_as<copilot::SessionCompactionCompleteData>())
{
std::cout << "\n*** COMPACTION COMPLETE ***\n";
std::cout << " Success: " << (complete->success ? "yes" : "no") << "\n";
if (complete->error)
std::cout << " Error: " << *complete->error << "\n";
if (complete->pre_compaction_tokens && complete->post_compaction_tokens)
{
std::cout << " Tokens: "
<< static_cast<int>(*complete->pre_compaction_tokens)
<< " -> "
<< static_cast<int>(*complete->post_compaction_tokens)
<< "\n";
}
if (complete->pre_compaction_messages_length
&& complete->post_compaction_messages_length)
{
std::cout << " Messages: "
<< static_cast<int>(*complete->pre_compaction_messages_length)
<< " -> "
<< static_cast<int>(*complete->post_compaction_messages_length)
<< "\n";
}
if (complete->compaction_tokens_used)
{
auto& tokens = *complete->compaction_tokens_used;
std::cout << " Compaction cost: in="
<< static_cast<int>(tokens.input)
<< " out=" << static_cast<int>(tokens.output)
<< " cached=" << static_cast<int>(tokens.cached_input)
<< "\n";
}
}
else if (auto* error = event.try_as<copilot::SessionErrorData>())
{
std::cerr << "\nError: " << error->message << "\n";
}
else if (event.type == copilot::SessionEventType::SessionIdle)
{
std::lock_guard<std::mutex> lock(mtx);
idle = true;
cv.notify_one();
}
}
);
// Interactive chat
std::cout << "Send multiple messages to build up context and trigger compaction.\n";
std::cout << "Type 'quit' to exit.\n\n> ";
std::string line;
while (std::getline(std::cin, line))
{
if (line == "quit" || line == "exit")
break;
if (line.empty())
{
std::cout << "> ";
continue;
}
idle = false;
copilot::MessageOptions msg_opts;
msg_opts.prompt = line;
session->send(msg_opts).get();
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [&idle]() { return idle.load(); });
}
std::cout << "\n> ";
}
// Cleanup
std::cout << "\nCleaning up...\n";
session->destroy().get();
client.stop().get();
return 0;
}
catch (const std::exception& e)
{
std::cerr << "Error: " << e.what() << "\n";
return 1;
}
}