samagotchi 0.62.0 → 0.64.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 +78 -1
- data/README.md +4 -1
- data/bin/chi +3 -2
- data/docs/architecture.md +12 -2
- data/docs/cli.md +20 -9
- data/docs/configuration.md +16 -9
- data/docs/context.md +13 -3
- data/docs/hooks.md +6 -3
- data/docs/internals/engine.md +10 -3
- data/docs/memory.md +1 -1
- data/docs/plugins.md +96 -2
- data/docs/releasing.md +1 -1
- data/docs/sessions.md +11 -8
- data/docs/sub-agent.md +27 -4
- data/docs/testing.md +13 -4
- data/lib/samagotchi/answer_command.rb +5 -1
- data/lib/samagotchi/answer_refs.rb +18 -26
- data/lib/samagotchi/bridge/turn_accumulator.rb +1 -0
- data/lib/samagotchi/bridge.rb +41 -5
- data/lib/samagotchi/bundles/claude-peer/manifest.yml +22 -0
- data/lib/samagotchi/bundles/claude-peer/plugin.rb +406 -0
- data/lib/samagotchi/bundles/claude-peer/scripts/chi-peer-SKILL.md +104 -0
- data/lib/samagotchi/bundles/claude-peer/scripts/pair +66 -0
- data/lib/samagotchi/bundles/claude-peer/skill_claude_peer.md +60 -0
- data/lib/samagotchi/bundles/dev/manifest.yml +2 -1
- data/lib/samagotchi/bundles/loop-guard/manifest.yml +2 -2
- data/lib/samagotchi/bundles/loop-guard/plugin.rb +17 -6
- data/lib/samagotchi/bundles/slow-commands/manifest.yml +2 -2
- data/lib/samagotchi/bundles/slow-commands/plugin.rb +5 -3
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +1 -1
- data/lib/samagotchi/bundles/system/manifest.yml +3 -3
- data/lib/samagotchi/bundles/system/memory_guide.md +1 -1
- data/lib/samagotchi/child_reports.rb +7 -2
- data/lib/samagotchi/cli/parent_wait.rb +9 -2
- data/lib/samagotchi/composer_route.rb +90 -0
- data/lib/samagotchi/config.rb +6 -3
- data/lib/samagotchi/context_absorber.rb +25 -6
- data/lib/samagotchi/continue_offer.rb +17 -3
- data/lib/samagotchi/delivery.rb +13 -8
- data/lib/samagotchi/engine.rb +2 -0
- data/lib/samagotchi/host_config.rb +6 -6
- data/lib/samagotchi/host_model.rb +2 -2
- data/lib/samagotchi/idle_recap.rb +2 -3
- data/lib/samagotchi/image_store.rb +8 -0
- data/lib/samagotchi/interrupted_turn.rb +7 -3
- data/lib/samagotchi/last_turn.rb +5 -2
- data/lib/samagotchi/pending_input_queue.rb +10 -3
- data/lib/samagotchi/plugin/attached_context.rb +7 -4
- data/lib/samagotchi/plugin/sessions.rb +27 -5
- data/lib/samagotchi/recap_setup.rb +3 -3
- data/lib/samagotchi/reply_wait.rb +171 -6
- data/lib/samagotchi/row_refs.rb +3 -4
- data/lib/samagotchi/send_command.rb +63 -19
- data/lib/samagotchi/session.rb +12 -0
- data/lib/samagotchi/session_commands.rb +1 -1
- data/lib/samagotchi/session_inbox.rb +63 -7
- data/lib/samagotchi/session_manager.rb +49 -20
- data/lib/samagotchi/terminal_ui/attach_launcher.rb +6 -3
- data/lib/samagotchi/terminal_ui/attached_loop.rb +73 -35
- data/lib/samagotchi/terminal_ui/formatting.rb +3 -19
- data/lib/samagotchi/terminal_ui.rb +103 -68
- data/lib/samagotchi/tool_activity.rb +5 -5
- data/lib/samagotchi/tools/delegate.rb +28 -1
- data/lib/samagotchi/tools/delegate_cursor.rb +9 -4
- data/lib/samagotchi/tools/delegate_wait.rb +17 -5
- data/lib/samagotchi/tools/execute.rb +33 -8
- data/lib/samagotchi/turn_checkpoint.rb +9 -3
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +6 -4
- data/lib/samagotchi/web/public/activity.js +2 -2
- data/lib/samagotchi/web/public/app.js +53 -91
- data/lib/samagotchi/web/public/card.js +73 -23
- data/lib/samagotchi/web/public/chains.js +6 -4
- data/lib/samagotchi/web/public/command_view.js +39 -35
- data/lib/samagotchi/web/public/commands.js +8 -8
- data/lib/samagotchi/web/public/composer.js +3 -3
- data/lib/samagotchi/web/public/copy.js +7 -15
- data/lib/samagotchi/web/public/diff_view.js +20 -23
- data/lib/samagotchi/web/public/format.js +0 -48
- data/lib/samagotchi/web/public/images.js +12 -16
- data/lib/samagotchi/web/public/question_cards.js +3 -2
- data/lib/samagotchi/web/public/read_view.js +10 -9
- data/lib/samagotchi/web/public/scope.js +23 -0
- data/lib/samagotchi/web/public/timing.js +2 -8
- data/lib/samagotchi/web/public/turn_html.js +119 -59
- data/lib/samagotchi/web/public/turn_model.js +13 -3
- data/lib/samagotchi/web/public/turn_view.js +73 -116
- data/lib/samagotchi/web/public/vendor/directive.js +8 -0
- data/lib/samagotchi/web/public/vendor/directives/unsafe-html.js +8 -0
- data/lib/samagotchi/worker.rb +53 -35
- data/lib/samagotchi/worker_inbound.rb +12 -11
- metadata +9 -1
data/lib/samagotchi/worker.rb
CHANGED
|
@@ -468,10 +468,10 @@ module Samagotchi
|
|
|
468
468
|
# would keep the hub's "needs you" badge on for good. Dropped and saved
|
|
469
469
|
# before the Engine and the Bridge exist (no question lock, no events).
|
|
470
470
|
def drop_dead_question
|
|
471
|
-
|
|
471
|
+
id = @session.drop_dead_question
|
|
472
|
+
return unless id
|
|
472
473
|
|
|
473
|
-
Log.info(:worker, "dead_question_dropped", id:
|
|
474
|
-
@session.pending_question = nil
|
|
474
|
+
Log.info(:worker, "dead_question_dropped", id: id)
|
|
475
475
|
save_or_log(:dead_question) { @session.save(state_dir: @state_dir) }
|
|
476
476
|
end
|
|
477
477
|
|
|
@@ -900,7 +900,7 @@ module Samagotchi
|
|
|
900
900
|
@reporting_turn = reports_to_parent?(turn_args[:origin])
|
|
901
901
|
restores = @turn_flow.restores
|
|
902
902
|
begin
|
|
903
|
-
@checkpoint.begin_turn(prompt: prompt)
|
|
903
|
+
@checkpoint.begin_turn(prompt: prompt, enqueued_id: turn_args[:origin]&.dig(:enqueued_id))
|
|
904
904
|
@session.status = Session::STATUS_RUNNING
|
|
905
905
|
# A continue that moved this session to the chain's new link wrote
|
|
906
906
|
# the new parent beside it (Session::PARENT_FILE): this turn's
|
|
@@ -929,7 +929,7 @@ module Samagotchi
|
|
|
929
929
|
# no reply: its text is what came before its last tool calls, and a
|
|
930
930
|
# wait (chi send --wait) gets the question instead.
|
|
931
931
|
unless response.nil? || response.strip.empty? || @continue_offer.awaiting?
|
|
932
|
-
SessionInbox.write_output(@session_dir, response)
|
|
932
|
+
SessionInbox.write_output(@session_dir, response, enqueued_id: turn_args[:origin]&.dig(:enqueued_id))
|
|
933
933
|
end
|
|
934
934
|
save_or_log(:turn) { save_session }
|
|
935
935
|
# The reports the turn merged were read unless its end took the turn
|
|
@@ -1045,10 +1045,12 @@ module Samagotchi
|
|
|
1045
1045
|
@pending_input_drain ||= lambda do
|
|
1046
1046
|
# An iteration boundary: tell whoever sent a command now that it waits.
|
|
1047
1047
|
refuse_queued_commands(mid_turn: true)
|
|
1048
|
-
# A line with images runs as its own
|
|
1049
|
-
#
|
|
1048
|
+
# A queued line or one with images runs as its own turn after this
|
|
1049
|
+
# one (steering merges text only): skipped here, not a barrier, so a
|
|
1050
|
+
# line sent after it still goes in at this boundary. Only the files
|
|
1051
|
+
# claimed below reach @merged_this_turn and the checkpoint.
|
|
1050
1052
|
files = SessionInbox.find_new_input_files(@session_dir).sort
|
|
1051
|
-
.
|
|
1053
|
+
.reject { |input_file| SessionInbox.waits_for_turn_end?(input_file) }
|
|
1052
1054
|
merged = files.filter_map do |input_file|
|
|
1053
1055
|
claimed_file = SessionInbox.claim_input_file(input_file)
|
|
1054
1056
|
next unless claimed_file
|
|
@@ -1103,22 +1105,36 @@ module Samagotchi
|
|
|
1103
1105
|
end
|
|
1104
1106
|
|
|
1105
1107
|
# Check again with the event log held, which the Bridge holds while it
|
|
1106
|
-
# queues a POST /turn, then close the Bridge so no client can
|
|
1107
|
-
# after the check, and stop the idle jobs (reminder callback,
|
|
1108
|
+
# queues a POST /turn, then close the Bridge's intake so no client can
|
|
1109
|
+
# queue one after the check, and stop the idle jobs (reminder callback,
|
|
1110
|
+
# recap). The Bridge stops after the log is let go (#stop_bridge_after).
|
|
1108
1111
|
# A client connecting from here on finds no worker: `chi --attach` fails
|
|
1109
1112
|
# and the web stream answers 503 (a small window, left as is).
|
|
1110
1113
|
# @return [Boolean] false when something came in since #due?
|
|
1111
1114
|
def leave_idle
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1115
|
+
stop_bridge_after do
|
|
1116
|
+
@engine.synchronize_events do
|
|
1117
|
+
next false unless @idle_exit.due?
|
|
1118
|
+
|
|
1119
|
+
@bridge&.close_intake
|
|
1120
|
+
@engine.stop_idle
|
|
1121
|
+
log_idle_exit
|
|
1122
|
+
true
|
|
1123
|
+
end
|
|
1119
1124
|
end
|
|
1120
1125
|
end
|
|
1121
1126
|
|
|
1127
|
+
# The Bridge stops once the block (which closed its intake with the
|
|
1128
|
+
# event log held) answers true, outside the log: Bridge#stop waits for
|
|
1129
|
+
# the requests it is answering, and one waiting on the log would hold
|
|
1130
|
+
# it for the whole grace before being killed.
|
|
1131
|
+
# @return [Boolean] what the block answered
|
|
1132
|
+
def stop_bridge_after
|
|
1133
|
+
leaving = yield
|
|
1134
|
+
@bridge&.stop if leaving
|
|
1135
|
+
leaving
|
|
1136
|
+
end
|
|
1137
|
+
|
|
1122
1138
|
# Bridge POST /exit, on a Bridge thread with the event log held.
|
|
1123
1139
|
# +delete+: the session is deleted after (/exit --delete), so no recap.
|
|
1124
1140
|
# +restart+: a new worker takes over (on the newest chi installed), so
|
|
@@ -1140,29 +1156,31 @@ module Samagotchi
|
|
|
1140
1156
|
end
|
|
1141
1157
|
|
|
1142
1158
|
# #leave_idle for an exit a client asked for: check again with the event
|
|
1143
|
-
# log held (a prompt may have come in since), then close the Bridge
|
|
1144
|
-
# stop the idle jobs. Other clients' streams no longer hold: the asker's
|
|
1159
|
+
# log held (a prompt may have come in since), then close the Bridge's
|
|
1160
|
+
# intake and stop the idle jobs (the Bridge stops after the log). Other clients' streams no longer hold: the asker's
|
|
1145
1161
|
# may not have closed yet, and a UI joining now finds the worker gone
|
|
1146
1162
|
# (:stream_closed), the window #leave_idle has too.
|
|
1147
1163
|
# @return [Boolean] false when something came in since the request
|
|
1148
1164
|
def leave_on_request
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1165
|
+
stop_bridge_after do
|
|
1166
|
+
@engine.synchronize_events do
|
|
1167
|
+
hold = if @exit_restart
|
|
1168
|
+
@idle_exit.hold_for_restart
|
|
1169
|
+
else
|
|
1170
|
+
@idle_exit.hold_for_request(requester: @exit_requested_by, streams: false)
|
|
1171
|
+
end
|
|
1172
|
+
if hold
|
|
1173
|
+
@exit_requested = nil
|
|
1174
|
+
@exit_restart = false
|
|
1175
|
+
Log.info(:worker, "exit_held", reason: hold)
|
|
1176
|
+
next false
|
|
1177
|
+
end
|
|
1161
1178
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1179
|
+
@bridge&.close_intake
|
|
1180
|
+
@engine.stop_idle
|
|
1181
|
+
Log.info(:worker, @exit_restart ? "restart_requested" : "exit_requested", by: @exit_requested_by || "a client")
|
|
1182
|
+
true
|
|
1183
|
+
end
|
|
1166
1184
|
end
|
|
1167
1185
|
end
|
|
1168
1186
|
|
|
@@ -106,9 +106,10 @@ module Samagotchi
|
|
|
106
106
|
# run): auto-attached context alone doesn't make a session worth
|
|
107
107
|
# keeping. Saved, then the subscriptions written (a crash between the
|
|
108
108
|
# two re-delivers; the note ids dedupe).
|
|
109
|
-
# +wake+: the session is idle with nothing queued, so
|
|
110
|
-
# source asked to wake
|
|
111
|
-
#
|
|
109
|
+
# +wake+: the session is idle with nothing queued, so a delivery with a
|
|
110
|
+
# wake note (an update whose source asked to wake, or a session push
|
|
111
|
+
# source's first text that asked) may start a turn (#context_wake_for):
|
|
112
|
+
# its wake note goes in as the turn's first message.
|
|
112
113
|
# @return [ContextWake, nil] the wake turn to run now
|
|
113
114
|
# @raise [SystemCallError, IOError] the caller logs it (context_failed)
|
|
114
115
|
def absorb_context(before_turn: false, wake: false)
|
|
@@ -134,7 +135,7 @@ module Samagotchi
|
|
|
134
135
|
waking && ContextWake.new(delivery: waking, turn_id: turn_id)
|
|
135
136
|
end
|
|
136
137
|
|
|
137
|
-
# A failed wake turn kept nothing but its note: the
|
|
138
|
+
# A failed wake turn kept nothing but its note: the note goes back to
|
|
138
139
|
# a plain note (no turn start, the background wording), so a reload
|
|
139
140
|
# draws no empty turn for it.
|
|
140
141
|
def unmark_wake(context_wake)
|
|
@@ -224,13 +225,13 @@ module Samagotchi
|
|
|
224
225
|
true
|
|
225
226
|
end
|
|
226
227
|
|
|
227
|
-
# The
|
|
228
|
-
#
|
|
229
|
-
#
|
|
230
|
-
# session.max_wakes, past the start
|
|
231
|
-
# the session in the last
|
|
232
|
-
#
|
|
233
|
-
# session was away.
|
|
228
|
+
# The delivery in +batch+ that may start a wake turn now: it has a wake
|
|
229
|
+
# note (ContextAbsorber decides: its source asked, wake: true),
|
|
230
|
+
# context.wake is on, the wake budget is open (WorkerWakes#context_open?:
|
|
231
|
+
# no continue offer, not paused, under session.max_wakes, past the start
|
|
232
|
+
# grace) and the source hasn't woken the session in the last
|
|
233
|
+
# CONTEXT_WAKE_WINDOW. The others stay plain notes. Within the start
|
|
234
|
+
# grace a change is a note: it came while the session was away.
|
|
234
235
|
def context_wake_for(batch, now: Time.now)
|
|
235
236
|
candidates = batch.deliveries.select(&:wake_note)
|
|
236
237
|
return nil if candidates.empty? || !context_wakes_on?
|
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.64.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Dedov
|
|
@@ -185,6 +185,11 @@ files:
|
|
|
185
185
|
- lib/samagotchi/bundles/btw/plugin.rb
|
|
186
186
|
- lib/samagotchi/bundles/check-in/manifest.yml
|
|
187
187
|
- lib/samagotchi/bundles/check-in/plugin.rb
|
|
188
|
+
- lib/samagotchi/bundles/claude-peer/manifest.yml
|
|
189
|
+
- lib/samagotchi/bundles/claude-peer/plugin.rb
|
|
190
|
+
- lib/samagotchi/bundles/claude-peer/scripts/chi-peer-SKILL.md
|
|
191
|
+
- lib/samagotchi/bundles/claude-peer/scripts/pair
|
|
192
|
+
- lib/samagotchi/bundles/claude-peer/skill_claude_peer.md
|
|
188
193
|
- lib/samagotchi/bundles/coordinator/manifest.yml
|
|
189
194
|
- lib/samagotchi/bundles/coordinator/plugin.rb
|
|
190
195
|
- lib/samagotchi/bundles/coordinator/skill_coordinator.md
|
|
@@ -230,6 +235,7 @@ files:
|
|
|
230
235
|
- lib/samagotchi/client_id.rb
|
|
231
236
|
- lib/samagotchi/command_steps.rb
|
|
232
237
|
- lib/samagotchi/commands/registry.rb
|
|
238
|
+
- lib/samagotchi/composer_route.rb
|
|
233
239
|
- lib/samagotchi/config.rb
|
|
234
240
|
- lib/samagotchi/config_text_edit.rb
|
|
235
241
|
- lib/samagotchi/context_absorber.rb
|
|
@@ -600,6 +606,8 @@ files:
|
|
|
600
606
|
- lib/samagotchi/web/public/turn_model.js
|
|
601
607
|
- lib/samagotchi/web/public/turn_view.js
|
|
602
608
|
- lib/samagotchi/web/public/update_notice.js
|
|
609
|
+
- lib/samagotchi/web/public/vendor/directive.js
|
|
610
|
+
- lib/samagotchi/web/public/vendor/directives/unsafe-html.js
|
|
603
611
|
- lib/samagotchi/web/public/vendor/lit-html.js
|
|
604
612
|
- lib/samagotchi/web/qr.rb
|
|
605
613
|
- lib/samagotchi/web/server.rb
|