legion-tty 0.4.4 → 0.4.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ea19b2f60e08522ddf09e24a577b745804f35189f764a9e8150a802f3dc33b5
4
- data.tar.gz: a1ff57a93aba51bc23f0421fa8f35525251f0dcd73f858b004965d68aeaf0083
3
+ metadata.gz: e82df7132986b553218c083f5b414f549a4aa72b1aa7cdf3a62bec7e944ff43d
4
+ data.tar.gz: d05fe8cc4cf17d78301d2a321fee9c9ebd1d9030973322973bd59b404f502f21
5
5
  SHA512:
6
- metadata.gz: '00195e25f48241ad47b602d4d37b4d19bb1c1dc817d63ecc144ffa145e198974e37020065b2937c6864d5917ad13fd98870c9396d5bd0e2aafaf1e6d4f58e5e7'
7
- data.tar.gz: 4b0c13ed2eaee447e559fd030f6e096c87ffac1b60316d525151a157820faf7510abda2fe40938916fffc67a1a385192511b3693b4005c43c89a62189bbcb231
6
+ metadata.gz: 357be1595f03767084c835e496c2609714bbe558ee486ec111d7d67ae6c43f44fbc09fb81518f64e0828bc3b582a658ed1c728b07bae5000a7b3107bd190d99a
7
+ data.tar.gz: 6ae28cd4f18f1a1e10f20ccfac53bface69bf65d7d5221b33f6f33b9ca3315dc2913da69abfa4758bf18c2caa84ef36e3f678ac5aea06ead5da68494f94f61ec
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.5] - 2026-03-19
4
+
5
+ ### Added
6
+ - `/compact [N]` command: remove older messages, keep last N pairs (default 5)
7
+ - `/copy` command: copy last assistant response to clipboard (macOS pbcopy, Linux xclip)
8
+ - `/diff` command: show new messages since last session load
9
+ - Session load tracking: `@loaded_message_count` for diff comparison
10
+
3
11
  ## [0.4.4] - 2026-03-19
4
12
 
5
13
  ### Added
@@ -12,8 +12,9 @@ module Legion
12
12
  module Screens
13
13
  # rubocop:disable Metrics/ClassLength
14
14
  class Chat < Base
15
- SLASH_COMMANDS = %w[/help /quit /clear /model /session /cost /export /tools /dashboard /hotkeys /save /load
16
- /sessions /system /delete /plan /palette /extensions /config /theme /search].freeze
15
+ SLASH_COMMANDS = %w[/help /quit /clear /compact /copy /diff /model /session /cost /export /tools /dashboard
16
+ /hotkeys /save /load /sessions /system /delete /plan /palette /extensions /config
17
+ /theme /search].freeze
17
18
 
18
19
  attr_reader :message_stream, :status_bar
19
20
 
@@ -259,6 +260,9 @@ module Legion
259
260
  when '/quit' then :quit
260
261
  when '/help' then handle_help
261
262
  when '/clear' then handle_clear
263
+ when '/compact' then handle_compact(input)
264
+ when '/copy' then handle_copy(input)
265
+ when '/diff' then handle_diff(input)
262
266
  when '/model' then handle_model(input)
263
267
  when '/session' then handle_session(input)
264
268
  when '/cost' then handle_cost
@@ -289,7 +293,10 @@ module Legion
289
293
  "/export [md|json] /tools /dashboard /hotkeys /save /load /sessions\n " \
290
294
  "/system <prompt> /delete <session> /plan /palette /extensions /config\n " \
291
295
  "/theme [name] -- switch color theme (purple, green, blue, amber)\n " \
292
- "/search <text> -- search message history\n\n" \
296
+ "/search <text> -- search message history\n " \
297
+ "/compact [n] -- keep last n message pairs (default 5)\n " \
298
+ "/copy -- copy last assistant message to clipboard\n " \
299
+ "/diff -- show new messages since session was loaded\n\n" \
293
300
  'Hotkeys: Ctrl+D=dashboard Ctrl+K=palette Ctrl+S=sessions Esc=back'
294
301
  )
295
302
  :handled
@@ -399,6 +406,7 @@ module Legion
399
406
  return :handled
400
407
  end
401
408
  @message_stream.messages.replace(data[:messages])
409
+ @loaded_message_count = @message_stream.messages.size
402
410
  @session_name = name
403
411
  @status_bar.update(session: name)
404
412
  @message_stream.add_message(role: :system,
@@ -611,6 +619,73 @@ module Legion
611
619
  :handled
612
620
  end
613
621
 
622
+ # rubocop:disable Metrics/AbcSize
623
+ def handle_compact(input)
624
+ keep = (input.split(nil, 2)[1] || '5').to_i.clamp(1, 50)
625
+ msgs = @message_stream.messages
626
+ if msgs.size <= keep * 2
627
+ @message_stream.add_message(role: :system, content: 'Conversation is already compact.')
628
+ return :handled
629
+ end
630
+
631
+ system_msgs = msgs.select { |m| m[:role] == :system }
632
+ recent = msgs.reject { |m| m[:role] == :system }.last(keep * 2)
633
+ removed_count = msgs.size - system_msgs.size - recent.size
634
+ @message_stream.messages.replace(system_msgs + recent)
635
+ @message_stream.add_message(
636
+ role: :system,
637
+ content: "Compacted: removed #{removed_count} older messages, kept #{recent.size} recent."
638
+ )
639
+ :handled
640
+ end
641
+ # rubocop:enable Metrics/AbcSize
642
+
643
+ def handle_copy(_input)
644
+ last_assistant = @message_stream.messages.reverse.find { |m| m[:role] == :assistant }
645
+ unless last_assistant
646
+ @message_stream.add_message(role: :system, content: 'No assistant message to copy.')
647
+ return :handled
648
+ end
649
+
650
+ content = last_assistant[:content].to_s
651
+ copy_to_clipboard(content)
652
+ @message_stream.add_message(
653
+ role: :system,
654
+ content: "Copied #{content.length} characters to clipboard."
655
+ )
656
+ :handled
657
+ end
658
+
659
+ def copy_to_clipboard(text)
660
+ IO.popen('pbcopy', 'w') { |io| io.write(text) }
661
+ rescue Errno::ENOENT
662
+ begin
663
+ IO.popen('xclip -selection clipboard', 'w') { |io| io.write(text) }
664
+ rescue Errno::ENOENT
665
+ nil
666
+ end
667
+ end
668
+
669
+ def handle_diff(_input)
670
+ if @loaded_message_count.nil?
671
+ @message_stream.add_message(role: :system, content: 'No session was loaded. Nothing to diff against.')
672
+ return :handled
673
+ end
674
+
675
+ new_count = @message_stream.messages.size - @loaded_message_count
676
+ if new_count <= 0
677
+ @message_stream.add_message(role: :system, content: 'No new messages since session was loaded.')
678
+ else
679
+ new_msgs = @message_stream.messages.last(new_count)
680
+ lines = new_msgs.map { |m| " + [#{m[:role]}] #{truncate_text(m[:content].to_s, 60)}" }
681
+ @message_stream.add_message(
682
+ role: :system,
683
+ content: "#{new_count} new message(s) since load:\n#{lines.join("\n")}"
684
+ )
685
+ end
686
+ :handled
687
+ end
688
+
614
689
  def search_messages(query)
615
690
  pattern = query.downcase
616
691
  @message_stream.messages.select do |msg|
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module TTY
5
- VERSION = '0.4.4'
5
+ VERSION = '0.4.5'
6
6
  end
7
7
  end
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
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity