samagotchi 0.154.1 → 0.156.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 +29 -1
- data/bin/chi +1 -1
- data/docs/architecture.md +12 -7
- data/docs/bundles.md +21 -0
- data/docs/cli.md +1 -1
- data/docs/guardrails.md +2 -2
- data/docs/hooks.md +1 -1
- data/docs/internals/anthropic.md +5 -5
- data/docs/internals/attached-context.md +9 -6
- data/docs/internals/background-tasks.md +1 -1
- data/docs/internals/block-renderers.md +8 -1
- data/docs/internals/engine.md +642 -831
- data/docs/internals/inline-widgets.md +136 -0
- data/docs/internals/llm-context-forget.md +8 -3
- data/docs/internals/objectives.md +8 -6
- data/docs/internals/participants.md +5 -5
- data/docs/internals/prompt-caching.md +13 -6
- data/docs/internals/remote-sessions.md +3 -1
- data/docs/internals/web-frontend.md +1 -1
- data/docs/internals/working-set.md +2 -1
- data/docs/plugins.md +2 -0
- data/docs/releasing.md +1 -1
- data/docs/sessions.md +4 -4
- data/docs/system-one.md +3 -2
- data/docs/testing.md +1 -1
- data/lib/samagotchi/block_renderers.rb +5 -0
- data/lib/samagotchi/bootstrap/config_writer.rb +1 -1
- data/lib/samagotchi/broadcast_command.rb +3 -3
- data/lib/samagotchi/bundle_command/check.rb +1 -1
- data/lib/samagotchi/bundle_command/try/sandbox.rb +1 -1
- data/lib/samagotchi/bundles/dev/manifest.yml +3 -2
- data/lib/samagotchi/bundles/inline-widgets/manifest.yml +11 -0
- data/lib/samagotchi/bundles/inline-widgets/plugin.rb +76 -0
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +2 -2
- data/lib/samagotchi/bundles/system/manifest.yml +2 -2
- data/lib/samagotchi/child_move.rb +7 -51
- data/lib/samagotchi/children_status.rb +1 -1
- data/lib/samagotchi/cli/parent_wait.rb +1 -1
- data/lib/samagotchi/config.rb +17 -112
- data/lib/samagotchi/context_command.rb +1 -2
- data/lib/samagotchi/context_window.rb +3 -3
- data/lib/samagotchi/desktop/macos.rb +1 -1
- data/lib/samagotchi/engine/context_judge.rb +21 -119
- data/lib/samagotchi/engine/guardrails.rb +4 -2
- data/lib/samagotchi/engine/messages.rb +9 -6
- data/lib/samagotchi/engine/models.rb +5 -2
- data/lib/samagotchi/engine/objectives.rb +30 -80
- data/lib/samagotchi/engine/participants.rb +15 -10
- data/lib/samagotchi/engine/plugins.rb +3 -1
- data/lib/samagotchi/engine/questions.rb +1 -1
- data/lib/samagotchi/engine/side_requests.rb +26 -13
- data/lib/samagotchi/engine/toolkit.rb +35 -191
- data/lib/samagotchi/engine/turn_end.rb +1 -1
- data/lib/samagotchi/engine/turn_helpers.rb +16 -39
- data/lib/samagotchi/engine/verify.rb +7 -143
- data/lib/samagotchi/engine.rb +166 -98
- data/lib/samagotchi/engine_peers.rb +1 -1
- data/lib/samagotchi/event_fanout.rb +18 -12
- data/lib/samagotchi/guardrail_wiring.rb +83 -82
- data/lib/samagotchi/guardrails/gate.rb +41 -40
- data/lib/samagotchi/guardrails/pair_boundary.rb +2 -1
- data/lib/samagotchi/guardrails/review_boundary.rb +2 -1
- data/lib/samagotchi/guardrails/targets.rb +28 -11
- data/lib/samagotchi/guardrails_command.rb +1 -1
- data/lib/samagotchi/host_config.rb +72 -1
- data/lib/samagotchi/host_model.rb +2 -6
- data/lib/samagotchi/host_registry.rb +1 -1
- data/lib/samagotchi/inline_widgets.rb +325 -0
- data/lib/samagotchi/kernel_loop.rb +215 -313
- data/lib/samagotchi/llm/anthropic_wire.rb +2 -2
- data/lib/samagotchi/llm/backend.rb +3 -1
- data/lib/samagotchi/llm/chat_loop.rb +87 -49
- data/lib/samagotchi/llm/native_backend.rb +3 -2
- data/lib/samagotchi/llm_context_apply.rb +54 -1
- data/lib/samagotchi/llm_context_forget.rb +5 -3
- data/lib/samagotchi/llm_context_notice.rb +1 -1
- data/lib/samagotchi/llm_context_strategy.rb +7 -9
- data/lib/samagotchi/llm_context_view.rb +9 -0
- data/lib/samagotchi/model_binding.rb +3 -3
- data/lib/samagotchi/model_price.rb +4 -10
- data/lib/samagotchi/model_profile.rb +6 -6
- data/lib/samagotchi/model_settings.rb +37 -2
- data/lib/samagotchi/note_command.rb +1 -2
- data/lib/samagotchi/objectives_audit.rb +4 -3
- data/lib/samagotchi/participants.rb +2 -2
- data/lib/samagotchi/plugin/context.rb +1 -1
- data/lib/samagotchi/plugin/prompt_sections.rb +7 -0
- data/lib/samagotchi/plugin/sessions.rb +2 -5
- data/lib/samagotchi/plugin/tool_spec.rb +5 -3
- data/lib/samagotchi/project_env.rb +1 -1
- data/lib/samagotchi/question_desk.rb +1 -1
- data/lib/samagotchi/reasoning_history.rb +3 -3
- data/lib/samagotchi/reminder_carry.rb +1 -1
- data/lib/samagotchi/reprefill_meter.rb +45 -0
- data/lib/samagotchi/review_command.rb +1 -1
- data/lib/samagotchi/revise_anchor.rb +1 -1
- data/lib/samagotchi/sampling_settings.rb +3 -3
- data/lib/samagotchi/self_report.rb +7 -7
- data/lib/samagotchi/session.rb +50 -7
- data/lib/samagotchi/session_access/local.rb +7 -5
- data/lib/samagotchi/session_access/remote.rb +17 -3
- 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_manager/delivery.rb +254 -0
- data/lib/samagotchi/session_manager/emptiness.rb +138 -0
- data/lib/samagotchi/session_manager/lifecycle.rb +274 -0
- data/lib/samagotchi/session_manager/listing.rb +189 -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 +26 -1540
- data/lib/samagotchi/session_metrics.rb +1 -1
- data/lib/samagotchi/sessions_command.rb +1 -1
- data/lib/samagotchi/share_command.rb +1 -1
- data/lib/samagotchi/starting_marker.rb +65 -0
- data/lib/samagotchi/steer_cut_after.rb +3 -3
- data/lib/samagotchi/system_one/recorder.rb +49 -0
- data/lib/samagotchi/system_prompt.rb +37 -30
- data/lib/samagotchi/terminal_ui/exit_lines.rb +1 -1
- data/lib/samagotchi/terminal_ui.rb +2 -6
- data/lib/samagotchi/testing/boundary.rb +7 -0
- data/lib/samagotchi/testing/bundle.rb +7 -5
- data/lib/samagotchi/testing/install.rb +3 -2
- data/lib/samagotchi/testing/sessions.rb +1 -1
- data/lib/samagotchi/thinking.rb +3 -3
- data/lib/samagotchi/token_usage.rb +1 -1
- data/lib/samagotchi/tool_activity.rb +15 -7
- data/lib/samagotchi/tool_declarations.rb +6 -6
- data/lib/samagotchi/tool_output_cut.rb +17 -0
- data/lib/samagotchi/tool_response.rb +4 -3
- data/lib/samagotchi/tool_runner.rb +96 -102
- data/lib/samagotchi/toolkit_binding.rb +40 -14
- data/lib/samagotchi/toolkit_command.rb +1 -1
- data/lib/samagotchi/tools/deferred_tools.rb +17 -21
- data/lib/samagotchi/tools/delegate.rb +10 -5
- data/lib/samagotchi/tools/delegate_result.rb +4 -4
- data/lib/samagotchi/tools/index_hint.rb +14 -0
- data/lib/samagotchi/tools/registry.rb +64 -44
- data/lib/samagotchi/tools/send_note.rb +4 -6
- data/lib/samagotchi/tools/tool_index.rb +150 -102
- data/lib/samagotchi/tools/tool_surface.rb +187 -0
- data/lib/samagotchi/turn_context.rb +68 -0
- data/lib/samagotchi/turn_stages/context_judge.rb +172 -0
- data/lib/samagotchi/turn_stages/objectives.rb +150 -0
- data/lib/samagotchi/turn_stages/toolkit_suggestion.rb +257 -0
- data/lib/samagotchi/turn_stages/verify_anchors.rb +168 -0
- data/lib/samagotchi/turn_stages/warmup.rb +82 -0
- data/lib/samagotchi/turn_state.rb +46 -4
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/vision_support.rb +3 -3
- data/lib/samagotchi/web/app.rb +15 -8
- data/lib/samagotchi/web/markdown_renderer.rb +39 -14
- data/lib/samagotchi/web/message_display.rb +1 -1
- data/lib/samagotchi/web/participant_access.rb +2 -2
- data/lib/samagotchi/web/public/app.js +5 -1
- data/lib/samagotchi/web/public/block_host.js +74 -199
- data/lib/samagotchi/web/public/block_renderers.css +2 -0
- data/lib/samagotchi/web/public/block_source.js +7 -4
- data/lib/samagotchi/web/public/block_watch.js +256 -0
- data/lib/samagotchi/web/public/composer_fold.js +3 -0
- data/lib/samagotchi/web/public/index.html +28 -9
- data/lib/samagotchi/web/public/inline_widgets.js +146 -0
- data/lib/samagotchi/web/public/owner_verify.js +1 -1
- data/lib/samagotchi/web/public/participant.js +1 -1
- data/lib/samagotchi/web/public/revise_stack.js +1 -1
- data/lib/samagotchi/web/public/stage_watch.js +6 -2
- data/lib/samagotchi/web/public/text_roots.js +1 -1
- data/lib/samagotchi/web/public/verify_target.js +1 -1
- data/lib/samagotchi/web/public/widget_picks.js +130 -0
- data/lib/samagotchi/web/public/widget_walk.js +230 -0
- data/lib/samagotchi/web/public/widgets.css +70 -0
- data/lib/samagotchi/web/session_access_routes.rb +3 -3
- data/lib/samagotchi/web/session_control.rb +3 -3
- data/lib/samagotchi/web/session_create.rb +3 -3
- data/lib/samagotchi/web/session_hub.rb +1 -1
- data/lib/samagotchi/web/session_show.rb +3 -3
- data/lib/samagotchi/web/session_summary.rb +3 -4
- data/lib/samagotchi/worker.rb +55 -27
- data/lib/samagotchi/worker_boot.rb +184 -0
- data/lib/samagotchi/worker_signals.rb +1 -1
- data/lib/samagotchi/worker_task_wakes.rb +2 -2
- metadata +29 -1
data/lib/samagotchi/engine.rb
CHANGED
|
@@ -27,9 +27,11 @@ require_relative "thinking_notices"
|
|
|
27
27
|
require_relative "cancellation_controller"
|
|
28
28
|
require_relative "context_window"
|
|
29
29
|
require_relative "kernel_loop"
|
|
30
|
+
require_relative "reprefill_meter"
|
|
30
31
|
require_relative "tools/builtins"
|
|
31
32
|
require_relative "tools/task_runtime"
|
|
32
33
|
require_relative "tools/tool_index"
|
|
34
|
+
require_relative "tools/tool_surface"
|
|
33
35
|
require_relative "peer_sources"
|
|
34
36
|
require_relative "session_commands"
|
|
35
37
|
require_relative "plugin/loader"
|
|
@@ -54,7 +56,13 @@ require_relative "context_judge"
|
|
|
54
56
|
require_relative "objectives_audit"
|
|
55
57
|
require_relative "owner_prompt"
|
|
56
58
|
require_relative "side_judgments"
|
|
59
|
+
require_relative "system_one/recorder"
|
|
57
60
|
require_relative "toolkit_suggest"
|
|
61
|
+
require_relative "turn_stages/context_judge"
|
|
62
|
+
require_relative "turn_stages/objectives"
|
|
63
|
+
require_relative "turn_stages/toolkit_suggestion"
|
|
64
|
+
require_relative "turn_stages/verify_anchors"
|
|
65
|
+
require_relative "turn_stages/warmup"
|
|
58
66
|
require_relative "tool_loads"
|
|
59
67
|
require_relative "answer_tail"
|
|
60
68
|
require_relative "archive_store"
|
|
@@ -79,6 +87,7 @@ require_relative "tools/memory"
|
|
|
79
87
|
require_relative "muted_memories"
|
|
80
88
|
require_relative "used_memories"
|
|
81
89
|
require_relative "turn_state"
|
|
90
|
+
require_relative "turn_context"
|
|
82
91
|
require_relative "steer_cut"
|
|
83
92
|
require_relative "engine_peers"
|
|
84
93
|
require_relative "engine_snapshots"
|
|
@@ -206,8 +215,6 @@ module Samagotchi
|
|
|
206
215
|
# steers) and the idle layer's activity clock. Built first: a plugin
|
|
207
216
|
# may steer or ask whether a turn runs while it loads.
|
|
208
217
|
@turn_state = TurnState.new(clock: -> { monotonic_now })
|
|
209
|
-
@objective_proposals = []
|
|
210
|
-
@objective_proposals_mutex = Mutex.new
|
|
211
218
|
# A message for the running turn cutting its generation.
|
|
212
219
|
@steer_cut = SteerCut.new(clock: -> { monotonic_now }, controller: -> { active_cancel_controller },
|
|
213
220
|
cut_after: -> { steer_cut_after })
|
|
@@ -223,12 +230,11 @@ module Samagotchi
|
|
|
223
230
|
@chat_backend_mutex = Mutex.new
|
|
224
231
|
@side_judgments = SideJudgments.new
|
|
225
232
|
@judgments = build_judgments
|
|
226
|
-
# On mode's cards an answer brought while a turn ran: shown once it
|
|
227
|
-
# has ended (#show_context_cards_after_turn).
|
|
228
|
-
@context_cards_after_turn = []
|
|
229
|
-
@context_cards_mutex = Mutex.new
|
|
230
|
-
@toolkit_warmup_thread = nil
|
|
231
233
|
@host_registry = host_registry || HostRegistry.new
|
|
234
|
+
# The turn stages over the objectives (its audit, view and proposals)
|
|
235
|
+
# and the Verify/Revise anchors (TurnStages).
|
|
236
|
+
@objectives_stage = build_objectives_stage
|
|
237
|
+
@verify_anchors = build_verify_anchors
|
|
232
238
|
# A model given here (a worker's session model) is the one it runs,
|
|
233
239
|
# so its host is checked; the config default is only checked once it
|
|
234
240
|
# is used (the one-shot checks the model it starts on, #switch_model!).
|
|
@@ -302,6 +308,8 @@ module Samagotchi
|
|
|
302
308
|
# The kernel (built here, or a spec's) and what it reads of the Engine;
|
|
303
309
|
# then the native backend over it.
|
|
304
310
|
wire_kernel(kernel, muted_memories)
|
|
311
|
+
# The turn-end warm-up's stage, over that kernel.
|
|
312
|
+
@turn_warmup = build_turn_warmup
|
|
305
313
|
Log.debug(:model, "backend", provider: backend.provider) if Log.level?(:debug)
|
|
306
314
|
@resume_session = session_id ? Session.load(session_id) : nil
|
|
307
315
|
@prompt_builder = build_system_prompt(memories, appended_prompt_files)
|
|
@@ -379,6 +387,11 @@ module Samagotchi
|
|
|
379
387
|
# The session's toolkit: the kits (the plugins' too, chi.toolkit),
|
|
380
388
|
# what its next turn declares, the turn-start apply.
|
|
381
389
|
@toolkit_binding = build_toolkit_binding
|
|
390
|
+
# The turn stages over it and the side asks (TurnStages): System 1's
|
|
391
|
+
# toolkit suggestion and the attached-context candidate judge, which a
|
|
392
|
+
# plugin may reach as it loads.
|
|
393
|
+
@toolkit_suggestion = build_toolkit_suggestion
|
|
394
|
+
@context_judge = build_context_judge
|
|
382
395
|
# The tools plugins publish without declaring (chi.tool_source), and
|
|
383
396
|
# the search and call tools that reach them (Tools::ToolIndex).
|
|
384
397
|
@tool_index = Tools::ToolIndex.new
|
|
@@ -396,6 +409,8 @@ module Samagotchi
|
|
|
396
409
|
# with no plugins too: a toolkit's left-out tools are reachable
|
|
397
410
|
# either way (declared per toolkit, Tools::Registry).
|
|
398
411
|
@tool_index.declare(@tools, failures: @plugin_failures)
|
|
412
|
+
# What readers off the turn thread see until the first turn's start.
|
|
413
|
+
publish_tools!
|
|
399
414
|
end
|
|
400
415
|
private :build_tools_and_plugins
|
|
401
416
|
|
|
@@ -424,45 +439,42 @@ module Samagotchi
|
|
|
424
439
|
end
|
|
425
440
|
private :subscribe_session_observers
|
|
426
441
|
|
|
427
|
-
# The kernel and what it holds of the Engine
|
|
428
|
-
#
|
|
429
|
-
#
|
|
442
|
+
# The kernel and what it holds of the Engine for its life, one
|
|
443
|
+
# KernelLoop::Services (stores, hooks, tools, the mutes, the question
|
|
444
|
+
# flow, peers, the gate, warm-up, the generation guard), and the native
|
|
445
|
+
# backend over it. After the plugins load. Nothing per turn: a turn's
|
|
446
|
+
# TurnContext goes down the backend's complete (#generate).
|
|
430
447
|
def wire_kernel(kernel, muted_memories)
|
|
431
|
-
#
|
|
432
|
-
# the
|
|
433
|
-
@kernel = kernel || KernelLoop.new(client: @client, profile: @model_binding.given_profile, model_name: effective_model_name,
|
|
434
|
-
hooks: @hooks, reminder_store: @reminder_store, tools: @tools)
|
|
435
|
-
@kernel.reminder_store = @reminder_store
|
|
436
|
-
@kernel.hooks = @hooks
|
|
437
|
-
@kernel.tools = @tools
|
|
438
|
-
sync_kernel_client!
|
|
439
|
-
sync_model_key!
|
|
440
|
-
# The mutes never change during a session, so no re-sync: the kernel's
|
|
441
|
-
# memory_read guard reads the same list for every turn.
|
|
448
|
+
# The mutes never change during a session: the kernel's memory_read
|
|
449
|
+
# guard reads the same list for every turn.
|
|
442
450
|
@muted_memory_names = MutedMemories.normalize_list(muted_memories)
|
|
443
|
-
|
|
444
|
-
#
|
|
445
|
-
@kernel.question_handler = proc { |payload| request_question(payload) }
|
|
446
|
-
# Every tool call asks this gate first. The kernel is never rebuilt, so
|
|
447
|
-
# it holds across model switches.
|
|
451
|
+
# Where the approvals live; also where list_sessions and send_note
|
|
452
|
+
# look for other sessions (a worker moves it, Worker).
|
|
448
453
|
self.guardrail_state_dir = Session.default_state_dir
|
|
449
|
-
# list_sessions and send_note speak for whichever session runs now.
|
|
450
|
-
@kernel.peers = PeerView.new(self)
|
|
451
|
-
# A plugin tool's row refs resolve against the session's folder, as
|
|
452
|
-
# answer refs do (AnswerRefs), not the process's.
|
|
453
|
-
@kernel.session_cwd = -> { @session&.working_directory }
|
|
454
|
-
# forget_outputs refuses what the user pinned in the working set.
|
|
455
|
-
@kernel.working_set_pins = -> { @session&.working_set_pins || [] }
|
|
456
|
-
# A cut tool output is saved whole in the session's folder.
|
|
457
|
-
@kernel.session_dir = -> { @session&.id && Session.session_dir(@session.id, state_dir: session_state_dir) }
|
|
458
|
-
@kernel.guardrail_gate = @guardrail_wiring.gate
|
|
459
|
-
@kernel.participant_turn = -> { Steer.participant_author?(turn_author) }
|
|
460
|
-
@kernel.participant_mode = -> { @guardrail_wiring.turn_mode }
|
|
461
|
-
# A pair turn stops once its participant passed their cap.
|
|
462
|
-
@kernel.generation_guard = -> { guard_participant_spend }
|
|
463
454
|
# The turn-end warm-up; the kernel asks it for a slot pin per request.
|
|
464
455
|
@prompt_warmup = PromptWarmup.new
|
|
465
|
-
|
|
456
|
+
# One re-prefill baseline for both loops (the native kernel's and the
|
|
457
|
+
# chat loop's requests), reset by the warm-up (KernelLoop#warmed_up!).
|
|
458
|
+
@reprefill = ReprefillMeter.new
|
|
459
|
+
services = KernelLoop::Services.new(
|
|
460
|
+
hooks: @hooks, tools: @tools, reminder_store: @reminder_store, muted_memory_names: @muted_memory_names,
|
|
461
|
+
# ask_user_question blocks on the Engine's question flow (TUI/Web answer it).
|
|
462
|
+
question_handler: proc { |payload| request_question(payload) },
|
|
463
|
+
# list_sessions and send_note speak for whichever session runs now.
|
|
464
|
+
peers: PeerView.new(self),
|
|
465
|
+
# Every tool call asks this gate first. The kernel is never rebuilt,
|
|
466
|
+
# so it holds across model switches.
|
|
467
|
+
gate: @guardrail_wiring.gate(hooks: @hooks, tools: @tools),
|
|
468
|
+
warmup: @prompt_warmup,
|
|
469
|
+
# A pair turn stops once its participant passed their cap.
|
|
470
|
+
generation_guard: ->(context) { guard_participant_spend(context) }
|
|
471
|
+
)
|
|
472
|
+
# A given kernel (specs) gets the same services as the one built here.
|
|
473
|
+
@kernel = kernel || KernelLoop.new(client: @client, profile: @model_binding.given_profile,
|
|
474
|
+
model_name: effective_model_name, services: services, reprefill: @reprefill)
|
|
475
|
+
@kernel.attach(services, reprefill: @reprefill) if kernel
|
|
476
|
+
sync_kernel_client!
|
|
477
|
+
sync_model_key!
|
|
466
478
|
# What a hook can do beyond reading its event (event[:notify],
|
|
467
479
|
# event[:ask_user], event[:stop_turn]): the Engine's routes to the UIs.
|
|
468
480
|
@hooks.runtime = hook_runtime
|
|
@@ -476,11 +488,9 @@ module Samagotchi
|
|
|
476
488
|
def build_guardrail_wiring
|
|
477
489
|
GuardrailWiring.new(
|
|
478
490
|
scratch: @scratch,
|
|
479
|
-
|
|
491
|
+
# Built before the tools (the hooks load into its failures).
|
|
480
492
|
tools: -> { @tools },
|
|
481
493
|
session: -> { @session },
|
|
482
|
-
model_key: -> { @model_binding.model_key },
|
|
483
|
-
model_name: -> { guardrail_model_name },
|
|
484
494
|
cancelled: -> { !!active_cancel_controller&.cancelled? },
|
|
485
495
|
# An approval of the model's call: :question_asked first (QuestionAsked).
|
|
486
496
|
ask: ->(fields) { open_question(question_asked(QuestionAsked::KIND_APPROVAL, fields)) },
|
|
@@ -495,7 +505,7 @@ module Samagotchi
|
|
|
495
505
|
system_one_runs: -> { system_one_runs },
|
|
496
506
|
cancel_controller: -> { active_cancel_controller },
|
|
497
507
|
# A participant's turn: their name on the owner's card, their
|
|
498
|
-
# grant's mode for the turn's (GuardrailWiring#
|
|
508
|
+
# grant's mode for the turn's (GuardrailWiring#begin_turn).
|
|
499
509
|
participant: ->(author) { @participants.entry_for(author, session: @session) }
|
|
500
510
|
)
|
|
501
511
|
end
|
|
@@ -511,7 +521,8 @@ module Samagotchi
|
|
|
511
521
|
thinking_notices: -> { @thinking_notices },
|
|
512
522
|
metrics: -> { @metrics },
|
|
513
523
|
hooks: -> { @hooks },
|
|
514
|
-
|
|
524
|
+
turn_context: -> { turn_context },
|
|
525
|
+
last_turn_context: -> { last_turn_context },
|
|
515
526
|
model_settings: -> { @model_settings },
|
|
516
527
|
session: -> { @session },
|
|
517
528
|
live_conversation: -> { live_conversation },
|
|
@@ -683,7 +694,7 @@ module Samagotchi
|
|
|
683
694
|
end
|
|
684
695
|
@side_judgments.join(SIDE_JUDGMENTS_JOIN_SECONDS)
|
|
685
696
|
# The warm-up's answer is dropped anyway.
|
|
686
|
-
|
|
697
|
+
@toolkit_suggestion.stop_warmup
|
|
687
698
|
left = threads.count(&:alive?)
|
|
688
699
|
Log.warn(:plugins, "anytime_commands_left", count: left) if left.positive?
|
|
689
700
|
@plugin_tasks.kill_leftovers
|
|
@@ -715,9 +726,9 @@ module Samagotchi
|
|
|
715
726
|
kept, event = yield(seconds)
|
|
716
727
|
event[:turn_id] = turn.id
|
|
717
728
|
event[:verify] = true if turn.verify
|
|
718
|
-
revises = stamp_opening(kept, turn, outcome)
|
|
729
|
+
revises = @verify_anchors.stamp_opening(kept, turn, outcome)
|
|
719
730
|
replace_session_messages(turn.session, kept) if kept
|
|
720
|
-
verdict = record_verdict(turn, outcome)
|
|
731
|
+
verdict = @verify_anchors.record_verdict(turn, outcome)
|
|
721
732
|
event[:verdict] = verdict if verdict
|
|
722
733
|
event[:revises] = revises.to_h if revises
|
|
723
734
|
emit_working_set(turn.on_event, turn.session, turn.session.messages)
|
|
@@ -778,14 +789,15 @@ module Samagotchi
|
|
|
778
789
|
end
|
|
779
790
|
private :build_recap
|
|
780
791
|
|
|
781
|
-
# One turn's
|
|
782
|
-
# single-threaded: the cross-thread turn state (the
|
|
783
|
-
# sink, steers) stays
|
|
792
|
+
# One turn's lifecycle state, for #run_turn and its endings. Per turn
|
|
793
|
+
# and single-threaded: the cross-thread turn state (the published
|
|
794
|
+
# TurnContext, the cancel slot, the sink, steers) stays in TurnState.
|
|
795
|
+
# +context+: the turn's TurnContext, the one source of truth for its
|
|
796
|
+
# id, session, origin and controller (read through #id, #session,
|
|
797
|
+
# #origin, #controller); #generate replaces it with the settings in.
|
|
784
798
|
# +ended+: the end event is out (what follows is post-turn work).
|
|
785
|
-
# +
|
|
786
|
-
#
|
|
787
|
-
# +id+: names the turn on :turn_started (its metrics record's id) and on
|
|
788
|
-
# its saved prompt, so a UI pairs the two whatever left the conversation.
|
|
799
|
+
# +prepared_settings+: the LLM::TurnSettings #prepare_turn makes (before
|
|
800
|
+
# the hooks); #generate completes them into the context's.
|
|
789
801
|
# +limit+: the iteration limit #generate ran it with.
|
|
790
802
|
# +resumed+: a step-limit Continue (run_turn's resumed:).
|
|
791
803
|
# +resume_from+: where its reasoning starts, the run it resumes
|
|
@@ -794,8 +806,15 @@ module Samagotchi
|
|
|
794
806
|
# +wall+: the wall time it started (MessageTime.now, once): the
|
|
795
807
|
# :turn_started event's at and its user message's (and reminders') stamp.
|
|
796
808
|
# +verify+, +revises+: a Verify turn's claim, a Revise turn's draft.
|
|
797
|
-
Turn = Struct.new(:
|
|
798
|
-
:
|
|
809
|
+
Turn = Struct.new(:context, :prompt, :continue, :on_event, :started_at, :messages, :ended, :prepared_settings,
|
|
810
|
+
:limit, :resumed, :resume_from, :wall, :verify, :revises, :outcome) do
|
|
811
|
+
# The turn's id (:turn_started's turn_id, its metrics record's id and
|
|
812
|
+
# its saved prompt's), session, origin and controller: its context's.
|
|
813
|
+
def id = context.id
|
|
814
|
+
def session = context.session
|
|
815
|
+
def origin = context.origin
|
|
816
|
+
def controller = context.controller
|
|
817
|
+
|
|
799
818
|
def resumed? = resumed ? true : false
|
|
800
819
|
|
|
801
820
|
# The turn ended as a completed one (not canceled, not failed): the
|
|
@@ -866,7 +885,7 @@ module Samagotchi
|
|
|
866
885
|
# wake's note) names it with this id
|
|
867
886
|
# @param verify [VerifyAnchor, nil] a Verify turn's claim (its verdict)
|
|
868
887
|
# @param revises [ReviseAnchor, nil] a Revise turn's draft: stamped on
|
|
869
|
-
# the prompt at the turn's end, metadata only (#stamp_opening)
|
|
888
|
+
# the prompt at the turn's end, metadata only (TurnStages::VerifyAnchors#stamp_opening)
|
|
870
889
|
#
|
|
871
890
|
# An Interrupt (SIGINT) cancels the turn: what it got to is kept in the
|
|
872
891
|
# session as after a Stop (the prompt, the loop's finished tool
|
|
@@ -897,7 +916,7 @@ module Samagotchi
|
|
|
897
916
|
pending_input: pending_input)
|
|
898
917
|
publish_used_memories(session, on_event)
|
|
899
918
|
complete_turn(turn, result)
|
|
900
|
-
|
|
919
|
+
@turn_warmup.after(turn, result, next_turn_waiting: next_turn_waiting)
|
|
901
920
|
result
|
|
902
921
|
rescue Interrupt => e
|
|
903
922
|
# After the end event (in the after_turn/session_end hooks) the
|
|
@@ -924,24 +943,23 @@ module Samagotchi
|
|
|
924
943
|
raise
|
|
925
944
|
ensure
|
|
926
945
|
release_turn(probe_cancel_before)
|
|
927
|
-
|
|
928
|
-
# Only a completed turn shows its proposal cards
|
|
929
|
-
#
|
|
930
|
-
|
|
931
|
-
turn.completed? ? show_objective_proposals : discard_objective_proposals(turn)
|
|
946
|
+
@context_judge.show_cards_after_turn
|
|
947
|
+
# Only a completed turn shows its proposal cards; any other's are
|
|
948
|
+
# dropped, so the next turn does not show them either.
|
|
949
|
+
show_objective_proposals(turn)
|
|
932
950
|
end
|
|
933
951
|
end
|
|
934
952
|
|
|
935
953
|
# The turn's state before anything can fail it: the session running,
|
|
936
|
-
# the turn flag, its cancel controller and sink. The
|
|
937
|
-
# is set here and cleared in #release_turn only.
|
|
954
|
+
# its TurnContext, the turn flag, its cancel controller and sink. The
|
|
955
|
+
# cross-thread state is set here and cleared in #release_turn only.
|
|
938
956
|
def begin_turn(session, prompt, on_event:, cancel_controller:, origin:, continue:, id: nil, verify: nil, revises: nil,
|
|
939
957
|
input_waiting: nil)
|
|
940
958
|
origin = TurnOrigin.of(origin)
|
|
941
959
|
# A participant's Verify fresh child: every turn is theirs (their
|
|
942
960
|
# author, boundary and cap), whoever started it.
|
|
943
961
|
origin = session.verify_fresh.origin_for(origin) if session.respond_to?(:verify_fresh) && session.verify_fresh
|
|
944
|
-
verify =
|
|
962
|
+
verify = @verify_anchors.verified(session, VerifyAnchor.from(verify), state_dir: session_state_dir)
|
|
945
963
|
# Track the active session for recap and status snapshot.
|
|
946
964
|
@session = session
|
|
947
965
|
# status is turn state: running now, idle again before the turn's end
|
|
@@ -950,25 +968,62 @@ module Samagotchi
|
|
|
950
968
|
@used_memories.absorb(session)
|
|
951
969
|
# Provide a cancellable controller for this turn (cross-process cancel via file flag)
|
|
952
970
|
effective_controller = cancel_controller || CancellationController.new
|
|
953
|
-
# The turn
|
|
954
|
-
#
|
|
955
|
-
|
|
956
|
-
#
|
|
957
|
-
#
|
|
958
|
-
#
|
|
959
|
-
|
|
971
|
+
# The turn's context, whole before the turn is published: who queued
|
|
972
|
+
# it, a participant's mode (participants.json), git asked afresh.
|
|
973
|
+
context = new_turn_context(session, origin, effective_controller, id || SecureRandom.uuid)
|
|
974
|
+
# The turn runs, with its context, controller and sink, in one step:
|
|
975
|
+
# a Stop, a plugin's card or its ctx.turn_author from another thread
|
|
976
|
+
# never sees a running turn without them (or with the last turn's).
|
|
977
|
+
# The idle recap detector does not fire (or render an invalidated
|
|
978
|
+
# recap) while the model is working. A hook's notice goes where the
|
|
979
|
+
# turn's events go (a one-shot prints only its sink; a worker's
|
|
980
|
+
# observers carry it to the bridge).
|
|
981
|
+
@turn_state.begin!(context: context, controller: effective_controller, sink: on_event, input_waiting: input_waiting)
|
|
960
982
|
# Drop a recap already in flight: the turn makes it stale.
|
|
961
983
|
@recap&.invalidate!
|
|
962
|
-
# The gate's context: who queued this turn, and git asked afresh.
|
|
963
|
-
@guardrail_wiring.begin_turn(origin)
|
|
964
984
|
|
|
965
|
-
Turn.new(
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
revises: ReviseAnchor.from(revises))
|
|
985
|
+
Turn.new(context: context, prompt: continue ? nil : prompt, continue: continue, on_event: on_event,
|
|
986
|
+
started_at: Process.clock_gettime(Process::CLOCK_MONOTONIC), wall: MessageTime.now,
|
|
987
|
+
verify: VerifyAnchor.from(verify), revises: ReviseAnchor.from(revises))
|
|
969
988
|
end
|
|
970
989
|
private :begin_turn
|
|
971
990
|
|
|
991
|
+
# A new turn's TurnContext (#begin_turn): the gate's turn facts
|
|
992
|
+
# (GuardrailWiring#begin_turn), the session's folders. Its settings and
|
|
993
|
+
# model come in #generate.
|
|
994
|
+
def new_turn_context(session, origin, controller, id)
|
|
995
|
+
start = @guardrail_wiring.begin_turn(origin, session: session)
|
|
996
|
+
TurnContext.new(id: id, session: session, origin: origin, author: origin.participant_author,
|
|
997
|
+
participant_mode: start.mode, participant: start.participant, controller: controller,
|
|
998
|
+
cwd: (session.working_directory if session.respond_to?(:working_directory)), session_dir: turn_session_dir(session),
|
|
999
|
+
state_dir: session_state_dir, git: start.git, settings: nil, model_key: nil,
|
|
1000
|
+
fallback_model_key: nil, model_name: nil, surface: nil)
|
|
1001
|
+
end
|
|
1002
|
+
private :new_turn_context
|
|
1003
|
+
|
|
1004
|
+
# The session's folder, nil when it can't be named (an id that isn't
|
|
1005
|
+
# one, a lookup that raised): a cut tool output then says it wasn't saved.
|
|
1006
|
+
def turn_session_dir(session)
|
|
1007
|
+
Session.session_dir(session.id, state_dir: session_state_dir)
|
|
1008
|
+
rescue StandardError => e
|
|
1009
|
+
Log.warn(:turn, "tool_output_save_failed", error: e.class.name)
|
|
1010
|
+
nil
|
|
1011
|
+
end
|
|
1012
|
+
private :turn_session_dir
|
|
1013
|
+
|
|
1014
|
+
# The running turn's TurnContext as other threads see it (TurnState),
|
|
1015
|
+
# nil between turns; its settings are nil until #generate.
|
|
1016
|
+
# @return [TurnContext, nil]
|
|
1017
|
+
def turn_context = @turn_state.context
|
|
1018
|
+
private :turn_context
|
|
1019
|
+
|
|
1020
|
+
# The last finished turn's TurnContext (TurnState#last_context), nil
|
|
1021
|
+
# before any: its author (the recap's), its settings (the working set's
|
|
1022
|
+
# between turns).
|
|
1023
|
+
# @return [TurnContext, nil]
|
|
1024
|
+
def last_turn_context = @turn_state.last_context
|
|
1025
|
+
private :last_turn_context
|
|
1026
|
+
|
|
972
1027
|
# Everything before the model is asked: :turn_started, the kernel's
|
|
973
1028
|
# per-turn settings, the plugins' setup, the session_start/before_turn
|
|
974
1029
|
# hooks, then the messages to send (#turn_messages). False when a Stop
|
|
@@ -987,14 +1042,14 @@ module Samagotchi
|
|
|
987
1042
|
# A participant's turn names them (author, author_name) for the UIs'
|
|
988
1043
|
# badge; the owner's turn_started stays as it was.
|
|
989
1044
|
turn_started.merge!(author_fields(turn.origin.author, session: session),
|
|
990
|
-
participant_mode_fields(turn.
|
|
1045
|
+
participant_mode_fields(turn.context))
|
|
991
1046
|
emit_event(turn.on_event, turn.tag(turn_started))
|
|
992
1047
|
raise image_error if image_error
|
|
993
1048
|
|
|
994
1049
|
# On mode's ask starts here too; the turn joins it before
|
|
995
1050
|
# apply_toolkit! below, so its latency hides behind the probes and
|
|
996
1051
|
# the init wait.
|
|
997
|
-
toolkit_suggestion
|
|
1052
|
+
@toolkit_suggestion.start(turn, recorder: system_one_recorder)
|
|
998
1053
|
|
|
999
1054
|
# The window and the profile probes run after run_turn's probe-cancel
|
|
1000
1055
|
# swap, so a Stop cuts them; a failure ends the turn as turn_failed.
|
|
@@ -1006,12 +1061,12 @@ module Samagotchi
|
|
|
1006
1061
|
refresh_profile!
|
|
1007
1062
|
|
|
1008
1063
|
# Before anything of the turn is kept or a reminder is used up.
|
|
1009
|
-
turn.
|
|
1010
|
-
refuse_images!(turn.
|
|
1064
|
+
turn.prepared_settings = turn_settings(session)
|
|
1065
|
+
refuse_images!(turn.prepared_settings.vision) unless image_refs.empty?
|
|
1011
1066
|
# A Stop during the probes: the turn ends before the load-failure
|
|
1012
1067
|
# warnings, which show once, so the next turn still shows them.
|
|
1013
1068
|
if turn.controller.cancelled?
|
|
1014
|
-
toolkit_suggestion
|
|
1069
|
+
@toolkit_suggestion.abandon(turn, :canceled)
|
|
1015
1070
|
return false
|
|
1016
1071
|
end
|
|
1017
1072
|
|
|
@@ -1028,11 +1083,11 @@ module Samagotchi
|
|
|
1028
1083
|
apply_staged_tools!
|
|
1029
1084
|
# On mode: the suggested kit, before anything is declared (a Stop
|
|
1030
1085
|
# during the wait is caught by the check below).
|
|
1031
|
-
|
|
1086
|
+
@toolkit_suggestion.settle(turn)
|
|
1032
1087
|
# The candidate judge: its asks run beside the turn; on mode's
|
|
1033
1088
|
# attaches reach the model at the next between-turn delivery.
|
|
1034
|
-
|
|
1035
|
-
|
|
1089
|
+
@context_judge.start(turn, recorder: system_one_recorder)
|
|
1090
|
+
@objectives_stage.incoming(turn, recorder: system_one_recorder)
|
|
1036
1091
|
apply_toolkit!(session, turn.on_event)
|
|
1037
1092
|
refresh_participants!(session)
|
|
1038
1093
|
# A Stop during the waits above: the turn ends here,
|
|
@@ -1055,7 +1110,8 @@ module Samagotchi
|
|
|
1055
1110
|
ensure
|
|
1056
1111
|
# A turn that ended (a failure, an Interrupt) before it settled the
|
|
1057
1112
|
# ask: its line says so. Nothing once it was settled.
|
|
1058
|
-
toolkit_suggestion
|
|
1113
|
+
@toolkit_suggestion.abandon(turn, :failed)
|
|
1114
|
+
@toolkit_suggestion.finish(turn)
|
|
1059
1115
|
end
|
|
1060
1116
|
private :prepare_turn
|
|
1061
1117
|
|
|
@@ -1087,7 +1143,7 @@ module Samagotchi
|
|
|
1087
1143
|
|
|
1088
1144
|
unless turn.continue
|
|
1089
1145
|
user_message = { role: "user", content: turn.prompt, turn_id: turn.id, **author_fields(turn.origin.author),
|
|
1090
|
-
**participant_mode_fields(turn.
|
|
1146
|
+
**participant_mode_fields(turn.context), MessageTime::KEY => turn.at }
|
|
1091
1147
|
user_message[:verify] = turn.verify.to_h if turn.verify
|
|
1092
1148
|
user_message[:images] = image_refs unless image_refs.empty?
|
|
1093
1149
|
turn.messages << user_message
|
|
@@ -1106,17 +1162,28 @@ module Samagotchi
|
|
|
1106
1162
|
# Route model name as bare (without host prefix) to the server;
|
|
1107
1163
|
# host selection already done via active client.
|
|
1108
1164
|
bare_for_backend = bare_model_name(model.name)
|
|
1109
|
-
# The turn's settings, set once here
|
|
1110
|
-
#
|
|
1111
|
-
#
|
|
1165
|
+
# The turn's settings, set once here into its context (with the model
|
|
1166
|
+
# key and name the gate and memory_read use: frozen now, after the
|
|
1167
|
+
# hooks that may switch the model), which goes down the backend's
|
|
1168
|
+
# complete to every tool call, and is published (TurnState).
|
|
1112
1169
|
explained = model.llm_context_explained(@model_settings.llm_context_session_args)
|
|
1113
1170
|
model_backend = backend(model)
|
|
1114
1171
|
# A host that loads tools runs a direct call of one the session
|
|
1115
1172
|
# reaches but doesn't declare (ToolRunner, KernelLoop#dispatch).
|
|
1116
1173
|
loads_tools = model_backend.respond_to?(:loads_tools?) && model_backend.loads_tools?(bare_for_backend)
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1174
|
+
settings = turn.prepared_settings.with(model_name: bare_for_backend, window_setting: model.window_setting,
|
|
1175
|
+
llm_context: explained&.resolved, price: model.price,
|
|
1176
|
+
loads_tools: loads_tools)
|
|
1177
|
+
# The turn's tools (Tools::ToolSurface), built once from the Registry
|
|
1178
|
+
# under those settings' layers and loads_tools: what the loops declare,
|
|
1179
|
+
# defer and dispatch until the turn ends; a change meanwhile (a
|
|
1180
|
+
# /toolkit change, a staged chi.replace_tools) is the next turn's.
|
|
1181
|
+
surface = Tools::ToolSurface.for(@tools, layers: settings.llm_context&.active_layers || [],
|
|
1182
|
+
loads_tools: loads_tools)
|
|
1183
|
+
turn.context = turn.context.with(settings: settings, model_key: @model_binding.model_key,
|
|
1184
|
+
fallback_model_key: @model_binding.fallback_model_key,
|
|
1185
|
+
model_name: guardrail_model_name, surface: surface)
|
|
1186
|
+
@turn_state.replace_context(turn.context)
|
|
1120
1187
|
log_llm_context(explained)
|
|
1121
1188
|
|
|
1122
1189
|
turn.limit = @no_interrupt ? IterationLimit.for(no_interrupt: true) : max_iterations || IterationLimit.for
|
|
@@ -1133,7 +1200,8 @@ module Samagotchi
|
|
|
1133
1200
|
model_name: bare_for_backend,
|
|
1134
1201
|
max_tool_output_chars: max_tool_output_chars,
|
|
1135
1202
|
pending_input: turn_drain(pending_input),
|
|
1136
|
-
reasoning_since: reasoning_since
|
|
1203
|
+
reasoning_since: reasoning_since,
|
|
1204
|
+
context: turn.context
|
|
1137
1205
|
)
|
|
1138
1206
|
result.run_start = run_start
|
|
1139
1207
|
result
|
|
@@ -4,7 +4,7 @@ require_relative "objectives"
|
|
|
4
4
|
|
|
5
5
|
module Samagotchi
|
|
6
6
|
# The views of an Engine its peers get: the kernel's tools
|
|
7
|
-
# (Engine#
|
|
7
|
+
# (KernelLoop::Services#peers, Engine#wire_kernel) and a delegate's approval relay
|
|
8
8
|
# (Engine#relay_peer).
|
|
9
9
|
class Engine
|
|
10
10
|
# The kernel's Tools::Peers, following the current session. cancelled?
|
|
@@ -26,7 +26,8 @@ module Samagotchi
|
|
|
26
26
|
# @param thinking_notices [#call] → ThinkingNotices
|
|
27
27
|
# @param metrics [#call] → SessionMetrics
|
|
28
28
|
# @param hooks [#call] → Hooks::Registry
|
|
29
|
-
# @param
|
|
29
|
+
# @param turn_context [#call] → TurnContext, nil: the running turn's (Engine#turn_context)
|
|
30
|
+
# @param last_turn_context [#call] → TurnContext, nil: the last finished turn's
|
|
30
31
|
# @param model_settings [#call] → SessionModelSettings
|
|
31
32
|
# @param session [#call] → Session, nil
|
|
32
33
|
# @param live_conversation [#call] → Array<Hash>, the running turn's conversation
|
|
@@ -35,8 +36,8 @@ module Samagotchi
|
|
|
35
36
|
# @param working_set_strategy [#call] → the strategy the working set is built under
|
|
36
37
|
# @param turn_running [#call] → Boolean
|
|
37
38
|
# @param announce_or_hold [#call] (event) → announces the event, or holds it
|
|
38
|
-
def initialize(observer:, used_memories:, muted:, steer_cut:, thinking_notices:, metrics:, hooks:,
|
|
39
|
-
model_settings:, session:, live_conversation:, used_memory_names:, served_expected_by:,
|
|
39
|
+
def initialize(observer:, used_memories:, muted:, steer_cut:, thinking_notices:, metrics:, hooks:, turn_context:,
|
|
40
|
+
last_turn_context:, model_settings:, session:, live_conversation:, used_memory_names:, served_expected_by:,
|
|
40
41
|
working_set_strategy:, turn_running:, announce_or_hold:)
|
|
41
42
|
@observer = observer
|
|
42
43
|
@used_memories = used_memories
|
|
@@ -45,7 +46,8 @@ module Samagotchi
|
|
|
45
46
|
@thinking_notices = thinking_notices
|
|
46
47
|
@metrics = metrics
|
|
47
48
|
@hooks = hooks
|
|
48
|
-
@
|
|
49
|
+
@turn_context = turn_context
|
|
50
|
+
@last_turn_context = last_turn_context
|
|
49
51
|
@model_settings = model_settings
|
|
50
52
|
@session = session
|
|
51
53
|
@live_conversation = live_conversation
|
|
@@ -149,15 +151,18 @@ module Samagotchi
|
|
|
149
151
|
end
|
|
150
152
|
|
|
151
153
|
# The strategy the set is built under: the running turn's
|
|
152
|
-
# (TurnSettings#llm_context: what its requests send)
|
|
153
|
-
# the
|
|
154
|
-
#
|
|
155
|
-
#
|
|
154
|
+
# (TurnSettings#llm_context: what its requests send), the last turn's
|
|
155
|
+
# while the running one has no settings yet (before Engine#generate);
|
|
156
|
+
# between turns the next turn's (as TurnStages::Warmup#after: the last turn's
|
|
157
|
+
# settings are stale after a /llm-context or /model change), the last
|
|
158
|
+
# turn's when it can't be resolved. One read of each published context
|
|
159
|
+
# (TurnState): any thread may ask (/working-set's anytime list).
|
|
156
160
|
def working_set_llm_context
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
running = turn_context
|
|
162
|
+
last = last_turn_context&.settings&.llm_context
|
|
163
|
+
return running.settings ? running.settings.llm_context : last if running
|
|
159
164
|
|
|
160
|
-
model_settings.turn_llm_context ||
|
|
165
|
+
model_settings.turn_llm_context || last
|
|
161
166
|
end
|
|
162
167
|
|
|
163
168
|
# A :generation_completed with the generation's decode speed (`speed:`
|
|
@@ -222,7 +227,8 @@ module Samagotchi
|
|
|
222
227
|
def thinking_notices = @thinking_notices.call
|
|
223
228
|
def metrics = @metrics.call
|
|
224
229
|
def hooks = @hooks.call
|
|
225
|
-
def
|
|
230
|
+
def turn_context = @turn_context.call
|
|
231
|
+
def last_turn_context = @last_turn_context.call
|
|
226
232
|
def model_settings = @model_settings.call
|
|
227
233
|
def session = @session.call
|
|
228
234
|
def live_conversation = @live_conversation.call
|