legion-tty 0.4.5 → 0.4.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/legion/tty/components/notification.rb +42 -0
- data/lib/legion/tty/screens/chat.rb +72 -2
- data/lib/legion/tty/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 750c41521ce23860a6e8613b4e84471e4c2813657ec68f23b24fcf0aa7015ecd
|
|
4
|
+
data.tar.gz: b203df2393abcc0afa085b7ec30c73fbbe3815d2f9886d1b3744fdbbf1fddc62
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06d4eab7afdfbdb8933c3166c3b5dc3cd028c7462f29d4601364ba759ae9b648bbdd1a7e4f304587dcc1148af166840815bba87d5c81044cd622355964cb9cc1
|
|
7
|
+
data.tar.gz: e331268056bf882144790fe0c88f95454050a6b16a017b033f00e29785f71a027107784fc8a4e25906a3d3cd733c0d20454577423d2e5a038b21b6d9fb490c29
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.6] - 2026-03-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `/stats` command: show conversation statistics (message counts, characters, token summary)
|
|
7
|
+
- `/personality <style>` command: switch between default/concise/detailed/friendly/technical personas
|
|
8
|
+
- Notification component: transient message display with TTL expiry and level-based icons/colors
|
|
9
|
+
|
|
3
10
|
## [0.4.5] - 2026-03-19
|
|
4
11
|
|
|
5
12
|
### Added
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../theme'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module TTY
|
|
7
|
+
module Components
|
|
8
|
+
class Notification
|
|
9
|
+
LEVELS = %i[info success warning error].freeze
|
|
10
|
+
ICONS = { info: 'i', success: '+', warning: '!', error: 'x' }.freeze
|
|
11
|
+
COLORS = { info: :info, success: :success, warning: :warning, error: :error }.freeze
|
|
12
|
+
|
|
13
|
+
attr_reader :message, :level, :created_at
|
|
14
|
+
|
|
15
|
+
def initialize(message:, level: :info, ttl: 5)
|
|
16
|
+
@message = message
|
|
17
|
+
@level = LEVELS.include?(level) ? level : :info
|
|
18
|
+
@ttl = ttl
|
|
19
|
+
@created_at = Time.now
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def expired?
|
|
23
|
+
Time.now - @created_at > @ttl
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def render(width: 80)
|
|
27
|
+
icon = Theme.c(COLORS[@level], ICONS[@level])
|
|
28
|
+
text = Theme.c(COLORS[@level], @message)
|
|
29
|
+
line = "#{icon} #{text}"
|
|
30
|
+
plain_len = strip_ansi(line).length
|
|
31
|
+
line + (' ' * [width - plain_len, 0].max)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def strip_ansi(str)
|
|
37
|
+
str.gsub(/\e\[[0-9;]*m/, '')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -14,7 +14,15 @@ module Legion
|
|
|
14
14
|
class Chat < Base
|
|
15
15
|
SLASH_COMMANDS = %w[/help /quit /clear /compact /copy /diff /model /session /cost /export /tools /dashboard
|
|
16
16
|
/hotkeys /save /load /sessions /system /delete /plan /palette /extensions /config
|
|
17
|
-
/theme /search].freeze
|
|
17
|
+
/theme /search /stats /personality].freeze
|
|
18
|
+
|
|
19
|
+
PERSONALITIES = {
|
|
20
|
+
'default' => 'You are Legion, an async cognition engine and AI assistant. Be helpful and concise.',
|
|
21
|
+
'concise' => 'You are Legion. Respond in as few words as possible. No filler.',
|
|
22
|
+
'detailed' => 'You are Legion. Provide thorough, detailed explanations with examples when helpful.',
|
|
23
|
+
'friendly' => 'You are Legion, a friendly AI companion. Use a warm, conversational tone.',
|
|
24
|
+
'technical' => 'You are Legion, a senior engineer. Use precise technical language. Include code examples.'
|
|
25
|
+
}.freeze
|
|
18
26
|
|
|
19
27
|
attr_reader :message_stream, :status_bar
|
|
20
28
|
|
|
@@ -281,6 +289,8 @@ module Legion
|
|
|
281
289
|
when '/config' then handle_config_screen
|
|
282
290
|
when '/theme' then handle_theme(input)
|
|
283
291
|
when '/search' then handle_search(input)
|
|
292
|
+
when '/stats' then handle_stats
|
|
293
|
+
when '/personality' then handle_personality(input)
|
|
284
294
|
else :handled
|
|
285
295
|
end
|
|
286
296
|
end
|
|
@@ -296,7 +306,9 @@ module Legion
|
|
|
296
306
|
"/search <text> -- search message history\n " \
|
|
297
307
|
"/compact [n] -- keep last n message pairs (default 5)\n " \
|
|
298
308
|
"/copy -- copy last assistant message to clipboard\n " \
|
|
299
|
-
"/diff -- show new messages since session was loaded\n
|
|
309
|
+
"/diff -- show new messages since session was loaded\n " \
|
|
310
|
+
"/stats -- show conversation statistics\n " \
|
|
311
|
+
"/personality [name] -- switch assistant personality\n\n" \
|
|
300
312
|
'Hotkeys: Ctrl+D=dashboard Ctrl+K=palette Ctrl+S=sessions Esc=back'
|
|
301
313
|
)
|
|
302
314
|
:handled
|
|
@@ -619,6 +631,64 @@ module Legion
|
|
|
619
631
|
:handled
|
|
620
632
|
end
|
|
621
633
|
|
|
634
|
+
def handle_stats
|
|
635
|
+
@message_stream.add_message(role: :system, content: build_stats_lines.join("\n"))
|
|
636
|
+
:handled
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
def build_stats_lines
|
|
640
|
+
msgs = @message_stream.messages
|
|
641
|
+
counts = count_by_role(msgs)
|
|
642
|
+
total_chars = msgs.sum { |m| m[:content].to_s.length }
|
|
643
|
+
lines = stats_header_lines(msgs, counts, total_chars)
|
|
644
|
+
lines << " Tool calls: #{counts[:tool]}" if counts[:tool].positive?
|
|
645
|
+
lines
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
def count_by_role(msgs)
|
|
649
|
+
%i[user assistant system tool].to_h { |role| [role, msgs.count { |m| m[:role] == role }] }
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
def stats_header_lines(msgs, counts, total_chars)
|
|
653
|
+
[
|
|
654
|
+
"Messages: #{msgs.size} total",
|
|
655
|
+
" User: #{counts[:user]}, Assistant: #{counts[:assistant]}, System: #{counts[:system]}",
|
|
656
|
+
"Characters: #{format_stat_number(total_chars)}",
|
|
657
|
+
"Session: #{@session_name}",
|
|
658
|
+
"Tokens: #{@token_tracker.summary}"
|
|
659
|
+
]
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
def format_stat_number(num)
|
|
663
|
+
num.to_s.chars.reverse.each_slice(3).map(&:join).join(',').reverse
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
def handle_personality(input)
|
|
667
|
+
name = input.split(nil, 2)[1]
|
|
668
|
+
if name && PERSONALITIES.key?(name)
|
|
669
|
+
apply_personality(name)
|
|
670
|
+
elsif name
|
|
671
|
+
available = PERSONALITIES.keys.join(', ')
|
|
672
|
+
@message_stream.add_message(role: :system,
|
|
673
|
+
content: "Unknown personality '#{name}'. Available: #{available}")
|
|
674
|
+
else
|
|
675
|
+
current = @personality || 'default'
|
|
676
|
+
available = PERSONALITIES.keys.join(', ')
|
|
677
|
+
@message_stream.add_message(role: :system, content: "Current: #{current}\nAvailable: #{available}")
|
|
678
|
+
end
|
|
679
|
+
:handled
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
def apply_personality(name)
|
|
683
|
+
@personality = name
|
|
684
|
+
if @llm_chat.respond_to?(:with_instructions)
|
|
685
|
+
@llm_chat.with_instructions(PERSONALITIES[name])
|
|
686
|
+
@message_stream.add_message(role: :system, content: "Personality switched to: #{name}")
|
|
687
|
+
else
|
|
688
|
+
@message_stream.add_message(role: :system, content: "Personality set to: #{name} (no active LLM)")
|
|
689
|
+
end
|
|
690
|
+
end
|
|
691
|
+
|
|
622
692
|
# rubocop:disable Metrics/AbcSize
|
|
623
693
|
def handle_compact(input)
|
|
624
694
|
keep = (input.split(nil, 2)[1] || '5').to_i.clamp(1, 50)
|
data/lib/legion/tty/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: legion-tty
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -207,6 +207,7 @@ files:
|
|
|
207
207
|
- lib/legion/tty/components/markdown_view.rb
|
|
208
208
|
- lib/legion/tty/components/message_stream.rb
|
|
209
209
|
- lib/legion/tty/components/model_picker.rb
|
|
210
|
+
- lib/legion/tty/components/notification.rb
|
|
210
211
|
- lib/legion/tty/components/progress_panel.rb
|
|
211
212
|
- lib/legion/tty/components/session_picker.rb
|
|
212
213
|
- lib/legion/tty/components/status_bar.rb
|