samagotchi 0.152.0 → 0.154.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 +45 -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/bundle-authoring.md +1 -1
- data/docs/bundles.md +93 -12
- data/docs/cli.md +83 -99
- data/docs/configuration.md +46 -40
- data/docs/context.md +3 -3
- data/docs/desktop.md +1 -1
- data/docs/guardrails.md +15 -15
- data/docs/hooks.md +13 -12
- data/docs/internals/anthropic.md +3 -3
- data/docs/internals/attached-context.md +5 -2
- data/docs/internals/background-tasks.md +3 -4
- data/docs/internals/block-renderers.md +4 -0
- data/docs/internals/bridge.md +3 -3
- data/docs/internals/context-telemetry.md +1 -1
- data/docs/internals/engine.md +42 -12
- data/docs/internals/objectives.md +6 -5
- data/docs/internals/participants.md +8 -8
- data/docs/internals/prompt-caching.md +8 -4
- data/docs/internals/remote-sessions.md +7 -7
- data/docs/internals/web-frontend.md +20 -17
- data/docs/internals/web-push.md +1 -1
- data/docs/memory.md +2 -2
- data/docs/plugins.md +52 -43
- data/docs/releasing.md +1 -1
- data/docs/sessions.md +25 -25
- data/docs/sub-agent.md +2 -2
- data/docs/system-one.md +1 -1
- data/docs/testing.md +18 -8
- data/lib/samagotchi/answer_text.rb +34 -0
- data/lib/samagotchi/bridge.rb +43 -32
- data/lib/samagotchi/bridge_client.rb +10 -9
- 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.rb +2 -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/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/bundles/web-search/manifest.yml +13 -0
- data/lib/samagotchi/bundles/web-search/plugin.rb +174 -0
- 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 +2 -2
- 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 +63 -2642
- 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/guardrails/review_boundary.rb +4 -3
- data/lib/samagotchi/hook_routes.rb +3 -3
- data/lib/samagotchi/idle_recap.rb +4 -5
- data/lib/samagotchi/idle_reminders.rb +3 -4
- data/lib/samagotchi/iteration_limit.rb +2 -2
- data/lib/samagotchi/kernel_loop.rb +10 -11
- data/lib/samagotchi/launch_mode.rb +13 -32
- data/lib/samagotchi/level_setting_command.rb +3 -2
- data/lib/samagotchi/llm_context_command.rb +3 -2
- data/lib/samagotchi/llm_context_stale.rb +2 -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/message_parts.rb +3 -2
- 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/pending_input_queue.rb +2 -2
- 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 +59 -36
- 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 +3 -3
- data/lib/samagotchi/sessions_command.rb +4 -4
- data/lib/samagotchi/share_command.rb +10 -10
- data/lib/samagotchi/steer.rb +1 -1
- data/lib/samagotchi/system_prompt.rb +102 -109
- 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 +2 -3
- 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 +1 -7
- 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 +3 -3
- data/lib/samagotchi/terminal_ui/status_row.rb +7 -8
- data/lib/samagotchi/terminal_ui.rb +142 -1387
- data/lib/samagotchi/title_command.rb +2 -2
- data/lib/samagotchi/tool_runner.rb +14 -16
- data/lib/samagotchi/toolkit.rb +8 -5
- data/lib/samagotchi/toolkit_binding.rb +30 -5
- data/lib/samagotchi/toolkit_command.rb +2 -1
- data/lib/samagotchi/toolkit_report_command.rb +9 -5
- data/lib/samagotchi/toolkit_suggest.rb +12 -6
- data/lib/samagotchi/tools/builtin_calls.rb +14 -10
- data/lib/samagotchi/tools/deferred_tools.rb +2 -2
- 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/registry.rb +44 -20
- data/lib/samagotchi/tools/send_note.rb +2 -1
- data/lib/samagotchi/tools/tool_index.rb +27 -21
- data/lib/samagotchi/turn_endings.rb +2 -2
- data/lib/samagotchi/turn_flow.rb +4 -5
- data/lib/samagotchi/update_hint.rb +2 -2
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +39 -50
- 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/app.js +61 -357
- 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/chains.js +2 -2
- data/lib/samagotchi/web/public/claim_link.js +4 -4
- data/lib/samagotchi/web/public/composer_mode.js +110 -0
- data/lib/samagotchi/web/public/format.js +3 -3
- data/lib/samagotchi/web/public/owner_claim.js +81 -0
- data/lib/samagotchi/web/public/owner_verify.js +112 -0
- data/lib/samagotchi/web/public/session_fields.js +3 -3
- data/lib/samagotchi/web/public/strip_grip.js +3 -3
- data/lib/samagotchi/web/public/strip_hidden.js +65 -0
- data/lib/samagotchi/web/public/version_notices.js +132 -0
- data/lib/samagotchi/web/push/store.rb +1 -1
- data/lib/samagotchi/web/session_access_routes.rb +5 -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 +2 -2
- data/lib/samagotchi/web/session_summary.rb +1 -1
- data/lib/samagotchi/worker.rb +106 -9
- data/lib/samagotchi/worker_link.rb +3 -3
- data/lib/samagotchi/working_set_command.rb +3 -2
- metadata +36 -6
- 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
data/docs/plugins.md
CHANGED
|
@@ -96,9 +96,8 @@ This adds a slash command. `name` is `/name`: a lowercase letter first, then a
|
|
|
96
96
|
block returns the text to show (a String), or nil to show nothing. If the
|
|
97
97
|
block raises, the user sees `/name: <error>`.
|
|
98
98
|
|
|
99
|
-
A plugin command works in
|
|
99
|
+
A plugin command works in both UIs, and in a `chi -p "/hello" --non-interactive` one-shot:
|
|
100
100
|
|
|
101
|
-
- **REPL** (`chi --no-shared`): typed at the prompt, and Tab completes it.
|
|
102
101
|
- **Attached TUI** (the default `chi`): the worker's snapshot names the
|
|
103
102
|
session's commands, so the TUI sends `/hello` to the worker and Tab
|
|
104
103
|
completes it. It needs a worker started after the bundle was installed.
|
|
@@ -107,7 +106,7 @@ A plugin command works in all three UIs:
|
|
|
107
106
|
runs it too.
|
|
108
107
|
|
|
109
108
|
A line that is not a known command keeps its old meaning: in the terminal
|
|
110
|
-
|
|
109
|
+
`/foo` goes to the model as a prompt; the web refuses it and names the
|
|
111
110
|
commands it knows.
|
|
112
111
|
|
|
113
112
|
Any whitespace may follow the name, a newline too: `/hello` on its own line
|
|
@@ -117,7 +116,7 @@ blank lines and indentation as typed; only the ends are stripped).
|
|
|
117
116
|
#### `anytime: true`
|
|
118
117
|
|
|
119
118
|
A plugin's normal command waits for its turn: typed while a turn runs, it is
|
|
120
|
-
refused as busy (the
|
|
119
|
+
refused as busy (the web puts it back into an empty composer; a plugin command can't
|
|
121
120
|
ask to run after the turn, as the built-in `/model X` does). An `anytime: true` command
|
|
122
121
|
runs **at once, on its own thread, beside the running turn**, and the turn
|
|
123
122
|
goes on:
|
|
@@ -128,9 +127,6 @@ goes on:
|
|
|
128
127
|
then its cards and notices **as it shows them**, and its output (the
|
|
129
128
|
`command_ran`) when it finishes. So a card can say "working…" first and
|
|
130
129
|
be replaced by the result.
|
|
131
|
-
- In the REPL, typed while a turn runs, it starts on a thread. Its cards
|
|
132
|
-
print as it shows them, above the live region; its output prints there
|
|
133
|
-
too while the turn runs, or at the prompt once the turn has ended.
|
|
134
130
|
|
|
135
131
|
Between turns an anytime command runs like any other, except that its
|
|
136
132
|
cards print as it shows them rather than after its output.
|
|
@@ -142,8 +138,8 @@ running turn: they are not rows of the turn's step, and their events carry
|
|
|
142
138
|
Its block runs on another thread than the turn, so it must be thread-safe:
|
|
143
139
|
|
|
144
140
|
- Read the conversation through `ctx.messages`, a frozen copy. While a turn
|
|
145
|
-
runs, a worker's holds that turn so far;
|
|
146
|
-
**before** that turn (`ctx.messages_partial?` says so).
|
|
141
|
+
runs, a worker's holds that turn so far; a `--non-interactive` one-shot's
|
|
142
|
+
is the conversation **before** that turn (`ctx.messages_partial?` says so).
|
|
147
143
|
- Show things only through `ctx` (`ctx.card`, `ctx.notify`), and return
|
|
148
144
|
the text to show.
|
|
149
145
|
- Keep your own state (instance variables) behind a `Mutex` if two
|
|
@@ -171,8 +167,7 @@ thinking is dropped). The TUI prefills `line --yes`, the web shows an Apply butt
|
|
|
171
167
|
then runs again with `--yes` in `args` (drop it from your words). Outside a command (a hook, an init task, your
|
|
172
168
|
own thread) it is always nil. A plain String or nil return is unchanged.
|
|
173
169
|
|
|
174
|
-
A command that asks must not be `anytime: true`:
|
|
175
|
-
be lost. Needs chi 0.132.0.
|
|
170
|
+
A command that asks must not be `anytime: true`: its Apply would be lost. Needs chi 0.132.0.
|
|
176
171
|
|
|
177
172
|
```ruby
|
|
178
173
|
chi.command "/tone", "show or set this session's tone" do |args, ctx|
|
|
@@ -191,8 +186,8 @@ end
|
|
|
191
186
|
`/help` (itself an anytime command) lists every command the session knows:
|
|
192
187
|
chi's own, each bundle's with the bundle's name, and the terminal UIs' own
|
|
193
188
|
(`/stats`, `/exit`, `/detach` …), marked where they run: `terminal only`,
|
|
194
|
-
`
|
|
195
|
-
It works in
|
|
189
|
+
`web only`, or `terminal and web only` (`/cut`).
|
|
190
|
+
It works in both UIs.
|
|
196
191
|
|
|
197
192
|
### `chi.annotation(label, command:, template: "{quote}", send: false)`
|
|
198
193
|
|
|
@@ -244,8 +239,13 @@ Web only: the terminals type the command (`/claude validate <text>`).
|
|
|
244
239
|
|
|
245
240
|
### `chi.tool(name, description, params:, schema:, label:, preview:, targets:, refs:) { |args, ctx| … }`
|
|
246
241
|
|
|
247
|
-
This adds a tool the model can call.
|
|
248
|
-
|
|
242
|
+
This adds a tool the model can call. A session's toolkit decides whether it
|
|
243
|
+
is declared, as for a built-in ([Toolkits](configuration.md#toolkits)): `full`
|
|
244
|
+
(and any kit on `base: full`) declares it, in the system prompt and in the
|
|
245
|
+
chat path's `tools:`, after chi's own tools; a kit that doesn't list it (`lean`,
|
|
246
|
+
`child`) leaves it **reachable**, found with `find_tools` as `chi/<name>` and
|
|
247
|
+
run by `call_tool` as the tool itself ([the chi group](#chitool_sourcecall-acts_as-label-wait-prefix));
|
|
248
|
+
`add:` declares it there, `remove:` takes it away.
|
|
249
249
|
|
|
250
250
|
- `name`: a–z first, then a–z, 0–9 and `_`, up to 48 characters.
|
|
251
251
|
- `params`: `{ name => property }`, where a property is a JSON Schema
|
|
@@ -462,6 +462,12 @@ end
|
|
|
462
462
|
tool raises `ArgumentError` at once, as `chi.tool` does, and nothing is
|
|
463
463
|
staged.
|
|
464
464
|
- Inside `register`, use `chi.tool`: `replace_tools` raises there.
|
|
465
|
+
- Whether the session needs `find_tools` and `call_tool` is set by the tools
|
|
466
|
+
registered when its worker started. A tool a set adds on a kit that
|
|
467
|
+
leaves it out is reachable when the kit declares them anyway (`lean` does,
|
|
468
|
+
for its left-out built-ins); on a kit that declares neither it stays out
|
|
469
|
+
of reach until the user declares it (`/toolkit add NAME`), with one warn
|
|
470
|
+
notice by your bundle's name.
|
|
465
471
|
|
|
466
472
|
### `chi.on(event, priority: 100) { |event, ctx| … }`
|
|
467
473
|
|
|
@@ -548,8 +554,8 @@ end
|
|
|
548
554
|
so far run, and the next `value` tries again.
|
|
549
555
|
- `service.running?`, `service.state` (`:idle`, `:running`, `:stopped`) and
|
|
550
556
|
`service.stop`.
|
|
551
|
-
- The services stop when chi leaves: the
|
|
552
|
-
|
|
557
|
+
- The services stop when chi leaves: the session's worker exits (an idle
|
|
558
|
+
exit, `/exit`, a crash, TERM), or a `--non-interactive` one-shot ends. See
|
|
553
559
|
[Shutdown](#shutdown). A stopped service never starts again; `value`
|
|
554
560
|
raises `Samagotchi::Plugin::Service::Stopped`.
|
|
555
561
|
- A plugin whose load fails after it started services has them stopped.
|
|
@@ -565,7 +571,7 @@ repo, logging in, starting a server for the first time. `register` itself
|
|
|
565
571
|
should return at once (everything in it runs before the session's UI is
|
|
566
572
|
up), so it hands the slow part to `chi.init`. The block runs **on its own
|
|
567
573
|
thread** once the session can show it: in a worker right after its Bridge
|
|
568
|
-
is up (so a new web chat opens at once), in
|
|
574
|
+
is up (so a new web chat opens at once), in a `--non-interactive` one-shot as its turn starts.
|
|
569
575
|
|
|
570
576
|
```ruby
|
|
571
577
|
class Plugin
|
|
@@ -589,7 +595,7 @@ end
|
|
|
589
595
|
|
|
590
596
|
- **What the UIs show.** Every UI shows a running task (web: a spinner line
|
|
591
597
|
over the composer, `mcp · Starting MCP server chrome (first run, saving
|
|
592
|
-
its tools)…`; the attached TUI: its activity row
|
|
598
|
+
its tools)…`; the attached TUI: its activity row) and a
|
|
593
599
|
line when it is done: `✓` and what the block returned, a short summary
|
|
594
600
|
(`chrome ready, 3 tools`), or `<label>: done` for anything else. A UI that
|
|
595
601
|
joins while it runs sees it too.
|
|
@@ -684,11 +690,12 @@ two tools in all, whatever the number of sources: `find_tools(query,
|
|
|
684
690
|
group?)` (a keyword search that answers each match's `inputSchema`) and
|
|
685
691
|
`call_tool(tool, args)` (calls one as `<group>/<tool>`; its row label is the
|
|
686
692
|
first source's `label`). The index has one group of its own, **`chi`**: the
|
|
687
|
-
built-ins the session's toolkit leaves out but
|
|
688
|
-
([toolkits](configuration.md#toolkits)), each with its
|
|
693
|
+
built-ins and plugin tools (`chi.tool`) the session's toolkit leaves out but
|
|
694
|
+
doesn't remove ([toolkits](configuration.md#toolkits)), each with its
|
|
695
|
+
registered schema; never `find_tools` and `call_tool` themselves.
|
|
689
696
|
The two tools are registered once, after the plugins load, and declared per
|
|
690
|
-
toolkit when it reaches a source group or has a reachable
|
|
691
|
-
with no source declares neither). Nothing a
|
|
697
|
+
toolkit when it reaches a source group or has a reachable tool, as the tools
|
|
698
|
+
stood then (`full` with no source declares neither). Nothing a
|
|
692
699
|
source publishes later changes the request's tools, only what a search
|
|
693
700
|
answers, so the prompt cache keeps: the search tool's description lists the
|
|
694
701
|
source groups as they were at load, and a `chi` line first, per toolkit.
|
|
@@ -703,24 +710,25 @@ session's toolkit. A source's
|
|
|
703
710
|
group named `chi`, or named like an earlier group, is left out of search,
|
|
704
711
|
lookup and the description, with one warning per name.
|
|
705
712
|
|
|
706
|
-
**A
|
|
713
|
+
**A chi tool through `call_tool` runs as that tool.** `call_tool(tool:
|
|
707
714
|
"chi/delegate", args: {…})` (or a bare `delegate` while it's reachable) is
|
|
708
715
|
turned into the `delegate` call itself before the guardrails, so rules on
|
|
709
716
|
`delegate`, approvals (keyed `delegate:…`, the same as a direct call's),
|
|
710
717
|
`before_tool_call`/`after_tool_call` hooks and the row see `delegate`, with
|
|
711
718
|
`call[:via] == "call_tool"`; the row reads "delegate (via call_tool)", live
|
|
712
|
-
and after a reload.
|
|
713
|
-
`
|
|
714
|
-
|
|
715
|
-
|
|
719
|
+
and after a reload. A plugin tool's the same: `chi/web_search` runs as
|
|
720
|
+
`web_search`, with its `label:`, `preview:` and `targets:`. `tool:
|
|
721
|
+
call_tool` rules see MCP calls and misses only. A `chi/` name the toolkit
|
|
722
|
+
removes or declares, or any chi tool once `call_tool` itself is removed, is
|
|
723
|
+
refused by its name before the guardrails (no hook, no card).
|
|
716
724
|
|
|
717
725
|
**On a Messages host the model calls them by name too.** With `api:
|
|
718
726
|
anthropic` (not Fireworks' dialect), every tool `call_tool` reaches goes in
|
|
719
727
|
the request's tools deferred (`defer_loading`: its name only, until
|
|
720
|
-
something loads it): a built-in by its name, a source's tool by its
|
|
728
|
+
something loads it): a built-in or plugin tool by its name, a source's tool by its
|
|
721
729
|
`acts_as` (`mcp_fs_read`; one with a refusal, an acts_as two tools share, or
|
|
722
730
|
a name another tool has stays out). A direct call of one runs whether
|
|
723
|
-
anything loaded it or not: a built-in as itself (as if declared), a
|
|
731
|
+
anything loaded it or not: a built-in or plugin tool as itself (as if declared), a
|
|
724
732
|
source's tool as the `call_tool` call it stands for, so its rules,
|
|
725
733
|
approvals, hooks and row are `call_tool`'s. Elsewhere such a call is
|
|
726
734
|
refused with the `call_tool` route, as before.
|
|
@@ -806,7 +814,7 @@ A cheap System 1 question this bundle asks with `ctx.judge` or `ctx.judge_later`
|
|
|
806
814
|
The plugin's context (the `ctx` its handlers get), for `register` itself:
|
|
807
815
|
its settings, log and data_dir, for example. A `ctx.notify` or `ctx.card`
|
|
808
816
|
while chi starts (inside `register`) is shown once the session's UI can show
|
|
809
|
-
it (a worker's Bridge is up
|
|
817
|
+
it (a worker's Bridge is up), after the plugins'
|
|
810
818
|
load warnings; a UI that joins later still gets it.
|
|
811
819
|
|
|
812
820
|
### Names
|
|
@@ -835,7 +843,7 @@ full label, `plugin.rb (bundle my-bundle)`.
|
|
|
835
843
|
| `ctx.scratch?` | whether the session is a `chi scratch` one (deleted when it ends) |
|
|
836
844
|
| `ctx.delegate?` | whether the session is a delegate child: a task another session handed over |
|
|
837
845
|
| `ctx.review?` | whether the session is a review session (`chi review`): one its participants read, not the owner's working session |
|
|
838
|
-
| `ctx.frontend` | what runs the session, read now: `:
|
|
846
|
+
| `ctx.frontend` | what runs the session, read now: `:one_shot` (`-p --non-interactive`: one turn, then exit) or `:worker` (a session worker: the web, an attached TUI). There is no `:repl` any more: a bundle that checks for it never matches. Only a worker's answers reach the web while it runs; a one-shot's show there once the session is opened. Until the host sets it (while the plugins load, inside `Engine.new`) it reads `:one_shot`, so read it in hooks and init tasks, not in `register` |
|
|
839
847
|
| `ctx.continues` | the id of the session this one continues (a [continue](sessions.md#session-chains)'s new link), else nil |
|
|
840
848
|
| `ctx.fork?` | whether the session is a fork (`ctx.sessions.fork`): it has a parent but isn't a delegate child, and started from a conversation, so its first prompt isn't its first user message |
|
|
841
849
|
| `ctx.model` | the model the session runs on now: its resolved ref (`host:id`), right after `/model` too |
|
|
@@ -848,8 +856,9 @@ full label, `plugin.rb (bundle my-bundle)`.
|
|
|
848
856
|
| `ctx.data_dir` | `$XDG_STATE_HOME/samagotchi/plugins/<bundle>/`, created on first use: what the bundle keeps across sessions |
|
|
849
857
|
| `ctx.session_dir` | this session's own folder there, created on use, read now; nil with no session yet. `ctx.session_dir(create: false)` is the same path with no folder made, for a read, so a session that saved nothing leaves none (a `File.read` of what isn't there raises `Errno::ENOENT`); needs chi newer than 0.143.0. chi removes it when the session is deleted, discarded or pruned, so don't build the path yourself. A `sessions/<id>.json` an older version of your bundle kept moves in as `state.json` (chi still removes one left there). Needs chi newer than 0.142.0 |
|
|
850
858
|
| `ctx.log` | `ctx.log.info(:event, key: value)`: debug-log records tagged `plugins`, with `bundle=<bundle>` |
|
|
851
|
-
| `ctx.messages` | the conversation, as a frozen copy, without the system prompt. While a turn runs, a session worker's (attached, web) adds that turn so far: its prompt, the model's text and the lines merged into it (no tool calls or thinking);
|
|
852
|
-
| `ctx.
|
|
859
|
+
| `ctx.messages` | the conversation, as a frozen copy, without the system prompt. While a turn runs, a session worker's (attached, web) adds that turn so far: its prompt, the model's text and the lines merged into it (no tool calls or thinking); a `--non-interactive` one-shot's is the conversation before that turn. An entry may carry `at`, when it happened (docs/sessions.md, Message times) |
|
|
860
|
+
| `ctx.last_answer` | the newest answer's text as the user saw it: the newest answer bubble of `ctx.messages`, its thoughts (one cut off before it closed too) and tool-call markup taken out, the rule chi's continue note uses. nil when there is none or it was a thought alone; mid-turn, a worker's can be the running turn's interim text. Needs chi newer than 0.153.0 |
|
|
861
|
+
| `ctx.messages_partial?` | whether `ctx.messages` leaves out a running turn (a `--non-interactive` one-shot mid-turn), so a plugin can say what its answer is about |
|
|
853
862
|
| `ctx.prompt_files` | the files whose text is in the session's system prompt now: the AGENTS.md chain (the work tree top down to the cwd) and the appended files (`append_system_prompt:`, `--append-system-prompt`); absolute paths, in prompt order, `[]` before the first build |
|
|
854
863
|
| `ctx.objectives` | the session's [objectives](internals/objectives.md), read now, as a frozen value: `empty?`, `items` (each `id`, `text`, `status` `"active"`, `"done"` or `"dropped"`, `done_when`), `find(id)`, `text` (the lines the model is shown) and `moves` (the latest move per id; mid-turn, a worker's leaves the running turn's out). An edit not yet absorbed counts. Empty when the session has none. Use its methods, not its class. Needs chi newer than 0.148.0 |
|
|
855
864
|
| `ctx.notify(text, level: :info, fallback_for: nil)` | one line to the user, labelled by the bundle (`my-bundle> …`). Every UI shows it, during a turn (a tool, a hook) or between turns (a command). `fallback_for: :display` marks a line that repeats the answer's display (`event[:present]`), which a UI that renders the display leaves out (`fallback_for: :editor`: a file the viewer could open from a ref in its editor): see [Hooks](hooks.md#what-a-hook-can-do-the-runtime). The keyword needs chi 0.35.0 (it raises on an older chi) |
|
|
@@ -865,9 +874,9 @@ full label, `plugin.rb (bundle my-bundle)`.
|
|
|
865
874
|
| `ctx.http` | an HTTP client for calling services (`get`, `post_json`, `request`): see [Calling services](#calling-services-ctxhttp) |
|
|
866
875
|
| `ctx.sessions` | fork, send to, read, list and stop other sessions: see [Other sessions](#other-sessions-ctxsessions) |
|
|
867
876
|
| `ctx.toolkit` | the name of the session's toolkit (`full` for a session from before toolkits); nil with no session |
|
|
868
|
-
| `ctx.declared_tools` | the tool names the session's next turn declares (its toolkit resolved, with its own adds and removes): ask this, not the name, whether a tool is there |
|
|
877
|
+
| `ctx.declared_tools` | the tool names the session's next turn declares (its toolkit resolved, with its own adds and removes): ask this, not the name, whether a tool is there. Your bundle's own `chi.tool` tools are in it only on a kit that declares them (`full`, an `add:`); elsewhere they are reachable, not declared (the testing kit answers every tool, as on full, unless `bundle.set(declared_tools: […])`) |
|
|
869
878
|
| `ctx.use_toolkit(name)` | put the session on toolkit `name` (yours from `chi.toolkit`, or chi's): saved, applied at the next turn's start and announced (`toolkit> toolkit: NAME from the next turn's start`, the web's tools chip follows). Only before the session's first model reply and outside a turn (the declared tools start every request, and a plugin doesn't ask first); otherwise it returns false and changes nothing: tell the user to run `/toolkit NAME`. An unknown name raises ArgumentError. Needs chi 0.66.0 |
|
|
870
|
-
| `ctx.load_tools(names)` | load tools the session reaches but doesn't declare, so the model calls them by name: built-ins (`"delegate"`, `"chi/delegate"`), MCP tools (`"mcp_fs_read"`, `"fs/read"`). Returns the names it staged (the wire names); a declared tool, one loaded before, a removed or unknown one is skipped (an unknown one logged), so calling it every turn is fine. From a `before_turn` hook it loads for that turn; anywhere else (mid-turn too) from the next turn's start. Call it from a hook: before the session's first turn its toolkit isn't applied yet and nothing resolves. **A hint, not access**: the tools keep their guardrails and approvals, and only a host that takes tool changes (`api: anthropic`, not Fireworks) gets one, as a system message after the user's (`[tools loaded: delegate (your-bundle)]` in the session, a notice line live); elsewhere nothing is sent or saved, and the tools stay reachable with `call_tool`. A hook may switch the model after you call it, so the return value can't promise delivery. Raises ArgumentError for anything but an Array. Needs chi 0.99.0 |
|
|
879
|
+
| `ctx.load_tools(names)` | load tools the session reaches but doesn't declare, so the model calls them by name: built-ins and plugin tools (`"delegate"`, `"chi/delegate"`, `"chi/web_search"`), MCP tools (`"mcp_fs_read"`, `"fs/read"`). Returns the names it staged (the wire names); a declared tool, one loaded before, a removed or unknown one is skipped (an unknown one logged), so calling it every turn is fine. From a `before_turn` hook it loads for that turn; anywhere else (mid-turn too) from the next turn's start. Call it from a hook: before the session's first turn its toolkit isn't applied yet and nothing resolves. **A hint, not access**: the tools keep their guardrails and approvals, and only a host that takes tool changes (`api: anthropic`, not Fireworks) gets one, as a system message after the user's (`[tools loaded: delegate (your-bundle)]` in the session, a notice line live); elsewhere nothing is sent or saved, and the tools stay reachable with `call_tool`. A hook may switch the model after you call it, so the return value can't promise delivery. Raises ArgumentError for anything but an Array. Needs chi 0.99.0 |
|
|
871
880
|
| `ctx.context` | attach outside text to this session and list it: see [Attached context](#attached-context-ctxcontext) |
|
|
872
881
|
| `ctx.cache_confirm(line, changed:)` | inside a command: nil to apply a prompt-cache-restarting change now, or a confirm to return as `[text, confirm]`: see [Commands that ask](#commands-that-ask-ctxcache_confirm). Needs chi 0.132.0 |
|
|
873
882
|
|
|
@@ -895,7 +904,7 @@ keeps JSON numbers and booleans. A name that is a core session setting is always
|
|
|
895
904
|
## Cards
|
|
896
905
|
|
|
897
906
|
A card is a small framed message with buttons: a title, a body and
|
|
898
|
-
actions. Core draws it in
|
|
907
|
+
actions. Core draws it in both UIs (the attached TUI and the web); a plugin has no JS or CSS of its
|
|
899
908
|
own.
|
|
900
909
|
|
|
901
910
|
```ruby
|
|
@@ -933,7 +942,6 @@ Where it shows:
|
|
|
933
942
|
|
|
934
943
|
| | during a turn (a tool, a hook) | between turns (a command) |
|
|
935
944
|
|---|---|---|
|
|
936
|
-
| REPL | where it happens, above the live region | at the prompt, after the command's output |
|
|
937
945
|
| attached TUI | where it happens | as it arrives |
|
|
938
946
|
| web | a row of the running step | between the turns |
|
|
939
947
|
|
|
@@ -1218,7 +1226,7 @@ ctx.sessions.review(subjects: ["docs/plan.md"], seed: handoff) # => a review se
|
|
|
1218
1226
|
prefix); it runs as a turn, and a stopped session is woken. It waits up to
|
|
1219
1227
|
5 s for the session's worker, so call it from an anytime command or a
|
|
1220
1228
|
thread of your own, never from a tool or hook of a running turn. A
|
|
1221
|
-
session
|
|
1229
|
+
session a `--non-interactive` one-shot has can't take it.
|
|
1222
1230
|
- A running turn takes it at its next step. `delivery: :queue` runs it as
|
|
1223
1231
|
a turn of its own after that turn instead (as `/queue TEXT` does; to an
|
|
1224
1232
|
idle session it simply runs). A plugin never cuts the running turn's
|
|
@@ -1497,6 +1505,7 @@ bundle.judgments.runs("progress").last["asked"] # the runs as chi saves
|
|
|
1497
1505
|
bundle.sessions.on(:children) { |all:| [] } # ctx.sessions, scripted and recorded
|
|
1498
1506
|
bundle.http.stub(:post, "http://127.0.0.1:9000/classify", json: { label: "safe" }) # ctx.http, never the network
|
|
1499
1507
|
bundle.set(running: false) # the session's values: cwd:, messages:, cancelled: …
|
|
1508
|
+
bundle.set(declared_tools: %w[read]) # ctx.declared_tools (default: every tool, as on full)
|
|
1500
1509
|
bundle.set(cost: 2.5) # ctx.cost: reported USD, or { reported:, estimated:, side:, known: }
|
|
1501
1510
|
bundle.set(usage: { tool_calls: 40, active_ms: 600_000 }) # ctx.usage: { turns:, tool_calls:, tool_calls_by_tool:, steps:, active_ms:, tool_ms_by_tool: }
|
|
1502
1511
|
bundle.set(turn_author: "p:p_0123abcd") # a participant's turn: ctx.turn_author, and author: on every event
|
|
@@ -1581,8 +1590,8 @@ docs/testing.md). **Minitest:** `require "samagotchi/testing/minitest"` and subc
|
|
|
1581
1590
|
|
|
1582
1591
|
## Shutdown
|
|
1583
1592
|
|
|
1584
|
-
When
|
|
1585
|
-
|
|
1593
|
+
When a session's worker exits (an idle exit, `/exit`, a crash, TERM), or a
|
|
1594
|
+
`--non-interactive` one-shot ends, chi shuts the session's Engine down:
|
|
1586
1595
|
|
|
1587
1596
|
1. The idle jobs (reminders, the recap) stop.
|
|
1588
1597
|
2. The plugins' init tasks are cancelled (`ctx.cancelled?` turns true).
|
|
@@ -1593,8 +1602,8 @@ crash, TERM), chi shuts the session's Engine down:
|
|
|
1593
1602
|
|
|
1594
1603
|
## Loading, and when it fails
|
|
1595
1604
|
|
|
1596
|
-
Plugins load when a session starts (`Engine.new`, in
|
|
1597
|
-
|
|
1605
|
+
Plugins load when a session starts (`Engine.new`, in a worker or a
|
|
1606
|
+
`--non-interactive` one-shot), after the bundle hooks. The steps are:
|
|
1598
1607
|
|
|
1599
1608
|
1. The file must match the sha256 recorded at install (not checked for a bundle installed with `--dev`).
|
|
1600
1609
|
2. chi must meet `requires_chi`. A bundle whose `requires_chi` this chi doesn't
|
data/docs/releasing.md
CHANGED
|
@@ -13,7 +13,7 @@ can run the whole release; the user approves the notes before the tag and the
|
|
|
13
13
|
and `rake release:check` enforce it). The system bundle upgrades itself when
|
|
14
14
|
chi starts.
|
|
15
15
|
- **Every other shipped bundle** (btw, check-in, guardrails, known-names,
|
|
16
|
-
loop-guard, mcp, skills, slow-commands, agents-md, cost-cap, work-cap, source-links, github-pr, coordinator, claude-peer, codex-peer, ruby, model-notes, decision-card, and the profiles core and dev) has its own semver in its
|
|
16
|
+
loop-guard, mcp, skills, slow-commands, agents-md, cost-cap, work-cap, source-links, github-pr, coordinator, claude-peer, codex-peer, ruby, model-notes, decision-card, web-search, and the profiles core and dev) has its own semver in its
|
|
17
17
|
`manifest.yml` and, when it needs a newer chi, a `requires_chi:` line. They never upgrade by themselves: users run
|
|
18
18
|
`chi update` (all of them, with the gem) or `chi bundle upgrade NAME`. So:
|
|
19
19
|
- a change to a bundle's files bumps that bundle's `version:`
|