Class: AgentHarness::Providers::GithubCopilot

Inherits:
Base
  • Object
show all
Defined in:
lib/agent_harness/providers/github_copilot.rb

Overview

GitHub Copilot CLI provider

Provides integration with the GitHub Copilot CLI tool.

Constant Summary collapse

MIN_JSON_OUTPUT_VERSION =
Gem::Version.new("0.0.422").freeze
REQUEST_PROBE_ENV_STACK_KEY =
:agent_harness_github_copilot_request_probe_env_stack
MODEL_PATTERN =

Model name pattern for GitHub Copilot (uses OpenAI models)

/^gpt-[\d.o-]+(?:-turbo)?(?:-mini)?$/i
SMOKE_TEST_CONTRACT =

Copilot-specific smoke test contract. The ‘what-the-shell` subcommand translates natural language into shell commands, so the generic “Reply with exactly OK.” prompt would produce something like `echo “OK”` rather than the literal text “OK”. We use a prompt that is meaningful for the shell-translation path and only require non-empty output (no exact match).

{
  prompt: "list files in the current directory",
  expected_output: nil,
  timeout: 30,
  require_output: true,
  success_message: "Smoke test passed"
}.freeze

Constants inherited from Base

Base::COMMON_ERROR_PATTERNS, Base::DEFAULT_SMOKE_TEST_CONTRACT

Instance Attribute Summary

Attributes inherited from Base

#config, #executor, #logger

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#configure, #initialize, #sandboxed_environment?

Methods included from Adapter

#build_mcp_flags, #fetch_mcp_servers, #health_status, included, metadata_package_name, normalize_metadata_installation, normalize_metadata_source_type, normalize_metadata_version_requirement, #parse_rate_limit_reset, #smoke_test, #smoke_test_contract, #supported_mcp_transports, #supports_dangerous_mode?, #supports_mcp?, #validate_config, #validate_mcp_servers!

Constructor Details

This class inherits a constructor from AgentHarness::Providers::Base

Class Method Details

.available?Boolean

Returns:

  • (Boolean)


41
42
43
44
# File 'lib/agent_harness/providers/github_copilot.rb', line 41

def available?
  executor = AgentHarness.configuration.command_executor
  !!executor.which(binary_name)
end

.binary_nameObject



37
38
39
# File 'lib/agent_harness/providers/github_copilot.rb', line 37

def binary_name
  "github-copilot-cli"
end

.discover_modelsObject



81
82
83
84
85
86
87
88
89
# File 'lib/agent_harness/providers/github_copilot.rb', line 81

def discover_models
  return [] unless available?

  [
    {name: "gpt-4o", family: "gpt-4o", tier: "standard", provider: "github_copilot"},
    {name: "gpt-4o-mini", family: "gpt-4o-mini", tier: "mini", provider: "github_copilot"},
    {name: "gpt-4-turbo", family: "gpt-4-turbo", tier: "advanced", provider: "github_copilot"}
  ]
end

.firewall_requirementsObject



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/agent_harness/providers/github_copilot.rb', line 58

def firewall_requirements
  {
    domains: [
      "copilot-proxy.githubusercontent.com",
      "api.githubcopilot.com",
      "copilot-telemetry.githubusercontent.com",
      "default.exp-tas.com",
      "copilot-completions.githubusercontent.com"
    ],
    ip_ranges: []
  }
end

.instruction_file_pathsObject



71
72
73
74
75
76
77
78
79
# File 'lib/agent_harness/providers/github_copilot.rb', line 71

def instruction_file_paths
  [
    {
      path: ".github/copilot-instructions.md",
      description: "GitHub Copilot agent instructions",
      symlink: true
    }
  ]
end

.model_family(provider_model_name) ⇒ Object



95
96
97
# File 'lib/agent_harness/providers/github_copilot.rb', line 95

def model_family(provider_model_name)
  provider_model_name
end

.provider_metadata_overridesObject



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/agent_harness/providers/github_copilot.rb', line 46

def 
  {
    auth: {
      service: :github,
      api_family: :github_copilot
    },
    identity: {
      bot_usernames: ["github-copilot[bot]"]
    }
  }
end

.provider_model_name(family_name) ⇒ Object



99
100
101
# File 'lib/agent_harness/providers/github_copilot.rb', line 99

def provider_model_name(family_name)
  family_name
end

.provider_nameObject



33
34
35
# File 'lib/agent_harness/providers/github_copilot.rb', line 33

def provider_name
  :github_copilot
end

.smoke_test_contractObject



91
92
93
# File 'lib/agent_harness/providers/github_copilot.rb', line 91

def smoke_test_contract
  SMOKE_TEST_CONTRACT
end

.supports_model_family?(family_name) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/agent_harness/providers/github_copilot.rb', line 103

def supports_model_family?(family_name)
  MODEL_PATTERN.match?(family_name)
end

Instance Method Details

#auth_typeObject



149
150
151
# File 'lib/agent_harness/providers/github_copilot.rb', line 149

def auth_type
  :oauth
end

#capabilitiesObject



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/agent_harness/providers/github_copilot.rb', line 124

def capabilities
  {
    streaming: false,
    file_upload: false,
    vision: false,
    tool_use: true,
    json_mode: false,
    mcp: false,
    dangerous_mode: true
  }
end

#configuration_schemaObject



116
117
118
119
120
121
122
# File 'lib/agent_harness/providers/github_copilot.rb', line 116

def configuration_schema
  {
    fields: [],
    auth_modes: [:oauth],
    openai_compatible: false
  }
end

#dangerous_mode_flagsObject



136
137
138
# File 'lib/agent_harness/providers/github_copilot.rb', line 136

def dangerous_mode_flags
  ["--allow-all-tools"]
end

#display_nameObject



112
113
114
# File 'lib/agent_harness/providers/github_copilot.rb', line 112

def display_name
  "GitHub Copilot CLI"
end

#error_patternsObject



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/agent_harness/providers/github_copilot.rb', line 172

def error_patterns
  {
    auth_expired: [
      /not.?authorized/i,
      /access.?denied/i,
      /permission.?denied/i,
      /not.?enabled/i,
      /subscription.?required/i
    ],
    rate_limited: [
      /usage.?limit/i,
      /rate.?limit/i
    ],
    transient: [
      /connection.?error/i,
      /timeout/i,
      /try.?again/i
    ],
    permanent: [
      /invalid.?command/i,
      /unknown.?flag/i
    ]
  }
end

#execution_semanticsObject



159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/agent_harness/providers/github_copilot.rb', line 159

def execution_semantics
  {
    prompt_delivery: :arg,
    output_format: copilot_cli_supports_json_output? ? :json : :text,
    sandbox_aware: false,
    uses_subcommand: true,
    non_interactive_flag: nil,
    legitimate_exit_codes: [0],
    stderr_is_diagnostic: true,
    parses_rate_limit_reset: false
  }
end

#nameObject



108
109
110
# File 'lib/agent_harness/providers/github_copilot.rb', line 108

def name
  "github_copilot"
end

#send_message(prompt:, **options) ⇒ Object



153
154
155
156
157
# File 'lib/agent_harness/providers/github_copilot.rb', line 153

def send_message(prompt:, **options)
  with_request_probe_env(request_probe_env_from_raw_runtime(options[:provider_runtime])) do
    super(prompt: prompt, **options)
  end
end

#session_flags(session_id) ⇒ Object



144
145
146
147
# File 'lib/agent_harness/providers/github_copilot.rb', line 144

def session_flags(session_id)
  return [] unless session_id && !session_id.empty?
  ["--resume", session_id]
end

#supports_sessions?Boolean

Returns:

  • (Boolean)


140
141
142
# File 'lib/agent_harness/providers/github_copilot.rb', line 140

def supports_sessions?
  true
end