samagotchi 0.153.0 → 0.154.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 +4 -4
- data/CHANGELOG.md +28 -1
- data/README.md +2 -3
- data/bin/chi +23 -24
- data/docs/architecture.md +30 -33
- data/docs/broadcast.md +5 -5
- data/docs/bundles.md +9 -12
- data/docs/cli.md +80 -96
- data/docs/configuration.md +27 -26
- data/docs/context.md +3 -3
- data/docs/desktop.md +1 -1
- data/docs/guardrails.md +8 -10
- data/docs/hooks.md +9 -9
- data/docs/internals/attached-context.md +2 -2
- data/docs/internals/background-tasks.md +3 -4
- data/docs/internals/block-renderers.md +4 -0
- data/docs/internals/bridge.md +3 -3
- data/docs/internals/context-telemetry.md +1 -1
- data/docs/internals/engine.md +33 -7
- data/docs/internals/objectives.md +6 -5
- data/docs/internals/participants.md +7 -7
- data/docs/internals/prompt-caching.md +1 -1
- data/docs/internals/remote-sessions.md +7 -7
- data/docs/internals/web-push.md +1 -1
- data/docs/memory.md +2 -2
- data/docs/plugins.md +23 -28
- data/docs/sessions.md +24 -24
- data/docs/sub-agent.md +2 -2
- data/docs/system-one.md +1 -1
- data/docs/testing.md +16 -6
- data/lib/samagotchi/answer_text.rb +34 -0
- data/lib/samagotchi/bridge.rb +43 -32
- data/lib/samagotchi/bridge_client.rb +10 -9
- data/lib/samagotchi/broadcast/recipients.rb +2 -2
- data/lib/samagotchi/broadcast/triage.rb +1 -1
- data/lib/samagotchi/broadcast_command.rb +5 -5
- data/lib/samagotchi/bundle_command/try/command.rb +1 -1
- data/lib/samagotchi/bundle_command/try/run.rb +1 -1
- data/lib/samagotchi/bundle_command.rb +2 -2
- data/lib/samagotchi/bundles/decision-card/manifest.yml +4 -4
- data/lib/samagotchi/bundles/decision-card/plugin.rb +1 -9
- data/lib/samagotchi/bundles/dev/manifest.yml +2 -2
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +3 -4
- data/lib/samagotchi/bundles/system/manifest.yml +3 -3
- data/lib/samagotchi/bundles/system/self_map.md +1 -1
- data/lib/samagotchi/child_move.rb +3 -3
- data/lib/samagotchi/commands/registry.rb +6 -6
- data/lib/samagotchi/composer_route.rb +4 -5
- data/lib/samagotchi/config.rb +14 -12
- data/lib/samagotchi/context_candidate_choice.rb +1 -1
- data/lib/samagotchi/context_candidates.rb +4 -3
- data/lib/samagotchi/continue_offer.rb +1 -1
- data/lib/samagotchi/debug_log.rb +1 -1
- data/lib/samagotchi/degrade.rb +75 -0
- data/lib/samagotchi/desktop/macos/ChiRunner.swift +2 -2
- data/lib/samagotchi/engine/cards.rb +87 -0
- data/lib/samagotchi/engine/context_judge.rb +138 -0
- data/lib/samagotchi/engine/events.rb +131 -0
- data/lib/samagotchi/engine/guardrails.rb +87 -0
- data/lib/samagotchi/engine/hooks.rb +119 -0
- data/lib/samagotchi/engine/messages.rb +124 -0
- data/lib/samagotchi/engine/model_settings.rb +127 -0
- data/lib/samagotchi/engine/models.rb +261 -0
- data/lib/samagotchi/engine/objectives.rb +116 -0
- data/lib/samagotchi/engine/participants.rb +86 -0
- data/lib/samagotchi/engine/plugins.rb +208 -0
- data/lib/samagotchi/engine/questions.rb +98 -0
- data/lib/samagotchi/engine/recap.rb +130 -0
- data/lib/samagotchi/engine/session.rb +131 -0
- data/lib/samagotchi/engine/side_requests.rb +135 -0
- data/lib/samagotchi/engine/steering.rb +134 -0
- data/lib/samagotchi/engine/toolkit.rb +269 -0
- data/lib/samagotchi/engine/turn_end.rb +180 -0
- data/lib/samagotchi/engine/turn_helpers.rb +160 -0
- data/lib/samagotchi/engine/verify.rb +153 -0
- data/lib/samagotchi/engine.rb +62 -2646
- data/lib/samagotchi/grants.rb +575 -0
- data/lib/samagotchi/guardrail_wiring.rb +2 -2
- data/lib/samagotchi/guardrails/context.rb +2 -3
- data/lib/samagotchi/guardrails/parent_approvals.rb +2 -2
- data/lib/samagotchi/guardrails/parent_policy.rb +2 -2
- data/lib/samagotchi/hook_routes.rb +3 -3
- data/lib/samagotchi/idle_recap.rb +4 -5
- data/lib/samagotchi/idle_reminders.rb +3 -4
- data/lib/samagotchi/iteration_limit.rb +2 -2
- data/lib/samagotchi/kernel_loop.rb +10 -11
- data/lib/samagotchi/launch_mode.rb +13 -32
- data/lib/samagotchi/level_setting_command.rb +3 -2
- data/lib/samagotchi/llm_context_command.rb +3 -2
- data/lib/samagotchi/log.rb +7 -7
- data/lib/samagotchi/log_line.rb +1 -1
- data/lib/samagotchi/log_path.rb +1 -1
- data/lib/samagotchi/note_command.rb +1 -1
- data/lib/samagotchi/note_delivery.rb +18 -8
- data/lib/samagotchi/objectives.rb +24 -3
- data/lib/samagotchi/objectives_check.rb +8 -27
- data/lib/samagotchi/objectives_command.rb +4 -69
- data/lib/samagotchi/objectives_edit.rb +87 -0
- data/lib/samagotchi/output_formatter.rb +7 -1
- data/lib/samagotchi/owner_lock.rb +7 -1
- data/lib/samagotchi/parent_answers_command.rb +5 -4
- data/lib/samagotchi/participant_exposure.rb +42 -0
- data/lib/samagotchi/participant_mode.rb +1 -1
- data/lib/samagotchi/participant_name.rb +1 -1
- data/lib/samagotchi/participants.rb +17 -17
- data/lib/samagotchi/participants_watch.rb +1 -1
- data/lib/samagotchi/pending_input_queue.rb +2 -2
- data/lib/samagotchi/plugin/api.rb +3 -2
- data/lib/samagotchi/plugin/context.rb +21 -7
- data/lib/samagotchi/plugin/peer.rb +2 -1
- data/lib/samagotchi/plugin/sessions.rb +6 -4
- data/lib/samagotchi/plugin_tasks.rb +1 -2
- data/lib/samagotchi/private_files.rb +29 -0
- data/lib/samagotchi/project_env.rb +2 -2
- data/lib/samagotchi/question_desk.rb +8 -7
- data/lib/samagotchi/recap_command.rb +2 -1
- data/lib/samagotchi/recap_setup.rb +1 -1
- data/lib/samagotchi/recap_store.rb +1 -1
- data/lib/samagotchi/redact.rb +86 -0
- data/lib/samagotchi/reminder_queue.rb +2 -2
- data/lib/samagotchi/remote_attach_command.rb +1 -1
- data/lib/samagotchi/reply_wait/poll.rb +2 -2
- data/lib/samagotchi/review_start.rb +1 -1
- data/lib/samagotchi/run_options.rb +6 -6
- data/lib/samagotchi/self_report.rb +42 -39
- data/lib/samagotchi/send_command/busy.rb +1 -1
- data/lib/samagotchi/send_command.rb +4 -1
- data/lib/samagotchi/session.rb +11 -2
- data/lib/samagotchi/session_access/contract.rb +3 -3
- data/lib/samagotchi/session_access/local.rb +9 -9
- data/lib/samagotchi/session_access/remote.rb +17 -7
- data/lib/samagotchi/session_access.rb +4 -4
- data/lib/samagotchi/session_archive_command.rb +2 -2
- data/lib/samagotchi/session_chain.rb +8 -6
- data/lib/samagotchi/session_commands.rb +45 -48
- data/lib/samagotchi/session_continue.rb +1 -1
- data/lib/samagotchi/session_delete_command.rb +4 -4
- data/lib/samagotchi/session_manager.rb +59 -36
- data/lib/samagotchi/session_metrics.rb +2 -2
- data/lib/samagotchi/session_model_settings.rb +3 -2
- data/lib/samagotchi/session_participants.rb +1 -1
- data/lib/samagotchi/session_retention.rb +3 -3
- data/lib/samagotchi/sessions_command.rb +4 -4
- data/lib/samagotchi/share_command.rb +10 -10
- data/lib/samagotchi/steer.rb +1 -1
- data/lib/samagotchi/system_prompt.rb +102 -109
- data/lib/samagotchi/task_watch.rb +1 -1
- data/lib/samagotchi/terminal_ui/attach_launcher.rb +72 -10
- data/lib/samagotchi/terminal_ui/attached_loop/composer.rb +12 -9
- data/lib/samagotchi/terminal_ui/attached_loop/exit_commands.rb +16 -0
- data/lib/samagotchi/terminal_ui/attached_loop/questions.rb +2 -3
- data/lib/samagotchi/terminal_ui/attached_loop.rb +17 -8
- data/lib/samagotchi/terminal_ui/attached_view.rb +2 -3
- data/lib/samagotchi/terminal_ui/event_renderer.rb +3 -5
- data/lib/samagotchi/terminal_ui/formatting.rb +7 -7
- data/lib/samagotchi/terminal_ui/input_support.rb +1 -7
- data/lib/samagotchi/terminal_ui/line_reader.rb +2 -2
- data/lib/samagotchi/terminal_ui/live_region.rb +2 -2
- data/lib/samagotchi/terminal_ui/log_tail.rb +135 -0
- data/lib/samagotchi/terminal_ui/one_shot_sink.rb +2 -2
- data/lib/samagotchi/terminal_ui/plain_surface.rb +1 -1
- data/lib/samagotchi/terminal_ui/question_prompt.rb +4 -5
- data/lib/samagotchi/terminal_ui/reline_seam.rb +3 -3
- data/lib/samagotchi/terminal_ui/status_row.rb +7 -8
- data/lib/samagotchi/terminal_ui.rb +142 -1387
- data/lib/samagotchi/title_command.rb +2 -2
- data/lib/samagotchi/tool_runner.rb +14 -16
- data/lib/samagotchi/toolkit_command.rb +2 -1
- data/lib/samagotchi/tools/delegate.rb +3 -1
- data/lib/samagotchi/tools/delegate_cursor.rb +3 -3
- data/lib/samagotchi/tools/delegate_wait.rb +1 -1
- data/lib/samagotchi/tools/objectives_tool.rb +2 -2
- data/lib/samagotchi/tools/send_note.rb +2 -1
- data/lib/samagotchi/turn_endings.rb +2 -2
- data/lib/samagotchi/turn_flow.rb +4 -5
- data/lib/samagotchi/update_hint.rb +2 -2
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +39 -50
- data/lib/samagotchi/web/participant_access.rb +2 -2
- data/lib/samagotchi/web/participant_review.rb +5 -5
- data/lib/samagotchi/web/participant_stream_filter.rb +8 -8
- data/lib/samagotchi/web/participant_view.rb +2 -82
- data/lib/samagotchi/web/participants_admin.rb +1 -1
- data/lib/samagotchi/web/public/block_host.js +35 -8
- data/lib/samagotchi/web/public/block_renderers.css +9 -5
- data/lib/samagotchi/web/public/chains.js +2 -2
- data/lib/samagotchi/web/public/claim_link.js +4 -4
- data/lib/samagotchi/web/public/composer_mode.js +1 -1
- data/lib/samagotchi/web/public/format.js +3 -3
- data/lib/samagotchi/web/push/store.rb +1 -1
- data/lib/samagotchi/web/session_access_routes.rb +5 -4
- data/lib/samagotchi/web/session_control.rb +12 -8
- data/lib/samagotchi/web/session_create.rb +1 -1
- data/lib/samagotchi/web/session_hub.rb +2 -2
- data/lib/samagotchi/web/session_show.rb +2 -2
- data/lib/samagotchi/web/session_summary.rb +1 -1
- data/lib/samagotchi/worker.rb +100 -9
- data/lib/samagotchi/worker_link.rb +3 -3
- data/lib/samagotchi/working_set_command.rb +3 -2
- metadata +29 -6
- data/lib/samagotchi/terminal_ui/between_turns.rb +0 -138
- data/lib/samagotchi/terminal_ui/repl_input.rb +0 -152
- data/lib/samagotchi/web/grants.rb +0 -575
- data/lib/samagotchi/web/participant_exposure.rb +0 -44
- data/lib/samagotchi/web/private_files.rb +0 -31
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: samagotchi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.154.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Dedov
|
|
@@ -185,6 +185,7 @@ files:
|
|
|
185
185
|
- lib/samagotchi/answer_display.rb
|
|
186
186
|
- lib/samagotchi/answer_refs.rb
|
|
187
187
|
- lib/samagotchi/answer_tail.rb
|
|
188
|
+
- lib/samagotchi/answer_text.rb
|
|
188
189
|
- lib/samagotchi/archive_store.rb
|
|
189
190
|
- lib/samagotchi/atomic_file.rb
|
|
190
191
|
- lib/samagotchi/block_renderers.rb
|
|
@@ -335,6 +336,7 @@ files:
|
|
|
335
336
|
- lib/samagotchi/cut.rb
|
|
336
337
|
- lib/samagotchi/cut_policy.rb
|
|
337
338
|
- lib/samagotchi/debug_log.rb
|
|
339
|
+
- lib/samagotchi/degrade.rb
|
|
338
340
|
- lib/samagotchi/delivery.rb
|
|
339
341
|
- lib/samagotchi/desktop.rb
|
|
340
342
|
- lib/samagotchi/desktop/macos.rb
|
|
@@ -356,6 +358,26 @@ files:
|
|
|
356
358
|
- lib/samagotchi/effective_model.rb
|
|
357
359
|
- lib/samagotchi/empty_answer_retry.rb
|
|
358
360
|
- lib/samagotchi/engine.rb
|
|
361
|
+
- lib/samagotchi/engine/cards.rb
|
|
362
|
+
- lib/samagotchi/engine/context_judge.rb
|
|
363
|
+
- lib/samagotchi/engine/events.rb
|
|
364
|
+
- lib/samagotchi/engine/guardrails.rb
|
|
365
|
+
- lib/samagotchi/engine/hooks.rb
|
|
366
|
+
- lib/samagotchi/engine/messages.rb
|
|
367
|
+
- lib/samagotchi/engine/model_settings.rb
|
|
368
|
+
- lib/samagotchi/engine/models.rb
|
|
369
|
+
- lib/samagotchi/engine/objectives.rb
|
|
370
|
+
- lib/samagotchi/engine/participants.rb
|
|
371
|
+
- lib/samagotchi/engine/plugins.rb
|
|
372
|
+
- lib/samagotchi/engine/questions.rb
|
|
373
|
+
- lib/samagotchi/engine/recap.rb
|
|
374
|
+
- lib/samagotchi/engine/session.rb
|
|
375
|
+
- lib/samagotchi/engine/side_requests.rb
|
|
376
|
+
- lib/samagotchi/engine/steering.rb
|
|
377
|
+
- lib/samagotchi/engine/toolkit.rb
|
|
378
|
+
- lib/samagotchi/engine/turn_end.rb
|
|
379
|
+
- lib/samagotchi/engine/turn_helpers.rb
|
|
380
|
+
- lib/samagotchi/engine/verify.rb
|
|
359
381
|
- lib/samagotchi/engine_peers.rb
|
|
360
382
|
- lib/samagotchi/engine_snapshots.rb
|
|
361
383
|
- lib/samagotchi/event_fanout.rb
|
|
@@ -367,6 +389,7 @@ files:
|
|
|
367
389
|
- lib/samagotchi/generation_phase.rb
|
|
368
390
|
- lib/samagotchi/git_env.rb
|
|
369
391
|
- lib/samagotchi/git_head.rb
|
|
392
|
+
- lib/samagotchi/grants.rb
|
|
370
393
|
- lib/samagotchi/guardrail_wiring.rb
|
|
371
394
|
- lib/samagotchi/guardrails.rb
|
|
372
395
|
- lib/samagotchi/guardrails/approval.rb
|
|
@@ -526,11 +549,13 @@ files:
|
|
|
526
549
|
- lib/samagotchi/objectives_audit.rb
|
|
527
550
|
- lib/samagotchi/objectives_check.rb
|
|
528
551
|
- lib/samagotchi/objectives_command.rb
|
|
552
|
+
- lib/samagotchi/objectives_edit.rb
|
|
529
553
|
- lib/samagotchi/output_formatter.rb
|
|
530
554
|
- lib/samagotchi/owner_lock.rb
|
|
531
555
|
- lib/samagotchi/owner_prompt.rb
|
|
532
556
|
- lib/samagotchi/parent_answers_command.rb
|
|
533
557
|
- lib/samagotchi/parent_report.rb
|
|
558
|
+
- lib/samagotchi/participant_exposure.rb
|
|
534
559
|
- lib/samagotchi/participant_messages.rb
|
|
535
560
|
- lib/samagotchi/participant_mode.rb
|
|
536
561
|
- lib/samagotchi/participant_name.rb
|
|
@@ -557,6 +582,7 @@ files:
|
|
|
557
582
|
- lib/samagotchi/plugin/tool_spec.rb
|
|
558
583
|
- lib/samagotchi/plugin_session_state.rb
|
|
559
584
|
- lib/samagotchi/plugin_tasks.rb
|
|
585
|
+
- lib/samagotchi/private_files.rb
|
|
560
586
|
- lib/samagotchi/process_group.rb
|
|
561
587
|
- lib/samagotchi/project_env.rb
|
|
562
588
|
- lib/samagotchi/project_scope.rb
|
|
@@ -578,6 +604,7 @@ files:
|
|
|
578
604
|
- lib/samagotchi/recap_setup.rb
|
|
579
605
|
- lib/samagotchi/recap_store.rb
|
|
580
606
|
- lib/samagotchi/recap_title.rb
|
|
607
|
+
- lib/samagotchi/redact.rb
|
|
581
608
|
- lib/samagotchi/redacted_inspect.rb
|
|
582
609
|
- lib/samagotchi/ref.rb
|
|
583
610
|
- lib/samagotchi/relay.rb
|
|
@@ -674,7 +701,6 @@ files:
|
|
|
674
701
|
- lib/samagotchi/terminal_ui/attached_loop/queueing.rb
|
|
675
702
|
- lib/samagotchi/terminal_ui/attached_loop/sending.rb
|
|
676
703
|
- lib/samagotchi/terminal_ui/attached_view.rb
|
|
677
|
-
- lib/samagotchi/terminal_ui/between_turns.rb
|
|
678
704
|
- lib/samagotchi/terminal_ui/event_renderer.rb
|
|
679
705
|
- lib/samagotchi/terminal_ui/exit_lines.rb
|
|
680
706
|
- lib/samagotchi/terminal_ui/formatting.rb
|
|
@@ -685,6 +711,7 @@ files:
|
|
|
685
711
|
- lib/samagotchi/terminal_ui/line_reader.rb
|
|
686
712
|
- lib/samagotchi/terminal_ui/live_region.rb
|
|
687
713
|
- lib/samagotchi/terminal_ui/local_link.rb
|
|
714
|
+
- lib/samagotchi/terminal_ui/log_tail.rb
|
|
688
715
|
- lib/samagotchi/terminal_ui/model_segments_text.rb
|
|
689
716
|
- lib/samagotchi/terminal_ui/one_shot_sink.rb
|
|
690
717
|
- lib/samagotchi/terminal_ui/own_turns.rb
|
|
@@ -696,7 +723,6 @@ files:
|
|
|
696
723
|
- lib/samagotchi/terminal_ui/reline_seam.rb
|
|
697
724
|
- lib/samagotchi/terminal_ui/remote_connector.rb
|
|
698
725
|
- lib/samagotchi/terminal_ui/remote_link.rb
|
|
699
|
-
- lib/samagotchi/terminal_ui/repl_input.rb
|
|
700
726
|
- lib/samagotchi/terminal_ui/screen.rb
|
|
701
727
|
- lib/samagotchi/terminal_ui/status_row.rb
|
|
702
728
|
- lib/samagotchi/terminal_ui/surface.rb
|
|
@@ -810,20 +836,17 @@ files:
|
|
|
810
836
|
- lib/samagotchi/web/block_renderer_routes.rb
|
|
811
837
|
- lib/samagotchi/web/capabilities.rb
|
|
812
838
|
- lib/samagotchi/web/editor.rb
|
|
813
|
-
- lib/samagotchi/web/grants.rb
|
|
814
839
|
- lib/samagotchi/web/info_probe.rb
|
|
815
840
|
- lib/samagotchi/web/lan.rb
|
|
816
841
|
- lib/samagotchi/web/link_codes.rb
|
|
817
842
|
- lib/samagotchi/web/markdown_renderer.rb
|
|
818
843
|
- lib/samagotchi/web/message_display.rb
|
|
819
844
|
- lib/samagotchi/web/participant_access.rb
|
|
820
|
-
- lib/samagotchi/web/participant_exposure.rb
|
|
821
845
|
- lib/samagotchi/web/participant_review.rb
|
|
822
846
|
- lib/samagotchi/web/participant_stream_filter.rb
|
|
823
847
|
- lib/samagotchi/web/participant_view.rb
|
|
824
848
|
- lib/samagotchi/web/participants_admin.rb
|
|
825
849
|
- lib/samagotchi/web/principal.rb
|
|
826
|
-
- lib/samagotchi/web/private_files.rb
|
|
827
850
|
- lib/samagotchi/web/project_list.rb
|
|
828
851
|
- lib/samagotchi/web/proxy_gate.rb
|
|
829
852
|
- lib/samagotchi/web/public/activity.js
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "formatting"
|
|
4
|
-
require_relative "event_renderer"
|
|
5
|
-
|
|
6
|
-
module Samagotchi
|
|
7
|
-
class TerminalUI
|
|
8
|
-
# What the REPL prints between turns: cards and plugins' notices shown
|
|
9
|
-
# outside a turn, anytime commands' output, plugins' init lines and load
|
|
10
|
-
# warnings, and a recap written while idle.
|
|
11
|
-
#
|
|
12
|
-
# They are announced on other threads (the Engine's observers, the idle
|
|
13
|
-
# scheduler, an anytime command's own), where they are only kept; the
|
|
14
|
-
# main thread prints them at the open prompt (#flush_recap,
|
|
15
|
-
# #flush_cards), after the command that showed them. One that comes
|
|
16
|
-
# while a turn runs prints at once (above the live region) where the
|
|
17
|
-
# turn wouldn't print it itself.
|
|
18
|
-
class BetweenTurns
|
|
19
|
-
include Formatting
|
|
20
|
-
|
|
21
|
-
# A plugin's init task and a load warning: shown between turns too.
|
|
22
|
-
INIT_EVENTS = %i[plugin_init_started plugin_init_finished guardrail_warning].freeze
|
|
23
|
-
|
|
24
|
-
# @param surface [Surface] where lines print (swapped with #surface=)
|
|
25
|
-
# @param view [AttachedView] turns the activity row for init tasks
|
|
26
|
-
# @param renderer [EventRenderer] draws cards
|
|
27
|
-
# @param turn_running [#call] whether a turn runs now
|
|
28
|
-
# @param quiet [Boolean] a --non-interactive run: no init lines
|
|
29
|
-
# @param gaps [GapClock, nil] the session's last activity: a recap
|
|
30
|
-
# after a quiet gap has its divider
|
|
31
|
-
def initialize(surface:, view:, renderer:, turn_running:, quiet: false, gaps: nil)
|
|
32
|
-
@surface = surface
|
|
33
|
-
@view = view
|
|
34
|
-
@renderer = renderer
|
|
35
|
-
@turn_running = turn_running
|
|
36
|
-
@quiet = quiet
|
|
37
|
-
@cards = Queue.new
|
|
38
|
-
@recap = nil
|
|
39
|
-
@gaps = gaps
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
attr_writer :surface
|
|
43
|
-
|
|
44
|
-
# The Engine's observer for cards, notices and init events (any
|
|
45
|
-
# thread). A card or a plugin's notice shown outside a turn is kept
|
|
46
|
-
# for the next flush; one shown during a turn is a turn event, the
|
|
47
|
-
# turn's sink prints it where it happens (EventRenderer).
|
|
48
|
-
#
|
|
49
|
-
# An anytime command's (event[:anytime]) print as it shows them: on
|
|
50
|
-
# the main thread (the command runs at the prompt) or beside a running
|
|
51
|
-
# turn, else at the next flush.
|
|
52
|
-
#
|
|
53
|
-
# A plugin's init task (chi.init) turns the activity row while it runs
|
|
54
|
-
# and prints a line when it is done; a load warning announced before
|
|
55
|
-
# the first turn, one. Beside a running turn they print at once.
|
|
56
|
-
def observe(event)
|
|
57
|
-
if INIT_EVENTS.include?(event[:type])
|
|
58
|
-
return if @quiet
|
|
59
|
-
return @view.init_started(event) if event[:type] == :plugin_init_started
|
|
60
|
-
|
|
61
|
-
@view.init_finished(event) if event[:type] == :plugin_init_finished
|
|
62
|
-
return show(event) if turn_running?
|
|
63
|
-
|
|
64
|
-
return @cards << event
|
|
65
|
-
end
|
|
66
|
-
return unless (event[:type] == :card && !event[:in_turn]) || (event[:type] == :hook_notice && event[:between_turns])
|
|
67
|
-
return show(event) if event[:anytime] && (Thread.current == Thread.main || turn_running?)
|
|
68
|
-
|
|
69
|
-
@cards << event
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Keep an item for the next flush (any thread).
|
|
73
|
-
def keep(item)
|
|
74
|
-
@cards << item
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# An anytime command's output: beside a running turn at once, else at
|
|
78
|
-
# the next flush.
|
|
79
|
-
def show_or_keep(item)
|
|
80
|
-
turn_running? ? show(item) : keep(item)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# The Engine's observer for :recap_ready (the idle scheduler's thread):
|
|
84
|
-
# kept for #flush_recap. One collected just as a turn started describes
|
|
85
|
-
# the chat before it, and is dropped.
|
|
86
|
-
def take_recap(event)
|
|
87
|
-
return unless event[:type] == :recap_ready
|
|
88
|
-
return if event[:recap].to_s.strip.empty? || turn_running?
|
|
89
|
-
|
|
90
|
-
@recap = { text: event[:recap].to_s, at: event[:created_at] }
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Print a recap written while idle (main thread, at the open prompt).
|
|
94
|
-
def flush_recap
|
|
95
|
-
recap = @recap
|
|
96
|
-
return unless recap
|
|
97
|
-
|
|
98
|
-
@recap = nil
|
|
99
|
-
line = @gaps&.divider
|
|
100
|
-
@surface.commit(gap_divider(line)) if line
|
|
101
|
-
@surface.commit(recap_block(recap[:text], at: recap[:at]))
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Print the cards, notices and anytime commands' output kept since the
|
|
105
|
-
# last flush (main thread). A card replaced later in the same batch
|
|
106
|
-
# (the same id: btw's "thinking…", then its answer) prints once, as its
|
|
107
|
-
# last.
|
|
108
|
-
def flush_cards
|
|
109
|
-
items = []
|
|
110
|
-
loop { items << @cards.pop(true) }
|
|
111
|
-
rescue ThreadError
|
|
112
|
-
items.each_with_index do |item, index|
|
|
113
|
-
replaced = item[:type] == :card && items.drop(index + 1).any? { |later| later[:type] == :card && later[:id] == item[:id] }
|
|
114
|
-
show(item) unless replaced
|
|
115
|
-
end
|
|
116
|
-
nil
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# A card, a notice, an anytime command's output (:command_output), a
|
|
120
|
-
# plugin init task's done line or a load warning.
|
|
121
|
-
def show(item)
|
|
122
|
-
case item[:type]
|
|
123
|
-
when :card then @renderer.render_card(item)
|
|
124
|
-
when :command_output then @surface.commit(item[:text])
|
|
125
|
-
when :guardrail_warning then @surface.commit(EventRenderer.load_warning_line(item))
|
|
126
|
-
when :plugin_init_finished
|
|
127
|
-
line = EventRenderer.init_line(item)
|
|
128
|
-
@surface.commit(line) if line
|
|
129
|
-
else @surface.commit(EventRenderer.hook_notice_line(item))
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
private
|
|
134
|
-
|
|
135
|
-
def turn_running? = @turn_running.call
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "monitor"
|
|
4
|
-
require_relative "line_reader"
|
|
5
|
-
|
|
6
|
-
module Samagotchi
|
|
7
|
-
class TerminalUI
|
|
8
|
-
# The REPL's input on a terminal: one LineReader keeps a prompt open for
|
|
9
|
-
# the whole session, turns included, and this routes what it reads. A
|
|
10
|
-
# line goes to a question waiting at the prompt (asked at ? ), to
|
|
11
|
-
# the running turn when its handler takes it (steering), else to the
|
|
12
|
-
# inbox the REPL loop takes its next line from.
|
|
13
|
-
class ReplInput
|
|
14
|
-
# @param prompt [#call] -> the prompt when no question waits
|
|
15
|
-
# @param read [#call] (prompt, prefill) -> line (nil = Ctrl-D)
|
|
16
|
-
# @param surface [Surface] the editor slot a dropped read leaves is
|
|
17
|
-
# cleared under its lock
|
|
18
|
-
def initialize(prompt:, read:, surface:)
|
|
19
|
-
@prompt = prompt
|
|
20
|
-
@read = read
|
|
21
|
-
@surface = surface
|
|
22
|
-
@inbox = Thread::Queue.new
|
|
23
|
-
# Lines a turn left over: they come before the inbox.
|
|
24
|
-
@front = []
|
|
25
|
-
@turn = nil
|
|
26
|
-
@lock = Monitor.new
|
|
27
|
-
@answers = nil
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def start(prefill: nil)
|
|
31
|
-
@reader = LineReader.new(self, prompt: method(:prompt_text), read: @read, prefill: prefill).start
|
|
32
|
-
self
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def open? = @reader&.alive? || false
|
|
36
|
-
|
|
37
|
-
def stop
|
|
38
|
-
@reader&.stop
|
|
39
|
-
@surface.clear_slot(:editor)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# From the reader thread: [:line, text] or [:interrupt, info].
|
|
43
|
-
def <<(item)
|
|
44
|
-
@lock.synchronize do
|
|
45
|
-
next @answers << item if @answers
|
|
46
|
-
|
|
47
|
-
taken = @turn && item.first == :line && @turn.call(item.last)
|
|
48
|
-
# Not now: the line goes back into the prompt.
|
|
49
|
-
next @reader&.prefill_next(item.last) if taken == :back
|
|
50
|
-
next if taken
|
|
51
|
-
|
|
52
|
-
@inbox << item
|
|
53
|
-
end
|
|
54
|
-
self
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# @return [Array, nil] the next item, nil after +timeout+ seconds
|
|
58
|
-
def pop(timeout:)
|
|
59
|
-
@lock.synchronize { return @front.shift unless @front.empty? }
|
|
60
|
-
@inbox.pop(timeout: timeout)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# While a turn runs, +handler+ (line -> truthy when it took the line,
|
|
64
|
-
# :back to put it back into the prompt) sees each line first. Once it ends, +leftovers+ (-> lines it took that the
|
|
65
|
-
# turn never merged) come next, in order, before anything in the inbox.
|
|
66
|
-
def during_turn(handler, leftovers:)
|
|
67
|
-
@lock.synchronize { @turn = handler }
|
|
68
|
-
yield
|
|
69
|
-
ensure
|
|
70
|
-
@lock.synchronize do
|
|
71
|
-
@turn = nil
|
|
72
|
-
@front.concat(Array(leftovers.call).map { |line| [:line, line] })
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def prompt_text
|
|
77
|
-
@lock.synchronize { @answers ? @choice_prompt : @prompt.call }
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Start the open read again when its prompt changed (a continue offer
|
|
81
|
-
# came or went); what was typed is kept.
|
|
82
|
-
def sync_prompt
|
|
83
|
-
return unless open?
|
|
84
|
-
|
|
85
|
-
with_surface_lock do
|
|
86
|
-
next if @reader.current == prompt_text
|
|
87
|
-
|
|
88
|
-
@surface.clear_slot(:editor)
|
|
89
|
-
@reader.reprompt(keep_text: true)
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Put +text+ into the open prompt, unless something is typed there.
|
|
94
|
-
# @return [Boolean] whether it went in
|
|
95
|
-
def prefill(text) = open? && @reader.prefill(text)
|
|
96
|
-
|
|
97
|
-
# What the open prompt holds, nil when none is open: a line typed
|
|
98
|
-
# ahead there is the next turn's input.
|
|
99
|
-
def typed_text = @reader&.typed_text
|
|
100
|
-
|
|
101
|
-
# Whether the next turn's input is already here: text typed ahead at
|
|
102
|
-
# the open prompt, or a line a turn took as steering but never merged
|
|
103
|
-
# (it runs as the next turn).
|
|
104
|
-
def waiting_input?
|
|
105
|
-
@lock.synchronize { return true unless @front.empty? }
|
|
106
|
-
|
|
107
|
-
!typed_text.to_s.strip.empty?
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# A question answered at the open prompt: the lines submitted from now
|
|
111
|
-
# on go to it, at the ? prompt. What was typed at the prompt is put aside
|
|
112
|
-
# and comes back once the question closes.
|
|
113
|
-
# @yield [Thread::Queue] the answers ([:line, text] or [:interrupt, info])
|
|
114
|
-
# A prompt closed by Ctrl-D mid-turn (the REPL exits after the turn)
|
|
115
|
-
# opens for the question and closes again after it.
|
|
116
|
-
def ask(choice_prompt)
|
|
117
|
-
was_open = open?
|
|
118
|
-
typed = was_open ? @reader.typed_text : nil
|
|
119
|
-
answers = Thread::Queue.new
|
|
120
|
-
@lock.synchronize do
|
|
121
|
-
@answers = answers
|
|
122
|
-
@choice_prompt = choice_prompt
|
|
123
|
-
end
|
|
124
|
-
was_open ? reprompt : start
|
|
125
|
-
yield answers
|
|
126
|
-
ensure
|
|
127
|
-
@lock.synchronize { @answers = nil }
|
|
128
|
-
if !was_open
|
|
129
|
-
stop
|
|
130
|
-
elsif open?
|
|
131
|
-
reprompt(prefill: typed)
|
|
132
|
-
else
|
|
133
|
-
# Ctrl-D at the question ended the reader: start it again.
|
|
134
|
-
start(prefill: typed)
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
private
|
|
139
|
-
|
|
140
|
-
def reprompt(prefill: nil)
|
|
141
|
-
with_surface_lock do
|
|
142
|
-
@surface.clear_slot(:editor)
|
|
143
|
-
@reader.reprompt(prefill: prefill)
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def with_surface_lock(&)
|
|
148
|
-
@surface.respond_to?(:synchronize) ? @surface.synchronize(&) : yield
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|