Skip to content

Commit bb49682

Browse files
authored
Merge: sync/upstream-d0eb531e — full v0.1.49 parity
feat: upstream parity sync (d0eb531e) — types, handlers, fluent setters
2 parents 2afbf06 + 4cf7c40 commit bb49682

20 files changed

Lines changed: 7090 additions & 99 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ add_library(copilot_sdk_cpp
6262
include/copilot/process.hpp
6363
include/copilot/client.hpp
6464
include/copilot/session.hpp
65+
include/copilot/rpc_methods.hpp
66+
include/copilot/rpc_types.hpp
6567
# Sources
6668
src/types.cpp
6769
src/events.cpp

examples/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,13 @@ set_target_properties(user_input PROPERTIES FOLDER "Examples")
8484
add_executable(reasoning_effort reasoning_effort.cpp)
8585
target_link_libraries(reasoning_effort PRIVATE copilot_sdk_cpp)
8686
set_target_properties(reasoning_effort PROPERTIES FOLDER "Examples")
87+
88+
# Instruction directories example (v0.1.49 - PR #1190)
89+
add_executable(instruction_directories instruction_directories.cpp)
90+
target_link_libraries(instruction_directories PRIVATE copilot_sdk_cpp)
91+
set_target_properties(instruction_directories PROPERTIES FOLDER "Examples")
92+
93+
# Remote session example (v0.1.49 - PR #1295, Mission Control integration)
94+
add_executable(remote_session remote_session.cpp)
95+
target_link_libraries(remote_session PRIVATE copilot_sdk_cpp)
96+
set_target_properties(remote_session PROPERTIES FOLDER "Examples")
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) 2025 Elias Bachaalany
2+
// SPDX-License-Identifier: MIT
3+
4+
/// @file instruction_directories.cpp
5+
/// @brief Compile-only demo for the v0.1.49 `instructionDirectories` field on
6+
/// `SessionConfig` and `ResumeSessionConfig`.
7+
///
8+
/// Builds a `SessionConfig` populated with per-session instruction directories
9+
/// and dumps the resulting `session.create` request payload that the SDK would
10+
/// send to the Copilot CLI. No network or CLI is required: this example
11+
/// exercises the public `build_session_create_request` helper so the API is
12+
/// exercised at build time and the JSON envelope is human-inspectable.
13+
///
14+
/// Background: instructionDirectories (upstream nodejs PR #1190) lets a host
15+
/// application supplement the global instruction set with additional
16+
/// directories scoped to a single session — useful for ephemeral or
17+
/// workspace-specific guidance without mutating the user's CLI config.
18+
19+
#include <copilot/copilot.hpp>
20+
21+
#include <iostream>
22+
23+
int main()
24+
{
25+
using namespace copilot;
26+
27+
SessionConfig cfg;
28+
cfg.client_name = "instruction-dirs-demo";
29+
cfg.instruction_directories = std::vector<std::string>{
30+
"/etc/copilot/instructions",
31+
"./workspace/.copilot/instructions",
32+
};
33+
cfg.enable_config_discovery = true;
34+
cfg.streaming = false;
35+
36+
json request = build_session_create_request(cfg);
37+
38+
std::cout << "session.create request payload:\n";
39+
std::cout << request.dump(2) << "\n";
40+
41+
// Sanity-check the fields actually round-tripped through the builder.
42+
if (!request.contains("instructionDirectories") ||
43+
!request["instructionDirectories"].is_array() ||
44+
request["instructionDirectories"].size() != 2)
45+
{
46+
std::cerr << "instructionDirectories field missing or malformed\n";
47+
return 1;
48+
}
49+
if (request.value("clientName", std::string{}) != "instruction-dirs-demo")
50+
{
51+
std::cerr << "clientName missing\n";
52+
return 1;
53+
}
54+
return 0;
55+
}

examples/remote_session.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright (c) 2025 Elias Bachaalany
2+
// SPDX-License-Identifier: MIT
3+
4+
/// @file remote_session.cpp
5+
/// @brief Compile-only demo for the v0.1.49 `remoteSession` field on
6+
/// `SessionConfig` (Mission Control integration, upstream nodejs PR #1295).
7+
///
8+
/// Demonstrates the three `RemoteSessionMode` values and shows how the
9+
/// resulting `session.create` payload differs. No live Copilot CLI is
10+
/// required: the example uses the public `build_session_create_request`
11+
/// helper to render each request payload for inspection.
12+
///
13+
/// Remote-session modes (matches upstream nodejs):
14+
/// * `Off` — explicitly disable remote steering for this session.
15+
/// * `Export` — export this session so it shows up in Mission Control
16+
/// without accepting remote commands.
17+
/// * `On` — enable full remote steering from GitHub web / mobile.
18+
19+
#include <copilot/copilot.hpp>
20+
21+
#include <iostream>
22+
#include <string>
23+
#include <vector>
24+
25+
namespace
26+
{
27+
28+
const char* mode_name(copilot::RemoteSessionMode mode)
29+
{
30+
using copilot::RemoteSessionMode;
31+
switch (mode)
32+
{
33+
case RemoteSessionMode::Off: return "off";
34+
case RemoteSessionMode::Export: return "export";
35+
case RemoteSessionMode::On: return "on";
36+
}
37+
return "?";
38+
}
39+
40+
} // namespace
41+
42+
int main()
43+
{
44+
using namespace copilot;
45+
46+
const std::vector<RemoteSessionMode> modes = {
47+
RemoteSessionMode::Off,
48+
RemoteSessionMode::Export,
49+
RemoteSessionMode::On,
50+
};
51+
52+
for (auto mode : modes)
53+
{
54+
SessionConfig cfg;
55+
cfg.client_name = "remote-session-demo";
56+
cfg.remote_session = mode;
57+
cfg.enable_session_telemetry = (mode != RemoteSessionMode::Off);
58+
59+
json request = build_session_create_request(cfg);
60+
61+
std::cout << "[mode=" << mode_name(mode) << "] session.create payload:\n";
62+
std::cout << request.dump(2) << "\n\n";
63+
64+
if (!request.contains("remoteSession"))
65+
{
66+
std::cerr << "remoteSession field missing for mode " << mode_name(mode) << "\n";
67+
return 1;
68+
}
69+
}
70+
71+
return 0;
72+
}

include/copilot/client.hpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ json build_session_create_request(const SessionConfig& config);
4646
/// @return JSON object ready to send to server
4747
json build_session_resume_request(const std::string& session_id, const ResumeSessionConfig& config);
4848

49+
/// Build the CLI argument vector that {@link Client} will pass to the spawned
50+
/// Copilot CLI process, given a fully-populated {@link ClientOptions}.
51+
/// Exposed for conformance unit testing of process-launch behavior. Mirrors
52+
/// what `start_cli_server()` emits before command resolution (i.e. no Node /
53+
/// `cmd /c` wrapping is applied).
54+
/// @param options Client options
55+
/// @return Argument list (does not include the executable itself)
56+
std::vector<std::string> build_cli_command_args(const ClientOptions& options);
57+
58+
/// Build the environment-variable map that {@link Client} will use when
59+
/// spawning the Copilot CLI process. The returned map reflects the SDK's
60+
/// additions and removals (COPILOT_HOME, COPILOT_CONNECTION_TOKEN,
61+
/// COPILOT_SDK_AUTH_TOKEN, NODE_DEBUG erase) layered on top of the explicit
62+
/// `options.environment`. Exposed for conformance unit testing.
63+
/// @param options Client options
64+
/// @return Environment map ready for ProcessOptions::environment
65+
std::map<std::string, std::string> build_cli_environment(const ClientOptions& options);
66+
4967
// =============================================================================
5068
// CopilotClient - Main client class
5169
// =============================================================================
@@ -126,6 +144,17 @@ class Client
126144
/// @return Future that resolves to list of session metadata
127145
std::future<std::vector<SessionMetadata>> list_sessions();
128146

147+
/// List sessions matching a filter (matches upstream nodejs SDK).
148+
/// @param filter Filter criteria (cwd / git_root / repository / branch)
149+
/// @return Future that resolves to list of matching session metadata
150+
std::future<std::vector<SessionMetadata>> list_sessions(SessionListFilter filter);
151+
152+
/// Get metadata for a specific session by ID (O(1) lookup).
153+
/// @param session_id ID of the session
154+
/// @return Future that resolves to metadata, or nullopt if not found
155+
std::future<std::optional<SessionMetadata>>
156+
get_session_metadata(const std::string& session_id);
157+
129158
/// Delete a session
130159
/// @param session_id ID of the session to delete
131160
/// @return Future that completes when deleted
@@ -157,6 +186,18 @@ class Client
157186
/// @throws Error if not authenticated
158187
std::future<std::vector<ModelInfo>> list_models();
159188

189+
/// Provide a custom handler for listing available models (BYOK mode).
190+
/// When set, Client::list_models() calls this handler instead of querying
191+
/// the CLI server. Results are still cached after the first successful call;
192+
/// pass nullptr to revert to default RPC-based behavior. Matches upstream
193+
/// nodejs CopilotClientOptions.onListModels.
194+
using ListModelsHandler = std::function<std::vector<ModelInfo>()>;
195+
void set_on_list_models(ListModelsHandler handler);
196+
197+
/// Get the negotiated protocol version (set after successful start()).
198+
/// Returns std::nullopt before connection is established.
199+
std::optional<int> negotiated_protocol_version() const;
200+
160201
// =========================================================================
161202
// Lifecycle Events
162203
// =========================================================================
@@ -217,6 +258,10 @@ class Client
217258
/// Handle incoming user input requests
218259
json handle_user_input_request(const json& params);
219260

261+
json handle_elicitation_request(const json& params);
262+
json handle_exit_plan_mode_request(const json& params);
263+
json handle_auto_mode_switch_request(const json& params);
264+
220265
/// Handle incoming hook invocations
221266
json handle_hooks_invoke(const json& params);
222267

@@ -241,9 +286,17 @@ class Client
241286
mutable std::mutex models_cache_mutex_;
242287
std::optional<std::vector<ModelInfo>> models_cache_;
243288

289+
// BYOK: optional custom models handler (when set, takes precedence over RPC).
290+
mutable std::mutex on_list_models_mutex_;
291+
ListModelsHandler on_list_models_;
292+
244293
// Lifecycle handlers
245294
mutable std::mutex lifecycle_mutex_;
246295
std::vector<LifecycleHandler> lifecycle_handlers_;
296+
297+
// Protocol version negotiation result (set after verify_protocol_version()).
298+
mutable std::mutex protocol_version_mutex_;
299+
std::optional<int> negotiated_protocol_version_;
247300
};
248301

249302
} // namespace copilot

include/copilot/copilot.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <copilot/events.hpp>
1414
#include <copilot/jsonrpc.hpp>
1515
#include <copilot/process.hpp>
16+
#include <copilot/rpc_methods.hpp>
17+
#include <copilot/rpc_types.hpp>
1618
#include <copilot/session.hpp>
1719
#include <copilot/tool_builder.hpp>
1820
#include <copilot/transport.hpp>

0 commit comments

Comments
 (0)