samagotchi 0.101.0 → 0.102.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -1
- data/bin/chi +13 -10
- data/docs/architecture.md +8 -6
- data/docs/cli.md +47 -7
- data/docs/configuration.md +25 -4
- data/docs/internals/bundles.md +1 -1
- data/docs/internals/engine.md +1 -1
- data/docs/internals/llm-context-forget.md +14 -0
- data/docs/internals/prompt-caching.md +8 -1
- data/docs/internals/working-set.md +86 -11
- data/docs/plugins.md +6 -3
- data/docs/sessions.md +28 -11
- data/docs/testing.md +7 -0
- data/lib/samagotchi/bridge/turn_accumulator.rb +16 -0
- data/lib/samagotchi/bridge.rb +9 -3
- data/lib/samagotchi/bundle_command/check.rb +5 -1
- data/lib/samagotchi/bundle_command/try/command.rb +6 -6
- data/lib/samagotchi/bundle_command/try/sandbox.rb +3 -3
- data/lib/samagotchi/bundle_command.rb +4 -4
- data/lib/samagotchi/bundles/system/manifest.yml +1 -1
- data/lib/samagotchi/commands/registry.rb +12 -1
- data/lib/samagotchi/config.rb +89 -53
- data/lib/samagotchi/engine.rb +131 -12
- data/lib/samagotchi/idle_scheduler.rb +16 -1
- data/lib/samagotchi/llm_context_edit.rb +32 -10
- data/lib/samagotchi/llm_context_forget.rb +12 -3
- data/lib/samagotchi/llm_context_view.rb +19 -7
- data/lib/samagotchi/memory_bundle/installer.rb +2 -0
- data/lib/samagotchi/memory_bundle/manifest.rb +13 -2
- data/lib/samagotchi/message_parts.rb +8 -3
- data/lib/samagotchi/plugin/context.rb +2 -2
- data/lib/samagotchi/prompt.rb +1 -1
- data/lib/samagotchi/recap_command.rb +68 -0
- data/lib/samagotchi/recap_setup.rb +27 -14
- data/lib/samagotchi/send_command.rb +14 -11
- data/lib/samagotchi/session.rb +19 -12
- data/lib/samagotchi/session_commands.rb +44 -2
- data/lib/samagotchi/session_config.rb +411 -0
- data/lib/samagotchi/session_setup.rb +9 -9
- data/lib/samagotchi/sessions_command.rb +6 -2
- data/lib/samagotchi/terminal_ui/attach_launcher.rb +5 -5
- data/lib/samagotchi/terminal_ui/attached_loop.rb +2 -1
- data/lib/samagotchi/terminal_ui/formatting.rb +10 -3
- data/lib/samagotchi/terminal_ui.rb +8 -6
- data/lib/samagotchi/testing/bundle.rb +3 -2
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +30 -13
- data/lib/samagotchi/web/public/app.js +2 -0
- data/lib/samagotchi/web/public/commands.js +8 -2
- data/lib/samagotchi/web/public/data.js +3 -2
- data/lib/samagotchi/web/public/index.html +20 -2
- data/lib/samagotchi/web/public/stream_handlers.js +4 -0
- data/lib/samagotchi/web/public/turn_html.js +5 -0
- data/lib/samagotchi/web/public/working_set.js +113 -21
- data/lib/samagotchi/web/public/working_set_view.js +136 -21
- data/lib/samagotchi/worker.rb +9 -6
- data/lib/samagotchi/working_set.rb +49 -11
- data/lib/samagotchi/working_set_command.rb +119 -0
- data/lib/samagotchi/working_set_steer.rb +250 -0
- metadata +5 -2
- data/lib/samagotchi/bundle_session_settings.rb +0 -251
|
@@ -7,8 +7,10 @@ require_relative "idle_target"
|
|
|
7
7
|
require_relative "recap_store"
|
|
8
8
|
|
|
9
9
|
module Samagotchi
|
|
10
|
-
# Builds (or disables) an Engine's idle recap job from the `recap:` kwarg
|
|
11
|
-
# and the Config registry.
|
|
10
|
+
# Builds (or disables) an Engine's idle recap job from the `recap:` kwarg,
|
|
11
|
+
# the session's own settings and the Config registry. The Engine builds
|
|
12
|
+
# one at start, and again when it binds a session whose own recap values
|
|
13
|
+
# differ (Engine#session=).
|
|
12
14
|
module RecapSetup
|
|
13
15
|
# Build (or disable) the idle recap job. On by default: with no recap
|
|
14
16
|
# host or model configured it asks the session's current model on its
|
|
@@ -18,9 +20,10 @@ module Samagotchi
|
|
|
18
20
|
# --model goes; an incomplete one warns and leaves recap off.
|
|
19
21
|
#
|
|
20
22
|
# Single precedence path: explicit `recap:` kwarg > Config registry
|
|
21
|
-
# (CLI > ENV > file > default). An explicit disable
|
|
22
|
-
# the kwarg or in the config file, `recap: {enabled:
|
|
23
|
-
# SAMAGOTCHI_RECAP_ENABLED=false)
|
|
23
|
+
# (session > CLI > ENV > file > default). An explicit disable
|
|
24
|
+
# (`recap: false` as the kwarg or in the config file, `recap: {enabled:
|
|
25
|
+
# false}`, or SAMAGOTCHI_RECAP_ENABLED=false) wins, but over a session's
|
|
26
|
+
# own recap.enabled (chi --set recap.enabled=true) only as the kwarg.
|
|
24
27
|
#
|
|
25
28
|
# @param recap [Hash, false, nil] the Engine's `recap:` kwarg
|
|
26
29
|
# @param engine [Engine] the recap job's engine
|
|
@@ -28,13 +31,22 @@ module Samagotchi
|
|
|
28
31
|
# @param session_target [#call] → the session's current model as a recap target
|
|
29
32
|
# @param session_id [#call] → String, nil
|
|
30
33
|
# @param state_dir [#call] → String
|
|
34
|
+
# @param session_config [#call] → the session's own core settings
|
|
35
|
+
# (SessionConfig::Settings#core), read once here
|
|
31
36
|
# @return [IdleRecap, nil]
|
|
32
|
-
def self.build(recap, engine:, host_registry:, session_target:, session_id:, state_dir:)
|
|
37
|
+
def self.build(recap, engine:, host_registry:, session_target:, session_id:, state_dir:, session_config: -> { {} })
|
|
33
38
|
return nil if recap == false
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
|
|
40
|
+
session = session_config.call || {}
|
|
41
|
+
# The session's own recap.enabled replaces both checks below.
|
|
42
|
+
if session.key?("recap.enabled")
|
|
43
|
+
return nil unless session["recap.enabled"]
|
|
44
|
+
else
|
|
45
|
+
# The REPL and a worker pass nothing: the config is read here alone
|
|
46
|
+
# (a scalar `recap: false` is only seen this way).
|
|
47
|
+
return nil if recap.nil? && ConfigFile.recap_config == false
|
|
48
|
+
return nil if Samagotchi::Config.get("recap.enabled") == false
|
|
49
|
+
end
|
|
38
50
|
|
|
39
51
|
# An explicit kwarg (a spec, an embedder) over the registry.
|
|
40
52
|
kwarg_config = recap.is_a?(Hash) ? recap : {}
|
|
@@ -64,7 +76,7 @@ module Samagotchi
|
|
|
64
76
|
inactivity: recap_number_setting(kwarg_config, :inactivity, "recap.inactivity", IdleRecap::DEFAULT_INACTIVITY_SECONDS, :float),
|
|
65
77
|
min_user_turns: recap_number_setting(kwarg_config, :min_user_turns, "recap.min_user_turns", IdleRecap::DEFAULT_MIN_USER_TURNS, :int),
|
|
66
78
|
timeout: recap_number_setting(kwarg_config, :timeout, "recap.timeout", IdleRecap::DEFAULT_TIMEOUT_SECONDS, :float),
|
|
67
|
-
sentences: recap_sentences(string_config(kwarg_config, :sentences) || registry_string("recap.sentences")),
|
|
79
|
+
sentences: recap_sentences(string_config(kwarg_config, :sentences) || registry_string("recap.sentences", session: session)),
|
|
68
80
|
store: RecapStore.new(session_id_lookup: -> { session_id.call }, state_dir_lookup: -> { state_dir.call }),
|
|
69
81
|
session_id: -> { session_id.call },
|
|
70
82
|
on_usage: ->(usage) { engine.note_side_usage(usage) }
|
|
@@ -108,9 +120,10 @@ module Samagotchi
|
|
|
108
120
|
end
|
|
109
121
|
private_class_method :recap_sentences
|
|
110
122
|
|
|
111
|
-
# Read a scalar recap setting via the Config registry (
|
|
112
|
-
|
|
113
|
-
|
|
123
|
+
# Read a scalar recap setting via the Config registry (session > CLI >
|
|
124
|
+
# ENV > file > default).
|
|
125
|
+
def self.registry_string(key, session: nil)
|
|
126
|
+
value = Samagotchi::Config.get(key, session: session)
|
|
114
127
|
value = value.to_s.strip
|
|
115
128
|
value.empty? ? nil : value
|
|
116
129
|
rescue StandardError
|
|
@@ -8,7 +8,7 @@ require_relative "session_commands"
|
|
|
8
8
|
require_relative "parent_answers_command"
|
|
9
9
|
require_relative "session_inbox"
|
|
10
10
|
require_relative "session_manager"
|
|
11
|
-
require_relative "
|
|
11
|
+
require_relative "session_config"
|
|
12
12
|
require_relative "session_chain"
|
|
13
13
|
require_relative "context_quote"
|
|
14
14
|
require_relative "reply_wait"
|
|
@@ -46,7 +46,7 @@ module Samagotchi
|
|
|
46
46
|
|
|
47
47
|
USAGE = <<~TEXT
|
|
48
48
|
Usage: chi send [-m TEXT] [--image PATH]... [--cut | --queue] (ID|PREFIX)...
|
|
49
|
-
chi send --new [--dir DIR] [--model M] [--llm-context LAYERS] [--thinking LEVEL] [--toolkit NAME] [--set
|
|
49
|
+
chi send --new [--dir DIR] [--model M] [--llm-context LAYERS] [--thinking LEVEL] [--toolkit NAME] [--set KEY=VALUE]... [--parent-answers LEVEL] [-m TEXT] [--image PATH]...
|
|
50
50
|
chi send --new --continues (ID|PREFIX|last:ID) [--model M] [-m TEXT] [--image PATH]...
|
|
51
51
|
chi send --wait [--timeout S] [--format json] [-m TEXT] [--image PATH]... (--new | ID)
|
|
52
52
|
chi send --queue --wait [--timeout S] [--format json] [-m TEXT] ID
|
|
@@ -92,12 +92,15 @@ module Samagotchi
|
|
|
92
92
|
(full, lean, child, a config or bundle one; default
|
|
93
93
|
config's toolkit.default), and tools declared on top
|
|
94
94
|
of it or left out (repeatable, a comma list too)
|
|
95
|
-
--set
|
|
96
|
-
(--new) a
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.
|
|
100
|
-
|
|
95
|
+
--set KEY=VALUE
|
|
96
|
+
(--new) a setting for this session, as chi --set:
|
|
97
|
+
a core key a session may set (recap.enabled,
|
|
98
|
+
recap.sentences), typed by it, or BUNDLE.KEY over
|
|
99
|
+
config.yml's bundles: (a key its bundle's manifest
|
|
100
|
+
lists in session_settings:; numbers (3, .5) and
|
|
101
|
+
booleans (true, off, no) are typed, the rest is
|
|
102
|
+
text); repeatable: --set recap.enabled=false,
|
|
103
|
+
--set cost-cap.cap=3
|
|
101
104
|
--parent-answers LEVEL
|
|
102
105
|
(--new) what a parent agent may answer on its
|
|
103
106
|
questions: hard, standard or soft, only stricter than
|
|
@@ -372,8 +375,8 @@ module Samagotchi
|
|
|
372
375
|
toolkit = Toolkit.from_flags(name: options[:toolkit], add: options[:tools], remove: options[:no_tools])
|
|
373
376
|
options[:toolkit_value] = toolkit if toolkit
|
|
374
377
|
begin
|
|
375
|
-
options[:
|
|
376
|
-
rescue
|
|
378
|
+
options[:settings] = SessionConfig.from_flags(options[:sets]) unless Array(options[:sets]).empty?
|
|
379
|
+
rescue SessionConfig::Error => e
|
|
377
380
|
return usage_error(e.message)
|
|
378
381
|
end
|
|
379
382
|
|
|
@@ -426,7 +429,7 @@ module Samagotchi
|
|
|
426
429
|
setup: SessionSetup.new(llm_context: options[:llm_context],
|
|
427
430
|
thinking: options[:thinking],
|
|
428
431
|
toolkit: options[:toolkit_value],
|
|
429
|
-
|
|
432
|
+
settings: options[:settings],
|
|
430
433
|
parent_answers: options[:parent_answers]),
|
|
431
434
|
state_dir: @state_dir)
|
|
432
435
|
end
|
data/lib/samagotchi/session.rb
CHANGED
|
@@ -213,16 +213,19 @@ module Samagotchi
|
|
|
213
213
|
@toolkit = value.is_a?(Toolkit) ? value : Toolkit.from_file(value)
|
|
214
214
|
end
|
|
215
215
|
|
|
216
|
-
# The session's own
|
|
217
|
-
#
|
|
218
|
-
#
|
|
219
|
-
#
|
|
220
|
-
#
|
|
221
|
-
|
|
216
|
+
# The session's own settings (chi --set), a SessionConfig::Settings:
|
|
217
|
+
# empty for none and for a session from before them. Its core part
|
|
218
|
+
# ({key => value}: recap.enabled) is the file's config_settings, its
|
|
219
|
+
# bundles part ({bundle => {key => value}}) the file's bundle_settings.
|
|
220
|
+
# Given when it was created; a respawn, a continue and a fork keep them
|
|
221
|
+
# (SessionSetup.of), a delegate child doesn't. Plugin::Context#settings
|
|
222
|
+
# lays the bundles part over config.yml's; the core part goes first in
|
|
223
|
+
# Config.get(key, session:) (RecapSetup).
|
|
224
|
+
attr_reader :settings
|
|
222
225
|
|
|
223
|
-
# @param value [
|
|
224
|
-
def
|
|
225
|
-
@
|
|
226
|
+
# @param value [SessionConfig::Settings, nil]
|
|
227
|
+
def settings=(value)
|
|
228
|
+
@settings = SessionConfig::Settings.of(value)
|
|
226
229
|
end
|
|
227
230
|
|
|
228
231
|
# The session's own guardrails.parent_answers (hard|standard|soft), nil
|
|
@@ -280,7 +283,7 @@ module Samagotchi
|
|
|
280
283
|
preloaded_memory_names: [], muted_memory_names: [], parent_id: nil, scratch: false,
|
|
281
284
|
last_turn: nil, model_typed: nil, delegate: false, llm_context: nil, prompt_notes: [],
|
|
282
285
|
continues: nil, thinking: nil, reasoning_history: nil, appended_prompt_files: [],
|
|
283
|
-
toolkit: nil,
|
|
286
|
+
toolkit: nil, settings: nil, interrupted_turn: nil, parent_answers: nil, title: nil)
|
|
284
287
|
@id = id
|
|
285
288
|
@metadata_version = metadata_version
|
|
286
289
|
@mode = mode
|
|
@@ -311,7 +314,7 @@ module Samagotchi
|
|
|
311
314
|
self.reasoning_history = reasoning_history
|
|
312
315
|
self.appended_prompt_files = appended_prompt_files
|
|
313
316
|
self.toolkit = toolkit
|
|
314
|
-
self.
|
|
317
|
+
self.settings = settings
|
|
315
318
|
self.parent_answers = parent_answers
|
|
316
319
|
self.interrupted_turn = interrupted_turn
|
|
317
320
|
@turn_checkpoint = nil
|
|
@@ -410,7 +413,7 @@ module Samagotchi
|
|
|
410
413
|
reasoning_history: setup.reasoning_history,
|
|
411
414
|
appended_prompt_files: setup.appended_prompt_files,
|
|
412
415
|
toolkit: setup.toolkit,
|
|
413
|
-
|
|
416
|
+
settings: setup.settings,
|
|
414
417
|
parent_answers: setup.parent_answers,
|
|
415
418
|
continues: continues
|
|
416
419
|
)
|
|
@@ -479,6 +482,7 @@ module Samagotchi
|
|
|
479
482
|
"appended_prompt_files" => [],
|
|
480
483
|
"toolkit" => nil,
|
|
481
484
|
"bundle_settings" => {},
|
|
485
|
+
"config_settings" => {},
|
|
482
486
|
"interrupted_turn" => nil,
|
|
483
487
|
"parent_answers" => nil
|
|
484
488
|
}.freeze
|
|
@@ -490,6 +494,7 @@ module Samagotchi
|
|
|
490
494
|
attrs = FIELDS.to_h do |key, default|
|
|
491
495
|
[key.to_sym, default.equal?(REQUIRED) ? data.fetch(key) : data.fetch(key, default)]
|
|
492
496
|
end
|
|
497
|
+
attrs[:settings] = SessionConfig::Settings.new(core: attrs.delete(:config_settings), bundles: attrs.delete(:bundle_settings))
|
|
493
498
|
attrs[:messages] = messages ? Array(attrs[:messages]).map { |msg| symbolize_message_keys(msg) } : []
|
|
494
499
|
new(**attrs)
|
|
495
500
|
end
|
|
@@ -618,6 +623,8 @@ module Samagotchi
|
|
|
618
623
|
when "thinking" then thinking_file
|
|
619
624
|
when "reasoning_history" then reasoning_history_file
|
|
620
625
|
when "toolkit" then @toolkit&.to_file
|
|
626
|
+
when "bundle_settings" then @settings.bundles
|
|
627
|
+
when "config_settings" then @settings.core
|
|
621
628
|
when "prompt_notes" then @prompt_notes.map(&:to_file)
|
|
622
629
|
when "last_turn" then @last_turn&.to_file
|
|
623
630
|
when "used_memory_names", "preloaded_memory_names", "muted_memory_names", "appended_prompt_files"
|
|
@@ -16,6 +16,8 @@ require_relative "toolkit_command"
|
|
|
16
16
|
require_relative "parent_answers_command"
|
|
17
17
|
require_relative "title_command"
|
|
18
18
|
require_relative "reasoning_history_command"
|
|
19
|
+
require_relative "working_set_command"
|
|
20
|
+
require_relative "recap_command"
|
|
19
21
|
require_relative "guardrails/parent_policy"
|
|
20
22
|
|
|
21
23
|
module Samagotchi
|
|
@@ -40,6 +42,8 @@ module Samagotchi
|
|
|
40
42
|
PARENT_ANSWERS_COMMAND = ParentAnswersCommand::NAME
|
|
41
43
|
TITLE_COMMAND = TitleCommand::NAME
|
|
42
44
|
REASONING_HISTORY_COMMAND = ReasoningHistoryCommand::NAME
|
|
45
|
+
WORKING_SET_COMMAND = WorkingSetCommand::NAME
|
|
46
|
+
RECAP_COMMAND = RecapCommand::NAME
|
|
43
47
|
# A remote catalog has hundreds of ids (OpenRouter ~380): plain /models
|
|
44
48
|
# shows this many per host; /models <text> lists every match.
|
|
45
49
|
MODELS_PER_HOST = 20
|
|
@@ -109,6 +113,11 @@ module Samagotchi
|
|
|
109
113
|
registry.register(TOOLKIT_COMMAND, "show or change the tools this session declares (NAME, add TOOL, remove TOOL)",
|
|
110
114
|
id: :toolkit, mid_turn: show_mid_turn(TOOLKIT_COMMAND),
|
|
111
115
|
match: ->(text) { text.match?(%r{\A/toolkit(?:\s+.*)?\z}) }) { |text| toolkit(text) }
|
|
116
|
+
# The list reads only: mid-turn too; a drop waits for the turn's end
|
|
117
|
+
# (the next turn's first request is the first with it).
|
|
118
|
+
registry.register(WORKING_SET_COMMAND, "list the working set; drop or undrop an item (drop KEY, undrop KEY)",
|
|
119
|
+
id: :working_set, mid_turn: show_mid_turn(WORKING_SET_COMMAND),
|
|
120
|
+
match: ->(text) { text.match?(%r{\A/working-set(?:\s+.*)?\z}) }) { |text| working_set(text) }
|
|
112
121
|
# Tighten-only from anyone; loosening is a user's at a UI (#run's user_ui:).
|
|
113
122
|
registry.register(PARENT_ANSWERS_COMMAND, "show or set what a parent agent may answer here (hard|standard|soft|default; " \
|
|
114
123
|
"never looser than config.yml's)",
|
|
@@ -119,7 +128,14 @@ module Samagotchi
|
|
|
119
128
|
id: :title, anytime: true, match: ->(text) { text.match?(%r{\A/title(?:\s+.*)?\z}) }) { |text| title(text) }
|
|
120
129
|
registry.register(HELP_COMMAND, "list the commands, the bundles' too", anytime: true) { |_text| reply(help_listing) }
|
|
121
130
|
registry.register("/stats", "show the session's stats", local: true)
|
|
122
|
-
|
|
131
|
+
# /recap with words (on|off|default, or a slip: the usage) runs here:
|
|
132
|
+
# it toggles the idle job only, so it doesn't wait for a running turn.
|
|
133
|
+
# The bare /recap shows the recap: the UIs' own, under the same name
|
|
134
|
+
# (Registry#register); /help lists the name once, with this entry's
|
|
135
|
+
# description.
|
|
136
|
+
registry.register(RECAP_COMMAND, "show the session's recap (in a terminal); on|off|default sets this session's own",
|
|
137
|
+
id: :recap_setting, anytime: true, match: ->(text) { text.match?(%r{\A/recap\s+\S}) }) { |text| recap_setting(text) }
|
|
138
|
+
registry.register(RECAP_COMMAND, "show the session's recap", local: true, match: ->(text) { text == RECAP_COMMAND })
|
|
123
139
|
# Bare `exit` too; any case; --delete after it.
|
|
124
140
|
registry.register("/exit", "leave (--delete also deletes the session)", local: true,
|
|
125
141
|
match: exit_match("/?exit"))
|
|
@@ -230,7 +246,9 @@ module Samagotchi
|
|
|
230
246
|
# own (marked by UI), each group by name.
|
|
231
247
|
# @return [String]
|
|
232
248
|
def help_listing
|
|
233
|
-
|
|
249
|
+
# A name with a UI's entry and the session's (/recap): listed once,
|
|
250
|
+
# as the session's (registered first).
|
|
251
|
+
entries = @registry.entries.uniq(&:name).sort_by { |entry| [help_group(entry), entry.name] }
|
|
234
252
|
width = entries.map { |entry| self.class.display_name(entry).length }.max
|
|
235
253
|
lines = entries.map do |entry|
|
|
236
254
|
notes = []
|
|
@@ -527,6 +545,22 @@ module Samagotchi
|
|
|
527
545
|
reply(output, status: status, changed: changed ? [:parent_answers] : [])
|
|
528
546
|
end
|
|
529
547
|
|
|
548
|
+
# /working-set (WorkingSetCommand): an op changes the conversation
|
|
549
|
+
# (changed :messages: the worker saves it, the web reads it again), so
|
|
550
|
+
# a rollback past it would drop it silently (as !cmd), and the working
|
|
551
|
+
# set goes out again (held after the command's command_ran).
|
|
552
|
+
def working_set(text)
|
|
553
|
+
output, changed, status = WorkingSetCommand.new(engine: @engine, save: ->(_session) { save_session })
|
|
554
|
+
.run(text.delete_prefix(WORKING_SET_COMMAND))
|
|
555
|
+
if changed
|
|
556
|
+
@turn_flow.note_conversation_changed
|
|
557
|
+
@engine.announce_working_set
|
|
558
|
+
end
|
|
559
|
+
reply(output, status: status, changed: changed ? [:messages] : [])
|
|
560
|
+
rescue ArgumentError => e
|
|
561
|
+
reply(e.message, status: :error)
|
|
562
|
+
end
|
|
563
|
+
|
|
530
564
|
# /title (TitleCommand); :title in changed when it named the session or
|
|
531
565
|
# cleared its name. A plain save: no setting moved, and it may run on
|
|
532
566
|
# an anytime thread beside a turn.
|
|
@@ -535,6 +569,14 @@ module Samagotchi
|
|
|
535
569
|
reply(output, status: status, changed: changed ? [:title] : [])
|
|
536
570
|
end
|
|
537
571
|
|
|
572
|
+
# /recap on|off|default (RecapCommand); :recap in changed when this
|
|
573
|
+
# session's own recap.enabled moved. It doesn't save: its host does on
|
|
574
|
+
# a changed result (Worker#run_command, the REPL).
|
|
575
|
+
def recap_setting(text)
|
|
576
|
+
output, changed, status = RecapCommand.new(engine: @engine).run(text.delete_prefix(RECAP_COMMAND))
|
|
577
|
+
reply(output, status: status, changed: changed ? [:recap] : [])
|
|
578
|
+
end
|
|
579
|
+
|
|
538
580
|
# A session setting changed (/llm-context, /thinking, /reasoning-history):
|
|
539
581
|
# saved with its model.
|
|
540
582
|
def save_setup(session)
|