swarm_cli 2.1.13 → 3.0.0.alpha2

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/exe/swarm3 +11 -0
  4. data/lib/swarm_cli/v3/activity_indicator.rb +168 -0
  5. data/lib/swarm_cli/v3/ansi_colors.rb +70 -0
  6. data/lib/swarm_cli/v3/cli.rb +721 -0
  7. data/lib/swarm_cli/v3/command_completer.rb +112 -0
  8. data/lib/swarm_cli/v3/display.rb +607 -0
  9. data/lib/swarm_cli/v3/dropdown.rb +130 -0
  10. data/lib/swarm_cli/v3/event_renderer.rb +161 -0
  11. data/lib/swarm_cli/v3/file_completer.rb +143 -0
  12. data/lib/swarm_cli/v3/raw_input_reader.rb +304 -0
  13. data/lib/swarm_cli/v3/reboot_tool.rb +123 -0
  14. data/lib/swarm_cli/v3/text_input.rb +235 -0
  15. data/lib/swarm_cli/v3.rb +52 -0
  16. metadata +30 -245
  17. data/exe/swarm +0 -6
  18. data/lib/swarm_cli/cli.rb +0 -201
  19. data/lib/swarm_cli/command_registry.rb +0 -61
  20. data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
  21. data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
  22. data/lib/swarm_cli/commands/migrate.rb +0 -55
  23. data/lib/swarm_cli/commands/run.rb +0 -173
  24. data/lib/swarm_cli/config_loader.rb +0 -98
  25. data/lib/swarm_cli/formatters/human_formatter.rb +0 -811
  26. data/lib/swarm_cli/formatters/json_formatter.rb +0 -62
  27. data/lib/swarm_cli/interactive_repl.rb +0 -895
  28. data/lib/swarm_cli/mcp_serve_options.rb +0 -44
  29. data/lib/swarm_cli/mcp_tools_options.rb +0 -59
  30. data/lib/swarm_cli/migrate_options.rb +0 -54
  31. data/lib/swarm_cli/migrator.rb +0 -132
  32. data/lib/swarm_cli/options.rb +0 -151
  33. data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
  34. data/lib/swarm_cli/ui/components/content_block.rb +0 -120
  35. data/lib/swarm_cli/ui/components/divider.rb +0 -57
  36. data/lib/swarm_cli/ui/components/panel.rb +0 -62
  37. data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
  38. data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
  39. data/lib/swarm_cli/ui/formatters/number.rb +0 -58
  40. data/lib/swarm_cli/ui/formatters/text.rb +0 -77
  41. data/lib/swarm_cli/ui/formatters/time.rb +0 -73
  42. data/lib/swarm_cli/ui/icons.rb +0 -36
  43. data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
  44. data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
  45. data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
  46. data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
  47. data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
  48. data/lib/swarm_cli/version.rb +0 -5
  49. data/lib/swarm_cli.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af3e0c037fa25f545dd90fe21908da554c7cb3242d752c58eabec95b7453c840
4
- data.tar.gz: 52aee53c8a31b17a0035d95e814f756ae01ca7b895aa94216e77a8a03af14b89
3
+ metadata.gz: 54f2afe1d7e949a29c1c257d51da1c2356d72093a7dc352795b9b49649ce6068
4
+ data.tar.gz: c5fc91ff7d7505d7ca44127b62100f8f0e26d92cfe497309f1589fdba6ac7894
5
5
  SHA512:
6
- metadata.gz: 444bfa6029186f64b6d6fea74c1bf6c7dd1976971a6ea383ac1c49bf128d1c515f074d53266a35414a1cd32f58cdfd2d83b8ecd3a934293d01e691a7b4df8d68
7
- data.tar.gz: 05e3f8f1e937f19c916f72fd78f74591df2b2862ad34885010b8b63dd4958e178f7112e1e9227192ef480da2efa53ce6f4d7563be3fba85893ddb086de828b09
6
+ metadata.gz: cb4ed1132f74f4f010ea4410e64a697e1145558512900565dc1c71e8fdc939b582e8bb7f364b390e999dae46c1e9569616a76c97dade67ce8765c1e5a363f2e5
7
+ data.tar.gz: 0db61c92971142f794bbbb238f8993aedda89dfa7e3233aa1a83715cb35da82f05bf35307a4b7c66e46cb2e150584e0b2a266e9d9a8b4787154e141b514eb8fc
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present Paulo Arruda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/exe/swarm3 ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # V3 CLI executable
5
+ #
6
+ # This uses the standalone V3 entry point which only loads V3 code
7
+ # and minimal dependencies. Works with swarm_sdk 3.x and swarm_cli 3.x.
8
+
9
+ require "swarm_cli/v3"
10
+
11
+ SwarmCLI::V3::CLI.start(ARGV)
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmCLI
4
+ module V3
5
+ # Renders the activity indicator above the separator line.
6
+ #
7
+ # Three states: +:idle+, +:working+, +:done+.
8
+ #
9
+ # - **idle** — nothing rendered, {#footer_lines} is 0.
10
+ # - **working** — breathing "Working..." animation, ticker thread running.
11
+ # Optionally shows a status suffix (e.g. "🧠 retrieval (133ms)").
12
+ # - **done** — static "Done (Xs)" message, no ticker. Stays in the footer
13
+ # until the next {#start} call clears it.
14
+ #
15
+ # The state machine:
16
+ # idle → start → working → stop → done → start → working …
17
+ #
18
+ # @example
19
+ # indicator = ActivityIndicator.new(on_tick: -> { display.redraw })
20
+ # indicator.start
21
+ # indicator.render # => "\n⏳ Working... (2s)\n"
22
+ # indicator.status = "🧠 retrieval: 133ms"
23
+ # indicator.render # => "\n⏳ Working... (2s • 🧠 retrieval: 133ms)\n"
24
+ # indicator.stop
25
+ # indicator.render # => "\n• Done (2s)\n"
26
+ class ActivityIndicator
27
+ TICK_INTERVAL = 0.15
28
+
29
+ # @param on_tick [#call, nil] callback invoked on every ticker tick
30
+ def initialize(on_tick: nil)
31
+ @on_tick = on_tick
32
+ @state = :idle
33
+ @work_start_time = nil
34
+ @done_elapsed = nil
35
+ @status = nil
36
+ @ticker_thread = nil
37
+ end
38
+
39
+ # Begin the working state and start the ticker thread.
40
+ #
41
+ # Transitions from any state (idle or done) to working.
42
+ #
43
+ # @return [void]
44
+ def start
45
+ @done_elapsed = nil
46
+ @status = nil
47
+ @work_start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
48
+ @state = :working
49
+ start_ticker
50
+ end
51
+
52
+ # End the working state and transition to done.
53
+ #
54
+ # The done state keeps the indicator visible in the footer with
55
+ # elapsed time until the next {#start} call.
56
+ #
57
+ # @return [void]
58
+ def stop
59
+ return unless @state == :working
60
+
61
+ stop_ticker
62
+ @done_elapsed = elapsed_seconds
63
+ @state = :done
64
+ @status = nil
65
+ @work_start_time = nil
66
+ end
67
+
68
+ # Set a status suffix shown on the working line.
69
+ #
70
+ # @param text [String, nil] status text (e.g. "🧠 retrieval (133ms)")
71
+ # @return [void]
72
+ attr_writer :status
73
+
74
+ # @return [Boolean] true if currently in the working state
75
+ def working?
76
+ @state == :working
77
+ end
78
+
79
+ # @return [Boolean] true if indicator occupies footer space (working or done)
80
+ def visible?
81
+ @state != :idle
82
+ end
83
+
84
+ # Render the indicator line for the current state.
85
+ #
86
+ # @return [String, nil] rendered indicator, or nil when idle
87
+ def render
88
+ case @state
89
+ when :working
90
+ render_working
91
+ when :done
92
+ render_done
93
+ end
94
+ end
95
+
96
+ # Number of extra footer lines this indicator contributes.
97
+ #
98
+ # @return [Integer] 0 when idle, 2 when working or done
99
+ def footer_lines
100
+ @state == :idle ? 0 : 2
101
+ end
102
+
103
+ private
104
+
105
+ def render_working
106
+ return unless @work_start_time
107
+
108
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
109
+ elapsed = (now - @work_start_time).round
110
+
111
+ # Sine wave over 256-color grayscale for a smooth breathe.
112
+ gray = 247 + (Math.sin(now * Math::PI) * 5).round
113
+ pulse = "\e[38;5;#{gray}m"
114
+
115
+ detail = format_duration(elapsed)
116
+ detail = "#{detail} \u{2022} #{@status}" if @status
117
+ "\n#{pulse}\u{23F3} Working...\e[0m \e[38;5;243m(#{detail})\e[0m\n"
118
+ end
119
+
120
+ def render_done
121
+ "\n#{ANSIColors.dim("\u{2022} Done (#{format_duration(@done_elapsed)})")}\n"
122
+ end
123
+
124
+ def elapsed_seconds
125
+ return 0 unless @work_start_time
126
+
127
+ (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @work_start_time).round
128
+ end
129
+
130
+ # Format seconds into a human-readable duration.
131
+ #
132
+ # @param seconds [Integer]
133
+ # @return [String] e.g. "3s", "2m 15s", "1h 5m"
134
+ def format_duration(seconds)
135
+ return "#{seconds}s" if seconds < 60
136
+
137
+ minutes, secs = seconds.divmod(60)
138
+ return "#{minutes}m #{secs}s" if minutes < 60
139
+
140
+ hours, mins = minutes.divmod(60)
141
+ return "#{hours}h #{mins}m" if hours < 24
142
+
143
+ days, hrs = hours.divmod(24)
144
+ "#{days}d #{hrs}h"
145
+ end
146
+
147
+ # Start a background thread that invokes +on_tick+ at ~7 fps.
148
+ def start_ticker
149
+ stop_ticker
150
+ @ticker_thread = Thread.new do
151
+ while @state == :working
152
+ sleep(TICK_INTERVAL)
153
+ @on_tick&.call
154
+ end
155
+ end
156
+ end
157
+
158
+ # Stop the ticker thread.
159
+ def stop_ticker
160
+ return unless @ticker_thread
161
+
162
+ @ticker_thread.kill
163
+ @ticker_thread.join(0.1)
164
+ @ticker_thread = nil
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwarmCLI
4
+ module V3
5
+ # Minimal ANSI escape code helpers for terminal styling.
6
+ #
7
+ # Avoids external dependencies (like Pastel) to keep the V3 CLI
8
+ # lightweight. Each method wraps text in an ANSI escape sequence
9
+ # and appends the reset code.
10
+ #
11
+ # @example
12
+ # ANSIColors.bold("hello") # => "\e[1mhello\e[0m"
13
+ # ANSIColors.red("error") # => "\e[31merror\e[0m"
14
+ module ANSIColors
15
+ RESET = "\e[0m"
16
+ BOLD = "\e[1m"
17
+ DIM = "\e[2m"
18
+ ITALIC = "\e[3m"
19
+ REVERSE = "\e[7m"
20
+ GREEN = "\e[32m"
21
+ CYAN = "\e[36m"
22
+ YELLOW = "\e[33m"
23
+ RED = "\e[31m"
24
+ BLUE = "\e[34m"
25
+ MAGENTA = "\e[35m"
26
+
27
+ class << self
28
+ # @param text [String] text to wrap
29
+ # @return [String] bold-styled text
30
+ def bold(text) = "#{BOLD}#{text}#{RESET}"
31
+
32
+ # @param text [String] text to wrap
33
+ # @return [String] dim-styled text
34
+ def dim(text) = "#{DIM}#{text}#{RESET}"
35
+
36
+ # @param text [String] text to wrap
37
+ # @return [String] italic-styled text
38
+ def italic(text) = "#{ITALIC}#{text}#{RESET}"
39
+
40
+ # @param text [String] text to wrap
41
+ # @return [String] reverse-video styled text
42
+ def reverse(text) = "#{REVERSE}#{text}#{RESET}"
43
+
44
+ # @param text [String] text to wrap
45
+ # @return [String] green-colored text
46
+ def green(text) = "#{GREEN}#{text}#{RESET}"
47
+
48
+ # @param text [String] text to wrap
49
+ # @return [String] cyan-colored text
50
+ def cyan(text) = "#{CYAN}#{text}#{RESET}"
51
+
52
+ # @param text [String] text to wrap
53
+ # @return [String] yellow-colored text
54
+ def yellow(text) = "#{YELLOW}#{text}#{RESET}"
55
+
56
+ # @param text [String] text to wrap
57
+ # @return [String] red-colored text
58
+ def red(text) = "#{RED}#{text}#{RESET}"
59
+
60
+ # @param text [String] text to wrap
61
+ # @return [String] blue-colored text
62
+ def blue(text) = "#{BLUE}#{text}#{RESET}"
63
+
64
+ # @param text [String] text to wrap
65
+ # @return [String] magenta-colored text
66
+ def magenta(text) = "#{MAGENTA}#{text}#{RESET}"
67
+ end
68
+ end
69
+ end
70
+ end