aidp 0.34.1 → 0.39.3
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/README.md +14 -14
- data/lib/aidp/agent_harness_adapter.rb +309 -0
- data/lib/aidp/cli/issue_importer.rb +20 -6
- data/lib/aidp/cli/jobs_command.rb +1 -1
- data/lib/aidp/cli/models_command.rb +9 -16
- data/lib/aidp/cli/prompts_command.rb +253 -0
- data/lib/aidp/cli/security_command.rb +4 -10
- data/lib/aidp/cli/storage_command.rb +277 -0
- data/lib/aidp/cli/temporal_command.rb +460 -0
- data/lib/aidp/cli.rb +24 -2
- data/lib/aidp/config.rb +15 -0
- data/lib/aidp/config_paths.rb +12 -2
- data/lib/aidp/database/migrations.rb +114 -0
- data/lib/aidp/database/repositories/checkpoint_repository.rb +174 -0
- data/lib/aidp/database/repositories/deprecated_models_repository.rb +206 -0
- data/lib/aidp/database/repositories/evaluation_repository.rb +208 -0
- data/lib/aidp/database/repositories/harness_state_repository.rb +140 -0
- data/lib/aidp/database/repositories/job_repository.rb +278 -0
- data/lib/aidp/database/repositories/model_cache_repository.rb +194 -0
- data/lib/aidp/database/repositories/progress_repository.rb +210 -0
- data/lib/aidp/database/repositories/prompt_archive_repository.rb +195 -0
- data/lib/aidp/database/repositories/prompt_feedback_repository.rb +266 -0
- data/lib/aidp/database/repositories/provider_info_cache_repository.rb +208 -0
- data/lib/aidp/database/repositories/provider_metrics_repository.rb +245 -0
- data/lib/aidp/database/repositories/secrets_repository.rb +187 -0
- data/lib/aidp/database/repositories/task_repository.rb +231 -0
- data/lib/aidp/database/repositories/template_version_repository.rb +383 -0
- data/lib/aidp/database/repositories/watch_state_repository.rb +472 -0
- data/lib/aidp/database/repositories/workstream_repository.rb +310 -0
- data/lib/aidp/database/repositories/worktree_repository.rb +240 -0
- data/lib/aidp/database/repository.rb +166 -0
- data/lib/aidp/database/schema.rb +347 -0
- data/lib/aidp/database/storage_migrator.rb +693 -0
- data/lib/aidp/database.rb +139 -0
- data/lib/aidp/debug_mixin.rb +2 -2
- data/lib/aidp/execute/checkpoint.rb +26 -0
- data/lib/aidp/execute/checkpoint_display.rb +16 -0
- data/lib/aidp/execute/prompt_evaluator.rb +30 -57
- data/lib/aidp/execute/work_loop_runner.rb +294 -46
- data/lib/aidp/firewall/provider_requirements_collector.rb +7 -23
- data/lib/aidp/harness/agent_harness_provider_manager.rb +275 -0
- data/lib/aidp/harness/ai_decision_engine.rb +78 -296
- data/lib/aidp/harness/config_schema.rb +59 -0
- data/lib/aidp/harness/configuration.rb +229 -10
- data/lib/aidp/harness/deprecation_cache.rb +53 -11
- data/lib/aidp/harness/enhanced_runner.rb +1 -1
- data/lib/aidp/harness/error_handler.rb +11 -5
- data/lib/aidp/harness/provider_config.rb +36 -0
- data/lib/aidp/harness/provider_factory.rb +26 -24
- data/lib/aidp/harness/provider_info.rb +9 -5
- data/lib/aidp/harness/provider_manager.rb +2 -2
- data/lib/aidp/harness/provider_metrics.rb +103 -1
- data/lib/aidp/harness/rspec_command_optimizer.rb +166 -0
- data/lib/aidp/harness/ruby_llm_registry.rb +97 -8
- data/lib/aidp/harness/runner.rb +7 -2
- data/lib/aidp/harness/state_manager.rb +1 -1
- data/lib/aidp/harness/test_runner.rb +167 -11
- data/lib/aidp/harness/thinking_depth_manager.rb +564 -5
- data/lib/aidp/harness/usage_limit.rb +179 -0
- data/lib/aidp/harness/usage_limit_enforcer.rb +240 -0
- data/lib/aidp/harness/usage_limit_tracker.rb +308 -0
- data/lib/aidp/harness/usage_period.rb +234 -0
- data/lib/aidp/init/agent_instructions_generator.rb +317 -0
- data/lib/aidp/init/runner.rb +25 -4
- data/lib/aidp/interfaces/activity_monitor_interface.rb +234 -0
- data/lib/aidp/interfaces/binary_checker_interface.rb +232 -0
- data/lib/aidp/interfaces/command_executor_interface.rb +216 -0
- data/lib/aidp/interfaces/logger_interface.rb +150 -0
- data/lib/aidp/interfaces/ui_interface.rb +254 -0
- data/lib/aidp/logger.rb +25 -7
- data/lib/aidp/orchestration_adapter.rb +279 -0
- data/lib/aidp/pr_worktree_manager.rb +4 -15
- data/lib/aidp/prompts/feedback_collector.rb +198 -0
- data/lib/aidp/prompts/prompt_template_manager.rb +415 -0
- data/lib/aidp/prompts/template_evolver.rb +305 -0
- data/lib/aidp/prompts/template_version_manager.rb +325 -0
- data/lib/aidp/setup/in_memory_config_adapter.rb +257 -0
- data/lib/aidp/setup/in_memory_config_manager.rb +262 -0
- data/lib/aidp/setup/wizard.rb +616 -176
- data/lib/aidp/shell_executor.rb +58 -0
- data/lib/aidp/style_guide/selector.rb +56 -1
- data/lib/aidp/temporal/activities/analyze_issue_activity.rb +198 -0
- data/lib/aidp/temporal/activities/analyze_sub_task_activity.rb +163 -0
- data/lib/aidp/temporal/activities/base_activity.rb +78 -0
- data/lib/aidp/temporal/activities/create_plan_activity.rb +115 -0
- data/lib/aidp/temporal/activities/create_pr_activity.rb +193 -0
- data/lib/aidp/temporal/activities/create_prompt_activity.rb +118 -0
- data/lib/aidp/temporal/activities/diagnose_failure_activity.rb +228 -0
- data/lib/aidp/temporal/activities/prepare_next_iteration_activity.rb +147 -0
- data/lib/aidp/temporal/activities/record_checkpoint_activity.rb +81 -0
- data/lib/aidp/temporal/activities/run_agent_activity.rb +139 -0
- data/lib/aidp/temporal/activities/run_tests_activity.rb +114 -0
- data/lib/aidp/temporal/activities/run_work_loop_iteration_activity.rb +249 -0
- data/lib/aidp/temporal/configuration.rb +169 -0
- data/lib/aidp/temporal/connection.rb +93 -0
- data/lib/aidp/temporal/worker.rb +119 -0
- data/lib/aidp/temporal/workflow_client.rb +171 -0
- data/lib/aidp/temporal/workflows/base_workflow.rb +73 -0
- data/lib/aidp/temporal/workflows/issue_to_pr_workflow.rb +278 -0
- data/lib/aidp/temporal/workflows/sub_issue_workflow.rb +253 -0
- data/lib/aidp/temporal/workflows/work_loop_workflow.rb +321 -0
- data/lib/aidp/temporal.rb +120 -0
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/base_processor.rb +35 -0
- data/lib/aidp/watch/build_processor.rb +132 -0
- data/lib/aidp/watch/github_state_extractor.rb +0 -8
- data/lib/aidp/watch/rebase_processor.rb +245 -0
- data/lib/aidp/watch/round_robin_scheduler.rb +150 -0
- data/lib/aidp/watch/runner.rb +366 -285
- data/lib/aidp/watch/state_store.rb +80 -0
- data/lib/aidp/watch/work_item.rb +96 -0
- data/lib/aidp/watch/worktree_cleanup_job.rb +226 -0
- data/lib/aidp/watch/worktree_reconciler.rb +643 -0
- data/lib/aidp/workflows/guided_agent.rb +1 -1
- data/lib/aidp/worktree.rb +62 -0
- data/templates/aidp.yml.example +70 -0
- metadata +117 -16
- data/lib/aidp/analyze/json_file_storage.rb +0 -292
- data/lib/aidp/execute/future_work_backlog.rb +0 -411
- data/lib/aidp/providers/adapter.rb +0 -239
- data/lib/aidp/providers/aider.rb +0 -264
- data/lib/aidp/providers/anthropic.rb +0 -614
- data/lib/aidp/providers/base.rb +0 -617
- data/lib/aidp/providers/capability_registry.rb +0 -204
- data/lib/aidp/providers/codex.rb +0 -267
- data/lib/aidp/providers/cursor.rb +0 -304
- data/lib/aidp/providers/error_taxonomy.rb +0 -195
- data/lib/aidp/providers/gemini.rb +0 -110
- data/lib/aidp/providers/github_copilot.rb +0 -227
- data/lib/aidp/providers/kilocode.rb +0 -157
- data/lib/aidp/providers/opencode.rb +0 -139
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "timeout"
|
|
4
|
-
require_relative "base"
|
|
5
|
-
require_relative "../util"
|
|
6
|
-
require_relative "../debug_mixin"
|
|
7
|
-
|
|
8
|
-
module Aidp
|
|
9
|
-
module Providers
|
|
10
|
-
class GithubCopilot < Base
|
|
11
|
-
include Aidp::DebugMixin
|
|
12
|
-
|
|
13
|
-
def self.available?
|
|
14
|
-
!!Aidp::Util.which("copilot")
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Get firewall requirements for GitHub Copilot provider
|
|
18
|
-
def self.firewall_requirements
|
|
19
|
-
{
|
|
20
|
-
domains: [
|
|
21
|
-
"copilot-proxy.githubusercontent.com",
|
|
22
|
-
"api.githubcopilot.com",
|
|
23
|
-
"copilot-telemetry.githubusercontent.com",
|
|
24
|
-
"default.exp-tas.com",
|
|
25
|
-
"copilot-completions.githubusercontent.com",
|
|
26
|
-
"business.githubcopilot.com",
|
|
27
|
-
"enterprise.githubcopilot.com",
|
|
28
|
-
"individual.githubcopilot.com"
|
|
29
|
-
],
|
|
30
|
-
ip_ranges: []
|
|
31
|
-
}
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def name
|
|
35
|
-
"github_copilot"
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def display_name
|
|
39
|
-
"GitHub Copilot CLI"
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def available?
|
|
43
|
-
return false unless self.class.available?
|
|
44
|
-
|
|
45
|
-
# Additional check to ensure the CLI is properly configured
|
|
46
|
-
begin
|
|
47
|
-
result = Aidp::Util.execute_command("copilot", ["--version"], timeout: 10)
|
|
48
|
-
result.exit_status == 0
|
|
49
|
-
rescue
|
|
50
|
-
false
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def send_message(prompt:, session: nil, options: {})
|
|
55
|
-
raise "copilot CLI not available" unless self.class.available?
|
|
56
|
-
|
|
57
|
-
# Smart timeout calculation
|
|
58
|
-
timeout_seconds = calculate_timeout
|
|
59
|
-
|
|
60
|
-
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds})
|
|
61
|
-
debug_log("📝 Sending prompt to copilot (length: #{prompt.length})", level: :info)
|
|
62
|
-
|
|
63
|
-
# Set up activity monitoring
|
|
64
|
-
setup_activity_monitoring("copilot", method(:activity_callback))
|
|
65
|
-
record_activity("Starting copilot execution")
|
|
66
|
-
|
|
67
|
-
# Create a spinner for activity display
|
|
68
|
-
spinner = TTY::Spinner.new("[:spinner] :title", format: :dots, hide_cursor: true)
|
|
69
|
-
spinner.auto_spin
|
|
70
|
-
|
|
71
|
-
activity_display_thread = Thread.new do
|
|
72
|
-
start_time = Time.now
|
|
73
|
-
loop do
|
|
74
|
-
sleep 0.5 # Update every 500ms to reduce spam
|
|
75
|
-
elapsed = Time.now - start_time
|
|
76
|
-
|
|
77
|
-
# Break if we've been running too long or state changed
|
|
78
|
-
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
|
79
|
-
|
|
80
|
-
update_spinner_status(spinner, elapsed, "🤖 GitHub Copilot CLI")
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
begin
|
|
85
|
-
# Use non-interactive mode for automation
|
|
86
|
-
args = ["-p", prompt, "--allow-all-tools"]
|
|
87
|
-
|
|
88
|
-
# Add session support if provided
|
|
89
|
-
if session && !session.empty?
|
|
90
|
-
args += ["--resume", session]
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Use debug_execute_command for better debugging (no input since prompt is in args)
|
|
94
|
-
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds)
|
|
95
|
-
|
|
96
|
-
# Log the results
|
|
97
|
-
debug_command("copilot", args: args, input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
98
|
-
|
|
99
|
-
# Detect authorization/access errors
|
|
100
|
-
auth_error = result.err.to_s =~ /not authorized|requires an enterprise|access denied|permission denied|not enabled/i
|
|
101
|
-
if auth_error
|
|
102
|
-
spinner.error("✗")
|
|
103
|
-
mark_failed("copilot authorization error: #{result.err}")
|
|
104
|
-
@unavailable = true
|
|
105
|
-
debug_error(StandardError.new("copilot authorization error"), {exit_code: result.exit_status, stderr: result.err})
|
|
106
|
-
raise Aidp::Providers::ProviderUnavailableError.new("copilot authorization error: #{result.err}")
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
if result.exit_status == 0
|
|
110
|
-
spinner.success("✓")
|
|
111
|
-
mark_completed
|
|
112
|
-
result.out
|
|
113
|
-
else
|
|
114
|
-
spinner.error("✗")
|
|
115
|
-
mark_failed("copilot failed with exit code #{result.exit_status}")
|
|
116
|
-
debug_error(StandardError.new("copilot failed"), {exit_code: result.exit_status, stderr: result.err})
|
|
117
|
-
raise "copilot failed with exit code #{result.exit_status}: #{result.err}"
|
|
118
|
-
end
|
|
119
|
-
rescue Aidp::Providers::ProviderUnavailableError
|
|
120
|
-
raise
|
|
121
|
-
rescue => e
|
|
122
|
-
spinner&.error("✗")
|
|
123
|
-
mark_failed("copilot execution failed: #{e.message}")
|
|
124
|
-
debug_error(e, {provider: "github_copilot", prompt_length: prompt.length})
|
|
125
|
-
raise
|
|
126
|
-
ensure
|
|
127
|
-
cleanup_activity_display(activity_display_thread, spinner)
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
# Enhanced send method with additional options
|
|
132
|
-
def send_with_options(prompt:, session: nil, tools: nil, log_level: nil, config_file: nil, directories: nil)
|
|
133
|
-
args = ["-p", prompt]
|
|
134
|
-
|
|
135
|
-
# Add session support
|
|
136
|
-
if session && !session.empty?
|
|
137
|
-
args += ["--resume", session]
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Add tool permissions
|
|
141
|
-
if tools && !tools.empty?
|
|
142
|
-
if tools.include?("all")
|
|
143
|
-
args += ["--allow-all-tools"]
|
|
144
|
-
else
|
|
145
|
-
tools.each do |tool|
|
|
146
|
-
args += ["--allow-tool", tool]
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
else
|
|
150
|
-
# Default to allowing all tools for automation
|
|
151
|
-
args += ["--allow-all-tools"]
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Add logging level
|
|
155
|
-
if log_level
|
|
156
|
-
args += ["--log-level", log_level]
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
# Add allowed directories
|
|
160
|
-
if directories && !directories.empty?
|
|
161
|
-
directories.each do |dir|
|
|
162
|
-
args += ["--add-dir", dir]
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Use the enhanced version of send
|
|
167
|
-
send_with_custom_args(prompt: prompt, args: args)
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Override health check for GitHub Copilot specific considerations
|
|
171
|
-
def harness_healthy?
|
|
172
|
-
return false unless super
|
|
173
|
-
|
|
174
|
-
# Additional health checks specific to GitHub Copilot CLI
|
|
175
|
-
# Check if we can access GitHub (basic connectivity test)
|
|
176
|
-
begin
|
|
177
|
-
result = Aidp::Util.execute_command("copilot", ["--help"], timeout: 5)
|
|
178
|
-
result.exit_status == 0
|
|
179
|
-
rescue
|
|
180
|
-
false
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
private
|
|
185
|
-
|
|
186
|
-
def send_with_custom_args(prompt:, args:)
|
|
187
|
-
timeout_seconds = calculate_timeout
|
|
188
|
-
|
|
189
|
-
debug_provider("copilot", "Starting execution", {timeout: timeout_seconds, args: args})
|
|
190
|
-
debug_log("📝 Sending prompt to copilot with custom args", level: :info)
|
|
191
|
-
|
|
192
|
-
setup_activity_monitoring("copilot", method(:activity_callback))
|
|
193
|
-
record_activity("Starting copilot execution with custom args")
|
|
194
|
-
|
|
195
|
-
begin
|
|
196
|
-
result = debug_execute_command("copilot", args: args, timeout: timeout_seconds)
|
|
197
|
-
debug_command("copilot", args: args, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
198
|
-
|
|
199
|
-
if result.exit_status == 0
|
|
200
|
-
mark_completed
|
|
201
|
-
result.out
|
|
202
|
-
else
|
|
203
|
-
mark_failed("copilot failed with exit code #{result.exit_status}")
|
|
204
|
-
debug_error(StandardError.new("copilot failed"), {exit_code: result.exit_status, stderr: result.err})
|
|
205
|
-
raise "copilot failed with exit code #{result.exit_status}: #{result.err}"
|
|
206
|
-
end
|
|
207
|
-
rescue => e
|
|
208
|
-
mark_failed("copilot execution failed: #{e.message}")
|
|
209
|
-
debug_error(e, {provider: "github_copilot", prompt_length: prompt.length})
|
|
210
|
-
raise
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def activity_callback(state, message, provider)
|
|
215
|
-
# Handle activity state changes
|
|
216
|
-
case state
|
|
217
|
-
when :stuck
|
|
218
|
-
display_message("\n⚠️ GitHub Copilot CLI appears stuck: #{message}", type: :warning)
|
|
219
|
-
when :completed
|
|
220
|
-
display_message("\n✅ GitHub Copilot CLI completed: #{message}", type: :success)
|
|
221
|
-
when :failed
|
|
222
|
-
display_message("\n❌ GitHub Copilot CLI failed: #{message}", type: :error)
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "timeout"
|
|
4
|
-
require_relative "base"
|
|
5
|
-
require_relative "../util"
|
|
6
|
-
require_relative "../debug_mixin"
|
|
7
|
-
|
|
8
|
-
module Aidp
|
|
9
|
-
module Providers
|
|
10
|
-
class Kilocode < Base
|
|
11
|
-
include Aidp::DebugMixin
|
|
12
|
-
|
|
13
|
-
# Model name pattern for OpenAI models (since Kilocode uses OpenAI)
|
|
14
|
-
MODEL_PATTERN = /^gpt-[\d.o-]+(?:-turbo)?(?:-mini)?$/i
|
|
15
|
-
|
|
16
|
-
def self.available?
|
|
17
|
-
!!Aidp::Util.which("kilocode")
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Check if this provider supports a given model family
|
|
21
|
-
#
|
|
22
|
-
# @param family_name [String] The model family name
|
|
23
|
-
# @return [Boolean] True if it matches OpenAI model pattern
|
|
24
|
-
def self.supports_model_family?(family_name)
|
|
25
|
-
MODEL_PATTERN.match?(family_name)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Discover available models from registry
|
|
29
|
-
#
|
|
30
|
-
# Note: Kilocode CLI doesn't have a standard model listing command
|
|
31
|
-
# Returns registry-based models that match OpenAI patterns
|
|
32
|
-
#
|
|
33
|
-
# @return [Array<Hash>] Array of discovered models
|
|
34
|
-
def self.discover_models
|
|
35
|
-
return [] unless available?
|
|
36
|
-
|
|
37
|
-
discover_models_from_registry(MODEL_PATTERN, "kilocode")
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Get firewall requirements for Kilocode provider
|
|
41
|
-
def self.firewall_requirements
|
|
42
|
-
{
|
|
43
|
-
domains: [
|
|
44
|
-
"kilocode.ai",
|
|
45
|
-
"api.kilocode.ai"
|
|
46
|
-
],
|
|
47
|
-
ip_ranges: []
|
|
48
|
-
}
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def name
|
|
52
|
-
"kilocode"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def display_name
|
|
56
|
-
"Kilocode"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def send_message(prompt:, session: nil, options: {})
|
|
60
|
-
raise "kilocode not available" unless self.class.available?
|
|
61
|
-
|
|
62
|
-
# Smart timeout calculation
|
|
63
|
-
timeout_seconds = calculate_timeout
|
|
64
|
-
|
|
65
|
-
debug_provider("kilocode", "Starting execution", {timeout: timeout_seconds})
|
|
66
|
-
debug_log("📝 Sending prompt to kilocode (length: #{prompt.length})", level: :info)
|
|
67
|
-
|
|
68
|
-
# Check if prompt is too large and warn
|
|
69
|
-
if prompt.length > 3000
|
|
70
|
-
debug_log("⚠️ Large prompt detected (#{prompt.length} chars) - this may cause rate limiting", level: :warn)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Set up activity monitoring
|
|
74
|
-
setup_activity_monitoring("kilocode", method(:activity_callback))
|
|
75
|
-
record_activity("Starting kilocode execution")
|
|
76
|
-
|
|
77
|
-
# Create a spinner for activity display
|
|
78
|
-
spinner = TTY::Spinner.new("[:spinner] :title", format: :dots, hide_cursor: true)
|
|
79
|
-
spinner.auto_spin
|
|
80
|
-
|
|
81
|
-
activity_display_thread = Thread.new do
|
|
82
|
-
start_time = Time.now
|
|
83
|
-
loop do
|
|
84
|
-
sleep 0.5 # Update every 500ms to reduce spam
|
|
85
|
-
elapsed = Time.now - start_time
|
|
86
|
-
|
|
87
|
-
# Break if we've been running too long or state changed
|
|
88
|
-
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
|
89
|
-
|
|
90
|
-
update_spinner_status(spinner, elapsed, "🔄 kilocode")
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
begin
|
|
95
|
-
# Build kilocode command arguments
|
|
96
|
-
args = ["--auto"]
|
|
97
|
-
|
|
98
|
-
# Add model if specified
|
|
99
|
-
model = ENV["KILOCODE_MODEL"]
|
|
100
|
-
if model
|
|
101
|
-
args.concat(["-m", model])
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Add workspace detection if needed
|
|
105
|
-
if Dir.exist?(".git") && ENV["KILOCODE_WORKSPACE"]
|
|
106
|
-
args.concat(["--workspace", ENV["KILOCODE_WORKSPACE"]])
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Set authentication via environment variable
|
|
110
|
-
env_vars = {}
|
|
111
|
-
if ENV["KILOCODE_TOKEN"]
|
|
112
|
-
env_vars["KILOCODE_TOKEN"] = ENV["KILOCODE_TOKEN"]
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# Use debug_execute_command for better debugging
|
|
116
|
-
result = debug_execute_command("kilocode", args: args, input: prompt, timeout: timeout_seconds, env: env_vars)
|
|
117
|
-
|
|
118
|
-
# Log the results
|
|
119
|
-
debug_command("kilocode", args: args, input: prompt, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
120
|
-
|
|
121
|
-
if result.exit_status == 0
|
|
122
|
-
spinner.success("✓")
|
|
123
|
-
mark_completed
|
|
124
|
-
result.out
|
|
125
|
-
else
|
|
126
|
-
spinner.error("✗")
|
|
127
|
-
mark_failed("kilocode failed with exit code #{result.exit_status}")
|
|
128
|
-
debug_error(StandardError.new("kilocode failed"), {exit_code: result.exit_status, stderr: result.err})
|
|
129
|
-
raise "kilocode failed with exit code #{result.exit_status}: #{result.err}"
|
|
130
|
-
end
|
|
131
|
-
rescue => e
|
|
132
|
-
spinner&.error("✗")
|
|
133
|
-
mark_failed("kilocode execution failed: #{e.message}")
|
|
134
|
-
debug_error(e, {provider: "kilocode", prompt_length: prompt.length})
|
|
135
|
-
raise
|
|
136
|
-
ensure
|
|
137
|
-
cleanup_activity_display(activity_display_thread, spinner)
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
private
|
|
142
|
-
|
|
143
|
-
def activity_callback(state, message, provider)
|
|
144
|
-
# This is now handled by the animated display thread
|
|
145
|
-
# Only print static messages for state changes
|
|
146
|
-
case state
|
|
147
|
-
when :starting
|
|
148
|
-
display_message("🚀 Starting kilocode execution...", type: :info)
|
|
149
|
-
when :completed
|
|
150
|
-
display_message("✅ kilocode execution completed", type: :success)
|
|
151
|
-
when :failed
|
|
152
|
-
display_message("❌ kilocode execution failed: #{message}", type: :error)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "timeout"
|
|
4
|
-
require_relative "base"
|
|
5
|
-
require_relative "../util"
|
|
6
|
-
require_relative "../debug_mixin"
|
|
7
|
-
|
|
8
|
-
module Aidp
|
|
9
|
-
module Providers
|
|
10
|
-
class Opencode < Base
|
|
11
|
-
include Aidp::DebugMixin
|
|
12
|
-
|
|
13
|
-
# Model name pattern for OpenAI models (since OpenCode uses OpenAI)
|
|
14
|
-
MODEL_PATTERN = /^gpt-[\d.o-]+(?:-turbo)?(?:-mini)?$/i
|
|
15
|
-
|
|
16
|
-
def self.available?
|
|
17
|
-
!!Aidp::Util.which("opencode")
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Check if this provider supports a given model family
|
|
21
|
-
#
|
|
22
|
-
# @param family_name [String] The model family name
|
|
23
|
-
# @return [Boolean] True if it matches OpenAI model pattern
|
|
24
|
-
def self.supports_model_family?(family_name)
|
|
25
|
-
MODEL_PATTERN.match?(family_name)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Discover available models from registry
|
|
29
|
-
#
|
|
30
|
-
# Note: OpenCode CLI doesn't have a standard model listing command
|
|
31
|
-
# Returns registry-based models that match OpenAI patterns
|
|
32
|
-
#
|
|
33
|
-
# @return [Array<Hash>] Array of discovered models
|
|
34
|
-
def self.discover_models
|
|
35
|
-
return [] unless available?
|
|
36
|
-
|
|
37
|
-
discover_models_from_registry(MODEL_PATTERN, "opencode")
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Get firewall requirements for OpenCode provider
|
|
41
|
-
def self.firewall_requirements
|
|
42
|
-
{
|
|
43
|
-
domains: [
|
|
44
|
-
"api.opencode.ai",
|
|
45
|
-
"auth.opencode.ai"
|
|
46
|
-
],
|
|
47
|
-
ip_ranges: []
|
|
48
|
-
}
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def name
|
|
52
|
-
"opencode"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def display_name
|
|
56
|
-
"OpenCode"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def send_message(prompt:, session: nil, options: {})
|
|
60
|
-
raise "opencode not available" unless self.class.available?
|
|
61
|
-
|
|
62
|
-
# Smart timeout calculation
|
|
63
|
-
timeout_seconds = calculate_timeout
|
|
64
|
-
|
|
65
|
-
debug_provider("opencode", "Starting execution", {timeout: timeout_seconds})
|
|
66
|
-
debug_log("📝 Sending prompt to opencode (length: #{prompt.length})", level: :info)
|
|
67
|
-
|
|
68
|
-
# Check if prompt is too large and warn
|
|
69
|
-
if prompt.length > 3000
|
|
70
|
-
debug_log("⚠️ Large prompt detected (#{prompt.length} chars) - this may cause rate limiting", level: :warn)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Set up activity monitoring
|
|
74
|
-
setup_activity_monitoring("opencode", method(:activity_callback))
|
|
75
|
-
record_activity("Starting opencode execution")
|
|
76
|
-
|
|
77
|
-
# Create a spinner for activity display
|
|
78
|
-
spinner = TTY::Spinner.new("[:spinner] :title", format: :dots, hide_cursor: true)
|
|
79
|
-
spinner.auto_spin
|
|
80
|
-
|
|
81
|
-
activity_display_thread = Thread.new do
|
|
82
|
-
start_time = Time.now
|
|
83
|
-
loop do
|
|
84
|
-
sleep 0.5 # Update every 500ms to reduce spam
|
|
85
|
-
elapsed = Time.now - start_time
|
|
86
|
-
|
|
87
|
-
# Break if we've been running too long or state changed
|
|
88
|
-
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
|
89
|
-
|
|
90
|
-
update_spinner_status(spinner, elapsed, "🔄 opencode")
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
begin
|
|
95
|
-
# Use debug_execute_command for better debugging
|
|
96
|
-
# opencode run command with prompt and model
|
|
97
|
-
model = ENV["OPENCODE_MODEL"] || "github-copilot/claude-3.5-sonnet"
|
|
98
|
-
result = debug_execute_command("opencode", args: ["run", "-m", model, prompt], timeout: timeout_seconds)
|
|
99
|
-
|
|
100
|
-
# Log the results
|
|
101
|
-
debug_command("opencode", args: ["run", "-m", model, prompt], input: nil, output: result.out, error: result.err, exit_code: result.exit_status)
|
|
102
|
-
|
|
103
|
-
if result.exit_status == 0
|
|
104
|
-
spinner.success("✓")
|
|
105
|
-
mark_completed
|
|
106
|
-
result.out
|
|
107
|
-
else
|
|
108
|
-
spinner.error("✗")
|
|
109
|
-
mark_failed("opencode failed with exit code #{result.exit_status}")
|
|
110
|
-
debug_error(StandardError.new("opencode failed"), {exit_code: result.exit_status, stderr: result.err})
|
|
111
|
-
raise "opencode failed with exit code #{result.exit_status}: #{result.err}"
|
|
112
|
-
end
|
|
113
|
-
rescue => e
|
|
114
|
-
spinner&.error("✗")
|
|
115
|
-
mark_failed("opencode execution failed: #{e.message}")
|
|
116
|
-
debug_error(e, {provider: "opencode", prompt_length: prompt.length})
|
|
117
|
-
raise
|
|
118
|
-
ensure
|
|
119
|
-
cleanup_activity_display(activity_display_thread, spinner)
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
private
|
|
124
|
-
|
|
125
|
-
def activity_callback(state, message, provider)
|
|
126
|
-
# This is now handled by the animated display thread
|
|
127
|
-
# Only print static messages for state changes
|
|
128
|
-
case state
|
|
129
|
-
when :starting
|
|
130
|
-
display_message("🚀 Starting opencode execution...", type: :info)
|
|
131
|
-
when :completed
|
|
132
|
-
display_message("✅ opencode execution completed", type: :success)
|
|
133
|
-
when :failed
|
|
134
|
-
display_message("❌ opencode execution failed: #{message}", type: :error)
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|