diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/dispatch/adapter/base.rb | 31 | ||||
| -rw-r--r-- | lib/dispatch/adapter/copilot.rb | 23 | ||||
| -rw-r--r-- | lib/dispatch/adapter/errors.rb | 30 | ||||
| -rw-r--r-- | lib/dispatch/adapter/message.rb | 31 | ||||
| -rw-r--r-- | lib/dispatch/adapter/model_info.rb | 17 | ||||
| -rw-r--r-- | lib/dispatch/adapter/rate_limiter.rb | 2 | ||||
| -rw-r--r-- | lib/dispatch/adapter/response.rb | 23 | ||||
| -rw-r--r-- | lib/dispatch/adapter/tool_definition.rb | 7 |
8 files changed, 14 insertions, 150 deletions
diff --git a/lib/dispatch/adapter/base.rb b/lib/dispatch/adapter/base.rb deleted file mode 100644 index 4b7a6ed..0000000 --- a/lib/dispatch/adapter/base.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -module Dispatch - module Adapter - class Base - def chat(_messages, system: nil, tools: [], stream: false, max_tokens: nil, thinking: nil, &_block) - raise NotImplementedError, "#{self.class}#chat must be implemented" - end - - def model_name - raise NotImplementedError, "#{self.class}#model_name must be implemented" - end - - def count_tokens(_messages, system: nil, tools: []) # rubocop:disable Lint/UnusedMethodArgument - -1 - end - - def list_models - raise NotImplementedError, "#{self.class}#list_models must be implemented" - end - - def provider_name - self.class.name - end - - def max_context_tokens - nil - end - end - end -end diff --git a/lib/dispatch/adapter/copilot.rb b/lib/dispatch/adapter/copilot.rb index d8a54a0..b14c5c0 100644 --- a/lib/dispatch/adapter/copilot.rb +++ b/lib/dispatch/adapter/copilot.rb @@ -6,12 +6,7 @@ require "json" require "securerandom" require "fileutils" -require_relative "errors" -require_relative "message" -require_relative "response" -require_relative "tool_definition" -require_relative "model_info" -require_relative "base" +require "dispatch/adapter/interface" require_relative "rate_limiter" require_relative "version" @@ -56,7 +51,7 @@ module Dispatch VALID_THINKING_LEVELS = %w[low medium high].freeze - def initialize(model: "gpt-4.1", github_token: nil, token_path: nil, max_tokens: 8192, thinking: nil, + def initialize(model: "gpt-4.1", github_token: nil, token_path: nil, max_tokens: 8192, thinking: "high", min_request_interval: 3.0, rate_limit: nil) super() @model = model @@ -88,9 +83,13 @@ module Dispatch body = { model: @model, messages: wire_messages, - max_tokens: effective_max_tokens, stream: stream } + if uses_max_completion_tokens? + body[:max_completion_tokens] = effective_max_tokens + else + body[:max_tokens] = effective_max_tokens + end body[:tools] = wire_tools unless wire_tools.empty? body[:reasoning_effort] = effective_thinking if effective_thinking @@ -178,6 +177,10 @@ module Dispatch ) end + def uses_max_completion_tokens? + @model.match?(/o[1-9]|gpt-5|gemini/) + end + def default_token_path File.join(Dir.home, ".config", "dispatch", "copilot_github_token") end @@ -457,13 +460,13 @@ module Dispatch def merge_consecutive_roles(messages) return messages if messages.empty? - merged = [messages.first.dup] + merged = [ messages.first.dup ] messages[1..].each do |msg| prev = merged.last if prev[:role] == msg[:role] && prev[:role] != "tool" && !msg.key?(:tool_calls) && !prev.key?(:tool_calls) - prev[:content] = [prev[:content], msg[:content]].compact.join("\n\n") + prev[:content] = [ prev[:content], msg[:content] ].compact.join("\n\n") else merged << msg.dup end diff --git a/lib/dispatch/adapter/errors.rb b/lib/dispatch/adapter/errors.rb deleted file mode 100644 index 86f9c14..0000000 --- a/lib/dispatch/adapter/errors.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -module Dispatch - module Adapter - class Error < StandardError - attr_reader :status_code, :provider - - def initialize(message = nil, status_code: nil, provider: nil) - @status_code = status_code - @provider = provider - super(message) - end - end - - class AuthenticationError < Error; end - - class RateLimitError < Error - attr_reader :retry_after - - def initialize(message = nil, status_code: nil, provider: nil, retry_after: nil) - @retry_after = retry_after - super(message, status_code:, provider:) - end - end - - class ServerError < Error; end - class RequestError < Error; end - class ConnectionError < Error; end - end -end diff --git a/lib/dispatch/adapter/message.rb b/lib/dispatch/adapter/message.rb deleted file mode 100644 index eb51c99..0000000 --- a/lib/dispatch/adapter/message.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -module Dispatch - module Adapter - Message = Struct.new(:role, :content, keyword_init: true) - - TextBlock = Struct.new(:type, :text, keyword_init: true) do - def initialize(text:, type: "text") - super(type:, text:) - end - end - - ImageBlock = Struct.new(:type, :source, :media_type, keyword_init: true) do - def initialize(source:, media_type:, type: "image") - super(type:, source:, media_type:) - end - end - - ToolUseBlock = Struct.new(:type, :id, :name, :arguments, keyword_init: true) do - def initialize(id:, name:, arguments:, type: "tool_use") - super(type:, id:, name:, arguments:) - end - end - - ToolResultBlock = Struct.new(:type, :tool_use_id, :content, :is_error, keyword_init: true) do - def initialize(tool_use_id:, content:, is_error: false, type: "tool_result") - super(type:, tool_use_id:, content:, is_error:) - end - end - end -end diff --git a/lib/dispatch/adapter/model_info.rb b/lib/dispatch/adapter/model_info.rb deleted file mode 100644 index 8ba2977..0000000 --- a/lib/dispatch/adapter/model_info.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -module Dispatch - module Adapter - ModelInfo = Struct.new( - :id, :name, :max_context_tokens, - :supports_vision, :supports_tool_use, :supports_streaming, - :premium_request_multiplier, - keyword_init: true - ) do - def initialize(id:, name:, max_context_tokens:, supports_vision:, supports_tool_use:, supports_streaming:, - premium_request_multiplier: nil) - super - end - end - end -end diff --git a/lib/dispatch/adapter/rate_limiter.rb b/lib/dispatch/adapter/rate_limiter.rb index 8d0789e..1b05582 100644 --- a/lib/dispatch/adapter/rate_limiter.rb +++ b/lib/dispatch/adapter/rate_limiter.rb @@ -90,7 +90,7 @@ module Dispatch def compute_wait(state, now) cooldown_wait = compute_cooldown_wait(state, now) window_wait = compute_window_wait(state, now) - [cooldown_wait, window_wait].max + [ cooldown_wait, window_wait ].max end def compute_cooldown_wait(state, now) diff --git a/lib/dispatch/adapter/response.rb b/lib/dispatch/adapter/response.rb deleted file mode 100644 index b4ba3eb..0000000 --- a/lib/dispatch/adapter/response.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Dispatch - module Adapter - Response = Struct.new(:content, :tool_calls, :model, :stop_reason, :usage, keyword_init: true) do - def initialize(model:, stop_reason:, usage:, content: nil, tool_calls: []) - super - end - end - - Usage = Struct.new(:input_tokens, :output_tokens, :cache_read_tokens, :cache_creation_tokens, keyword_init: true) do - def initialize(input_tokens:, output_tokens:, cache_read_tokens: 0, cache_creation_tokens: 0) - super - end - end - - StreamDelta = Struct.new(:type, :text, :tool_call_id, :tool_name, :argument_delta, keyword_init: true) do - def initialize(type:, text: nil, tool_call_id: nil, tool_name: nil, argument_delta: nil) - super - end - end - end -end diff --git a/lib/dispatch/adapter/tool_definition.rb b/lib/dispatch/adapter/tool_definition.rb deleted file mode 100644 index 7b435a3..0000000 --- a/lib/dispatch/adapter/tool_definition.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -module Dispatch - module Adapter - ToolDefinition = Struct.new(:name, :description, :parameters, keyword_init: true) - end -end |
