copilot-sdk-supercharged 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/copilot/client.rb +51 -1
- data/lib/copilot/json_rpc_client.rb +4 -2
- data/lib/copilot/session.rb +56 -2
- data/lib/copilot/types.rb +61 -0
- data/lib/copilot/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d80c4e262952967db3b9ed58e8899587afa12b158074ab57d7f475af58ccd68
|
|
4
|
+
data.tar.gz: 302abe246cec1dd679f2036f49407a10b01756c421634a3c97f6fb1105743606
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e7aa7ee115dfe39db890cffa6d1d4535caf0b6926cde80b0346b5ce3e8e5a9ca24b688af91c49b223aa5fbdb1e95733052f142b4bcef42d18d69101ccae1fde5
|
|
7
|
+
data.tar.gz: f51f8baeb7ede5fb5db28855db3e94f397379e78d75e9f6aa871a6c970733b8bfd80ab5d3013acc21510add30f29be55e7db79cb6251061355470b220e95655a
|
data/lib/copilot/client.rb
CHANGED
|
@@ -55,7 +55,8 @@ module Copilot
|
|
|
55
55
|
auto_restart: true,
|
|
56
56
|
env: nil,
|
|
57
57
|
github_token: nil,
|
|
58
|
-
use_logged_in_user: nil
|
|
58
|
+
use_logged_in_user: nil,
|
|
59
|
+
on_get_trace_context: nil
|
|
59
60
|
)
|
|
60
61
|
# Validate mutually exclusive options
|
|
61
62
|
if cli_url && (use_stdio == false || cli_path)
|
|
@@ -95,6 +96,7 @@ module Copilot
|
|
|
95
96
|
env: env,
|
|
96
97
|
github_token: github_token,
|
|
97
98
|
use_logged_in_user: use_logged_in_user,
|
|
99
|
+
on_get_trace_context: on_get_trace_context,
|
|
98
100
|
)
|
|
99
101
|
|
|
100
102
|
@process = nil
|
|
@@ -281,6 +283,10 @@ module Copilot
|
|
|
281
283
|
session._register_permission_handler(config[:on_permission_request]) if config[:on_permission_request]
|
|
282
284
|
session._register_user_input_handler(config[:on_user_input_request]) if config[:on_user_input_request]
|
|
283
285
|
session._register_hooks(config[:hooks]) if config[:hooks]
|
|
286
|
+
session._register_exit_plan_mode_handler(config[:on_exit_plan_mode]) if config[:on_exit_plan_mode]
|
|
287
|
+
if @options.on_get_trace_context
|
|
288
|
+
session._register_trace_context_provider(@options.on_get_trace_context)
|
|
289
|
+
end
|
|
284
290
|
|
|
285
291
|
@sessions_lock.synchronize { @sessions[session_id] = session }
|
|
286
292
|
session
|
|
@@ -305,6 +311,10 @@ module Copilot
|
|
|
305
311
|
session._register_permission_handler(config[:on_permission_request]) if config[:on_permission_request]
|
|
306
312
|
session._register_user_input_handler(config[:on_user_input_request]) if config[:on_user_input_request]
|
|
307
313
|
session._register_hooks(config[:hooks]) if config[:hooks]
|
|
314
|
+
session._register_exit_plan_mode_handler(config[:on_exit_plan_mode]) if config[:on_exit_plan_mode]
|
|
315
|
+
if @options.on_get_trace_context
|
|
316
|
+
session._register_trace_context_provider(@options.on_get_trace_context)
|
|
317
|
+
end
|
|
308
318
|
|
|
309
319
|
@sessions_lock.synchronize { @sessions[resumed_id] = session }
|
|
310
320
|
session
|
|
@@ -633,6 +643,10 @@ module Copilot
|
|
|
633
643
|
@rpc_client.on_request("hooks.invoke") do |params|
|
|
634
644
|
handle_hooks_invoke(params)
|
|
635
645
|
end
|
|
646
|
+
|
|
647
|
+
@rpc_client.on_request("exitPlanMode.request") do |params|
|
|
648
|
+
handle_exit_plan_mode_request(params)
|
|
649
|
+
end
|
|
636
650
|
end
|
|
637
651
|
|
|
638
652
|
def verify_protocol_version
|
|
@@ -769,6 +783,21 @@ module Copilot
|
|
|
769
783
|
{ output: output }
|
|
770
784
|
end
|
|
771
785
|
|
|
786
|
+
def handle_exit_plan_mode_request(params)
|
|
787
|
+
session_id = params["sessionId"]
|
|
788
|
+
raise "Invalid exit plan mode request payload" unless session_id
|
|
789
|
+
|
|
790
|
+
session = @sessions_lock.synchronize { @sessions[session_id] }
|
|
791
|
+
raise "Session not found: #{session_id}" unless session
|
|
792
|
+
|
|
793
|
+
begin
|
|
794
|
+
result = session._handle_exit_plan_mode_request(params)
|
|
795
|
+
result
|
|
796
|
+
rescue StandardError
|
|
797
|
+
{ approved: true }
|
|
798
|
+
end
|
|
799
|
+
end
|
|
800
|
+
|
|
772
801
|
# ---- Payload builders ----
|
|
773
802
|
|
|
774
803
|
def build_create_session_payload(config)
|
|
@@ -789,6 +818,7 @@ module Copilot
|
|
|
789
818
|
payload[:requestPermission] = true if config[:on_permission_request]
|
|
790
819
|
payload[:requestUserInput] = true if config[:on_user_input_request]
|
|
791
820
|
payload[:hooks] = true if config[:hooks]&.respond_to?(:any_handler?) && config[:hooks].any_handler?
|
|
821
|
+
payload[:requestExitPlanMode] = true if config[:on_exit_plan_mode]
|
|
792
822
|
payload[:workingDirectory] = config[:working_directory] if config[:working_directory]
|
|
793
823
|
payload[:streaming] = config[:streaming] unless config[:streaming].nil?
|
|
794
824
|
|
|
@@ -796,6 +826,9 @@ module Copilot
|
|
|
796
826
|
payload[:provider] = config[:provider].respond_to?(:to_wire) ? config[:provider].to_wire : config[:provider]
|
|
797
827
|
end
|
|
798
828
|
|
|
829
|
+
token = config[:auth_token] || config[:github_token] || config[:git_hub_token]
|
|
830
|
+
payload[:gitHubToken] = token if token
|
|
831
|
+
|
|
799
832
|
payload[:mcpServers] = config[:mcp_servers] if config[:mcp_servers]
|
|
800
833
|
|
|
801
834
|
if config[:custom_agents]
|
|
@@ -812,6 +845,23 @@ module Copilot
|
|
|
812
845
|
payload[:infiniteSessions] = is_cfg.respond_to?(:to_wire) ? is_cfg.to_wire : is_cfg
|
|
813
846
|
end
|
|
814
847
|
|
|
848
|
+
# --- Upstream-sync session options (parity with @github/copilot-sdk) ---
|
|
849
|
+
payload[:enableCitations] = config[:enable_citations] unless config[:enable_citations].nil?
|
|
850
|
+
payload[:excludedBuiltinAgents] = config[:excluded_builtin_agents] if config[:excluded_builtin_agents]
|
|
851
|
+
if config[:session_limits]
|
|
852
|
+
sl = config[:session_limits]
|
|
853
|
+
payload[:sessionLimits] = sl.respond_to?(:to_wire) ? sl.to_wire : sl
|
|
854
|
+
end
|
|
855
|
+
if config[:memory]
|
|
856
|
+
mem = config[:memory]
|
|
857
|
+
payload[:memory] = mem.respond_to?(:to_wire) ? mem.to_wire : mem
|
|
858
|
+
end
|
|
859
|
+
payload[:otlpProtocol] = config[:otlp_protocol] if config[:otlp_protocol]
|
|
860
|
+
payload[:enableWebSocketResponses] = config[:enable_web_socket_responses] unless config[:enable_web_socket_responses].nil?
|
|
861
|
+
payload[:expAssignments] = config[:exp_assignments] if config[:exp_assignments]
|
|
862
|
+
# MCP OAuth host token handler: signal to the runtime that a handler is registered.
|
|
863
|
+
payload[:mcpAuthHandler] = true if config[:on_mcp_auth_request]
|
|
864
|
+
|
|
815
865
|
payload
|
|
816
866
|
end
|
|
817
867
|
|
|
@@ -79,7 +79,8 @@ module Copilot
|
|
|
79
79
|
# @return [Object] the +result+ from the JSON-RPC response
|
|
80
80
|
# @raise [JsonRpcError] if the server returns an error
|
|
81
81
|
# @raise [Timeout::Error] if the request times out
|
|
82
|
-
def request(method, params = nil, timeout: 30)
|
|
82
|
+
def request(method, params = nil, timeout: 30, **kwargs)
|
|
83
|
+
params = kwargs if params.nil? && !kwargs.empty?
|
|
83
84
|
request_id = SecureRandom.uuid
|
|
84
85
|
queue = Queue.new
|
|
85
86
|
|
|
@@ -126,7 +127,8 @@ module Copilot
|
|
|
126
127
|
#
|
|
127
128
|
# @param method [String] the RPC method name
|
|
128
129
|
# @param params [Hash, nil] optional parameters
|
|
129
|
-
def notify(method, params = nil)
|
|
130
|
+
def notify(method, params = nil, **kwargs)
|
|
131
|
+
params = kwargs if params.nil? && !kwargs.empty?
|
|
130
132
|
send_message({
|
|
131
133
|
jsonrpc: "2.0",
|
|
132
134
|
method: method,
|
data/lib/copilot/session.rb
CHANGED
|
@@ -53,6 +53,11 @@ module Copilot
|
|
|
53
53
|
|
|
54
54
|
@hooks = nil
|
|
55
55
|
@hooks_lock = Mutex.new
|
|
56
|
+
|
|
57
|
+
@exit_plan_mode_handler = nil
|
|
58
|
+
@exit_plan_mode_handler_lock = Mutex.new
|
|
59
|
+
|
|
60
|
+
@trace_context_provider = nil
|
|
56
61
|
end
|
|
57
62
|
|
|
58
63
|
# Send a message to this session.
|
|
@@ -63,12 +68,31 @@ module Copilot
|
|
|
63
68
|
# @param response_format [String, nil] desired response format ("text", "image", "json_object")
|
|
64
69
|
# @param image_options [ImageOptions, nil] options for image generation
|
|
65
70
|
# @return [String] the message ID
|
|
66
|
-
def send(prompt:, attachments: nil, mode: nil, response_format: nil, image_options: nil)
|
|
71
|
+
def send(prompt:, attachments: nil, mode: nil, agent_mode: nil, display_prompt: nil, request_headers: nil, response_format: nil, image_options: nil)
|
|
67
72
|
payload = { sessionId: @session_id, prompt: prompt }
|
|
68
73
|
payload[:attachments] = attachments if attachments
|
|
69
74
|
payload[:mode] = mode if mode
|
|
75
|
+
payload[:agentMode] = agent_mode if agent_mode
|
|
76
|
+
payload[:displayPrompt] = display_prompt if display_prompt
|
|
77
|
+
payload[:requestHeaders] = request_headers if request_headers
|
|
70
78
|
payload[:responseFormat] = response_format if response_format
|
|
71
79
|
payload[:imageOptions] = image_options.to_h if image_options
|
|
80
|
+
|
|
81
|
+
# Inject trace context if provider is available
|
|
82
|
+
if @trace_context_provider
|
|
83
|
+
begin
|
|
84
|
+
tc = @trace_context_provider.call
|
|
85
|
+
if tc
|
|
86
|
+
tp = tc.respond_to?(:traceparent) ? tc.traceparent : tc[:traceparent]
|
|
87
|
+
ts = tc.respond_to?(:tracestate) ? tc.tracestate : tc[:tracestate]
|
|
88
|
+
payload[:traceparent] = tp if tp
|
|
89
|
+
payload[:tracestate] = ts if ts
|
|
90
|
+
end
|
|
91
|
+
rescue StandardError
|
|
92
|
+
# ignore trace context errors
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
72
96
|
response = @rpc_client.request("session.send", payload)
|
|
73
97
|
response["messageId"]
|
|
74
98
|
end
|
|
@@ -87,7 +111,7 @@ module Copilot
|
|
|
87
111
|
# @return [SessionEvent, nil] the final assistant.message event, or nil
|
|
88
112
|
# @raise [Timeout::Error] if the timeout expires before session.idle
|
|
89
113
|
# @raise [RuntimeError] if the session emits a session.error event
|
|
90
|
-
def send_and_wait(prompt:, attachments: nil, mode: nil, response_format: nil, image_options: nil, timeout: 60)
|
|
114
|
+
def send_and_wait(prompt:, attachments: nil, mode: nil, agent_mode: nil, display_prompt: nil, request_headers: nil, response_format: nil, image_options: nil, timeout: 60)
|
|
91
115
|
idle_mutex = Mutex.new
|
|
92
116
|
idle_cv = ConditionVariable.new
|
|
93
117
|
idle_fired = false
|
|
@@ -118,6 +142,8 @@ module Copilot
|
|
|
118
142
|
|
|
119
143
|
begin
|
|
120
144
|
self.send(prompt: prompt, attachments: attachments, mode: mode,
|
|
145
|
+
agent_mode: agent_mode, display_prompt: display_prompt,
|
|
146
|
+
request_headers: request_headers,
|
|
121
147
|
response_format: response_format, image_options: image_options)
|
|
122
148
|
|
|
123
149
|
idle_mutex.synchronize do
|
|
@@ -202,6 +228,8 @@ module Copilot
|
|
|
202
228
|
@permission_handler_lock.synchronize { @permission_handler = nil }
|
|
203
229
|
@user_input_handler_lock.synchronize { @user_input_handler = nil }
|
|
204
230
|
@hooks_lock.synchronize { @hooks = nil }
|
|
231
|
+
@exit_plan_mode_handler_lock.synchronize { @exit_plan_mode_handler = nil }
|
|
232
|
+
@trace_context_provider = nil
|
|
205
233
|
end
|
|
206
234
|
|
|
207
235
|
# Abort the currently processing message.
|
|
@@ -286,6 +314,32 @@ module Copilot
|
|
|
286
314
|
@hooks_lock.synchronize { @hooks = hooks }
|
|
287
315
|
end
|
|
288
316
|
|
|
317
|
+
# @api private
|
|
318
|
+
def _register_exit_plan_mode_handler(handler)
|
|
319
|
+
@exit_plan_mode_handler_lock.synchronize { @exit_plan_mode_handler = handler }
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# @api private
|
|
323
|
+
def _handle_exit_plan_mode_request(params)
|
|
324
|
+
handler = @exit_plan_mode_handler_lock.synchronize { @exit_plan_mode_handler }
|
|
325
|
+
unless handler
|
|
326
|
+
return { approved: true }
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
begin
|
|
330
|
+
request = ExitPlanModeRequest.from_hash(params)
|
|
331
|
+
result = handler.call(request)
|
|
332
|
+
result.is_a?(ExitPlanModeResponse) ? result.to_h : result
|
|
333
|
+
rescue StandardError
|
|
334
|
+
{ approved: true }
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# @api private
|
|
339
|
+
def _register_trace_context_provider(provider)
|
|
340
|
+
@trace_context_provider = provider
|
|
341
|
+
end
|
|
342
|
+
|
|
289
343
|
# @api private
|
|
290
344
|
def _handle_hooks_invoke(hook_type, input_data)
|
|
291
345
|
hooks = @hooks_lock.synchronize { @hooks }
|
data/lib/copilot/types.rb
CHANGED
|
@@ -596,6 +596,67 @@ module Copilot
|
|
|
596
596
|
:github_token, :use_logged_in_user, :session_idle_timeout_seconds,
|
|
597
597
|
:session_fs,
|
|
598
598
|
:copilot_home, :tcp_connection_token,
|
|
599
|
+
:request_handler,
|
|
599
600
|
keyword_init: true
|
|
600
601
|
)
|
|
602
|
+
|
|
603
|
+
# --- Upstream-sync feature types (parity with @github/copilot-sdk) ---
|
|
604
|
+
|
|
605
|
+
# Per-session AI-credit budget; set +max_ai_credits+ to cap spend.
|
|
606
|
+
SessionLimitsConfig = Struct.new(:max_ai_credits, keyword_init: true) do
|
|
607
|
+
def to_wire
|
|
608
|
+
{ maxAiCredits: max_ai_credits }.compact
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
# Opt-in persistent session memory.
|
|
613
|
+
MemoryConfiguration = Struct.new(:enabled, keyword_init: true) do
|
|
614
|
+
def to_wire
|
|
615
|
+
{ enabled: enabled }.compact
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
# Arguments passed to a BYOK +bearer_token_provider+ callable (per-session scoping).
|
|
620
|
+
ProviderTokenArgs = Struct.new(:session_id, keyword_init: true)
|
|
621
|
+
|
|
622
|
+
# Intercept outbound LLM inference HTTP/WebSocket requests. Assign an instance to
|
|
623
|
+
# +ClientOptions#request_handler+ and override +send_request+ to mutate, replace,
|
|
624
|
+
# or forward the request. BYOK providers may also set +bearer_token_provider+.
|
|
625
|
+
class CopilotRequestHandler
|
|
626
|
+
def send_request(request, _context)
|
|
627
|
+
request
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
# Tool "defer" loading policy: eager pre-load ("never") or lazy via search ("auto").
|
|
632
|
+
module ToolDefer
|
|
633
|
+
AUTO = "auto"
|
|
634
|
+
NEVER = "never"
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# System-message section identifiers (used with system_message section overrides).
|
|
638
|
+
# The "preamble" section targets only the identity preamble; the "preserve" action
|
|
639
|
+
# protects an individually-addressable section from a group-level remove.
|
|
640
|
+
module SystemMessageSection
|
|
641
|
+
PREAMBLE = "preamble"
|
|
642
|
+
IDENTITY = "identity"
|
|
643
|
+
TOOL_INSTRUCTIONS = "tool_instructions"
|
|
644
|
+
PRESERVE = "preserve"
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
# Hook names include :on_pre_tool_use, :on_post_tool_use, :on_pre_mcp_tool_call,
|
|
648
|
+
# and :on_mcp_auth_request (MCP OAuth host token handler).
|
|
649
|
+
|
|
650
|
+
# GitHub-anchored attachment variants.
|
|
651
|
+
module GitHubAttachment
|
|
652
|
+
GITHUB_COMMIT = "GitHubCommit"
|
|
653
|
+
GITHUB_RELEASE = "GitHubRelease"
|
|
654
|
+
GITHUB_ACTIONS_JOB = "GitHubActionsJob"
|
|
655
|
+
GITHUB_REPOSITORY = "GitHubRepository"
|
|
656
|
+
GITHUB_FILE_DIFF = "GitHubFileDiff"
|
|
657
|
+
GITHUB_TREE_COMPARISON = "GitHubTreeComparison"
|
|
658
|
+
GITHUB_URL = "GitHubUrl"
|
|
659
|
+
GITHUB_FILE = "GitHubFile"
|
|
660
|
+
GITHUB_SNIPPET = "GitHubSnippet"
|
|
661
|
+
end
|
|
601
662
|
end
|
data/lib/copilot/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: copilot-sdk-supercharged
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeremiah Isaacson
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |
|
|
14
14
|
A Ruby SDK for interacting with the GitHub Copilot CLI server via JSON-RPC 2.0.
|