-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathrequest_handler.hpp
More file actions
142 lines (120 loc) · 3.78 KB
/
Copy pathrequest_handler.hpp
File metadata and controls
142 lines (120 loc) · 3.78 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
// Copyright (c) 2025 Elias Bachaalany
// SPDX-License-Identifier: MIT
#pragma once
#include <copilot/types.hpp>
#include <atomic>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
namespace copilot
{
struct CopilotRequestContext
{
std::string request_id;
std::optional<std::string> session_id;
std::optional<std::string> agent_id;
std::optional<std::string> parent_agent_id;
std::optional<std::string> interaction_type;
std::string transport = "http";
std::string url;
std::map<std::string, std::vector<std::string>> headers;
std::shared_ptr<std::atomic_bool> cancelled;
bool is_cancelled() const noexcept { return cancelled && cancelled->load(); }
};
struct CopilotHttpRequest
{
std::string method;
std::string url;
std::map<std::string, std::vector<std::string>> headers;
std::string body;
};
struct CopilotHttpResponse
{
int status = 200;
std::optional<std::string> status_text;
std::map<std::string, std::vector<std::string>> headers;
std::vector<std::string> chunks;
bool binary = false;
};
struct CopilotWebSocketCloseStatus
{
std::optional<std::string> description;
std::optional<std::string> error_code;
std::optional<std::string> error;
};
class CopilotWebSocketHandler
{
public:
using ResponseSender =
std::function<void(const std::string&, bool, bool, const std::optional<std::string>&)>;
virtual ~CopilotWebSocketHandler() = default;
virtual void open(const CopilotRequestContext&) {}
virtual void send_request_message(const std::string& data, bool binary) = 0;
virtual void close(const CopilotWebSocketCloseStatus& status)
{
if (status.error)
fail_response(*status.error);
else
complete_response();
}
void send_response_message(const std::string& data, bool binary = false)
{
if (!response_sender_)
throw std::runtime_error("WebSocket response bridge is not attached");
response_sender_(data, binary, false, std::nullopt);
}
void complete_response()
{
if (response_sender_)
response_sender_("", false, true, std::nullopt);
}
void fail_response(const std::string& message)
{
if (response_sender_)
response_sender_("", false, true, message);
}
void bind_response_sender(ResponseSender sender)
{
response_sender_ = std::move(sender);
}
private:
ResponseSender response_sender_;
};
class CopilotRequestHandler
{
public:
virtual ~CopilotRequestHandler() = default;
virtual CopilotHttpResponse send_request(
const CopilotHttpRequest& request,
const CopilotRequestContext& context) = 0;
virtual std::shared_ptr<CopilotWebSocketHandler> open_websocket(
const CopilotRequestContext&)
{
return {};
}
};
/// Adapts official httpRequestStart/httpRequestChunk callbacks to high-level handlers.
class CopilotRequestHandlerBridge
: public std::enable_shared_from_this<CopilotRequestHandlerBridge>
{
public:
using SendRpc = std::function<void(const std::string&, const json&)>;
CopilotRequestHandlerBridge(
std::shared_ptr<CopilotRequestHandler> handler,
SendRpc send_rpc);
~CopilotRequestHandlerBridge();
json handle(const std::string& method, const json& params);
void cancel_all();
std::size_t pending_count() const;
private:
struct Exchange;
void complete_http(const std::shared_ptr<Exchange>& exchange);
void fail(const std::shared_ptr<Exchange>& exchange, const std::string& message);
std::shared_ptr<CopilotRequestHandler> handler_;
SendRpc send_rpc_;
mutable std::mutex mutex_;
std::unordered_map<std::string, std::shared_ptr<Exchange>> pending_;
};
} // namespace copilot