schwarm-cli 0.1.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 +7 -0
- data/bin/schwarm +14 -0
- data/lib/schwarm_cli/client/agent_sessions.rb +16 -0
- data/lib/schwarm_cli/client/recurring_tasks.rb +33 -0
- data/lib/schwarm_cli/client/repositories.rb +37 -0
- data/lib/schwarm_cli/client/repository_agents.rb +37 -0
- data/lib/schwarm_cli/client/repository_skills.rb +25 -0
- data/lib/schwarm_cli/client/resource.rb +20 -0
- data/lib/schwarm_cli/client/secret_files.rb +29 -0
- data/lib/schwarm_cli/client/shared_agents.rb +33 -0
- data/lib/schwarm_cli/client/skill_files.rb +29 -0
- data/lib/schwarm_cli/client/skills.rb +29 -0
- data/lib/schwarm_cli/client/task_templates.rb +29 -0
- data/lib/schwarm_cli/client/tasks.rb +49 -0
- data/lib/schwarm_cli/client/user_messages.rb +11 -0
- data/lib/schwarm_cli/client.rb +101 -0
- data/lib/schwarm_cli/commands/agents.rb +92 -0
- data/lib/schwarm_cli/commands/base.rb +63 -0
- data/lib/schwarm_cli/commands/configure.rb +31 -0
- data/lib/schwarm_cli/commands/main.rb +64 -0
- data/lib/schwarm_cli/commands/recurring.rb +85 -0
- data/lib/schwarm_cli/commands/repo_skills.rb +50 -0
- data/lib/schwarm_cli/commands/repos.rb +86 -0
- data/lib/schwarm_cli/commands/secrets.rb +82 -0
- data/lib/schwarm_cli/commands/sessions.rb +30 -0
- data/lib/schwarm_cli/commands/shared_agents.rb +81 -0
- data/lib/schwarm_cli/commands/skill_files.rb +77 -0
- data/lib/schwarm_cli/commands/skills.rb +68 -0
- data/lib/schwarm_cli/commands/tasks.rb +146 -0
- data/lib/schwarm_cli/commands/templates.rb +58 -0
- data/lib/schwarm_cli/config.rb +46 -0
- data/lib/schwarm_cli/formatters/json.rb +13 -0
- data/lib/schwarm_cli/formatters/table.rb +39 -0
- data/lib/schwarm_cli/version.rb +5 -0
- data/lib/schwarm_cli.rb +12 -0
- metadata +148 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "gum"
|
|
4
|
+
|
|
5
|
+
module SchwarmCli
|
|
6
|
+
module Commands
|
|
7
|
+
class Configure < Base
|
|
8
|
+
desc "setup", "Set up Schwarm CLI configuration"
|
|
9
|
+
default_task :setup
|
|
10
|
+
|
|
11
|
+
def setup
|
|
12
|
+
url = Gum.input(header: "Schwarm Server URL", value: "https://schwarm.getdexter.net")
|
|
13
|
+
abort "Cancelled." unless url
|
|
14
|
+
|
|
15
|
+
api_key = Gum.input(header: "API Key", password: true, placeholder: "sk-schwarm-...")
|
|
16
|
+
abort "Cancelled." unless api_key
|
|
17
|
+
|
|
18
|
+
config = SchwarmCli::Config.new(url:, api_key:)
|
|
19
|
+
client = SchwarmCli::Client.new(url:, api_key:)
|
|
20
|
+
Gum.spin("Testing connection...") { client.repositories.list(per_page: 1) }
|
|
21
|
+
|
|
22
|
+
config.save
|
|
23
|
+
puts "Configuration saved to #{config.config_path}"
|
|
24
|
+
rescue Faraday::UnauthorizedError
|
|
25
|
+
abort "Error: Invalid API key."
|
|
26
|
+
rescue Faraday::Error => e
|
|
27
|
+
abort "Error: Could not connect to server (#{e.message})."
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base"
|
|
4
|
+
require_relative "tasks"
|
|
5
|
+
require_relative "repos"
|
|
6
|
+
require_relative "templates"
|
|
7
|
+
require_relative "skills"
|
|
8
|
+
require_relative "skill_files"
|
|
9
|
+
require_relative "agents"
|
|
10
|
+
require_relative "shared_agents"
|
|
11
|
+
require_relative "recurring"
|
|
12
|
+
require_relative "secrets"
|
|
13
|
+
require_relative "sessions"
|
|
14
|
+
require_relative "repo_skills"
|
|
15
|
+
require_relative "configure"
|
|
16
|
+
|
|
17
|
+
module SchwarmCli
|
|
18
|
+
module Commands
|
|
19
|
+
class Main < Thor
|
|
20
|
+
desc "tasks SUBCOMMAND", "Manage tasks"
|
|
21
|
+
subcommand "tasks", Tasks
|
|
22
|
+
|
|
23
|
+
desc "repos SUBCOMMAND", "Manage repositories"
|
|
24
|
+
subcommand "repos", Repos
|
|
25
|
+
|
|
26
|
+
desc "templates SUBCOMMAND", "Manage task templates"
|
|
27
|
+
subcommand "templates", Templates
|
|
28
|
+
|
|
29
|
+
desc "skills SUBCOMMAND", "Manage skills"
|
|
30
|
+
subcommand "skills", SkillsCmd
|
|
31
|
+
|
|
32
|
+
desc "skill-files SUBCOMMAND", "Manage skill files"
|
|
33
|
+
subcommand "skill-files", SkillFilesCmd
|
|
34
|
+
|
|
35
|
+
desc "agents SUBCOMMAND", "Manage repository agents"
|
|
36
|
+
subcommand "agents", Agents
|
|
37
|
+
|
|
38
|
+
desc "shared-agents SUBCOMMAND", "Manage shared agents"
|
|
39
|
+
subcommand "shared-agents", SharedAgentsCmd
|
|
40
|
+
|
|
41
|
+
desc "recurring SUBCOMMAND", "Manage recurring tasks"
|
|
42
|
+
subcommand "recurring", Recurring
|
|
43
|
+
|
|
44
|
+
desc "secrets SUBCOMMAND", "Manage secret files"
|
|
45
|
+
subcommand "secrets", Secrets
|
|
46
|
+
|
|
47
|
+
desc "sessions SUBCOMMAND", "View agent sessions"
|
|
48
|
+
subcommand "sessions", Sessions
|
|
49
|
+
|
|
50
|
+
desc "repo-skills SUBCOMMAND", "Manage repository-skill associations"
|
|
51
|
+
subcommand "repo-skills", RepoSkills
|
|
52
|
+
|
|
53
|
+
desc "configure", "Set up Schwarm CLI configuration"
|
|
54
|
+
subcommand "configure", Configure
|
|
55
|
+
|
|
56
|
+
desc "version", "Show CLI version"
|
|
57
|
+
def version
|
|
58
|
+
puts "schwarm-cli #{SchwarmCli::VERSION}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
map %w[-v --version] => :version
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Recurring < Base
|
|
6
|
+
desc "list", "List recurring tasks"
|
|
7
|
+
option :repo, type: :string, desc: "Filter by repository ID"
|
|
8
|
+
option :query, type: :string, desc: "Search by name"
|
|
9
|
+
def list
|
|
10
|
+
handle_errors do
|
|
11
|
+
data = client.recurring.list(repository_id: options[:repo], query: options[:query])
|
|
12
|
+
output_list(data, columns: [%w[ID id], %w[NAME name], %w[REPO github_repository_id],
|
|
13
|
+
%w[ENABLED enabled], %w[SCHEDULE schedule]])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "show ID", "Show recurring task details"
|
|
18
|
+
def show(id)
|
|
19
|
+
handle_errors do
|
|
20
|
+
data = client.recurring.find(id)
|
|
21
|
+
output_record(data, fields: {
|
|
22
|
+
"ID" => "id", "Name" => "name", "Repository" => "github_repository_id",
|
|
23
|
+
"Enabled" => "enabled", "Schedule" => "schedule", "Prompt" => "prompt",
|
|
24
|
+
"Created" => "created_at", "Updated" => "updated_at"
|
|
25
|
+
})
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc "create", "Create a recurring task"
|
|
30
|
+
option :name, type: :string, required: true, desc: "Task name"
|
|
31
|
+
option :repo, type: :string, required: true, desc: "Repository ID"
|
|
32
|
+
option :prompt, type: :string, required: true, desc: "Task prompt"
|
|
33
|
+
option :schedule, type: :string, required: true, desc: "Cron schedule"
|
|
34
|
+
def create
|
|
35
|
+
handle_errors do
|
|
36
|
+
attrs = {
|
|
37
|
+
name: options[:name], github_repository_id: options[:repo],
|
|
38
|
+
prompt: options[:prompt], schedule: options[:schedule]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
data = client.recurring.create(**attrs)
|
|
42
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Schedule" => "schedule" })
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
desc "update ID", "Update a recurring task"
|
|
47
|
+
option :name, type: :string, desc: "Task name"
|
|
48
|
+
option :prompt, type: :string, desc: "Task prompt"
|
|
49
|
+
option :schedule, type: :string, desc: "Cron schedule"
|
|
50
|
+
def update(id)
|
|
51
|
+
handle_errors do
|
|
52
|
+
data = client.recurring.update(id, **update_attrs)
|
|
53
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Schedule" => "schedule" })
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc "delete ID", "Delete a recurring task"
|
|
58
|
+
def delete(id)
|
|
59
|
+
handle_errors do
|
|
60
|
+
client.recurring.destroy(id)
|
|
61
|
+
puts "Recurring task #{id} deleted."
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
desc "toggle ID", "Toggle recurring task enabled/disabled"
|
|
66
|
+
def toggle(id)
|
|
67
|
+
handle_errors do
|
|
68
|
+
data = client.recurring.toggle(id)
|
|
69
|
+
status = data.dig("data", "enabled") ? "enabled" : "disabled"
|
|
70
|
+
puts "Recurring task #{id} #{status}."
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def update_attrs
|
|
77
|
+
{}.tap do |attrs|
|
|
78
|
+
attrs[:name] = options[:name] if options[:name]
|
|
79
|
+
attrs[:prompt] = options[:prompt] if options[:prompt]
|
|
80
|
+
attrs[:schedule] = options[:schedule] if options[:schedule]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class RepoSkills < Base
|
|
6
|
+
desc "list", "List repository-skill associations"
|
|
7
|
+
option :repo, type: :string, desc: "Filter by repository ID"
|
|
8
|
+
option :skill, type: :string, desc: "Filter by skill ID"
|
|
9
|
+
def list
|
|
10
|
+
handle_errors do
|
|
11
|
+
data = client.repo_skills.list(repository_id: options[:repo], skill_id: options[:skill])
|
|
12
|
+
output_list(data, columns: [%w[ID id], %w[REPO github_repository_id],
|
|
13
|
+
%w[SKILL skill_id]])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "show ID", "Show repository-skill association"
|
|
18
|
+
def show(id)
|
|
19
|
+
handle_errors do
|
|
20
|
+
data = client.repo_skills.find(id)
|
|
21
|
+
output_record(data, fields: {
|
|
22
|
+
"ID" => "id", "Repository" => "github_repository_id",
|
|
23
|
+
"Skill" => "skill_id", "Created" => "created_at"
|
|
24
|
+
})
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "create", "Associate a skill with a repository"
|
|
29
|
+
option :repo, type: :string, required: true, desc: "Repository ID"
|
|
30
|
+
option :skill, type: :string, required: true, desc: "Skill ID"
|
|
31
|
+
def create
|
|
32
|
+
handle_errors do
|
|
33
|
+
data = client.repo_skills.create(
|
|
34
|
+
github_repository_id: options[:repo], skill_id: options[:skill]
|
|
35
|
+
)
|
|
36
|
+
output_record(data, fields: { "ID" => "id", "Repository" => "github_repository_id",
|
|
37
|
+
"Skill" => "skill_id" })
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
desc "delete ID", "Remove a repository-skill association"
|
|
42
|
+
def delete(id)
|
|
43
|
+
handle_errors do
|
|
44
|
+
client.repo_skills.destroy(id)
|
|
45
|
+
puts "Repository-skill association #{id} deleted."
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Repos < Base
|
|
6
|
+
desc "list", "List repositories"
|
|
7
|
+
option :status, type: :string, desc: "Filter by status"
|
|
8
|
+
option :query, type: :string, desc: "Search by name"
|
|
9
|
+
def list
|
|
10
|
+
handle_errors do
|
|
11
|
+
data = client.repositories.list(status: options[:status], query: options[:query])
|
|
12
|
+
output_list(data, columns: [%w[ID id], %w[NAME name], %w[STATUS status]])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "show ID", "Show repository details"
|
|
17
|
+
def show(id)
|
|
18
|
+
handle_errors do
|
|
19
|
+
data = client.repositories.find(id)
|
|
20
|
+
output_record(data, fields: {
|
|
21
|
+
"ID" => "id", "Name" => "name", "URL" => "url",
|
|
22
|
+
"Status" => "status", "Base Branch" => "base_branch"
|
|
23
|
+
})
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc "create", "Create a repository"
|
|
28
|
+
option :name, type: :string, required: true, desc: "Repository name"
|
|
29
|
+
option :url, type: :string, desc: "Repository URL"
|
|
30
|
+
option :base_branch, type: :string, desc: "Base branch (default: main)"
|
|
31
|
+
def create
|
|
32
|
+
handle_errors do
|
|
33
|
+
data = client.repositories.create(**create_attrs)
|
|
34
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Status" => "status" })
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc "update ID", "Update a repository"
|
|
39
|
+
option :name, type: :string, desc: "Repository name"
|
|
40
|
+
option :base_branch, type: :string, desc: "Base branch"
|
|
41
|
+
def update(id)
|
|
42
|
+
handle_errors do
|
|
43
|
+
attrs = {}
|
|
44
|
+
attrs[:name] = options[:name] if options[:name]
|
|
45
|
+
attrs[:base_branch] = options[:base_branch] if options[:base_branch]
|
|
46
|
+
|
|
47
|
+
data = client.repositories.update(id, **attrs)
|
|
48
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Status" => "status" })
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
desc "delete ID", "Delete a repository"
|
|
53
|
+
def delete(id)
|
|
54
|
+
handle_errors do
|
|
55
|
+
client.repositories.destroy(id)
|
|
56
|
+
puts "Repository #{id} deleted."
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
desc "pause ID", "Pause a repository"
|
|
61
|
+
def pause(id)
|
|
62
|
+
handle_errors do
|
|
63
|
+
data = client.repositories.pause(id)
|
|
64
|
+
puts "Repository #{id} paused (#{data.dig('data', 'status')})."
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
desc "resume ID", "Resume a repository"
|
|
69
|
+
def resume(id)
|
|
70
|
+
handle_errors do
|
|
71
|
+
data = client.repositories.resume(id)
|
|
72
|
+
puts "Repository #{id} resumed (#{data.dig('data', 'status')})."
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def create_attrs
|
|
79
|
+
{ name: options[:name] }.tap do |attrs|
|
|
80
|
+
attrs[:url] = options[:url] if options[:url]
|
|
81
|
+
attrs[:base_branch] = options[:base_branch] if options[:base_branch]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Secrets < Base
|
|
6
|
+
desc "list", "List secret files"
|
|
7
|
+
option :repo, type: :string, desc: "Filter by repository ID"
|
|
8
|
+
def list
|
|
9
|
+
handle_errors do
|
|
10
|
+
data = client.secrets.list(repository_id: options[:repo])
|
|
11
|
+
output_list(data, columns: [%w[ID id], %w[NAME name], %w[REPO github_repository_id],
|
|
12
|
+
%w[PATH path]])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "show ID", "Show secret file details"
|
|
17
|
+
def show(id)
|
|
18
|
+
handle_errors do
|
|
19
|
+
data = client.secrets.find(id)
|
|
20
|
+
output_record(data, fields: {
|
|
21
|
+
"ID" => "id", "Name" => "name", "Repository" => "github_repository_id",
|
|
22
|
+
"Path" => "path", "Created" => "created_at", "Updated" => "updated_at"
|
|
23
|
+
})
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc "create", "Create a secret file"
|
|
28
|
+
option :name, type: :string, required: true, desc: "Secret name"
|
|
29
|
+
option :repo, type: :string, required: true, desc: "Repository ID"
|
|
30
|
+
option :path, type: :string, required: true, desc: "File path in workspace"
|
|
31
|
+
option :content, type: :string, desc: "Secret content"
|
|
32
|
+
option :file, type: :string, desc: "Read content from file"
|
|
33
|
+
def create
|
|
34
|
+
handle_errors do
|
|
35
|
+
content = read_content
|
|
36
|
+
attrs = { name: options[:name], github_repository_id: options[:repo], path: options[:path], content: }
|
|
37
|
+
|
|
38
|
+
data = client.secrets.create(**attrs)
|
|
39
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Path" => "path" })
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc "update ID", "Update a secret file"
|
|
44
|
+
option :name, type: :string, desc: "Secret name"
|
|
45
|
+
option :path, type: :string, desc: "File path in workspace"
|
|
46
|
+
option :content, type: :string, desc: "Secret content"
|
|
47
|
+
option :file, type: :string, desc: "Read content from file"
|
|
48
|
+
def update(id)
|
|
49
|
+
handle_errors do
|
|
50
|
+
data = client.secrets.update(id, **update_attrs)
|
|
51
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Path" => "path" })
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
desc "delete ID", "Delete a secret file"
|
|
56
|
+
def delete(id)
|
|
57
|
+
handle_errors do
|
|
58
|
+
client.secrets.destroy(id)
|
|
59
|
+
puts "Secret #{id} deleted."
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def update_attrs
|
|
66
|
+
{ name: options[:name], path: options[:path] }.compact.tap do |attrs|
|
|
67
|
+
attrs[:content] = read_content if options[:content] || options[:file]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def read_content
|
|
72
|
+
if options[:file]
|
|
73
|
+
file_path = File.expand_path(options[:file])
|
|
74
|
+
abort "Error: File not found: #{file_path}" unless File.exist?(file_path)
|
|
75
|
+
File.read(file_path)
|
|
76
|
+
else
|
|
77
|
+
options[:content]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Sessions < Base
|
|
6
|
+
desc "list", "List agent sessions"
|
|
7
|
+
option :source, type: :string, desc: "Filter by source"
|
|
8
|
+
option :status, type: :string, desc: "Filter by status"
|
|
9
|
+
def list
|
|
10
|
+
handle_errors do
|
|
11
|
+
data = client.sessions.list(source: options[:source], status: options[:status])
|
|
12
|
+
output_list(data, columns: [%w[ID id], %w[SOURCE source], %w[STATUS status],
|
|
13
|
+
%w[CREATED created_at]])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "show ID", "Show agent session details"
|
|
18
|
+
def show(id)
|
|
19
|
+
handle_errors do
|
|
20
|
+
data = client.sessions.find(id)
|
|
21
|
+
output_record(data, fields: {
|
|
22
|
+
"ID" => "id", "Source" => "source", "Status" => "status",
|
|
23
|
+
"Prompt" => "prompt", "Result" => "result",
|
|
24
|
+
"Created" => "created_at", "Updated" => "updated_at"
|
|
25
|
+
})
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class SharedAgentsCmd < Base
|
|
6
|
+
desc "list", "List shared agents"
|
|
7
|
+
option :query, type: :string, desc: "Search by name"
|
|
8
|
+
def list
|
|
9
|
+
handle_errors do
|
|
10
|
+
data = client.shared_agents.list(query: options[:query])
|
|
11
|
+
output_list(data, columns: [%w[ID id], %w[NAME name], %w[ENABLED enabled],
|
|
12
|
+
%w[SCHEDULE schedule]])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "show ID", "Show shared agent details"
|
|
17
|
+
def show(id)
|
|
18
|
+
handle_errors do
|
|
19
|
+
data = client.shared_agents.find(id)
|
|
20
|
+
output_record(data, fields: {
|
|
21
|
+
"ID" => "id", "Name" => "name", "Enabled" => "enabled",
|
|
22
|
+
"Schedule" => "schedule", "Prompt" => "prompt",
|
|
23
|
+
"Created" => "created_at", "Updated" => "updated_at"
|
|
24
|
+
})
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "create", "Create a shared agent"
|
|
29
|
+
option :name, type: :string, required: true, desc: "Agent name"
|
|
30
|
+
option :prompt, type: :string, required: true, desc: "Agent prompt"
|
|
31
|
+
option :schedule, type: :string, desc: "Cron schedule"
|
|
32
|
+
def create
|
|
33
|
+
handle_errors do
|
|
34
|
+
attrs = { name: options[:name], prompt: options[:prompt] }
|
|
35
|
+
attrs[:schedule] = options[:schedule] if options[:schedule]
|
|
36
|
+
|
|
37
|
+
data = client.shared_agents.create(**attrs)
|
|
38
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Enabled" => "enabled" })
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
desc "update ID", "Update a shared agent"
|
|
43
|
+
option :name, type: :string, desc: "Agent name"
|
|
44
|
+
option :prompt, type: :string, desc: "Agent prompt"
|
|
45
|
+
option :schedule, type: :string, desc: "Cron schedule"
|
|
46
|
+
def update(id)
|
|
47
|
+
handle_errors do
|
|
48
|
+
data = client.shared_agents.update(id, **update_attrs)
|
|
49
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Enabled" => "enabled" })
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
desc "delete ID", "Delete a shared agent"
|
|
54
|
+
def delete(id)
|
|
55
|
+
handle_errors do
|
|
56
|
+
client.shared_agents.destroy(id)
|
|
57
|
+
puts "Shared agent #{id} deleted."
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
desc "toggle ID", "Toggle shared agent enabled/disabled"
|
|
62
|
+
def toggle(id)
|
|
63
|
+
handle_errors do
|
|
64
|
+
data = client.shared_agents.toggle(id)
|
|
65
|
+
status = data.dig("data", "enabled") ? "enabled" : "disabled"
|
|
66
|
+
puts "Shared agent #{id} #{status}."
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def update_attrs
|
|
73
|
+
{}.tap do |attrs|
|
|
74
|
+
attrs[:name] = options[:name] if options[:name]
|
|
75
|
+
attrs[:prompt] = options[:prompt] if options[:prompt]
|
|
76
|
+
attrs[:schedule] = options[:schedule] if options[:schedule]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class SkillFilesCmd < Base
|
|
6
|
+
class_option :skill, type: :string, required: true, desc: "Skill ID"
|
|
7
|
+
|
|
8
|
+
desc "list", "List skill files"
|
|
9
|
+
def list
|
|
10
|
+
handle_errors do
|
|
11
|
+
data = client.skill_files.list(skill_id: options[:skill])
|
|
12
|
+
output_list(data, columns: [%w[ID id], %w[PATH path], %w[CREATED created_at]])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "show ID", "Show skill file details"
|
|
17
|
+
def show(id)
|
|
18
|
+
handle_errors do
|
|
19
|
+
data = client.skill_files.find(skill_id: options[:skill], id:)
|
|
20
|
+
output_record(data, fields: {
|
|
21
|
+
"ID" => "id", "Path" => "path", "Content" => "content", "Created" => "created_at"
|
|
22
|
+
})
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
desc "create", "Create a skill file"
|
|
27
|
+
option :path, type: :string, required: true, desc: "File path"
|
|
28
|
+
option :content, type: :string, desc: "File content"
|
|
29
|
+
option :file, type: :string, desc: "Read content from file"
|
|
30
|
+
def create
|
|
31
|
+
handle_errors do
|
|
32
|
+
content = read_content
|
|
33
|
+
data = client.skill_files.create(skill_id: options[:skill], path: options[:path], content:)
|
|
34
|
+
output_record(data, fields: { "ID" => "id", "Path" => "path" })
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc "update ID", "Update a skill file"
|
|
39
|
+
option :path, type: :string, desc: "File path"
|
|
40
|
+
option :content, type: :string, desc: "File content"
|
|
41
|
+
option :file, type: :string, desc: "Read content from file"
|
|
42
|
+
def update(id)
|
|
43
|
+
handle_errors do
|
|
44
|
+
data = client.skill_files.update(skill_id: options[:skill], id:, **update_attrs)
|
|
45
|
+
output_record(data, fields: { "ID" => "id", "Path" => "path" })
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
desc "delete ID", "Delete a skill file"
|
|
50
|
+
def delete(id)
|
|
51
|
+
handle_errors do
|
|
52
|
+
client.skill_files.destroy(skill_id: options[:skill], id:)
|
|
53
|
+
puts "Skill file #{id} deleted."
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def update_attrs
|
|
60
|
+
{}.tap do |attrs|
|
|
61
|
+
attrs[:path] = options[:path] if options[:path]
|
|
62
|
+
attrs[:content] = read_content if options[:content] || options[:file]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def read_content
|
|
67
|
+
if options[:file]
|
|
68
|
+
file_path = File.expand_path(options[:file])
|
|
69
|
+
abort "Error: File not found: #{file_path}" unless File.exist?(file_path)
|
|
70
|
+
File.read(file_path)
|
|
71
|
+
else
|
|
72
|
+
options[:content]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
module Commands
|
|
5
|
+
class SkillsCmd < Base
|
|
6
|
+
desc "list", "List skills"
|
|
7
|
+
option :query, type: :string, desc: "Search by name"
|
|
8
|
+
def list
|
|
9
|
+
handle_errors do
|
|
10
|
+
data = client.skills.list(query: options[:query])
|
|
11
|
+
output_list(data, columns: [%w[ID id], %w[NAME name], %w[GLOBAL global]])
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
desc "show ID", "Show skill details"
|
|
16
|
+
def show(id)
|
|
17
|
+
handle_errors do
|
|
18
|
+
data = client.skills.find(id)
|
|
19
|
+
output_record(data, fields: {
|
|
20
|
+
"ID" => "id", "Name" => "name", "Description" => "description",
|
|
21
|
+
"Global" => "global", "Created" => "created_at"
|
|
22
|
+
})
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
desc "create", "Create a skill"
|
|
27
|
+
option :name, type: :string, required: true, desc: "Skill name"
|
|
28
|
+
option :description, type: :string, desc: "Skill description"
|
|
29
|
+
option :global, type: :boolean, default: false, desc: "Make skill global"
|
|
30
|
+
def create
|
|
31
|
+
handle_errors do
|
|
32
|
+
attrs = { name: options[:name], global: options[:global] }
|
|
33
|
+
attrs[:description] = options[:description] if options[:description]
|
|
34
|
+
|
|
35
|
+
data = client.skills.create(**attrs)
|
|
36
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Global" => "global" })
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
desc "update ID", "Update a skill"
|
|
41
|
+
option :name, type: :string, desc: "Skill name"
|
|
42
|
+
option :description, type: :string, desc: "Skill description"
|
|
43
|
+
option :global, type: :boolean, desc: "Make skill global"
|
|
44
|
+
def update(id)
|
|
45
|
+
handle_errors do
|
|
46
|
+
data = client.skills.update(id, **update_attrs)
|
|
47
|
+
output_record(data, fields: { "ID" => "id", "Name" => "name", "Global" => "global" })
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
desc "delete ID", "Delete a skill"
|
|
52
|
+
def delete(id)
|
|
53
|
+
handle_errors do
|
|
54
|
+
client.skills.destroy(id)
|
|
55
|
+
puts "Skill #{id} deleted."
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def update_attrs
|
|
62
|
+
{ name: options[:name], description: options[:description] }.compact.tap do |attrs|
|
|
63
|
+
attrs[:global] = options[:global] unless options[:global].nil?
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|