fantasy-cli 1.2.6
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +456 -0
- data/bin/gsd +8 -0
- data/bin/gsd-core-darwin-amd64 +0 -0
- data/bin/gsd-core-darwin-arm64 +0 -0
- data/bin/gsd-core-linux-amd64 +0 -0
- data/bin/gsd-core-linux-arm64 +0 -0
- data/bin/gsd-core-windows-amd64.exe +0 -0
- data/bin/gsd-core-windows-arm64.exe +0 -0
- data/bin/gsd-core.exe +0 -0
- data/lib/gsd/agents/coordinator.rb +195 -0
- data/lib/gsd/agents/task_manager.rb +158 -0
- data/lib/gsd/agents/worker.rb +162 -0
- data/lib/gsd/agents.rb +30 -0
- data/lib/gsd/ai/chat.rb +486 -0
- data/lib/gsd/ai/cli.rb +248 -0
- data/lib/gsd/ai/command_parser.rb +97 -0
- data/lib/gsd/ai/commands/base.rb +42 -0
- data/lib/gsd/ai/commands/clear.rb +20 -0
- data/lib/gsd/ai/commands/context.rb +30 -0
- data/lib/gsd/ai/commands/cost.rb +30 -0
- data/lib/gsd/ai/commands/export.rb +42 -0
- data/lib/gsd/ai/commands/help.rb +61 -0
- data/lib/gsd/ai/commands/model.rb +67 -0
- data/lib/gsd/ai/commands/reset.rb +22 -0
- data/lib/gsd/ai/config.rb +256 -0
- data/lib/gsd/ai/context.rb +324 -0
- data/lib/gsd/ai/cost_tracker.rb +361 -0
- data/lib/gsd/ai/git_context.rb +169 -0
- data/lib/gsd/ai/history.rb +384 -0
- data/lib/gsd/ai/providers/anthropic.rb +429 -0
- data/lib/gsd/ai/providers/base.rb +282 -0
- data/lib/gsd/ai/providers/lmstudio.rb +279 -0
- data/lib/gsd/ai/providers/ollama.rb +336 -0
- data/lib/gsd/ai/providers/openai.rb +396 -0
- data/lib/gsd/ai/providers/openrouter.rb +429 -0
- data/lib/gsd/ai/reference_resolver.rb +225 -0
- data/lib/gsd/ai/repl.rb +349 -0
- data/lib/gsd/ai/streaming.rb +438 -0
- data/lib/gsd/ai/ui.rb +429 -0
- data/lib/gsd/buddy/cli.rb +284 -0
- data/lib/gsd/buddy/gacha.rb +148 -0
- data/lib/gsd/buddy/renderer.rb +108 -0
- data/lib/gsd/buddy/species.rb +190 -0
- data/lib/gsd/buddy/stats.rb +156 -0
- data/lib/gsd/buddy.rb +28 -0
- data/lib/gsd/cli.rb +455 -0
- data/lib/gsd/commands.rb +198 -0
- data/lib/gsd/config.rb +183 -0
- data/lib/gsd/error.rb +188 -0
- data/lib/gsd/frontmatter.rb +123 -0
- data/lib/gsd/go/bridge.rb +173 -0
- data/lib/gsd/history.rb +76 -0
- data/lib/gsd/milestone.rb +75 -0
- data/lib/gsd/output.rb +184 -0
- data/lib/gsd/phase.rb +102 -0
- data/lib/gsd/plugins/base.rb +92 -0
- data/lib/gsd/plugins/cli.rb +330 -0
- data/lib/gsd/plugins/config.rb +164 -0
- data/lib/gsd/plugins/hooks.rb +132 -0
- data/lib/gsd/plugins/installer.rb +158 -0
- data/lib/gsd/plugins/loader.rb +122 -0
- data/lib/gsd/plugins/manager.rb +187 -0
- data/lib/gsd/plugins/marketplace.rb +142 -0
- data/lib/gsd/plugins/sandbox.rb +114 -0
- data/lib/gsd/plugins/search.rb +131 -0
- data/lib/gsd/plugins/validator.rb +157 -0
- data/lib/gsd/plugins.rb +48 -0
- data/lib/gsd/profile.rb +127 -0
- data/lib/gsd/research.rb +85 -0
- data/lib/gsd/roadmap.rb +90 -0
- data/lib/gsd/skills/bundled/commit.md +58 -0
- data/lib/gsd/skills/bundled/debug.md +28 -0
- data/lib/gsd/skills/bundled/explain.md +41 -0
- data/lib/gsd/skills/bundled/plan.md +42 -0
- data/lib/gsd/skills/bundled/verify.md +26 -0
- data/lib/gsd/skills/loader.rb +189 -0
- data/lib/gsd/state.rb +102 -0
- data/lib/gsd/template.rb +106 -0
- data/lib/gsd/tools/ask_user_question.rb +179 -0
- data/lib/gsd/tools/base.rb +204 -0
- data/lib/gsd/tools/bash.rb +246 -0
- data/lib/gsd/tools/file_edit.rb +297 -0
- data/lib/gsd/tools/file_read.rb +199 -0
- data/lib/gsd/tools/file_write.rb +153 -0
- data/lib/gsd/tools/glob.rb +202 -0
- data/lib/gsd/tools/grep.rb +227 -0
- data/lib/gsd/tools/gsd_frontmatter.rb +165 -0
- data/lib/gsd/tools/gsd_phase.rb +140 -0
- data/lib/gsd/tools/gsd_roadmap.rb +108 -0
- data/lib/gsd/tools/gsd_state.rb +143 -0
- data/lib/gsd/tools/gsd_template.rb +157 -0
- data/lib/gsd/tools/gsd_verify.rb +159 -0
- data/lib/gsd/tools/registry.rb +103 -0
- data/lib/gsd/tools/task.rb +235 -0
- data/lib/gsd/tools/todo_write.rb +290 -0
- data/lib/gsd/tools/web.rb +260 -0
- data/lib/gsd/tui/app.rb +366 -0
- data/lib/gsd/tui/auto_complete.rb +79 -0
- data/lib/gsd/tui/colors.rb +111 -0
- data/lib/gsd/tui/command_palette.rb +126 -0
- data/lib/gsd/tui/header.rb +38 -0
- data/lib/gsd/tui/input_box.rb +199 -0
- data/lib/gsd/tui/spinner.rb +40 -0
- data/lib/gsd/tui/status_bar.rb +51 -0
- data/lib/gsd/tui.rb +17 -0
- data/lib/gsd/validator.rb +216 -0
- data/lib/gsd/verify.rb +175 -0
- data/lib/gsd/version.rb +5 -0
- data/lib/gsd/workstream.rb +91 -0
- metadata +231 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gsd
|
|
4
|
+
module Agents
|
|
5
|
+
# Task Manager - Gerenciamento de tarefas
|
|
6
|
+
#
|
|
7
|
+
# Responsável por:
|
|
8
|
+
# - Criar tarefas
|
|
9
|
+
# - Atribuir tarefas a workers
|
|
10
|
+
# - Monitorar progresso
|
|
11
|
+
# - Agregar resultados
|
|
12
|
+
class TaskManager
|
|
13
|
+
attr_reader :tasks, :assignments
|
|
14
|
+
|
|
15
|
+
# Inicializa o Task Manager
|
|
16
|
+
def initialize
|
|
17
|
+
@tasks = {}
|
|
18
|
+
@assignments = {}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Cria tarefa
|
|
22
|
+
#
|
|
23
|
+
# @param description [String] Descrição
|
|
24
|
+
# @param priority [Integer] Prioridade (1-10)
|
|
25
|
+
# @return [Hash] Tarefa criada
|
|
26
|
+
def create_task(description, priority: 5)
|
|
27
|
+
task_id = "task-#{SecureRandom.uuid[0..8]}"
|
|
28
|
+
|
|
29
|
+
task = {
|
|
30
|
+
id: task_id,
|
|
31
|
+
description: description,
|
|
32
|
+
priority: priority,
|
|
33
|
+
status: :pending,
|
|
34
|
+
assigned_to: nil,
|
|
35
|
+
created_at: Time.now,
|
|
36
|
+
started_at: nil,
|
|
37
|
+
completed_at: nil,
|
|
38
|
+
results: nil
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@tasks[task_id] = task
|
|
42
|
+
task
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Atribui tarefa a worker
|
|
46
|
+
#
|
|
47
|
+
# @param task_id [String] ID da tarefa
|
|
48
|
+
# @param worker_id [String] ID do worker
|
|
49
|
+
# @return [Boolean] true se sucesso
|
|
50
|
+
def assign_task(task_id, worker_id)
|
|
51
|
+
task = @tasks[task_id]
|
|
52
|
+
return false unless task
|
|
53
|
+
|
|
54
|
+
task[:assigned_to] = worker_id
|
|
55
|
+
task[:status] = :assigned
|
|
56
|
+
|
|
57
|
+
@assignments[worker_id] ||= []
|
|
58
|
+
@assignments[worker_id] << task_id
|
|
59
|
+
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Inicia tarefa
|
|
64
|
+
#
|
|
65
|
+
# @param task_id [String] ID da tarefa
|
|
66
|
+
# @return [void]
|
|
67
|
+
def start_task(task_id)
|
|
68
|
+
task = @tasks[task_id]
|
|
69
|
+
return unless task
|
|
70
|
+
|
|
71
|
+
task[:status] = :running
|
|
72
|
+
task[:started_at] = Time.now
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Completa tarefa
|
|
76
|
+
#
|
|
77
|
+
# @param task_id [String] ID da tarefa
|
|
78
|
+
# @param results [Hash] Resultados
|
|
79
|
+
# @return [void]
|
|
80
|
+
def complete_task(task_id, results)
|
|
81
|
+
task = @tasks[task_id]
|
|
82
|
+
return unless task
|
|
83
|
+
|
|
84
|
+
task[:status] = :completed
|
|
85
|
+
task[:completed_at] = Time.now
|
|
86
|
+
task[:results] = results
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Falha na tarefa
|
|
90
|
+
#
|
|
91
|
+
# @param task_id [String] ID da tarefa
|
|
92
|
+
# @param error [String] Erro
|
|
93
|
+
# @return [void]
|
|
94
|
+
def fail_task(task_id, error)
|
|
95
|
+
task = @tasks[task_id]
|
|
96
|
+
return unless task
|
|
97
|
+
|
|
98
|
+
task[:status] = :failed
|
|
99
|
+
task[:completed_at] = Time.now
|
|
100
|
+
task[:error] = error
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Obtém tarefa
|
|
104
|
+
#
|
|
105
|
+
# @param task_id [String] ID da tarefa
|
|
106
|
+
# @return [Hash, nil] Tarefa
|
|
107
|
+
def get_task(task_id)
|
|
108
|
+
@tasks[task_id]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Lista tarefas
|
|
112
|
+
#
|
|
113
|
+
# @param status [Symbol, nil] Filtrar por status
|
|
114
|
+
# @return [Array<Hash>] Lista de tarefas
|
|
115
|
+
def list_tasks(status: nil)
|
|
116
|
+
if status
|
|
117
|
+
@tasks.values.select { |t| t[:status] == status }
|
|
118
|
+
else
|
|
119
|
+
@tasks.values
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Tarefas de um worker
|
|
124
|
+
#
|
|
125
|
+
# @param worker_id [String] ID do worker
|
|
126
|
+
# @return [Array<String>] IDs das tarefas
|
|
127
|
+
def worker_tasks(worker_id)
|
|
128
|
+
@assignments[worker_id] || []
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Progresso das tarefas
|
|
132
|
+
#
|
|
133
|
+
# @return [Hash] Progresso
|
|
134
|
+
def progress
|
|
135
|
+
total = @tasks.count
|
|
136
|
+
return { total: 0 } if total == 0
|
|
137
|
+
|
|
138
|
+
{
|
|
139
|
+
total: total,
|
|
140
|
+
pending: @tasks.count { |_, t| t[:status] == :pending },
|
|
141
|
+
running: @tasks.count { |_, t| t[:status] == :running },
|
|
142
|
+
completed: @tasks.count { |_, t| t[:status] == :completed },
|
|
143
|
+
failed: @tasks.count { |_, t| t[:status] == :failed },
|
|
144
|
+
percent_complete: (@tasks.count { |_, t| t[:status] == :completed }.to_f / total * 100).round(2)
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Limpa tarefas completadas
|
|
149
|
+
#
|
|
150
|
+
# @return [Integer] Número de tarefas limpas
|
|
151
|
+
def cleanup
|
|
152
|
+
completed = @tasks.select { |_, t| t[:status] == :completed }
|
|
153
|
+
completed.each_key { |id| @tasks.delete(id) }
|
|
154
|
+
completed.count
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'timeout'
|
|
4
|
+
|
|
5
|
+
module Gsd
|
|
6
|
+
module Agents
|
|
7
|
+
# Worker - Agente worker base
|
|
8
|
+
#
|
|
9
|
+
# Responsável por:
|
|
10
|
+
# - Executar tarefas
|
|
11
|
+
# - Reportar resultados
|
|
12
|
+
# - Gerenciar estado
|
|
13
|
+
class Worker
|
|
14
|
+
attr_reader :id, :type, :prompt, :status
|
|
15
|
+
|
|
16
|
+
# Status possíveis
|
|
17
|
+
STATUSES = [:pending, :running, :completed, :failed, :stopped].freeze
|
|
18
|
+
|
|
19
|
+
# Inicializa o Worker
|
|
20
|
+
#
|
|
21
|
+
# @param id [String] ID único
|
|
22
|
+
# @param type [Symbol] Tipo do agente
|
|
23
|
+
# @param prompt [String] Prompt inicial
|
|
24
|
+
# @param timeout [Integer] Timeout em segundos
|
|
25
|
+
def initialize(id:, type:, prompt:, timeout: 300, **options)
|
|
26
|
+
@id = id
|
|
27
|
+
@type = type
|
|
28
|
+
@prompt = prompt
|
|
29
|
+
@timeout = timeout
|
|
30
|
+
@status = :pending
|
|
31
|
+
@results = nil
|
|
32
|
+
@error = nil
|
|
33
|
+
@started_at = nil
|
|
34
|
+
@completed_at = nil
|
|
35
|
+
@messages = []
|
|
36
|
+
@options = options
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Executa o worker
|
|
40
|
+
#
|
|
41
|
+
# @return [Hash] Resultados
|
|
42
|
+
def execute
|
|
43
|
+
@status = :running
|
|
44
|
+
@started_at = Time.now
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
Timeout.timeout(@timeout) do
|
|
48
|
+
@results = run_task
|
|
49
|
+
end
|
|
50
|
+
@status = :completed
|
|
51
|
+
rescue Timeout::Error => e
|
|
52
|
+
@status = :failed
|
|
53
|
+
@error = "Timeout after #{@timeout}s"
|
|
54
|
+
rescue => e
|
|
55
|
+
@status = :failed
|
|
56
|
+
@error = e.message
|
|
57
|
+
ensure
|
|
58
|
+
@completed_at = Time.now
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@results
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Continua execução com nova mensagem
|
|
65
|
+
#
|
|
66
|
+
# @param message [String] Mensagem
|
|
67
|
+
# @return [void]
|
|
68
|
+
def continue(message)
|
|
69
|
+
@messages << {
|
|
70
|
+
role: :user,
|
|
71
|
+
content: message,
|
|
72
|
+
timestamp: Time.now
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# Re-executa se completado
|
|
76
|
+
execute if @status == :completed
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Para o worker
|
|
80
|
+
#
|
|
81
|
+
# @return [void]
|
|
82
|
+
def stop
|
|
83
|
+
@status = :stopped
|
|
84
|
+
@completed_at = Time.now
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Aguarda conclusão
|
|
88
|
+
#
|
|
89
|
+
# @param timeout [Integer] Timeout
|
|
90
|
+
# @return [void]
|
|
91
|
+
def wait(timeout: nil)
|
|
92
|
+
# Implementação simplificada
|
|
93
|
+
sleep(0.1) while @status == :running || @status == :pending
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Verifica se está ativo
|
|
97
|
+
#
|
|
98
|
+
# @return [Boolean] true se ativo
|
|
99
|
+
def active?
|
|
100
|
+
[:pending, :running].include?(@status)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Verifica se completou
|
|
104
|
+
#
|
|
105
|
+
# @return [Boolean] true se completado
|
|
106
|
+
def completed?
|
|
107
|
+
@status == :completed
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Verifica se falhou
|
|
111
|
+
#
|
|
112
|
+
# @return [Boolean] true se falhou
|
|
113
|
+
def failed?
|
|
114
|
+
@status == :failed
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Retorna resultados
|
|
118
|
+
#
|
|
119
|
+
# @return [Hash, nil] Resultados
|
|
120
|
+
def results
|
|
121
|
+
@results
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Retorna erro
|
|
125
|
+
#
|
|
126
|
+
# @return [String, nil] Erro
|
|
127
|
+
def error
|
|
128
|
+
@error
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Retorna status completo
|
|
132
|
+
#
|
|
133
|
+
# @return [Hash] Status
|
|
134
|
+
def status
|
|
135
|
+
{
|
|
136
|
+
id: @id,
|
|
137
|
+
type: @type,
|
|
138
|
+
status: @status,
|
|
139
|
+
prompt: @prompt[0..100] + '...',
|
|
140
|
+
started_at: @started_at,
|
|
141
|
+
completed_at: @completed_at,
|
|
142
|
+
has_results: !@results.nil?,
|
|
143
|
+
has_error: !@error.nil?
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
# Executa tarefa
|
|
150
|
+
#
|
|
151
|
+
# @return [Hash] Resultados
|
|
152
|
+
def run_task
|
|
153
|
+
# Implementação base - subclasses devem sobrescrever
|
|
154
|
+
{
|
|
155
|
+
content: "Worker #{@id} executed task: #{@prompt}",
|
|
156
|
+
type: @type,
|
|
157
|
+
duration: Time.now - @started_at
|
|
158
|
+
}
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
data/lib/gsd/agents.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# GSD Agents Module
|
|
4
|
+
#
|
|
5
|
+
# Sistema multi-agent para GSD Tools
|
|
6
|
+
#
|
|
7
|
+
# Uso:
|
|
8
|
+
# require 'gsd/agents'
|
|
9
|
+
#
|
|
10
|
+
# # Criar coordinator
|
|
11
|
+
# coordinator = Gsd::Agents::Coordinator.new
|
|
12
|
+
#
|
|
13
|
+
# # Spawn worker
|
|
14
|
+
# worker = coordinator.spawn(type: :worker, prompt: "Investigate bug")
|
|
15
|
+
#
|
|
16
|
+
# # Aguardar conclusão
|
|
17
|
+
# coordinator.wait_all
|
|
18
|
+
#
|
|
19
|
+
# # Obter resultados
|
|
20
|
+
# results = coordinator.get_results(worker.id)
|
|
21
|
+
|
|
22
|
+
module Gsd
|
|
23
|
+
module Agents
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Load agent files
|
|
28
|
+
require 'gsd/agents/coordinator'
|
|
29
|
+
require 'gsd/agents/worker'
|
|
30
|
+
require 'gsd/agents/task_manager'
|