samagotchi 0.155.0 → 0.157.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 +57 -1
- data/bin/chi +2 -1
- data/docs/architecture.md +22 -13
- data/docs/bundles.md +3 -1
- data/docs/cli.md +9 -8
- data/docs/configuration.md +36 -4
- data/docs/guardrails.md +9 -5
- data/docs/hooks.md +11 -5
- data/docs/internals/anthropic.md +1 -1
- data/docs/internals/attached-context.md +3 -2
- data/docs/internals/background-tasks.md +1 -1
- data/docs/internals/bridge.md +83 -6
- data/docs/internals/bundles.md +28 -18
- data/docs/internals/context-telemetry.md +4 -3
- data/docs/internals/engine.md +641 -937
- data/docs/internals/llm-context-forget.md +8 -3
- data/docs/internals/objectives.md +2 -2
- data/docs/internals/participants.md +3 -2
- data/docs/internals/prompt-caching.md +4 -1
- data/docs/internals/remote-sessions.md +8 -3
- data/docs/internals/web-frontend.md +3 -2
- data/docs/internals/working-set.md +2 -2
- data/docs/memory.md +13 -2
- data/docs/plugins.md +35 -2
- data/docs/sessions.md +11 -11
- data/docs/sub-agent.md +17 -2
- data/docs/system-one.md +3 -2
- data/docs/testing.md +53 -2
- data/lib/samagotchi/answer_command.rb +2 -1
- data/lib/samagotchi/archive_store.rb +4 -3
- data/lib/samagotchi/bootstrap/config_writer.rb +1 -1
- data/lib/samagotchi/bootstrap_command.rb +3 -2
- data/lib/samagotchi/bridge/card_places.rb +10 -4
- data/lib/samagotchi/bridge/card_store.rb +3 -0
- data/lib/samagotchi/bridge/turn_accumulator.rb +109 -9
- data/lib/samagotchi/bridge/turn_drawings.rb +265 -0
- data/lib/samagotchi/bridge.rb +31 -6
- data/lib/samagotchi/broadcast/recipients.rb +8 -8
- data/lib/samagotchi/broadcast/triage_model.rb +1 -1
- data/lib/samagotchi/broadcast_command.rb +3 -3
- data/lib/samagotchi/bundle_command/check.rb +18 -0
- data/lib/samagotchi/bundle_command/try/sandbox.rb +2 -2
- data/lib/samagotchi/bundle_command/try/trace.rb +1 -1
- data/lib/samagotchi/bundle_command.rb +5 -2
- data/lib/samagotchi/bundles/known-names/manifest.yml +4 -7
- data/lib/samagotchi/bundles/known-names/{hooks/known_names.rb → plugin.rb} +17 -0
- data/lib/samagotchi/bundles/source-links/manifest.yml +4 -7
- data/lib/samagotchi/bundles/source-links/{hooks/source_links.rb → plugin.rb} +23 -4
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +2 -2
- data/lib/samagotchi/bundles/system/manifest.yml +3 -3
- data/lib/samagotchi/bundles/system/memory_guide.md +1 -1
- data/lib/samagotchi/child_move.rb +13 -57
- data/lib/samagotchi/child_reports.rb +2 -2
- data/lib/samagotchi/children_status.rb +15 -21
- data/lib/samagotchi/cli/parent_wait.rb +9 -23
- data/lib/samagotchi/config.rb +20 -112
- data/lib/samagotchi/context_command.rb +1 -2
- data/lib/samagotchi/context_sources.rb +5 -4
- data/lib/samagotchi/context_window.rb +9 -12
- data/lib/samagotchi/desktop/macos.rb +1 -1
- data/lib/samagotchi/effective_model.rb +57 -22
- data/lib/samagotchi/engine/context_judge.rb +19 -11
- data/lib/samagotchi/engine/messages.rb +1 -1
- data/lib/samagotchi/engine/models.rb +5 -2
- data/lib/samagotchi/engine/objectives.rb +29 -11
- data/lib/samagotchi/engine/plugins.rb +1 -1
- data/lib/samagotchi/engine/recap.rb +8 -4
- data/lib/samagotchi/engine/side_requests.rb +21 -11
- data/lib/samagotchi/engine/toolkit.rb +10 -9
- data/lib/samagotchi/engine/turn_end.rb +1 -1
- data/lib/samagotchi/engine/turn_helpers.rb +7 -7
- data/lib/samagotchi/engine/verify.rb +1 -1
- data/lib/samagotchi/engine.rb +43 -12
- data/lib/samagotchi/events.rb +3 -2
- data/lib/samagotchi/extension_load.rb +6 -3
- data/lib/samagotchi/guardrails/targets.rb +24 -9
- data/lib/samagotchi/guardrails_command.rb +1 -1
- data/lib/samagotchi/host_address.rb +52 -0
- data/lib/samagotchi/host_config.rb +72 -1
- data/lib/samagotchi/host_model.rb +2 -6
- data/lib/samagotchi/host_registry.rb +58 -46
- data/lib/samagotchi/kernel_loop.rb +53 -124
- data/lib/samagotchi/llm/anthropic_wire.rb +2 -2
- data/lib/samagotchi/llm/chat_loop.rb +40 -21
- data/lib/samagotchi/llm/native_backend.rb +1 -1
- data/lib/samagotchi/llm_context_apply.rb +54 -1
- data/lib/samagotchi/llm_context_notice.rb +1 -1
- data/lib/samagotchi/llm_context_strategy.rb +29 -67
- data/lib/samagotchi/llm_context_view.rb +9 -0
- data/lib/samagotchi/memory_bundle/asset_installer.rb +71 -76
- data/lib/samagotchi/memory_bundle/builder.rb +2 -1
- data/lib/samagotchi/memory_bundle/file_actions.rb +193 -0
- data/lib/samagotchi/memory_bundle/file_digest.rb +13 -0
- data/lib/samagotchi/memory_bundle/file_state.rb +152 -0
- data/lib/samagotchi/memory_bundle/installed_copy.rb +2 -1
- data/lib/samagotchi/memory_bundle/installed_manifest.rb +8 -1
- data/lib/samagotchi/memory_bundle/installer.rb +185 -169
- data/lib/samagotchi/memory_bundle/manifest.rb +14 -4
- data/lib/samagotchi/memory_bundle/merger.rb +69 -65
- data/lib/samagotchi/memory_bundle/plugin_ref.rb +6 -5
- data/lib/samagotchi/memory_bundle/profile.rb +5 -5
- data/lib/samagotchi/memory_bundle/provenance.rb +15 -1
- data/lib/samagotchi/memory_bundle/remerge.rb +25 -12
- data/lib/samagotchi/memory_bundle/shipped_update.rb +51 -6
- data/lib/samagotchi/memory_bundle/status.rb +14 -20
- data/lib/samagotchi/memory_bundle/system_bundle.rb +24 -6
- data/lib/samagotchi/memory_bundle/trash.rb +23 -8
- data/lib/samagotchi/memory_bundle/uninstaller.rb +16 -11
- data/lib/samagotchi/memory_usage.rb +1 -1
- data/lib/samagotchi/model_lookup.rb +75 -0
- data/lib/samagotchi/model_price.rb +4 -10
- data/lib/samagotchi/model_profile.rb +7 -6
- data/lib/samagotchi/model_settings.rb +37 -2
- data/lib/samagotchi/models_command.rb +1 -1
- data/lib/samagotchi/note_command.rb +2 -3
- data/lib/samagotchi/objectives_audit.rb +4 -3
- data/lib/samagotchi/participant_mode.rb +2 -1
- data/lib/samagotchi/participants.rb +2 -2
- data/lib/samagotchi/plugin/api.rb +41 -6
- data/lib/samagotchi/plugin/context.rb +1 -1
- data/lib/samagotchi/plugin/loader.rb +33 -10
- data/lib/samagotchi/plugin/sessions.rb +3 -6
- data/lib/samagotchi/plugin/tool_spec.rb +5 -3
- data/lib/samagotchi/project_env.rb +1 -1
- data/lib/samagotchi/reasoning_history.rb +14 -20
- data/lib/samagotchi/recap_place.rb +27 -0
- data/lib/samagotchi/reminder_carry.rb +1 -1
- data/lib/samagotchi/reply_wait/liveness.rb +38 -0
- data/lib/samagotchi/reply_wait/poll.rb +44 -15
- data/lib/samagotchi/reply_wait/target.rb +113 -0
- data/lib/samagotchi/reply_wait.rb +22 -2
- data/lib/samagotchi/reprefill_meter.rb +45 -0
- data/lib/samagotchi/review_command.rb +1 -1
- data/lib/samagotchi/sampling_settings.rb +9 -16
- data/lib/samagotchi/self_report.rb +36 -37
- data/lib/samagotchi/send_command.rb +17 -23
- data/lib/samagotchi/session.rb +370 -445
- data/lib/samagotchi/session_access/local.rb +12 -11
- data/lib/samagotchi/session_access/remote.rb +22 -6
- data/lib/samagotchi/session_archive_command.rb +2 -2
- data/lib/samagotchi/session_chain.rb +7 -6
- data/lib/samagotchi/session_continue.rb +6 -5
- data/lib/samagotchi/session_delete_command.rb +1 -1
- data/lib/samagotchi/session_field.rb +133 -0
- data/lib/samagotchi/session_inbox.rb +49 -1
- data/lib/samagotchi/session_manager/delivery.rb +254 -0
- data/lib/samagotchi/session_manager/emptiness.rb +139 -0
- data/lib/samagotchi/session_manager/lifecycle.rb +274 -0
- data/lib/samagotchi/session_manager/listing.rb +118 -0
- data/lib/samagotchi/session_manager/removal.rb +190 -0
- data/lib/samagotchi/session_manager/spawn.rb +242 -0
- data/lib/samagotchi/session_manager/worker_command.rb +157 -0
- data/lib/samagotchi/session_manager.rb +28 -1541
- data/lib/samagotchi/session_metrics.rb +8 -5
- data/lib/samagotchi/session_paths.rb +57 -0
- data/lib/samagotchi/session_retention.rb +2 -2
- data/lib/samagotchi/session_row.rb +200 -0
- data/lib/samagotchi/session_setup.rb +15 -12
- data/lib/samagotchi/sessions_command.rb +11 -129
- data/lib/samagotchi/share_command.rb +1 -1
- data/lib/samagotchi/starting_marker.rb +65 -0
- data/lib/samagotchi/steer_cut_after.rb +7 -14
- data/lib/samagotchi/system_one/recorder.rb +49 -0
- data/lib/samagotchi/terminal_ui/attached_loop.rb +6 -26
- data/lib/samagotchi/terminal_ui/exit_lines.rb +1 -1
- data/lib/samagotchi/terminal_ui/join_replay.rb +86 -8
- data/lib/samagotchi/terminal_ui/local_link.rb +2 -2
- data/lib/samagotchi/terminal_ui.rb +5 -7
- data/lib/samagotchi/testing/install.rb +2 -1
- data/lib/samagotchi/testing/sessions.rb +1 -1
- data/lib/samagotchi/thinking.rb +16 -21
- data/lib/samagotchi/token_usage.rb +1 -1
- data/lib/samagotchi/tool_activity.rb +10 -4
- data/lib/samagotchi/tool_declarations.rb +2 -2
- data/lib/samagotchi/tool_output_cut.rb +17 -0
- data/lib/samagotchi/tool_response.rb +5 -3
- data/lib/samagotchi/tool_runner.rb +25 -5
- data/lib/samagotchi/toolkit_command.rb +1 -1
- data/lib/samagotchi/tools/delegate.rb +55 -45
- data/lib/samagotchi/tools/delegate_relay.rb +5 -5
- data/lib/samagotchi/tools/delegate_result.rb +5 -5
- data/lib/samagotchi/tools/delegate_wait.rb +41 -17
- data/lib/samagotchi/tools/index_hint.rb +14 -0
- data/lib/samagotchi/tools/list_sessions.rb +7 -7
- data/lib/samagotchi/tools/registry.rb +28 -11
- data/lib/samagotchi/tools/send_note.rb +4 -6
- data/lib/samagotchi/tools/tool_index.rb +52 -51
- data/lib/samagotchi/tools/tool_surface.rb +22 -8
- data/lib/samagotchi/turn_context.rb +2 -1
- data/lib/samagotchi/turn_stages/context_judge.rb +38 -36
- data/lib/samagotchi/turn_stages/objectives.rb +56 -52
- data/lib/samagotchi/turn_stages/toolkit_suggestion.rb +13 -17
- data/lib/samagotchi/turn_stages/verify_anchors.rb +9 -10
- data/lib/samagotchi/turn_stages/warmup.rb +14 -15
- data/lib/samagotchi/update_command.rb +11 -7
- data/lib/samagotchi/verify_fresh.rb +7 -11
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/vision_support.rb +11 -14
- data/lib/samagotchi/web/app.rb +45 -28
- data/lib/samagotchi/web/message_display.rb +57 -7
- data/lib/samagotchi/web/participant_access.rb +3 -3
- data/lib/samagotchi/web/public/activity.js +16 -7
- data/lib/samagotchi/web/public/app.js +29 -8
- data/lib/samagotchi/web/public/bubbles.js +8 -3
- data/lib/samagotchi/web/public/cards_place.js +15 -0
- data/lib/samagotchi/web/public/commands.js +5 -1
- data/lib/samagotchi/web/public/data.js +4 -2
- data/lib/samagotchi/web/public/history_shape.js +220 -0
- data/lib/samagotchi/web/public/recap_stamp.js +17 -0
- data/lib/samagotchi/web/public/reload_check.js +71 -0
- data/lib/samagotchi/web/public/stage_model.js +7 -5
- data/lib/samagotchi/web/public/stage_view.js +7 -3
- data/lib/samagotchi/web/public/stream_handlers.js +8 -2
- data/lib/samagotchi/web/public/timing.js +43 -2
- data/lib/samagotchi/web/public/turn_block.js +215 -30
- data/lib/samagotchi/web/public/turn_drawing.js +43 -0
- data/lib/samagotchi/web/public/turn_events.js +10 -1
- data/lib/samagotchi/web/public/turn_pieces.js +29 -0
- data/lib/samagotchi/web/reload_check_route.rb +95 -0
- data/lib/samagotchi/web/server.rb +4 -2
- data/lib/samagotchi/web/session_access_routes.rb +6 -6
- data/lib/samagotchi/web/session_control.rb +4 -4
- data/lib/samagotchi/web/session_create.rb +3 -3
- data/lib/samagotchi/web/session_hub.rb +9 -17
- data/lib/samagotchi/web/session_show.rb +67 -5
- data/lib/samagotchi/web/session_summary.rb +39 -28
- data/lib/samagotchi/worker.rb +83 -32
- data/lib/samagotchi/worker_boot.rb +184 -0
- data/lib/samagotchi/worker_link.rb +3 -0
- data/lib/samagotchi/worker_signals.rb +1 -1
- data/lib/samagotchi/worker_task_wakes.rb +2 -2
- metadata +32 -4
- data/lib/samagotchi/send_command/wait_target.rb +0 -85
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "session_manager"
|
|
4
|
+
|
|
5
|
+
module Samagotchi
|
|
6
|
+
# WorkerBoot: the worker process, from run_session_loop (what the boot
|
|
7
|
+
# string SessionManager#worker_command writes runs, through
|
|
8
|
+
# SessionManager.run_session_loop) to what it does as it leaves (CROSS-VERSION
|
|
9
|
+
# CONTRACT: spec/worker_contract_spec.rb). It takes the session's OwnerLock,
|
|
10
|
+
# leaves the spawner's process tree, installs the signals and the project
|
|
11
|
+
# env, and runs the Worker (worker.rb loads only then, after the lock). Calls
|
|
12
|
+
# SessionManager's resume_session, discardable? and delete_session; the env
|
|
13
|
+
# keys it reads are SessionManager's, which the spawner sets.
|
|
14
|
+
module WorkerBoot
|
|
15
|
+
class << self
|
|
16
|
+
# Run the session loop inside the forked process: the worker's main,
|
|
17
|
+
# which the boot string reaches through SessionManager.run_session_loop.
|
|
18
|
+
#
|
|
19
|
+
# Every worker starts its per-session Bridge (the single live client
|
|
20
|
+
# transport) on a port bound to 127.0.0.1 before the loop and stops it on
|
|
21
|
+
# exit. If the bridge fails to start the worker degrades: turns still flow
|
|
22
|
+
# through the input-dir loop, but there is no live SSE or in-process
|
|
23
|
+
# cancel/answer.
|
|
24
|
+
#
|
|
25
|
+
# The worker first takes the session's OwnerLock; when another owner holds
|
|
26
|
+
# it (a racing resume spawned two workers, or the TUI has the session) it
|
|
27
|
+
# exits quietly.
|
|
28
|
+
#
|
|
29
|
+
# A worker nobody uses returns once session.idle_exit_minutes have passed
|
|
30
|
+
# (see WorkerIdleExit), and one a client asked to exit (Bridge POST /exit)
|
|
31
|
+
# returns as soon as nothing keeps it. The next send wakes a new one.
|
|
32
|
+
# @param idle_exit_minutes [Numeric, nil] nil: session.idle_exit_minutes
|
|
33
|
+
# @param poll_interval [Numeric, nil] seconds between the loop's fallback
|
|
34
|
+
# ticks (nil: Worker::FALLBACK_TICK_SECONDS); queued turns wake it at once
|
|
35
|
+
# A stopped session's worker exits 0 (a signalled one too) and a
|
|
36
|
+
# crashed one 1, there.
|
|
37
|
+
# @return [Symbol] :idle_exit, :exit_requested, :restart or :scratch_left
|
|
38
|
+
def run_session_loop(session_id, state_dir: nil, owner_wait: OwnerLock::DEFAULT_WAIT,
|
|
39
|
+
idle_exit_minutes: nil, poll_interval: nil)
|
|
40
|
+
# A worker inherits chi's locale (LC_ALL=C too): read files as UTF-8.
|
|
41
|
+
Utf8Default.apply!
|
|
42
|
+
sd = state_dir || Session.default_state_dir
|
|
43
|
+
# The spawner passed the file and level through ENV; a worker's stderr
|
|
44
|
+
# is /dev/null, so warnings only reach the file.
|
|
45
|
+
Log.configure(stderr: false)
|
|
46
|
+
Log.session_id = session_id
|
|
47
|
+
session_dir = Session.session_dir(session_id, state_dir: sd)
|
|
48
|
+
# Read (and taken out of ENV, so nothing the worker runs inherits it)
|
|
49
|
+
# before anything else: set by spawn_options for a spawned worker.
|
|
50
|
+
spawned = ENV.delete(SessionManager::WORKER_PROCESS_ENV) == "1"
|
|
51
|
+
# Out of the spawner's process tree before the lock (it records this
|
|
52
|
+
# process's pid) and before any thread starts.
|
|
53
|
+
detach_from_spawner(session_dir) if ENV.delete(SessionManager::WORKER_DETACH_ENV) == "1"
|
|
54
|
+
# Kept in a module ivar so the lock's File lives as long as the worker.
|
|
55
|
+
@owner_lock = OwnerLock.acquire(session_dir, kind: "worker", wait: owner_wait)
|
|
56
|
+
exit(0) unless @owner_lock
|
|
57
|
+
# Set by the boot string when the newest installed chi didn't load.
|
|
58
|
+
fallback = ENV.delete(SessionManager::BOOT_FALLBACK_ENV)
|
|
59
|
+
Log.info(:worker, "start", cwd: Dir.pwd, version: VERSION)
|
|
60
|
+
Log.warn(:worker, "boot_fallback", version: VERSION, error: fallback) if fallback
|
|
61
|
+
# Tools follow the project (its `mise env`, computed once per worker;
|
|
62
|
+
# this process's ENV is left as it is); never in a loop run in-process.
|
|
63
|
+
apply_project_env(session_id, state_dir: sd) if spawned
|
|
64
|
+
# A spawned worker stops its turn on TERM/HUP/INT and saves it; a
|
|
65
|
+
# loop run in-process (specs) traps nothing.
|
|
66
|
+
signals = spawned ? WorkerSignals.new.install! : WorkerSignals::NONE
|
|
67
|
+
# Only now, after the detach and the lock: the Engine and all it loads.
|
|
68
|
+
require_relative "worker"
|
|
69
|
+
worker = Worker.new(session_id: session_id, state_dir: sd, session_dir: session_dir,
|
|
70
|
+
idle_exit_minutes: idle_exit_minutes, poll_interval: poll_interval, signals: signals,
|
|
71
|
+
owner_lock: @owner_lock)
|
|
72
|
+
result = begin
|
|
73
|
+
worker.run
|
|
74
|
+
rescue StandardError, ScriptError => e
|
|
75
|
+
# The worker's stderr is /dev/null: the log is the only trace.
|
|
76
|
+
Log.exception(:worker, "crashed", e)
|
|
77
|
+
raise
|
|
78
|
+
ensure
|
|
79
|
+
@owner_lock.release
|
|
80
|
+
# A signal from here on ends the process as Ruby's default does.
|
|
81
|
+
signals.restore!
|
|
82
|
+
end
|
|
83
|
+
Log.info(:worker, "stop", reason: result)
|
|
84
|
+
# A scratch session goes with its worker however it leaves (its
|
|
85
|
+
# terminal deletes it too, whichever comes first); nothing resumes it.
|
|
86
|
+
if worker.scratch?
|
|
87
|
+
delete_left_scratch(session_id, state_dir: sd)
|
|
88
|
+
exit(result == :crashed ? 1 : 0) if %i[stopped signal crashed].include?(result)
|
|
89
|
+
return result
|
|
90
|
+
end
|
|
91
|
+
# A stopped session is left as it is: no resume for input that came
|
|
92
|
+
# in, no discard. One whose worker a signal stopped isn't discarded
|
|
93
|
+
# either; input that came in (queued behind the turn it stopped)
|
|
94
|
+
# wakes a new worker, as after an idle exit.
|
|
95
|
+
exit(0) if result == :stopped
|
|
96
|
+
if result == :signal
|
|
97
|
+
SessionManager.resume_session(session_id, state_dir: sd) unless SessionInbox.find_new_input_files(session_dir).empty?
|
|
98
|
+
exit(0)
|
|
99
|
+
end
|
|
100
|
+
exit(1) if result == :crashed
|
|
101
|
+
# Only after the release: a writer that still saw this worker as the
|
|
102
|
+
# owner may have queued input since the last check. Either it finds no
|
|
103
|
+
# owner after its write and wakes one, or this finds its input.
|
|
104
|
+
# A restart starts its successor here, on the newest chi installed
|
|
105
|
+
# (worker_command), once this one's lock is free.
|
|
106
|
+
# Delegate reports that rang while it left wake one too.
|
|
107
|
+
if result == :restart && Session.stopped_marker?(session_id, state_dir: sd)
|
|
108
|
+
# A stop landed as it left: no successor (resume_session would clear
|
|
109
|
+
# the stop), and the reminders go with it.
|
|
110
|
+
ReminderCarry.remove(session_dir)
|
|
111
|
+
Log.info(:worker, "restart_dropped", why: :stopped)
|
|
112
|
+
elsif result == :restart ||
|
|
113
|
+
(%i[idle_exit exit_requested].include?(result) &&
|
|
114
|
+
(!SessionInbox.find_new_input_files(session_dir).empty? || worker.wake_due?))
|
|
115
|
+
SessionManager.resume_session(session_id, state_dir: sd)
|
|
116
|
+
elsif worker.discard?
|
|
117
|
+
discard_left_session(session_id, state_dir: sd, default_model: worker.default_model)
|
|
118
|
+
end
|
|
119
|
+
result
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# A spawned worker leaves its spawner's process tree: a killer that
|
|
123
|
+
# walks the tree by parent pid (a terminal closing, a tool's teardown
|
|
124
|
+
# of a `chi send --wait` it ran in the background) no longer reaches it.
|
|
125
|
+
# This process (the spawner's child, which its Process.detach waits on)
|
|
126
|
+
# forks the worker, which starts a session of its own (setsid: no
|
|
127
|
+
# controlling terminal, no SIGHUP from one) and returns to run the loop;
|
|
128
|
+
# this one waits until the worker holds the session's OwnerLock, or has
|
|
129
|
+
# exited, or WORKER_START_GRACE passed, and exits: the spawner's waiter
|
|
130
|
+
# stays alive exactly while the worker starts (#still_starting?). The
|
|
131
|
+
# worker is reparented to init (launchd), which reaps it.
|
|
132
|
+
private def detach_from_spawner(session_dir)
|
|
133
|
+
worker = Process.fork
|
|
134
|
+
unless worker
|
|
135
|
+
Process.setsid
|
|
136
|
+
return
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + SessionManager::WORKER_START_GRACE
|
|
140
|
+
until Process.waitpid(worker, Process::WNOHANG) || OwnerLock.owner(session_dir)&.pid == worker ||
|
|
141
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
|
|
142
|
+
sleep(OwnerLock::RETRY_INTERVAL)
|
|
143
|
+
end
|
|
144
|
+
Process.exit!(0)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Delete a scratch session its worker left (its terminal gone:
|
|
148
|
+
# Worker#leave_scratch, or any other way out), now the lock is free.
|
|
149
|
+
# Its terminal may have deleted it first.
|
|
150
|
+
private def delete_left_scratch(session_id, state_dir:)
|
|
151
|
+
SessionManager.delete_session(session_id, state_dir: state_dir)
|
|
152
|
+
Log.info(:worker, "scratch_deleted", sid: session_id)
|
|
153
|
+
rescue SessionManager::DeleteRefused, ArgumentError, SystemCallError => e
|
|
154
|
+
Log.info(:worker, "scratch_kept", sid: session_id, error: e.class.name, msg: e.message)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Delete a session its worker left empty. Checked again now the lock is
|
|
158
|
+
# free: a note or input may have come in since the worker looked, and a
|
|
159
|
+
# worker woken meanwhile owns it (delete_session refuses). A `chi send`
|
|
160
|
+
# landing between this check and the delete fails with "no session"
|
|
161
|
+
# (a window of an empty session's last moments, left as is).
|
|
162
|
+
private def discard_left_session(session_id, state_dir:, default_model:)
|
|
163
|
+
return unless SessionManager.discardable?(session_id, state_dir: state_dir, default_model: default_model)
|
|
164
|
+
|
|
165
|
+
SessionManager.delete_session(session_id, state_dir: state_dir, purge_runs: false)
|
|
166
|
+
Log.info(:worker, "discarded_empty", sid: session_id)
|
|
167
|
+
rescue SessionManager::DeleteRefused, SessionManager::OwnedByTUI, ArgumentError, SystemCallError => e
|
|
168
|
+
Log.info(:worker, "kept_session", sid: session_id, error: e.class.name, msg: e.message)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# The tools' ProjectEnv for the session's folder (its working_directory;
|
|
172
|
+
# spawn_options chdirs there unless it is gone), installed for this
|
|
173
|
+
# process's tool spawns. Never fatal: a worker without it still runs.
|
|
174
|
+
private def apply_project_env(session_id, state_dir:)
|
|
175
|
+
session = Session.summary_from_file(Session.session_file(session_id, state_dir: state_dir))
|
|
176
|
+
dir = session&.working_directory.to_s
|
|
177
|
+
overlay = ProjectEnv.install!(ProjectEnv.compute(dir))
|
|
178
|
+
Log.info(:worker, "project_env_applied", dir: dir, ruby: overlay.ruby) if overlay.applied
|
|
179
|
+
rescue StandardError => e
|
|
180
|
+
Log.warn(:worker, "project_env", reason: "error", error: e.class.name, msg: e.message)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
@@ -113,6 +113,9 @@ module Samagotchi
|
|
|
113
113
|
|
|
114
114
|
def not_live(session_id) = "no live worker for session #{session_id}"
|
|
115
115
|
def unanswered(session_id) = "the worker for session #{session_id} didn't answer"
|
|
116
|
+
# A worker chi started that never came up within its wait (chi send
|
|
117
|
+
# --new's, a delegate child's).
|
|
118
|
+
def did_not_start = "its worker did not start"
|
|
116
119
|
|
|
117
120
|
# @param session_dir [String]
|
|
118
121
|
# @param unlink [Boolean] remove a Stale sidecar (the clients that would
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Samagotchi
|
|
4
4
|
# TERM, HUP and INT in a worker process: the running turn stops as a Stop
|
|
5
5
|
# does (reason :signal), is saved, and the worker leaves (Worker#run
|
|
6
|
-
# returns :signal).
|
|
6
|
+
# returns :signal). WorkerBoot.run_session_loop installs the traps in
|
|
7
7
|
# a spawned worker only (WORKER_PROCESS_ENV), never in a process that runs
|
|
8
8
|
# the loop in-process (the specs, which fire #fire directly).
|
|
9
9
|
#
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
require "securerandom"
|
|
4
4
|
|
|
5
5
|
require_relative "child_reports"
|
|
6
|
-
require_relative "kernel_loop"
|
|
7
6
|
require_relative "log"
|
|
8
7
|
require_relative "task_finish_note"
|
|
9
8
|
require_relative "task_watch"
|
|
9
|
+
require_relative "tool_output_cut"
|
|
10
10
|
require_relative "tools/task_runtime"
|
|
11
11
|
require_relative "worker_inbound"
|
|
12
12
|
require_relative "worker_wakes"
|
|
@@ -130,7 +130,7 @@ module Samagotchi
|
|
|
130
130
|
|
|
131
131
|
def note(entry, record, wake:, turn_id: nil)
|
|
132
132
|
TaskFinishNote.note(record, limit_sec: entry.limit_sec, early_sec: entry.early_sec, wake: wake, turn_id: turn_id,
|
|
133
|
-
cap:
|
|
133
|
+
cap: ToolOutputCut.max_chars(nil))
|
|
134
134
|
end
|
|
135
135
|
|
|
136
136
|
def add_note(entry, record)
|
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.157.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Dedov
|
|
@@ -204,6 +204,7 @@ files:
|
|
|
204
204
|
- lib/samagotchi/bridge/ring_buffer.rb
|
|
205
205
|
- lib/samagotchi/bridge/sse_writer.rb
|
|
206
206
|
- lib/samagotchi/bridge/turn_accumulator.rb
|
|
207
|
+
- lib/samagotchi/bridge/turn_drawings.rb
|
|
207
208
|
- lib/samagotchi/bridge/turn_notice.rb
|
|
208
209
|
- lib/samagotchi/bridge_client.rb
|
|
209
210
|
- lib/samagotchi/bridge_client/event_stream.rb
|
|
@@ -267,9 +268,9 @@ files:
|
|
|
267
268
|
- lib/samagotchi/bundles/guardrails/manifest.yml
|
|
268
269
|
- lib/samagotchi/bundles/inline-widgets/manifest.yml
|
|
269
270
|
- lib/samagotchi/bundles/inline-widgets/plugin.rb
|
|
270
|
-
- lib/samagotchi/bundles/known-names/hooks/known_names.rb
|
|
271
271
|
- lib/samagotchi/bundles/known-names/known_names.md
|
|
272
272
|
- lib/samagotchi/bundles/known-names/manifest.yml
|
|
273
|
+
- lib/samagotchi/bundles/known-names/plugin.rb
|
|
273
274
|
- lib/samagotchi/bundles/loop-guard/manifest.yml
|
|
274
275
|
- lib/samagotchi/bundles/loop-guard/plugin.rb
|
|
275
276
|
- lib/samagotchi/bundles/mcp/manifest.yml
|
|
@@ -284,8 +285,8 @@ files:
|
|
|
284
285
|
- lib/samagotchi/bundles/skills/plugin.rb
|
|
285
286
|
- lib/samagotchi/bundles/slow-commands/manifest.yml
|
|
286
287
|
- lib/samagotchi/bundles/slow-commands/plugin.rb
|
|
287
|
-
- lib/samagotchi/bundles/source-links/hooks/source_links.rb
|
|
288
288
|
- lib/samagotchi/bundles/source-links/manifest.yml
|
|
289
|
+
- lib/samagotchi/bundles/source-links/plugin.rb
|
|
289
290
|
- lib/samagotchi/bundles/source-links/source_links.md
|
|
290
291
|
- lib/samagotchi/bundles/system/config_modification_protocol.md
|
|
291
292
|
- lib/samagotchi/bundles/system/delegated.md
|
|
@@ -438,6 +439,7 @@ files:
|
|
|
438
439
|
- lib/samagotchi/hooks/loader.rb
|
|
439
440
|
- lib/samagotchi/hooks/registry.rb
|
|
440
441
|
- lib/samagotchi/hooks/stream_watch.rb
|
|
442
|
+
- lib/samagotchi/host_address.rb
|
|
441
443
|
- lib/samagotchi/host_config.rb
|
|
442
444
|
- lib/samagotchi/host_keys.rb
|
|
443
445
|
- lib/samagotchi/host_model.rb
|
|
@@ -501,8 +503,10 @@ files:
|
|
|
501
503
|
- lib/samagotchi/memory_bundle/builder.rb
|
|
502
504
|
- lib/samagotchi/memory_bundle/bundle_hook.rb
|
|
503
505
|
- lib/samagotchi/memory_bundle/entry_size.rb
|
|
506
|
+
- lib/samagotchi/memory_bundle/file_actions.rb
|
|
504
507
|
- lib/samagotchi/memory_bundle/file_digest.rb
|
|
505
508
|
- lib/samagotchi/memory_bundle/file_standing.rb
|
|
509
|
+
- lib/samagotchi/memory_bundle/file_state.rb
|
|
506
510
|
- lib/samagotchi/memory_bundle/index_size.rb
|
|
507
511
|
- lib/samagotchi/memory_bundle/index_sync.rb
|
|
508
512
|
- lib/samagotchi/memory_bundle/index_updater.rb
|
|
@@ -538,6 +542,7 @@ files:
|
|
|
538
542
|
- lib/samagotchi/model_binding.rb
|
|
539
543
|
- lib/samagotchi/model_catalog.rb
|
|
540
544
|
- lib/samagotchi/model_list_store.rb
|
|
545
|
+
- lib/samagotchi/model_lookup.rb
|
|
541
546
|
- lib/samagotchi/model_match.rb
|
|
542
547
|
- lib/samagotchi/model_notes.rb
|
|
543
548
|
- lib/samagotchi/model_overlay.rb
|
|
@@ -604,6 +609,7 @@ files:
|
|
|
604
609
|
- lib/samagotchi/reasoning_history.rb
|
|
605
610
|
- lib/samagotchi/reasoning_history_command.rb
|
|
606
611
|
- lib/samagotchi/recap_command.rb
|
|
612
|
+
- lib/samagotchi/recap_place.rb
|
|
607
613
|
- lib/samagotchi/recap_setup.rb
|
|
608
614
|
- lib/samagotchi/recap_store.rb
|
|
609
615
|
- lib/samagotchi/recap_title.rb
|
|
@@ -621,7 +627,10 @@ files:
|
|
|
621
627
|
- lib/samagotchi/remote_command.rb
|
|
622
628
|
- lib/samagotchi/remotes.rb
|
|
623
629
|
- lib/samagotchi/reply_wait.rb
|
|
630
|
+
- lib/samagotchi/reply_wait/liveness.rb
|
|
624
631
|
- lib/samagotchi/reply_wait/poll.rb
|
|
632
|
+
- lib/samagotchi/reply_wait/target.rb
|
|
633
|
+
- lib/samagotchi/reprefill_meter.rb
|
|
625
634
|
- lib/samagotchi/review_apply.rb
|
|
626
635
|
- lib/samagotchi/review_command.rb
|
|
627
636
|
- lib/samagotchi/review_start.rb
|
|
@@ -634,7 +643,6 @@ files:
|
|
|
634
643
|
- lib/samagotchi/send_command.rb
|
|
635
644
|
- lib/samagotchi/send_command/busy.rb
|
|
636
645
|
- lib/samagotchi/send_command/parent_gate.rb
|
|
637
|
-
- lib/samagotchi/send_command/wait_target.rb
|
|
638
646
|
- lib/samagotchi/served_model.rb
|
|
639
647
|
- lib/samagotchi/session.rb
|
|
640
648
|
- lib/samagotchi/session_access.rb
|
|
@@ -650,8 +658,16 @@ files:
|
|
|
650
658
|
- lib/samagotchi/session_config.rb
|
|
651
659
|
- lib/samagotchi/session_continue.rb
|
|
652
660
|
- lib/samagotchi/session_delete_command.rb
|
|
661
|
+
- lib/samagotchi/session_field.rb
|
|
653
662
|
- lib/samagotchi/session_inbox.rb
|
|
654
663
|
- lib/samagotchi/session_manager.rb
|
|
664
|
+
- lib/samagotchi/session_manager/delivery.rb
|
|
665
|
+
- lib/samagotchi/session_manager/emptiness.rb
|
|
666
|
+
- lib/samagotchi/session_manager/lifecycle.rb
|
|
667
|
+
- lib/samagotchi/session_manager/listing.rb
|
|
668
|
+
- lib/samagotchi/session_manager/removal.rb
|
|
669
|
+
- lib/samagotchi/session_manager/spawn.rb
|
|
670
|
+
- lib/samagotchi/session_manager/worker_command.rb
|
|
655
671
|
- lib/samagotchi/session_metrics.rb
|
|
656
672
|
- lib/samagotchi/session_metrics/cost.rb
|
|
657
673
|
- lib/samagotchi/session_metrics/model_segment.rb
|
|
@@ -661,8 +677,10 @@ files:
|
|
|
661
677
|
- lib/samagotchi/session_model_settings.rb
|
|
662
678
|
- lib/samagotchi/session_observer.rb
|
|
663
679
|
- lib/samagotchi/session_participants.rb
|
|
680
|
+
- lib/samagotchi/session_paths.rb
|
|
664
681
|
- lib/samagotchi/session_retention.rb
|
|
665
682
|
- lib/samagotchi/session_review.rb
|
|
683
|
+
- lib/samagotchi/session_row.rb
|
|
666
684
|
- lib/samagotchi/session_setting.rb
|
|
667
685
|
- lib/samagotchi/session_setup.rb
|
|
668
686
|
- lib/samagotchi/sessions_command.rb
|
|
@@ -670,6 +688,7 @@ files:
|
|
|
670
688
|
- lib/samagotchi/share_command.rb
|
|
671
689
|
- lib/samagotchi/side_judgments.rb
|
|
672
690
|
- lib/samagotchi/side_usage.rb
|
|
691
|
+
- lib/samagotchi/starting_marker.rb
|
|
673
692
|
- lib/samagotchi/steer.rb
|
|
674
693
|
- lib/samagotchi/steer_cut.rb
|
|
675
694
|
- lib/samagotchi/steer_cut_after.rb
|
|
@@ -687,6 +706,7 @@ files:
|
|
|
687
706
|
- lib/samagotchi/system_one/log.rb
|
|
688
707
|
- lib/samagotchi/system_one/question.rb
|
|
689
708
|
- lib/samagotchi/system_one/record.rb
|
|
709
|
+
- lib/samagotchi/system_one/recorder.rb
|
|
690
710
|
- lib/samagotchi/system_one/recording.rb
|
|
691
711
|
- lib/samagotchi/system_one/runs.rb
|
|
692
712
|
- lib/samagotchi/system_one/runs_store.rb
|
|
@@ -791,6 +811,7 @@ files:
|
|
|
791
811
|
- lib/samagotchi/tools/edit.rb
|
|
792
812
|
- lib/samagotchi/tools/execute.rb
|
|
793
813
|
- lib/samagotchi/tools/forget_outputs.rb
|
|
814
|
+
- lib/samagotchi/tools/index_hint.rb
|
|
794
815
|
- lib/samagotchi/tools/list_reminders.rb
|
|
795
816
|
- lib/samagotchi/tools/list_sessions.rb
|
|
796
817
|
- lib/samagotchi/tools/memory.rb
|
|
@@ -911,6 +932,7 @@ files:
|
|
|
911
932
|
- lib/samagotchi/web/public/forms.css
|
|
912
933
|
- lib/samagotchi/web/public/hash_intent.js
|
|
913
934
|
- lib/samagotchi/web/public/history_reveal.js
|
|
935
|
+
- lib/samagotchi/web/public/history_shape.js
|
|
914
936
|
- lib/samagotchi/web/public/icons/chi-180.png
|
|
915
937
|
- lib/samagotchi/web/public/icons/chi-192.png
|
|
916
938
|
- lib/samagotchi/web/public/icons/chi-512.png
|
|
@@ -962,9 +984,11 @@ files:
|
|
|
962
984
|
- lib/samagotchi/web/public/question_cards.js
|
|
963
985
|
- lib/samagotchi/web/public/read_view.js
|
|
964
986
|
- lib/samagotchi/web/public/reasoning_history_chip.js
|
|
987
|
+
- lib/samagotchi/web/public/recap_stamp.js
|
|
965
988
|
- lib/samagotchi/web/public/ref_menu.js
|
|
966
989
|
- lib/samagotchi/web/public/ref_scan.js
|
|
967
990
|
- lib/samagotchi/web/public/refs.js
|
|
991
|
+
- lib/samagotchi/web/public/reload_check.js
|
|
968
992
|
- lib/samagotchi/web/public/restore.js
|
|
969
993
|
- lib/samagotchi/web/public/review_apply.js
|
|
970
994
|
- lib/samagotchi/web/public/review_history.js
|
|
@@ -1019,9 +1043,11 @@ files:
|
|
|
1019
1043
|
- lib/samagotchi/web/public/toolkit_chip.js
|
|
1020
1044
|
- lib/samagotchi/web/public/tools_overview.js
|
|
1021
1045
|
- lib/samagotchi/web/public/turn_block.js
|
|
1046
|
+
- lib/samagotchi/web/public/turn_drawing.js
|
|
1022
1047
|
- lib/samagotchi/web/public/turn_events.js
|
|
1023
1048
|
- lib/samagotchi/web/public/turn_html.js
|
|
1024
1049
|
- lib/samagotchi/web/public/turn_model.js
|
|
1050
|
+
- lib/samagotchi/web/public/turn_pieces.js
|
|
1025
1051
|
- lib/samagotchi/web/public/turn_range.js
|
|
1026
1052
|
- lib/samagotchi/web/public/unqueue.js
|
|
1027
1053
|
- lib/samagotchi/web/public/update_notice.js
|
|
@@ -1054,6 +1080,7 @@ files:
|
|
|
1054
1080
|
- lib/samagotchi/web/push/store.rb
|
|
1055
1081
|
- lib/samagotchi/web/push_routes.rb
|
|
1056
1082
|
- lib/samagotchi/web/qr.rb
|
|
1083
|
+
- lib/samagotchi/web/reload_check_route.rb
|
|
1057
1084
|
- lib/samagotchi/web/running.rb
|
|
1058
1085
|
- lib/samagotchi/web/server.rb
|
|
1059
1086
|
- lib/samagotchi/web/session_access_routes.rb
|
|
@@ -1070,6 +1097,7 @@ files:
|
|
|
1070
1097
|
- lib/samagotchi/web/update_ops.rb
|
|
1071
1098
|
- lib/samagotchi/web/verify_fresh_routes.rb
|
|
1072
1099
|
- lib/samagotchi/worker.rb
|
|
1100
|
+
- lib/samagotchi/worker_boot.rb
|
|
1073
1101
|
- lib/samagotchi/worker_idle_exit.rb
|
|
1074
1102
|
- lib/samagotchi/worker_inbound.rb
|
|
1075
1103
|
- lib/samagotchi/worker_link.rb
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../delivery"
|
|
4
|
-
require_relative "../reply_wait"
|
|
5
|
-
require_relative "../session"
|
|
6
|
-
|
|
7
|
-
module Samagotchi
|
|
8
|
-
class SendCommand
|
|
9
|
-
# Which turn chi send --wait waits for and names in its report:
|
|
10
|
-
# ReplyWait's +turn+ (an enqueued_id; nil: the next reply), +queued+
|
|
11
|
-
# and +ended_before+, and ParentWait's +report_turn_id+ (the turn_id
|
|
12
|
-
# of the --format json line). Each run path builds it its way.
|
|
13
|
-
WaitTarget = Data.define(:turn, :report_turn_id, :queued, :ended_before) do
|
|
14
|
-
def initialize(turn: nil, report_turn_id: nil, queued: false, ended_before: false) = super
|
|
15
|
-
|
|
16
|
-
# A --new session's first message: its own turn, the ack's id (a
|
|
17
|
-
# file-delivered one's also names the outcome of a session command
|
|
18
|
-
# that runs no turn), so a worker that dies in it and the next one's
|
|
19
|
-
# settle end the wait (TurnCheckpoint.settled_turn). A message merged
|
|
20
|
-
# into a turn starting then falls back to that turn's reply
|
|
21
|
-
# (ReplyWait's turn: without queued:); no id (an older worker), the
|
|
22
|
-
# next reply. A prompt the session was created with has no delivery:
|
|
23
|
-
# its turn is the id the create gave it (+direct_turn+,
|
|
24
|
-
# Session#first_turn_id), and nothing can merge into it, so the wait
|
|
25
|
-
# is for that turn alone (ReplyWait's queued:).
|
|
26
|
-
# @param delivered [SessionManager::DeliverResult, nil] nil when the
|
|
27
|
-
# message started the session itself (no delivery)
|
|
28
|
-
# @param direct_turn [String, nil] that first turn's id, for a direct
|
|
29
|
-
# start
|
|
30
|
-
def self.first_message(delivered, direct_turn: nil)
|
|
31
|
-
return new unless delivered || !direct_turn.to_s.strip.empty?
|
|
32
|
-
|
|
33
|
-
return new(turn: direct_turn, report_turn_id: direct_turn, queued: true) if delivered.nil?
|
|
34
|
-
|
|
35
|
-
new(turn: delivered.enqueued_id, report_turn_id: delivered.enqueued_id)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# A message to an existing session. --queue: its own turn, the ack's
|
|
39
|
-
# id, also when the turn running at the check ended before it went in
|
|
40
|
-
# (an idle worker's ack says next_step, and the file still runs as
|
|
41
|
-
# that turn). A file fallback's id names its turn too, and so does a
|
|
42
|
-
# plain message to an idle session, as #first_message's. Otherwise
|
|
43
|
-
# (a session left running by a dead worker, the busy check's owner
|
|
44
|
-
# gone) the next reply, reported as the turn that was running when it
|
|
45
|
-
# went in (+running_turn+, ReplyWait.own_turn). A plain message the
|
|
46
|
-
# worker queued (its ack says queue: a participant's review turn was
|
|
47
|
-
# running, which takes no steer) is a --queue's.
|
|
48
|
-
# @param running [Boolean] the session was running when it went in
|
|
49
|
-
def self.message(delivered, queue:, running:, running_turn:)
|
|
50
|
-
queue ||= delivered.delivery == Delivery::QUEUE
|
|
51
|
-
turn = delivered.enqueued_id if queue || delivered.file? || !running
|
|
52
|
-
report = if queue then turn
|
|
53
|
-
elsif running then running_turn
|
|
54
|
-
else delivered.enqueued_id
|
|
55
|
-
end
|
|
56
|
-
new(turn: turn, report_turn_id: report, queued: queue && !turn.nil?)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# --wait with no message: --turn's (+requested+), or the turn running
|
|
60
|
-
# now or whose continue offer stands (ReplyWait.own_turn). Settled
|
|
61
|
-
# (idle, a turn ended, no question standing: a continue offer waits
|
|
62
|
-
# for its answer), its last turn's end is the answer (ended_before);
|
|
63
|
-
# with --turn, when that turn is the last one.
|
|
64
|
-
def self.wait_only(session, session_dir:, requested:)
|
|
65
|
-
settled = session.status == Session::STATUS_IDLE && !session.last_turn.nil? && session.pending_question.nil?
|
|
66
|
-
own = requested ? nil : ReplyWait.own_turn(session, session_dir: session_dir)
|
|
67
|
-
wait_only_of(own_turn: own, settled: settled, last_turn_id: session.last_turn&.enqueued_id, requested: requested)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# #wait_only from what SessionAccess#prepare_wait read
|
|
71
|
-
# (SessionAccess::WaitStart): its own_turn, settled and last_turn_id.
|
|
72
|
-
def self.after(start, requested:)
|
|
73
|
-
wait_only_of(own_turn: start.own_turn, settled: start.settled, last_turn_id: start.last_turn_id,
|
|
74
|
-
requested: requested)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def self.wait_only_of(own_turn:, settled:, last_turn_id:, requested:)
|
|
78
|
-
turn = requested || own_turn
|
|
79
|
-
ended_before = requested ? last_turn_id == requested : settled
|
|
80
|
-
new(turn: turn, report_turn_id: turn || (last_turn_id if settled), ended_before: ended_before)
|
|
81
|
-
end
|
|
82
|
-
private_class_method :wait_only_of
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|