samagotchi 0.153.0 → 0.154.1
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 +42 -1
- data/README.md +2 -3
- data/bin/chi +23 -24
- data/docs/architecture.md +30 -33
- data/docs/broadcast.md +5 -5
- data/docs/bundles.md +9 -12
- data/docs/cli.md +82 -96
- data/docs/configuration.md +27 -26
- data/docs/context.md +3 -3
- data/docs/desktop.md +1 -1
- data/docs/guardrails.md +8 -10
- data/docs/hooks.md +9 -9
- data/docs/internals/attached-context.md +2 -2
- data/docs/internals/background-tasks.md +3 -4
- data/docs/internals/block-renderers.md +4 -0
- data/docs/internals/bridge.md +21 -8
- data/docs/internals/context-telemetry.md +1 -1
- data/docs/internals/engine.md +33 -7
- data/docs/internals/objectives.md +6 -5
- data/docs/internals/participants.md +7 -7
- data/docs/internals/prompt-caching.md +4 -2
- data/docs/internals/remote-sessions.md +7 -7
- data/docs/internals/web-frontend.md +2 -2
- data/docs/internals/web-push.md +1 -1
- data/docs/memory.md +2 -2
- data/docs/plugins.md +23 -28
- data/docs/sessions.md +24 -24
- data/docs/sub-agent.md +2 -2
- data/docs/system-one.md +1 -1
- data/docs/testing.md +31 -6
- data/lib/samagotchi/answer_text.rb +33 -0
- data/lib/samagotchi/bridge/card_places.rb +56 -7
- data/lib/samagotchi/bridge/card_store.rb +24 -9
- data/lib/samagotchi/bridge.rb +52 -32
- data/lib/samagotchi/bridge_client.rb +19 -14
- data/lib/samagotchi/broadcast/recipients.rb +2 -2
- data/lib/samagotchi/broadcast/triage.rb +1 -1
- data/lib/samagotchi/broadcast_command.rb +5 -5
- data/lib/samagotchi/bundle_command/try/command.rb +1 -1
- data/lib/samagotchi/bundle_command/try/run.rb +1 -1
- data/lib/samagotchi/bundle_command/try/trace.rb +1 -1
- data/lib/samagotchi/bundle_command.rb +2 -2
- data/lib/samagotchi/bundles/btw/manifest.yml +2 -2
- data/lib/samagotchi/bundles/btw/plugin.rb +1 -1
- data/lib/samagotchi/bundles/coordinator/manifest.yml +2 -2
- data/lib/samagotchi/bundles/coordinator/plugin.rb +3 -2
- data/lib/samagotchi/bundles/decision-card/manifest.yml +4 -4
- data/lib/samagotchi/bundles/decision-card/plugin.rb +1 -9
- data/lib/samagotchi/bundles/dev/manifest.yml +2 -2
- data/lib/samagotchi/bundles/github-pr/manifest.yml +2 -2
- data/lib/samagotchi/bundles/github-pr/plugin.rb +3 -3
- data/lib/samagotchi/bundles/skills/manifest.yml +2 -2
- data/lib/samagotchi/bundles/skills/plugin.rb +3 -2
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +3 -4
- data/lib/samagotchi/bundles/system/manifest.yml +3 -3
- data/lib/samagotchi/bundles/system/self_map.md +1 -1
- data/lib/samagotchi/child_move.rb +3 -3
- data/lib/samagotchi/commands/registry.rb +6 -6
- data/lib/samagotchi/composer_route.rb +4 -5
- data/lib/samagotchi/config.rb +14 -12
- data/lib/samagotchi/context_candidate_choice.rb +1 -1
- data/lib/samagotchi/context_candidates.rb +4 -3
- data/lib/samagotchi/continue_offer.rb +1 -1
- data/lib/samagotchi/debug_log.rb +1 -1
- data/lib/samagotchi/degrade.rb +75 -0
- data/lib/samagotchi/desktop/macos/ChiRunner.swift +3 -3
- data/lib/samagotchi/engine/cards.rb +87 -0
- data/lib/samagotchi/engine/context_judge.rb +138 -0
- data/lib/samagotchi/engine/events.rb +131 -0
- data/lib/samagotchi/engine/guardrails.rb +87 -0
- data/lib/samagotchi/engine/hooks.rb +119 -0
- data/lib/samagotchi/engine/messages.rb +124 -0
- data/lib/samagotchi/engine/model_settings.rb +127 -0
- data/lib/samagotchi/engine/models.rb +261 -0
- data/lib/samagotchi/engine/objectives.rb +116 -0
- data/lib/samagotchi/engine/participants.rb +86 -0
- data/lib/samagotchi/engine/plugins.rb +208 -0
- data/lib/samagotchi/engine/questions.rb +98 -0
- data/lib/samagotchi/engine/recap.rb +130 -0
- data/lib/samagotchi/engine/session.rb +131 -0
- data/lib/samagotchi/engine/side_requests.rb +135 -0
- data/lib/samagotchi/engine/steering.rb +134 -0
- data/lib/samagotchi/engine/toolkit.rb +269 -0
- data/lib/samagotchi/engine/turn_end.rb +180 -0
- data/lib/samagotchi/engine/turn_helpers.rb +160 -0
- data/lib/samagotchi/engine/verify.rb +153 -0
- data/lib/samagotchi/engine.rb +62 -2646
- data/lib/samagotchi/engine_snapshots.rb +9 -8
- data/lib/samagotchi/grants.rb +575 -0
- data/lib/samagotchi/guardrail_wiring.rb +2 -2
- data/lib/samagotchi/guardrails/context.rb +2 -3
- data/lib/samagotchi/guardrails/parent_approvals.rb +2 -2
- data/lib/samagotchi/guardrails/parent_policy.rb +2 -2
- data/lib/samagotchi/hook_routes.rb +3 -3
- data/lib/samagotchi/idle_recap.rb +7 -6
- data/lib/samagotchi/idle_reminders.rb +3 -4
- data/lib/samagotchi/iteration_limit.rb +2 -2
- data/lib/samagotchi/kernel_loop.rb +13 -13
- data/lib/samagotchi/launch_mode.rb +13 -32
- data/lib/samagotchi/level_setting_command.rb +3 -2
- data/lib/samagotchi/llm/chat_loop.rb +3 -1
- data/lib/samagotchi/llm_context_command.rb +3 -2
- data/lib/samagotchi/log.rb +7 -7
- data/lib/samagotchi/log_line.rb +1 -1
- data/lib/samagotchi/log_path.rb +1 -1
- data/lib/samagotchi/note_command.rb +1 -1
- data/lib/samagotchi/note_delivery.rb +18 -8
- data/lib/samagotchi/objectives.rb +24 -3
- data/lib/samagotchi/objectives_check.rb +8 -27
- data/lib/samagotchi/objectives_command.rb +4 -69
- data/lib/samagotchi/objectives_edit.rb +87 -0
- data/lib/samagotchi/output_formatter.rb +7 -1
- data/lib/samagotchi/owner_lock.rb +7 -1
- data/lib/samagotchi/parent_answers_command.rb +5 -4
- data/lib/samagotchi/participant_exposure.rb +42 -0
- data/lib/samagotchi/participant_mode.rb +1 -1
- data/lib/samagotchi/participant_name.rb +1 -1
- data/lib/samagotchi/participants.rb +17 -17
- data/lib/samagotchi/participants_watch.rb +1 -1
- data/lib/samagotchi/plugin/api.rb +3 -2
- data/lib/samagotchi/plugin/context.rb +21 -7
- data/lib/samagotchi/plugin/peer.rb +2 -1
- data/lib/samagotchi/plugin/sessions.rb +6 -4
- data/lib/samagotchi/plugin_tasks.rb +1 -2
- data/lib/samagotchi/private_files.rb +29 -0
- data/lib/samagotchi/project_env.rb +2 -2
- data/lib/samagotchi/question_desk.rb +8 -7
- data/lib/samagotchi/recap_command.rb +2 -1
- data/lib/samagotchi/recap_setup.rb +1 -1
- data/lib/samagotchi/recap_store.rb +1 -1
- data/lib/samagotchi/redact.rb +86 -0
- data/lib/samagotchi/reminder_queue.rb +2 -2
- data/lib/samagotchi/remote_attach_command.rb +1 -1
- data/lib/samagotchi/reply_wait/poll.rb +2 -2
- data/lib/samagotchi/review_start.rb +1 -1
- data/lib/samagotchi/run_options.rb +6 -6
- data/lib/samagotchi/self_report.rb +42 -39
- data/lib/samagotchi/send_command/busy.rb +1 -1
- data/lib/samagotchi/send_command.rb +4 -1
- data/lib/samagotchi/session.rb +11 -2
- data/lib/samagotchi/session_access/contract.rb +3 -3
- data/lib/samagotchi/session_access/local.rb +9 -9
- data/lib/samagotchi/session_access/remote.rb +17 -7
- data/lib/samagotchi/session_access.rb +4 -4
- data/lib/samagotchi/session_archive_command.rb +2 -2
- data/lib/samagotchi/session_chain.rb +8 -6
- data/lib/samagotchi/session_commands.rb +45 -48
- data/lib/samagotchi/session_continue.rb +1 -1
- data/lib/samagotchi/session_delete_command.rb +4 -4
- data/lib/samagotchi/session_manager.rb +67 -49
- data/lib/samagotchi/session_metrics.rb +2 -2
- data/lib/samagotchi/session_model_settings.rb +3 -2
- data/lib/samagotchi/session_participants.rb +1 -1
- data/lib/samagotchi/session_retention.rb +27 -7
- data/lib/samagotchi/sessions_command.rb +4 -4
- data/lib/samagotchi/share_command.rb +10 -10
- data/lib/samagotchi/steer.rb +13 -2
- data/lib/samagotchi/stream_event.rb +22 -0
- data/lib/samagotchi/system_prompt.rb +154 -145
- data/lib/samagotchi/task_watch.rb +1 -1
- data/lib/samagotchi/terminal_ui/attach_launcher.rb +72 -10
- data/lib/samagotchi/terminal_ui/attached_loop/composer.rb +12 -9
- data/lib/samagotchi/terminal_ui/attached_loop/exit_commands.rb +16 -0
- data/lib/samagotchi/terminal_ui/attached_loop/questions.rb +2 -3
- data/lib/samagotchi/terminal_ui/attached_loop.rb +17 -8
- data/lib/samagotchi/terminal_ui/attached_view.rb +1 -11
- data/lib/samagotchi/terminal_ui/event_renderer.rb +3 -5
- data/lib/samagotchi/terminal_ui/formatting.rb +7 -7
- data/lib/samagotchi/terminal_ui/input_support.rb +17 -22
- data/lib/samagotchi/terminal_ui/join_replay.rb +16 -12
- data/lib/samagotchi/terminal_ui/line_reader.rb +2 -2
- data/lib/samagotchi/terminal_ui/live_region.rb +2 -2
- data/lib/samagotchi/terminal_ui/log_tail.rb +135 -0
- data/lib/samagotchi/terminal_ui/one_shot_sink.rb +2 -2
- data/lib/samagotchi/terminal_ui/plain_surface.rb +1 -1
- data/lib/samagotchi/terminal_ui/question_prompt.rb +4 -5
- data/lib/samagotchi/terminal_ui/reline_seam.rb +2 -12
- data/lib/samagotchi/terminal_ui/status_row.rb +6 -14
- data/lib/samagotchi/terminal_ui.rb +142 -1387
- data/lib/samagotchi/title_command.rb +2 -2
- data/lib/samagotchi/tool_runner.rb +15 -16
- data/lib/samagotchi/toolkit_command.rb +2 -1
- data/lib/samagotchi/tools/delegate.rb +3 -1
- data/lib/samagotchi/tools/delegate_cursor.rb +3 -3
- data/lib/samagotchi/tools/delegate_wait.rb +1 -1
- data/lib/samagotchi/tools/objectives_tool.rb +2 -2
- data/lib/samagotchi/tools/send_note.rb +2 -1
- data/lib/samagotchi/turn_endings.rb +2 -2
- data/lib/samagotchi/turn_flow.rb +11 -7
- data/lib/samagotchi/update_hint.rb +2 -2
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +42 -51
- data/lib/samagotchi/web/message_display.rb +7 -0
- data/lib/samagotchi/web/participant_access.rb +2 -2
- data/lib/samagotchi/web/participant_review.rb +5 -5
- data/lib/samagotchi/web/participant_stream_filter.rb +8 -8
- data/lib/samagotchi/web/participant_view.rb +2 -82
- data/lib/samagotchi/web/participants_admin.rb +1 -1
- data/lib/samagotchi/web/public/block_host.js +35 -8
- data/lib/samagotchi/web/public/block_renderers.css +9 -5
- data/lib/samagotchi/web/public/card_stamps.js +27 -0
- data/lib/samagotchi/web/public/cards_place.js +5 -3
- data/lib/samagotchi/web/public/chains.js +2 -2
- data/lib/samagotchi/web/public/claim_link.js +4 -4
- data/lib/samagotchi/web/public/composer_mode.js +1 -1
- data/lib/samagotchi/web/public/format.js +4 -3
- data/lib/samagotchi/web/public/turn_html.js +8 -4
- data/lib/samagotchi/web/push/store.rb +1 -1
- data/lib/samagotchi/web/session_access_routes.rb +13 -4
- data/lib/samagotchi/web/session_control.rb +12 -8
- data/lib/samagotchi/web/session_create.rb +1 -1
- data/lib/samagotchi/web/session_hub.rb +2 -2
- data/lib/samagotchi/web/session_show.rb +6 -2
- data/lib/samagotchi/web/session_summary.rb +1 -1
- data/lib/samagotchi/worker.rb +103 -9
- data/lib/samagotchi/worker_link.rb +3 -3
- data/lib/samagotchi/working_set_command.rb +3 -2
- data/lib/samagotchi.rb +0 -1
- metadata +31 -7
- data/lib/samagotchi/pending_input_queue.rb +0 -55
- data/lib/samagotchi/terminal_ui/between_turns.rb +0 -138
- data/lib/samagotchi/terminal_ui/repl_input.rb +0 -152
- data/lib/samagotchi/web/grants.rb +0 -575
- data/lib/samagotchi/web/participant_exposure.rb +0 -44
- data/lib/samagotchi/web/private_files.rb +0 -31
|
@@ -7,6 +7,7 @@ require_relative "session_setting"
|
|
|
7
7
|
require_relative "steer_cut"
|
|
8
8
|
require_relative "steer_cut_after"
|
|
9
9
|
require_relative "thinking"
|
|
10
|
+
require_relative "session"
|
|
10
11
|
|
|
11
12
|
module Samagotchi
|
|
12
13
|
# The session's settings on its effective model, as the Engine reads them:
|
|
@@ -163,7 +164,7 @@ module Samagotchi
|
|
|
163
164
|
# @raise [ArgumentError] with no session yet
|
|
164
165
|
def reasoning_history_override=(level)
|
|
165
166
|
session = @session.call
|
|
166
|
-
raise ArgumentError,
|
|
167
|
+
raise ArgumentError, Session::NONE_YET unless session
|
|
167
168
|
|
|
168
169
|
SessionSetting::REASONING_HISTORY.set(session, level)
|
|
169
170
|
end
|
|
@@ -178,7 +179,7 @@ module Samagotchi
|
|
|
178
179
|
# @raise [ArgumentError] with no session yet
|
|
179
180
|
def thinking_override=(level)
|
|
180
181
|
session = @session.call
|
|
181
|
-
raise ArgumentError,
|
|
182
|
+
raise ArgumentError, Session::NONE_YET unless session
|
|
182
183
|
|
|
183
184
|
SessionSetting::THINKING.set(session, level)
|
|
184
185
|
end
|
|
@@ -4,7 +4,7 @@ require_relative "steer"
|
|
|
4
4
|
require_relative "participant_mode"
|
|
5
5
|
|
|
6
6
|
module Samagotchi
|
|
7
|
-
# Loaded only when a session is read: it brings
|
|
7
|
+
# Loaded only when a session is read: it brings Grants.
|
|
8
8
|
autoload :Participants, File.expand_path("participants", __dir__)
|
|
9
9
|
|
|
10
10
|
# What a session's Engine knows of its participants: participants.json
|
|
@@ -18,7 +18,7 @@ module Samagotchi
|
|
|
18
18
|
# (session.retention_days), count (session.max_count, counting only the
|
|
19
19
|
# sessions that stay), statuses kept (session.keep_status), sessions left
|
|
20
20
|
# empty (SessionManager.discardable?, an hour on), leftover scratch
|
|
21
|
-
# sessions and skeleton-only directories; a session with a live owner
|
|
21
|
+
# sessions (once past SCRATCH_START_GRACE) and skeleton-only directories; a session with a live owner
|
|
22
22
|
# always stays.
|
|
23
23
|
module SessionRetention
|
|
24
24
|
# The session.retention_days / max_count / keep_status defaults.
|
|
@@ -30,7 +30,7 @@ module Samagotchi
|
|
|
30
30
|
DEFAULT_KEEP_STATUS = [].freeze
|
|
31
31
|
|
|
32
32
|
# How long a session may sit empty before the sweep takes it: its
|
|
33
|
-
# worker
|
|
33
|
+
# worker deletes it as it leaves, so the sweep only catches
|
|
34
34
|
# those killed first (a reboot, kill -9).
|
|
35
35
|
EMPTY_GRACE_SECONDS = 3600
|
|
36
36
|
|
|
@@ -69,7 +69,7 @@ module Samagotchi
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# Directories with no session file and nothing but the skeleton, nobody
|
|
72
|
-
# owning them: a
|
|
72
|
+
# owning them: a one-shot killed before its first save, or a worker woken
|
|
73
73
|
# just as its session was discarded.
|
|
74
74
|
# @return [Array<String>] their ids
|
|
75
75
|
private_class_method def self.prune_orphan_dirs(state_dir, dry_run:)
|
|
@@ -93,6 +93,16 @@ module Samagotchi
|
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
# How long after its save an unowned scratch session may still be
|
|
97
|
+
# waiting for the worker just spawned for it to take its owner lock.
|
|
98
|
+
SCRATCH_START_GRACE = SessionManager::WORKER_START_GRACE
|
|
99
|
+
|
|
100
|
+
private_class_method def self.scratch_starting?(path, now)
|
|
101
|
+
now - File.mtime(path) < SCRATCH_START_GRACE
|
|
102
|
+
rescue SystemCallError
|
|
103
|
+
false
|
|
104
|
+
end
|
|
105
|
+
|
|
96
106
|
# Lazy sweep guard: runs prune at most once per SWEEP_INTERVAL_HOURS
|
|
97
107
|
# (session.sweep_interval_hours).
|
|
98
108
|
MARKER = ".last_retention"
|
|
@@ -161,8 +171,10 @@ module Samagotchi
|
|
|
161
171
|
# +any_age+ makes every session eligible, whatever its age and the
|
|
162
172
|
# count (`chi sessions clean` with no --days: test runs are throwaway).
|
|
163
173
|
#
|
|
164
|
-
# A scratch session nobody owns (its
|
|
165
|
-
# age, its status and the count; +test_only+ takes it too.
|
|
174
|
+
# A scratch session nobody owns (its terminal and worker were killed) goes whatever its
|
|
175
|
+
# age, its status and the count; +test_only+ takes it too. One saved
|
|
176
|
+
# within SCRATCH_START_GRACE (its file's mtime, against +now+) stays: its
|
|
177
|
+
# worker may not have taken the owner lock yet.
|
|
166
178
|
#
|
|
167
179
|
# +max_count+ counts the sessions that stay: one deleted whatever its
|
|
168
180
|
# place (scratch, left empty, expired, +any_age+) takes no slot.
|
|
@@ -173,7 +185,7 @@ module Samagotchi
|
|
|
173
185
|
# @return [Hash] { deleted: [ids], kept: [ids], skipped: [ids] }
|
|
174
186
|
def self.apply(state_dir: Session.default_state_dir, days: DEFAULT_RETENTION_DAYS, max_count: DEFAULT_MAX_COUNT,
|
|
175
187
|
keep_status: DEFAULT_KEEP_STATUS, dry_run: false, test_only: false, alive_check: nil,
|
|
176
|
-
empty_check: nil, any_age: false)
|
|
188
|
+
empty_check: nil, any_age: false, now: Time.now)
|
|
177
189
|
keep_status = Array(keep_status).map(&:to_s)
|
|
178
190
|
# Fetch all sessions sorted newest-first for count logic
|
|
179
191
|
all = Session.list(state_dir: state_dir, sort: "updated_at", order: "desc")
|
|
@@ -182,7 +194,6 @@ module Samagotchi
|
|
|
182
194
|
all = all.select { |session| session.test_run || session.scratch }
|
|
183
195
|
end
|
|
184
196
|
|
|
185
|
-
now = Time.now
|
|
186
197
|
cutoff = days.to_i.positive? ? now - (days.to_i * 86_400) : nil
|
|
187
198
|
max = max_count.to_i
|
|
188
199
|
|
|
@@ -217,6 +228,15 @@ module Samagotchi
|
|
|
217
228
|
end
|
|
218
229
|
end
|
|
219
230
|
|
|
231
|
+
# A scratch session saved within SCRATCH_START_GRACE: `chi scratch`
|
|
232
|
+
# saves it, then spawns the worker that takes its owner lock, so no
|
|
233
|
+
# owner yet doesn't mean a leftover. Kept, it takes no count slot.
|
|
234
|
+
if session.scratch && scratch_starting?(path, now)
|
|
235
|
+
kept << session.id
|
|
236
|
+
passed_over += 1
|
|
237
|
+
next
|
|
238
|
+
end
|
|
239
|
+
|
|
220
240
|
left_empty = begin
|
|
221
241
|
empty_check&.call(session.id)
|
|
222
242
|
rescue StandardError
|
|
@@ -21,7 +21,7 @@ module Samagotchi
|
|
|
21
21
|
# `chi sessions`: list, stop, restart, archive/unarchive, delete, prune,
|
|
22
22
|
# clean and stats sessions from the shell (bin/chi dispatches here before
|
|
23
23
|
# OptionParser; the subcommands have their own flags). Not SessionCommands,
|
|
24
|
-
# the
|
|
24
|
+
# the slash commands a session's worker runs (session_commands.rb).
|
|
25
25
|
class SessionsCommand
|
|
26
26
|
include CLI::Command
|
|
27
27
|
|
|
@@ -207,15 +207,15 @@ module Samagotchi
|
|
|
207
207
|
)
|
|
208
208
|
case format
|
|
209
209
|
when "json"
|
|
210
|
-
# owner: "worker", "tui" (a chi
|
|
210
|
+
# owner: "worker", "tui" (a one-turn chi run: it takes no notes or messages)
|
|
211
211
|
# or nil; recap: the saved recap's first sentence, or nil; project:
|
|
212
212
|
# its git project's root, or nil
|
|
213
213
|
# parent_id: the session that delegated it (the delegate tool), or nil
|
|
214
214
|
# delegate: started by the delegate tool (a fork has a parent_id too)
|
|
215
215
|
# continues: the session it continues (its chain's previous link), or nil
|
|
216
216
|
# archived: hidden from the lists (only with --archived can it be true)
|
|
217
|
-
# scratch: a `chi scratch` session (deleted when its
|
|
218
|
-
# leftover one at the next sweep)
|
|
217
|
+
# scratch: a `chi scratch` session (deleted when its terminal leaves,
|
|
218
|
+
# a leftover one at the next sweep)
|
|
219
219
|
# ctx_pct: how full the context was after the last turn, or nil
|
|
220
220
|
# title: the session's own name (/title; desc shows it too), or nil;
|
|
221
221
|
# auto_title: the one its recap gave it (RecapTitle), or nil
|
|
@@ -8,12 +8,12 @@ require_relative "cli/flags"
|
|
|
8
8
|
require_relative "session"
|
|
9
9
|
require_relative "session_access"
|
|
10
10
|
require_relative "session_access/local"
|
|
11
|
-
require_relative "
|
|
11
|
+
require_relative "grants"
|
|
12
12
|
require_relative "web/qr"
|
|
13
13
|
|
|
14
14
|
module Samagotchi
|
|
15
15
|
# `chi share`: invite a participant to review a session (the
|
|
16
|
-
# shared-sessions plan: a
|
|
16
|
+
# shared-sessions plan: a Grants grant, one session, one person or
|
|
17
17
|
# agent, 7 days unless --expires says otherwise), list the participants,
|
|
18
18
|
# revoke them. Local or through chi --remote NAME (SessionAccess). The
|
|
19
19
|
# token is printed once, in the link; chi keeps only its digest. See
|
|
@@ -95,9 +95,9 @@ module Samagotchi
|
|
|
95
95
|
return parsed if parsed.is_a?(Integer)
|
|
96
96
|
|
|
97
97
|
send(:"run_#{@sub || "invite"}", parsed.options, parsed.args)
|
|
98
|
-
rescue SessionAccess::BadRequest,
|
|
98
|
+
rescue SessionAccess::BadRequest, Grants::BadIdentity => e
|
|
99
99
|
usage_error(e.message)
|
|
100
|
-
rescue
|
|
100
|
+
rescue Grants::Unwritable => e
|
|
101
101
|
error_line("#{command_name}: #{e.message}")
|
|
102
102
|
CLI::Exit::FAILED
|
|
103
103
|
rescue ArgumentError => e
|
|
@@ -114,13 +114,13 @@ module Samagotchi
|
|
|
114
114
|
return usage_error("give one session ID") unless args.size == 1
|
|
115
115
|
return usage_error("--name NAME: who the link is for") if options[:name].to_s.strip.empty?
|
|
116
116
|
|
|
117
|
-
ttl =
|
|
117
|
+
ttl = Grants.parse_ttl(options[:expires])
|
|
118
118
|
return usage_error("--expires takes Nh or Nd, 1h to 30d (e.g. 3d)") if ttl == false
|
|
119
119
|
|
|
120
120
|
cap = options[:cap] && dollars(options[:cap])
|
|
121
121
|
return usage_error(CAP_USAGE) if cap == false
|
|
122
122
|
|
|
123
|
-
identity = options[:identity] &&
|
|
123
|
+
identity = options[:identity] && Grants.clean_identity(options[:identity])
|
|
124
124
|
|
|
125
125
|
id = @access.resolve(args.first)
|
|
126
126
|
invitation = @access.invite(id, name: options[:name], kind: options[:agent] ? "agent" : "human", ttl: ttl, cap: cap,
|
|
@@ -149,13 +149,13 @@ module Samagotchi
|
|
|
149
149
|
0
|
|
150
150
|
end
|
|
151
151
|
|
|
152
|
-
CAP_USAGE = "a cap is dollars, $0 to $#{
|
|
152
|
+
CAP_USAGE = "a cap is dollars, $0 to $#{Grants::MAX_CAP.to_i} (e.g. --cap 5)".freeze
|
|
153
153
|
|
|
154
154
|
def run_cap(_options, args)
|
|
155
155
|
return usage_error("give a session ID, a participant and dollars (chi share cap ID p_… 5)") unless args.size == 3
|
|
156
156
|
|
|
157
157
|
participant = args[1]
|
|
158
|
-
return usage_error("not a participant: #{participant} (chi share ls lists them)") unless
|
|
158
|
+
return usage_error("not a participant: #{participant} (chi share ls lists them)") unless Grants::ID_RE.match?(participant)
|
|
159
159
|
|
|
160
160
|
cap = dollars(args[2])
|
|
161
161
|
return usage_error(CAP_USAGE) if cap == false
|
|
@@ -172,7 +172,7 @@ module Samagotchi
|
|
|
172
172
|
return false unless text.match?(/\A\d+(?:\.\d+)?\z/)
|
|
173
173
|
|
|
174
174
|
value = text.to_f
|
|
175
|
-
|
|
175
|
+
Grants.cap?(value) ? value : false
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
def money(value) = value.nil? ? "-" : format("$%.2f", value)
|
|
@@ -184,7 +184,7 @@ module Samagotchi
|
|
|
184
184
|
return usage_error("give a session ID (and a participant), or --all")
|
|
185
185
|
end
|
|
186
186
|
participant = args[1]
|
|
187
|
-
return usage_error("not a participant: #{participant} (chi share ls lists them)") if participant && !
|
|
187
|
+
return usage_error("not a participant: #{participant} (chi share ls lists them)") if participant && !Grants::ID_RE.match?(participant)
|
|
188
188
|
|
|
189
189
|
id = args.first && @access.resolve(args.first)
|
|
190
190
|
revoked = @access.revoke_participants(id, participant: participant)
|
data/lib/samagotchi/steer.rb
CHANGED
|
@@ -28,6 +28,12 @@ module Samagotchi
|
|
|
28
28
|
module Steer
|
|
29
29
|
KIND = "steer"
|
|
30
30
|
INPUT_KIND = "input"
|
|
31
|
+
# KernelLoop's line asking a Qwen model to finish the tool call it left
|
|
32
|
+
# open: a user line inside the running turn, the model's alone. No turn
|
|
33
|
+
# opens with it (#turn_prompt?), and the page draws nothing for it, as it
|
|
34
|
+
# showed nothing live. Its kind adds no header (#header): its bytes go
|
|
35
|
+
# out as before it had one.
|
|
36
|
+
RECOVERY_KIND = "recovery"
|
|
31
37
|
|
|
32
38
|
# A drain item for an input line with its sender (source nil = the user).
|
|
33
39
|
# A plain String is still a valid item: the user's line. +mark+: fields
|
|
@@ -136,7 +142,7 @@ module Samagotchi
|
|
|
136
142
|
PARTICIPANT_SOURCE = "participant"
|
|
137
143
|
# The owner's author, when one is written out; absent means the same.
|
|
138
144
|
OWNER_AUTHOR = "owner"
|
|
139
|
-
# A participant's author: this prefix, then its id (
|
|
145
|
+
# A participant's author: this prefix, then its id (Grants'
|
|
140
146
|
# grant id), "p:<id>" (#author_for, #participant_id).
|
|
141
147
|
PARTICIPANT_PREFIX = "p:"
|
|
142
148
|
# A participant's message's keys, which every message copy keeps.
|
|
@@ -317,6 +323,11 @@ module Samagotchi
|
|
|
317
323
|
message.is_a?(Hash) && (message[:role] || message["role"]).to_s == "user" && !steer?(message)
|
|
318
324
|
end
|
|
319
325
|
|
|
326
|
+
# KernelLoop's recovery line (RECOVERY_KIND).
|
|
327
|
+
def recovery?(message)
|
|
328
|
+
message.is_a?(Hash) && (message[:kind] || message["kind"]).to_s == RECOVERY_KIND
|
|
329
|
+
end
|
|
330
|
+
|
|
320
331
|
# The user's lines merged into a running turn (Merge#messages).
|
|
321
332
|
def input?(message)
|
|
322
333
|
message.is_a?(Hash) && (message[:kind] || message["kind"]).to_s == INPUT_KIND
|
|
@@ -333,7 +344,7 @@ module Samagotchi
|
|
|
333
344
|
start = (message[:turn_start] || message["turn_start"]) == true
|
|
334
345
|
return start if (message[:role] || message["role"]).to_s == "system"
|
|
335
346
|
|
|
336
|
-
prompt?(message) && (!input?(message) || start)
|
|
347
|
+
prompt?(message) && !recovery?(message) && (!input?(message) || start)
|
|
337
348
|
end
|
|
338
349
|
|
|
339
350
|
# A stored `!shell` line: "!(cmd)\n<output>", no turn id. A user message,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "degrade"
|
|
4
|
+
|
|
5
|
+
module Samagotchi
|
|
6
|
+
# The one rule for handing a loop event to its on_stream_event callback
|
|
7
|
+
# (KernelLoop#emit_stream_event, ToolRunner#emit): no callback is fine, and
|
|
8
|
+
# a failing one (a UI gone) must not break the turn or the tool call. Its
|
|
9
|
+
# failure is a Degrade record under :turn, named by the caller (+failure+,
|
|
10
|
+
# so a log still says which side lost the event), with the event's type.
|
|
11
|
+
module StreamEvent
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
# @param callback [#call, nil] the loop's on_stream_event
|
|
15
|
+
# @param event [Hash] the event
|
|
16
|
+
# @param failure [String] the Degrade event slug when +callback+ raises
|
|
17
|
+
# @return the callback's value, nil when it raised or there is none
|
|
18
|
+
def emit(callback, event, failure:)
|
|
19
|
+
Degrade.call(:turn, failure, type: (event[:type] if event.is_a?(Hash))) { callback&.call(event) }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|