swarm_cli 2.1.2 → 2.1.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/lib/swarm_cli/formatters/human_formatter.rb +103 -0
- data/lib/swarm_cli/interactive_repl.rb +9 -3
- data/lib/swarm_cli/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: de6df6703665661e75ad0727c187c8fd20c1711b3dc24864bba27a4b9dd26ee1
|
|
4
|
+
data.tar.gz: 2c58cabd8e53712d73e51df8492cbef03a2b1c34b68021b162ed57e0c8e8402d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a23fd6ace54fbbf1e61170f8c39752bb4e547d01f3870cd54b00ff1064a490cbd426b19e5a0b2e9b3bd6fac44f5e67244e54aa86820053d87ca9e2ce80a64ca2
|
|
7
|
+
data.tar.gz: 463832c8cea0a8abdf252aa6485e0c70343e3ea4df6de37ba7addaa4e52bd41974425721415ce878ef5fe6b267ac067cb4cacb6b8e91e2d39fff2344c29f24f5
|
|
@@ -95,11 +95,20 @@ module SwarmCLI
|
|
|
95
95
|
handle_breakpoint_enter(entry)
|
|
96
96
|
when "breakpoint_exit"
|
|
97
97
|
handle_breakpoint_exit(entry)
|
|
98
|
+
when "llm_retry_attempt"
|
|
99
|
+
handle_llm_retry_attempt(entry)
|
|
100
|
+
when "llm_retry_exhausted"
|
|
101
|
+
handle_llm_retry_exhausted(entry)
|
|
102
|
+
when "response_parse_error"
|
|
103
|
+
handle_response_parse_error(entry)
|
|
98
104
|
end
|
|
99
105
|
end
|
|
100
106
|
|
|
101
107
|
# Called when swarm execution completes successfully
|
|
102
108
|
def on_success(result:)
|
|
109
|
+
# Defensive: ensure all spinners are stopped before showing result
|
|
110
|
+
@spinner_manager.stop_all
|
|
111
|
+
|
|
103
112
|
if @mode == :non_interactive
|
|
104
113
|
# Full result display with summary
|
|
105
114
|
@output.puts
|
|
@@ -115,6 +124,9 @@ module SwarmCLI
|
|
|
115
124
|
|
|
116
125
|
# Called when swarm execution fails
|
|
117
126
|
def on_error(error:, duration: nil)
|
|
127
|
+
# Defensive: ensure all spinners are stopped before showing error
|
|
128
|
+
@spinner_manager.stop_all
|
|
129
|
+
|
|
118
130
|
@output.puts
|
|
119
131
|
@output.puts @divider.full
|
|
120
132
|
print_error(error)
|
|
@@ -575,6 +587,97 @@ module SwarmCLI
|
|
|
575
587
|
@output.puts
|
|
576
588
|
end
|
|
577
589
|
|
|
590
|
+
def handle_llm_retry_attempt(entry)
|
|
591
|
+
agent = entry[:agent]
|
|
592
|
+
attempt = entry[:attempt]
|
|
593
|
+
max_retries = entry[:max_retries]
|
|
594
|
+
error_class = entry[:error_class]
|
|
595
|
+
error_message = entry[:error_message]
|
|
596
|
+
retry_delay = entry[:retry_delay]
|
|
597
|
+
|
|
598
|
+
# Stop agent thinking spinner (if active)
|
|
599
|
+
unless @quiet
|
|
600
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
601
|
+
@spinner_manager.stop(spinner_key) if @spinner_manager.active?(spinner_key)
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
lines = [
|
|
605
|
+
@pastel.yellow("LLM API request failed (attempt #{attempt}/#{max_retries})"),
|
|
606
|
+
@pastel.dim("Error: #{error_class}: #{error_message}"),
|
|
607
|
+
@pastel.dim("Retrying in #{retry_delay}s..."),
|
|
608
|
+
]
|
|
609
|
+
|
|
610
|
+
@output.puts @panel.render(
|
|
611
|
+
type: :warning,
|
|
612
|
+
title: "RETRY #{@agent_badge.render(agent)}",
|
|
613
|
+
lines: lines,
|
|
614
|
+
indent: @depth_tracker.get(agent),
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
# Restart spinner for next attempt
|
|
618
|
+
unless @quiet
|
|
619
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
620
|
+
@spinner_manager.start(spinner_key, "#{agent} is retrying...")
|
|
621
|
+
end
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def handle_llm_retry_exhausted(entry)
|
|
625
|
+
agent = entry[:agent]
|
|
626
|
+
attempts = entry[:attempts]
|
|
627
|
+
error_class = entry[:error_class]
|
|
628
|
+
error_message = entry[:error_message]
|
|
629
|
+
|
|
630
|
+
# Stop agent thinking spinner (if active)
|
|
631
|
+
unless @quiet
|
|
632
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
633
|
+
@spinner_manager.stop(spinner_key) if @spinner_manager.active?(spinner_key)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
lines = [
|
|
637
|
+
@pastel.red("LLM API request failed after #{attempts} attempts"),
|
|
638
|
+
@pastel.dim("Error: #{error_class}: #{error_message}"),
|
|
639
|
+
@pastel.dim("No more retries available"),
|
|
640
|
+
]
|
|
641
|
+
|
|
642
|
+
@output.puts @panel.render(
|
|
643
|
+
type: :error,
|
|
644
|
+
title: "RETRY EXHAUSTED #{@agent_badge.render(agent)}",
|
|
645
|
+
lines: lines,
|
|
646
|
+
indent: @depth_tracker.get(agent),
|
|
647
|
+
)
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
def handle_response_parse_error(entry)
|
|
651
|
+
agent = entry[:agent]
|
|
652
|
+
error_class = entry[:error_class]
|
|
653
|
+
error_message = entry[:error_message]
|
|
654
|
+
|
|
655
|
+
# Stop agent thinking spinner (if active)
|
|
656
|
+
unless @quiet
|
|
657
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
658
|
+
@spinner_manager.stop(spinner_key) if @spinner_manager.active?(spinner_key)
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
lines = [
|
|
662
|
+
@pastel.red("Failed to parse LLM API response"),
|
|
663
|
+
@pastel.dim("Error: #{error_class}: #{error_message}"),
|
|
664
|
+
]
|
|
665
|
+
|
|
666
|
+
# Add response body preview if available (truncated)
|
|
667
|
+
if entry[:response_body]
|
|
668
|
+
body_preview = entry[:response_body].to_s[0..200]
|
|
669
|
+
body_preview += "..." if entry[:response_body].to_s.length > 200
|
|
670
|
+
lines << @pastel.dim("Response: #{body_preview}")
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
@output.puts @panel.render(
|
|
674
|
+
type: :error,
|
|
675
|
+
title: "PARSE ERROR #{@agent_badge.render(agent)}",
|
|
676
|
+
lines: lines,
|
|
677
|
+
indent: @depth_tracker.get(agent),
|
|
678
|
+
)
|
|
679
|
+
end
|
|
680
|
+
|
|
578
681
|
def display_todo_list(agent, timestamp)
|
|
579
682
|
todos = SwarmSDK::Tools::Stores::TodoManager.get_todos(agent.to_sym)
|
|
580
683
|
indent = @depth_tracker.indent(agent)
|
|
@@ -81,6 +81,9 @@ module SwarmCLI
|
|
|
81
81
|
display_session_summary
|
|
82
82
|
exit(130)
|
|
83
83
|
ensure
|
|
84
|
+
# Defensive: ensure all spinners are stopped on exit
|
|
85
|
+
@formatter&.spinner_manager&.stop_all
|
|
86
|
+
|
|
84
87
|
# Save history on exit
|
|
85
88
|
save_persistent_history
|
|
86
89
|
end
|
|
@@ -432,11 +435,12 @@ module SwarmCLI
|
|
|
432
435
|
end
|
|
433
436
|
end
|
|
434
437
|
|
|
438
|
+
# CRITICAL: Stop all spinners after execution completes
|
|
439
|
+
# This ensures spinner doesn't interfere with error/success display or REPL prompt
|
|
440
|
+
@formatter.spinner_manager.stop_all
|
|
441
|
+
|
|
435
442
|
# Handle cancellation (result is nil when cancelled)
|
|
436
443
|
if result.nil?
|
|
437
|
-
# Stop all active spinners
|
|
438
|
-
@formatter.spinner_manager.stop_all
|
|
439
|
-
|
|
440
444
|
puts ""
|
|
441
445
|
puts @colors[:warning].call("✗ Request cancelled by user")
|
|
442
446
|
puts ""
|
|
@@ -459,6 +463,8 @@ module SwarmCLI
|
|
|
459
463
|
# Add response to history
|
|
460
464
|
@conversation_history << { role: "agent", content: result.content }
|
|
461
465
|
rescue StandardError => e
|
|
466
|
+
# Defensive: ensure spinners are stopped on exception
|
|
467
|
+
@formatter.spinner_manager.stop_all
|
|
462
468
|
@formatter.on_error(error: e)
|
|
463
469
|
end
|
|
464
470
|
|
data/lib/swarm_cli/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: swarm_cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Paulo Arruda
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '2.
|
|
46
|
+
version: '2.2'
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '2.
|
|
53
|
+
version: '2.2'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: tty-box
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|