samagotchi 0.4.0 → 0.5.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 +80 -1
- data/README.md +13 -2
- data/bin/chi +29 -39
- data/docs/cli.md +135 -73
- data/docs/configuration.md +15 -20
- data/docs/hooks.md +1 -1
- data/docs/memory.md +40 -0
- data/docs/plugins.md +50 -0
- data/docs/releasing.md +9 -6
- data/docs/sessions.md +3 -3
- data/lib/samagotchi/bootstrap/config_writer.rb +1 -2
- data/lib/samagotchi/bridge/sse_writer.rb +0 -3
- data/lib/samagotchi/bridge/turn_accumulator.rb +1 -0
- data/lib/samagotchi/bridge.rb +16 -11
- data/lib/samagotchi/bundles/skills/manifest.yml +10 -0
- data/lib/samagotchi/bundles/skills/plugin.rb +419 -0
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +7 -8
- data/lib/samagotchi/bundles/system/identity.md +5 -0
- data/lib/samagotchi/bundles/system/manifest.yml +5 -5
- data/lib/samagotchi/bundles/system/memory_guide.md +26 -0
- data/lib/samagotchi/bundles/system/self_map.md +2 -1
- data/lib/samagotchi/client.rb +16 -20
- data/lib/samagotchi/config.rb +40 -100
- data/lib/samagotchi/engine.rb +50 -354
- data/lib/samagotchi/kernel_loop.rb +33 -44
- data/lib/samagotchi/live_versions.rb +7 -1
- data/lib/samagotchi/llm/errors.rb +17 -0
- data/lib/samagotchi/llm/http.rb +4 -18
- data/lib/samagotchi/llm/openai_chat.rb +17 -0
- data/lib/samagotchi/model_profile.rb +4 -10
- data/lib/samagotchi/note_command.rb +2 -1
- data/lib/samagotchi/reply_wait.rb +48 -4
- data/lib/samagotchi/self_report.rb +20 -2
- data/lib/samagotchi/send_command.rb +84 -6
- data/lib/samagotchi/session.rb +4 -2
- data/lib/samagotchi/session_manager.rb +18 -37
- data/lib/samagotchi/system_prompt.rb +403 -0
- data/lib/samagotchi/terminal_ui/attach_launcher.rb +5 -3
- data/lib/samagotchi/terminal_ui/attached_loop.rb +120 -83
- data/lib/samagotchi/terminal_ui/attached_view.rb +27 -12
- data/lib/samagotchi/terminal_ui/event_renderer.rb +23 -7
- data/lib/samagotchi/terminal_ui/formatting.rb +32 -22
- data/lib/samagotchi/terminal_ui/input_support.rb +3 -4
- data/lib/samagotchi/terminal_ui/plain_surface.rb +13 -7
- data/lib/samagotchi/terminal_ui/status_row.rb +81 -0
- data/lib/samagotchi/terminal_ui/surface.rb +1 -1
- data/lib/samagotchi/terminal_ui.rb +95 -690
- data/lib/samagotchi/thinking.rb +11 -0
- data/lib/samagotchi/tool_activity.rb +52 -2
- data/lib/samagotchi/tool_runner.rb +3 -0
- data/lib/samagotchi/tools/execute.rb +3 -3
- data/lib/samagotchi/tools/output_guardrails.rb +8 -7
- data/lib/samagotchi/tools/read.rb +4 -4
- data/lib/samagotchi/update_command.rb +2 -1
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +170 -35
- data/lib/samagotchi/web/lan.rb +99 -0
- data/lib/samagotchi/web/message_parts.rb +15 -11
- data/lib/samagotchi/web/public/activity.js +7 -0
- data/lib/samagotchi/web/public/app.js +99 -54
- data/lib/samagotchi/web/public/chat_view.js +5 -1
- data/lib/samagotchi/web/public/index.html +163 -17
- data/lib/samagotchi/web/public/model_pick.js +136 -0
- data/lib/samagotchi/web/public/model_picker.js +224 -0
- data/lib/samagotchi/web/public/notify.js +10 -0
- data/lib/samagotchi/web/public/stage_model.js +110 -0
- data/lib/samagotchi/web/public/stage_view.js +580 -0
- data/lib/samagotchi/web/public/timing.js +6 -2
- data/lib/samagotchi/web/public/turn_events.js +9 -5
- data/lib/samagotchi/web/public/turn_model.js +11 -3
- data/lib/samagotchi/web/public/turn_view.js +74 -19
- data/lib/samagotchi/web/qr.rb +40 -0
- data/lib/samagotchi/web/server.rb +101 -11
- data/lib/samagotchi/web/token.rb +97 -0
- metadata +27 -3
- data/lib/samagotchi/terminal_ui/legacy_surface.rb +0 -111
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 94cd11abcfad07ad2843b4e0fc2eea368d77ab6080403d308db906270a1832c6
|
|
4
|
+
data.tar.gz: 21ac6e7093ee196d98e2ba50979cdbb28f1a3a10ab0e9cac9bad01c88a078daf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa39259864928d70d8cf830d0c7cc15c6865cea75d383484979897800a9f79d6f9fa4d79df3700285d9871e8d0cf5420e9af7c0143ab08e71182befa287b52af
|
|
7
|
+
data.tar.gz: 24f0fe6863767b628c1eec6957bf6cf33d8966b45f8b2cbdfd7ab268d6c323835dba8ff09fbdd9359775263693228a7a11f0d125cf0a38d7f044d6932ca7c4b9
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,84 @@ and commands may change between minor versions. How releases are made:
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.5.0] - 2026-09-30
|
|
12
|
+
|
|
13
|
+
### Security
|
|
14
|
+
|
|
15
|
+
- `chi web` and the worker Bridge refuse requests from other websites. Before,
|
|
16
|
+
a page open in your browser could start a session that runs commands, or
|
|
17
|
+
read your sessions and their output. Please update if you run `chi web`.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Skills: a memory named `skill_<name>` holds the steps of a task you did with
|
|
22
|
+
chi. Say "let's memorize this" and chi saves it; next time it reads and
|
|
23
|
+
follows it, and fixes a step that turned out different in the same turn
|
|
24
|
+
(docs/memory.md, Skills). The system bundle's identity and memory guide
|
|
25
|
+
teach it.
|
|
26
|
+
- The `skills` bundle (`chi bundle install skills`): `/skill save [name]
|
|
27
|
+
[--system]`, `/skill list`, `/skill show`, `/skill diff`; older versions of
|
|
28
|
+
each skill kept (`history_keep`) with a one-line diff after every update;
|
|
29
|
+
a nudge when a followed skill's step fails and the model goes on without
|
|
30
|
+
fixing it (docs/plugins.md, The skills bundle).
|
|
31
|
+
- `chi web --web-host lan` (`web.host: lan`, or one of this machine's IPv4
|
|
32
|
+
addresses): the web UI on your phone. chi web also listens on the LAN
|
|
33
|
+
address and prints a link with an access token and its QR code; every
|
|
34
|
+
request from another machine needs the token, which the page keeps in a
|
|
35
|
+
cookie. `chi web --new-token` replaces it; `chi self` says when chi web runs
|
|
36
|
+
on the LAN. Plain http: for a home network only. New runtime dependency:
|
|
37
|
+
`rqrcode_core`.
|
|
38
|
+
- A third web view, `web.view: stage` (`--web-view stage`): the running turn
|
|
39
|
+
sits above the composer, its tool calls in an expandable cloud, and hands
|
|
40
|
+
off smoothly into the history when it ends. `web.view: turn | stage | chat`
|
|
41
|
+
replaces `web.turn_view` (turn stays the default).
|
|
42
|
+
- The start page's model picker is searchable: models grouped by host, your
|
|
43
|
+
last 5 picks first, every typed word matched ("deepseek4.1 fla" finds
|
|
44
|
+
`openrouter · deepseek/deepseek-v4.1-flash`), arrow keys, Enter and Esc.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- config.yml edits apply without restarting `chi web`: new sessions read the
|
|
49
|
+
file, and running ones pick up settings they read each time (retries,
|
|
50
|
+
limits, log level). Old flat `UPPER_CASE` keys and `backend:` are no longer
|
|
51
|
+
read; they warn as unknown keys.
|
|
52
|
+
- The terminal REPL (`chi --no-shared`, `chi scratch`) shows turns the way
|
|
53
|
+
the attached terminal does, and all three UIs end a turn with the same
|
|
54
|
+
words ("✕ turn canceled (Ctrl-C) · 3.1s", "✕ turn failed: …"); a provider
|
|
55
|
+
retry shows as a dim line. The REPL-only settings `thinking.ui`,
|
|
56
|
+
`thinking.render_interval` and `status.width_mode` / `max_width` /
|
|
57
|
+
`fixed_width` are gone.
|
|
58
|
+
- `session.keep_status` defaults to none: a session left "running" by a
|
|
59
|
+
crashed worker is cleaned up like any other; a session with a live worker
|
|
60
|
+
is never removed.
|
|
61
|
+
- `chi send --image` to a model that can't take images is refused before
|
|
62
|
+
anything is sent, with the reason, instead of failing in the session.
|
|
63
|
+
- A low/medium/high thinking level on a llama.cpp chat host whose template
|
|
64
|
+
ignores it says so once.
|
|
65
|
+
- The web answers `/stats`, `/recap` and `/detach` itself (they're terminal
|
|
66
|
+
commands) instead of showing a worker error.
|
|
67
|
+
- Piped input to an attached chi (`echo "do X" | chi`, `chi -p X` with no
|
|
68
|
+
terminal) waits for its turns to end and exits 1 if one failed, instead of
|
|
69
|
+
detaching at once.
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- OpenRouter's "overloaded" error sent inside an HTTP 200 is retried like a
|
|
74
|
+
503 instead of failing the turn.
|
|
75
|
+
- The context line the model sees during a long tool loop counts the tool
|
|
76
|
+
output added since the last request, so the model knows when to wrap up.
|
|
77
|
+
- `chi send --wait` no longer hangs when the turn fails very fast (for
|
|
78
|
+
example right after an earlier failure); it says the turn failed and why.
|
|
79
|
+
- On Linux the system prompt now gets the "prefer rg" hint when rg is
|
|
80
|
+
installed (the check only worked on macOS).
|
|
81
|
+
- `chi sessions list --live` shows the test sessions of a test run.
|
|
82
|
+
- `chi -p` with no terminal (stdin from a pipe or /dev/null) sends its prompt
|
|
83
|
+
once: a failed turn re-sent it in a loop (hundreds of requests a second),
|
|
84
|
+
and an attached `chi -p` didn't send it at all.
|
|
85
|
+
|
|
86
|
+
Update with `chi update`. Bundle added: skills 0.1.0 (`chi bundle install
|
|
87
|
+
skills`).
|
|
88
|
+
|
|
11
89
|
## [0.4.0] - 2026-09-30
|
|
12
90
|
|
|
13
91
|
### Added
|
|
@@ -234,7 +312,8 @@ and long-lived sessions.
|
|
|
234
312
|
- A macOS desktop helper (`chi desktop install`): a "Send to chi" Service and a
|
|
235
313
|
hotkey panel that send selected text or the clipboard to your sessions.
|
|
236
314
|
|
|
237
|
-
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.
|
|
315
|
+
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.5.0...HEAD
|
|
316
|
+
[0.5.0]: https://github.com/dm1try/samagotchi/compare/v0.4.0...v0.5.0
|
|
238
317
|
[0.4.0]: https://github.com/dm1try/samagotchi/compare/v0.3.0...v0.4.0
|
|
239
318
|
[0.3.0]: https://github.com/dm1try/samagotchi/compare/v0.2.0...v0.3.0
|
|
240
319
|
[0.2.0]: https://github.com/dm1try/samagotchi/releases/tag/v0.2.0
|
data/README.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# samagotchi
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
chi is a local-first, human-in-the-loop agent harness. It remembers what you
|
|
4
|
+
teach it, as memories and skills, and corrects them when a step turns out
|
|
5
|
+
different. You stay in the loop from the terminal or the browser.
|
|
6
|
+
|
|
7
|
+
Samagotchi is the engine; chi (pronounced "chee") is its short name and CLI
|
|
8
|
+
command.
|
|
5
9
|
|
|
6
10
|
> **Pre-1.0:** config and commands may change between minor versions (0.2 →
|
|
7
11
|
> 0.3); the [CHANGELOG](CHANGELOG.md) says what changed. chi is used daily and
|
|
@@ -103,6 +107,7 @@ chi --no-shared # the plain in-process REPL
|
|
|
103
107
|
chi -p "explain lib/" --non-interactive # one turn, print the answer, exit
|
|
104
108
|
chi --resume <session-id> # continue a saved session
|
|
105
109
|
chi web --open # web UI: this project's sessions (--scope=all: every one)
|
|
110
|
+
chi web --web-host lan # the web UI on your phone too: scan the QR code it prints
|
|
106
111
|
chi sessions list # this project's saved sessions (--scope=all: every one)
|
|
107
112
|
pbpaste | chi note --source slack <id> # background context for a session (no turn)
|
|
108
113
|
pbpaste | chi send -m "same bug?" <id> # a message to a session, the clipboard quoted above it
|
|
@@ -113,6 +118,12 @@ chi send --new --wait -m "review feat/x" # a new session you can watch in the w
|
|
|
113
118
|
|
|
114
119
|
`/model` switches models, Ctrl-C cancels a turn, and Ctrl-D or `/detach` detaches (the session keeps running; `chi --attach ID` comes back). `/exit` detaches and stops the session's worker too, unless something still needs it (a running turn, another UI); `chi --resume ID` picks the conversation up again. `/exit --delete` also deletes the session once the worker has gone; `chi sessions delete ID` deletes one from the shell. `/archive` (or `chi sessions archive ID`) hides a session from every list and keeps it for good; `chi sessions list --archived` finds it again.
|
|
115
120
|
|
|
121
|
+
`chi web --web-host lan` opens the web UI to your home network with an
|
|
122
|
+
access token: anyone with the printed link (or its QR code) can run commands
|
|
123
|
+
as you, and it is plain http, readable by anyone on the same Wi-Fi. Use it at
|
|
124
|
+
home, never on a shared network, and `chi web --new-token` if a link leaks.
|
|
125
|
+
See [chi web on your phone](docs/cli.md#chi-web-on-your-phone).
|
|
126
|
+
|
|
116
127
|
### Context notes
|
|
117
128
|
|
|
118
129
|
`chi note` pushes text into one or more sessions as background, not as a
|
data/bin/chi
CHANGED
|
@@ -14,7 +14,7 @@ end
|
|
|
14
14
|
require "optparse"
|
|
15
15
|
require "samagotchi/config"
|
|
16
16
|
|
|
17
|
-
Samagotchi::ConfigFile.
|
|
17
|
+
Samagotchi::ConfigFile.load!
|
|
18
18
|
require "samagotchi"
|
|
19
19
|
|
|
20
20
|
# `chi self`: print version, source dir, config/memory/session paths, model and
|
|
@@ -50,7 +50,7 @@ if ARGV[0] == "sessions"
|
|
|
50
50
|
puts " delete [--force] ID... # delete sessions for good (IDs or unique prefixes); --force stops a live worker first"
|
|
51
51
|
puts " prune [--dry-run] [--days N] [--keep N] [--keep-status running,...] [--test-only]"
|
|
52
52
|
puts " clean [--dry-run] [--days N] # test sessions (SAMAGOTCHI_ENV=test, CI) and leftover chi scratch ones: all of them, or those older than N days"
|
|
53
|
-
puts "Defaults: days=14 keep=500 keep_status=
|
|
53
|
+
puts "Defaults: days=14 keep=500 keep_status=none (config: session.retention_days, session.max_count, session.keep_status)"
|
|
54
54
|
exit 0
|
|
55
55
|
end
|
|
56
56
|
dry_run = sessions_args.include?("--dry-run")
|
|
@@ -110,10 +110,12 @@ if ARGV[0] == "sessions"
|
|
|
110
110
|
project = scope == "all" || cwd ? nil : Samagotchi::ProjectScope.root_for(Dir.pwd)
|
|
111
111
|
scope_note = ->(count) { "#{count} session(s) in #{File.basename(project)} (--scope=all: every project)" }
|
|
112
112
|
# The picker (chi note from a script): filters apply before the limit,
|
|
113
|
-
# and test runs stay out
|
|
113
|
+
# and test runs stay out, unless this is one (SAMAGOTCHI_ENV=test, CI):
|
|
114
|
+
# then its own sessions are what it looks for.
|
|
114
115
|
if live || cwd || (format && format != "text")
|
|
115
116
|
summaries = Samagotchi::SessionManager.session_summaries(
|
|
116
|
-
live: live, cwd: cwd, limit: limit || (live ? 10 : nil), include_tests:
|
|
117
|
+
live: live, cwd: cwd, limit: limit || (live ? 10 : nil), include_tests: Samagotchi::Session.test_session_env?,
|
|
118
|
+
project_root: project,
|
|
117
119
|
include_archived: include_archived
|
|
118
120
|
)
|
|
119
121
|
case format
|
|
@@ -142,7 +144,7 @@ if ARGV[0] == "sessions"
|
|
|
142
144
|
end
|
|
143
145
|
# A delegated session points at its parent.
|
|
144
146
|
child = summary[:parent_short_id] ? " ↳ #{summary[:parent_short_id]}" : ""
|
|
145
|
-
flag = summary[:scratch] ? " [scratch]" : ""
|
|
147
|
+
flag = summary[:scratch] ? " [scratch]" : (summary[:test_run] ? " [test]" : "")
|
|
146
148
|
flag += " [archived]" if summary[:archived]
|
|
147
149
|
ctx = Samagotchi::SessionMetrics.context_label(summary[:ctx_pct])
|
|
148
150
|
puts "#{summary[:id]} #{state.ljust(8)} #{ctx.ljust(8)} #{summary[:updated_at]} #{desc}#{flag}#{child}"
|
|
@@ -899,15 +901,9 @@ scratch = ARGV[0] == "scratch"
|
|
|
899
901
|
ARGV.shift if scratch
|
|
900
902
|
|
|
901
903
|
# no_interrupt / no_default_input start from config.yml or the env; the flags below turn them on.
|
|
902
|
-
options = { verbose: false, no_interrupt: Samagotchi::Config.get("no_interrupt"), non_interactive: false, no_default_input: Samagotchi::Config.get("no_default_input"), web: false, web_port: nil, web_open: false, web_markdown: nil,
|
|
904
|
+
options = { verbose: false, no_interrupt: Samagotchi::Config.get("no_interrupt"), non_interactive: false, no_default_input: Samagotchi::Config.get("no_default_input"), web: false, web_port: nil, web_open: false, web_markdown: nil, web_view: nil }
|
|
903
905
|
cli_overrides = {}
|
|
904
906
|
|
|
905
|
-
if ARGV.any? { |arg| arg == "--backend" || arg.start_with?("--backend=") }
|
|
906
|
-
warn "Error: --backend was removed. A host's api: in config.yml picks the loop " \
|
|
907
|
-
"(api: openai for the chat API; see docs/configuration.md)."
|
|
908
|
-
exit 1
|
|
909
|
-
end
|
|
910
|
-
|
|
911
907
|
# Strict kebab enforcement: --recap_base_url is unknown (OptionParser would otherwise accept _ as -)
|
|
912
908
|
ARGV.each do |arg|
|
|
913
909
|
next unless arg.start_with?("--") && arg.include?("_")
|
|
@@ -916,7 +912,7 @@ ARGV.each do |arg|
|
|
|
916
912
|
base = arg.split("=", 2).first
|
|
917
913
|
# If dashed version is a known flag (registry or hardcoded), reject underscore variant
|
|
918
914
|
dashed = base.tr("_", "-")
|
|
919
|
-
known = %w[--prompt --resume --attach --shared --no-shared --model --thinking --memory --mute --no-interrupt --non-interactive --verbose --no-default-input --port --open] + Samagotchi::Config.cli_entries.map(&:cli_flag)
|
|
915
|
+
known = %w[--prompt --resume --attach --shared --no-shared --model --thinking --memory --mute --no-interrupt --non-interactive --verbose --no-default-input --port --open --new-token] + Samagotchi::Config.cli_entries.map(&:cli_flag)
|
|
920
916
|
if known.include?(dashed) || known.include?(base)
|
|
921
917
|
warn "Unknown option: #{arg} (did you mean #{dashed}?)"
|
|
922
918
|
exit 1
|
|
@@ -956,12 +952,12 @@ parser = OptionParser.new do |opts|
|
|
|
956
952
|
opts.on("--no-default-input", "Skip default REPL input prefill") { options[:no_default_input] = true; cli_overrides["no_default_input"] = true }
|
|
957
953
|
opts.on("--port PORT", "Port for `chi web` (default: 4567, env SAMAGOTCHI_WEB_PORT)") { |p| options[:web_port] = p.to_i; cli_overrides["web.port"] = p.to_s }
|
|
958
954
|
opts.on("--open", "Open browser for `chi web`") { options[:web_open] = true }
|
|
955
|
+
opts.on("--new-token", "`chi web`: replace the LAN access token (web.host: lan); links and QR codes made with the old one stop working") { options[:new_token] = true }
|
|
959
956
|
opts.on("--scope VALUE", %w[project all],
|
|
960
957
|
"Which sessions `chi web` and `chi sessions list` show: project (the default: this folder's git project; " \
|
|
961
958
|
"every session outside a repo) or all") { |v| options[:scope] = v }
|
|
962
959
|
# Accepted values of string entries that the registry doesn't type as enums.
|
|
963
|
-
value_hints = { "
|
|
964
|
-
"web.host" => "127.0.0.1|::1|localhost", "recap.sentences" => "N|N-M",
|
|
960
|
+
value_hints = { "status.line" => "on|off", "web.host" => "127.0.0.1|::1|localhost|lan|IP", "recap.sentences" => "N|N-M",
|
|
965
961
|
"web.annotate_presets" => "text|text" }
|
|
966
962
|
# Universal config flags (implicit convention: ENV SAMAGOTCHI_* ↔ YAML dotted ↔ CLI --kebab)
|
|
967
963
|
# Generated from Samagotchi::Config registry — Option A: snake leaf in YAML, kebab in CLI.
|
|
@@ -969,7 +965,7 @@ parser = OptionParser.new do |opts|
|
|
|
969
965
|
next if %w[no_interrupt no_default_input].include?(entry.key)
|
|
970
966
|
next if entry.key == "web.port" # already handled as --port
|
|
971
967
|
next if entry.key == "default.model" # alias --model above
|
|
972
|
-
next if
|
|
968
|
+
next if entry.key == "web.markdown" # handled below with explicit inverse flags
|
|
973
969
|
case entry.type
|
|
974
970
|
when :bool
|
|
975
971
|
# --[no-]: a bool that defaults to on is only useful switched off.
|
|
@@ -989,8 +985,6 @@ parser = OptionParser.new do |opts|
|
|
|
989
985
|
end
|
|
990
986
|
opts.on("--web-markdown", "Render finalized LLM Markdown in `chi web` (requires optional commonmarker gem)") { options[:web_markdown] = true; cli_overrides["web.markdown"] = true }
|
|
991
987
|
opts.on("--no-web-markdown", "Disable Markdown rendering in `chi web`") { options[:web_markdown] = false; cli_overrides["web.markdown"] = false }
|
|
992
|
-
opts.on("--web-turn-view", "Show each turn in `chi web` as one block of steps (the live one at the bottom; the default); ?view=turn|chat overrides per page") { options[:web_turn_view] = true; cli_overrides["web.turn_view"] = true }
|
|
993
|
-
opts.on("--no-web-turn-view", "Show turns in `chi web` as the classic row of bubbles instead of the turn view") { options[:web_turn_view] = false; cli_overrides["web.turn_view"] = false }
|
|
994
988
|
# Strict underscore rejection: --recap_base_url etc. are not registered and will raise OptionParser::InvalidOption
|
|
995
989
|
opts.on("--version", "Print chi's version") { puts "chi #{Samagotchi::VERSION}"; exit }
|
|
996
990
|
opts.on("-h", "--help", "Show help") { puts opts; exit }
|
|
@@ -1011,6 +1005,10 @@ if stray
|
|
|
1011
1005
|
warn "Error: #{web || scratch ? "unexpected argument" : "unknown command"} #{stray} (see chi --help)"
|
|
1012
1006
|
exit 1
|
|
1013
1007
|
end
|
|
1008
|
+
if options[:new_token] && !web
|
|
1009
|
+
warn "Error: --new-token goes with chi web (chi web --new-token)"
|
|
1010
|
+
exit 1
|
|
1011
|
+
end
|
|
1014
1012
|
|
|
1015
1013
|
# A scratch session is new, runs here and goes when it ends.
|
|
1016
1014
|
if scratch
|
|
@@ -1021,16 +1019,9 @@ if scratch
|
|
|
1021
1019
|
end
|
|
1022
1020
|
end
|
|
1023
1021
|
|
|
1024
|
-
# Apply CLI precedence: CLI > ENV > file
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
# Keep ENV in sync for legacy readers still using ENV directly
|
|
1028
|
-
cli_overrides.each do |k, v|
|
|
1029
|
-
entry = Samagotchi::Config.find_by_key(k)
|
|
1030
|
-
next unless entry&.env_exposed?
|
|
1031
|
-
ENV[entry.env_key] = v.to_s
|
|
1032
|
-
end
|
|
1033
|
-
end
|
|
1022
|
+
# Apply CLI precedence: CLI > ENV > file. Workers this chi spawns get
|
|
1023
|
+
# these through their env (Config.cli_env).
|
|
1024
|
+
Samagotchi::Config.reload!(cli_overrides: cli_overrides) unless cli_overrides.empty?
|
|
1034
1025
|
|
|
1035
1026
|
# The debug log (Samagotchi::LogPath, level log.level) for every command.
|
|
1036
1027
|
# -v (the plain REPL only): debug records, each mirrored to stderr.
|
|
@@ -1053,10 +1044,10 @@ when "web"
|
|
|
1053
1044
|
options[:web_markdown] = true
|
|
1054
1045
|
elsif arg == "--no-web-markdown"
|
|
1055
1046
|
options[:web_markdown] = false
|
|
1056
|
-
elsif arg == "--web-
|
|
1057
|
-
options[:
|
|
1058
|
-
elsif arg
|
|
1059
|
-
options[:
|
|
1047
|
+
elsif arg == "--web-view" && Samagotchi::Config::BY_KEY["web.view"].enum_values.include?(web_args[i + 1])
|
|
1048
|
+
options[:web_view] = web_args[i + 1]
|
|
1049
|
+
elsif arg.start_with?("--web-view=") && Samagotchi::Config::BY_KEY["web.view"].enum_values.include?(arg.split("=", 2).last)
|
|
1050
|
+
options[:web_view] = arg.split("=", 2).last
|
|
1060
1051
|
elsif arg.start_with?("--port=")
|
|
1061
1052
|
options[:web_port] = arg.split("=", 2).last.to_i
|
|
1062
1053
|
end
|
|
@@ -1076,15 +1067,12 @@ end
|
|
|
1076
1067
|
if options[:web]
|
|
1077
1068
|
chi_update_hint.call
|
|
1078
1069
|
require "samagotchi/web/server"
|
|
1079
|
-
port = options[:web_port] || Samagotchi::Config.get("web.port")
|
|
1080
|
-
# legacy env fallback
|
|
1081
|
-
port = ENV.fetch("SAMAGOTCHI_WEB_PORT", port.to_s).to_i rescue port.to_i
|
|
1070
|
+
port = options[:web_port] || Samagotchi::Config.get("web.port")
|
|
1082
1071
|
markdown = options[:web_markdown]
|
|
1083
1072
|
markdown = Samagotchi::Config.get("web.markdown") if markdown.nil?
|
|
1084
|
-
|
|
1085
|
-
turn_view = Samagotchi::Config.get("web.turn_view") if turn_view.nil?
|
|
1073
|
+
view = options[:web_view] || Samagotchi::Config.get("web.view")
|
|
1086
1074
|
exit Samagotchi::Web::Server.launch(port: port, scope: options[:scope] || "project", open_browser: options[:web_open],
|
|
1087
|
-
markdown: markdown,
|
|
1075
|
+
markdown: markdown, view: view, new_token: options[:new_token],
|
|
1088
1076
|
annotate_presets: Samagotchi::Config.get("web.annotate_presets"))
|
|
1089
1077
|
end
|
|
1090
1078
|
|
|
@@ -1183,7 +1171,7 @@ if launch == :attached
|
|
|
1183
1171
|
end
|
|
1184
1172
|
|
|
1185
1173
|
begin
|
|
1186
|
-
Samagotchi::TerminalUI.new(
|
|
1174
|
+
ended = Samagotchi::TerminalUI.new(
|
|
1187
1175
|
prompt: options[:prompt],
|
|
1188
1176
|
session_id: options[:resume],
|
|
1189
1177
|
no_interrupt: options[:no_interrupt] || options[:non_interactive],
|
|
@@ -1194,6 +1182,8 @@ begin
|
|
|
1194
1182
|
model_name: options[:model],
|
|
1195
1183
|
scratch: scratch
|
|
1196
1184
|
).run
|
|
1185
|
+
# `chi -p X </dev/null`: the turn failed (nothing was sent again).
|
|
1186
|
+
exit 1 if ended == :turn_failed
|
|
1197
1187
|
rescue Samagotchi::TerminalUI::SessionBusy, Samagotchi::TerminalUI::SessionNotFound, Samagotchi::ModelProfile::MissingModel => e
|
|
1198
1188
|
warn "Error: #{e.message}"
|
|
1199
1189
|
exit 1
|
data/docs/cli.md
CHANGED
|
@@ -12,15 +12,16 @@
|
|
|
12
12
|
- `chi --attach <session-id>` — attach the terminal to a session's worker (e.g. one started from the Web UI), waking one if it has exited
|
|
13
13
|
- A session id can be shortened to any unique prefix (like git): `chi --attach 2ea8`. `--resume`, `--attach`, `sessions stop`, `sessions archive` and `sessions delete` take one; an ambiguous prefix lists the sessions it matches.
|
|
14
14
|
- `chi web [--port 4567] [--open] [--scope=all]` — start the Web UI (single localhost port session control plane) on this git project's sessions (`--scope=all`, or a folder in no repo: every session); if a chi web already runs on the port, print (with `--open`, open) its page for this folder and exit. Something else on the port (an older chi web too) exits 1 with "port N is in use"
|
|
15
|
+
- `chi web --web-host lan` — the Web UI on your home network too, for your phone: a link with an access token and its QR code (see [chi web on your phone](#chi-web-on-your-phone)); `chi web --new-token` replaces the token
|
|
15
16
|
- `chi web --web-markdown` — opt in to sanitized Markdown rendering for completed assistant messages
|
|
16
|
-
- `chi web --
|
|
17
|
+
- `chi web --web-view stage|chat` — draw turns with the stage view (the running turn pinned above the composer) or as the classic row of bubbles instead of the default turn view (each turn as one block of steps, the running one at the bottom); `?view=turn|stage|chat` on the page URL overrides it (see [Web views](#web-views))
|
|
17
18
|
- `chi sessions list|stop|archive|unarchive|delete|prune|clean` — manage persisted sessions; `list` shows this git project's, `list --scope=all` every one, a delegated session with `↳ <parent>`, `list --archived` the archived ones too (see [Sessions](sessions.md))
|
|
18
19
|
- `chi note [--source NAME] [-m TEXT] (ID|PREFIX)... | --all` — add a context note (TEXT or stdin) to sessions: background the model sees on its next turn; it starts no turn (see [Sessions: Context notes](sessions.md#context-notes))
|
|
19
20
|
- `chi send [-m TEXT] [--image PATH]... (ID|PREFIX)...` — send a message to sessions as if typed there: a turn starts (or a running one picks it up); piped stdin goes above `-m` as quoted context, and `--image` attaches images (see [Sessions: Sending a message](sessions.md#sending-a-message)); `--new` starts a session with it instead, and `--wait` prints the answer (`--wait ID` with no message waits for the next reply without sending; see [Starting a session](sessions.md#starting-a-session))
|
|
20
21
|
- `chi desktop install|upgrade|uninstall|status` — the macOS "Send to chi" helper: a Service and a ⌃⌥⌘N hotkey that send text to live sessions as context notes (see [Desktop helper](desktop.md))
|
|
21
22
|
- `chi self` — print version, source dir (checkout or installed gem), config/memory/session paths, model/host and bundles
|
|
22
23
|
- `chi update [--dry-run] [--no-gem] [--no-bundles] [--no-desktop]` — update an installed chi: the gem, the system bundle, the shipped bundles you installed and the desktop helper, in one table (see [Updating](#updating))
|
|
23
|
-
- `chi bundle install|upgrade|uninstall|status|diff|list|build` — manage memory bundles (see [Bundle hooks](hooks.md#bundle-hooks-unified-workflow-bundle)); `list` shows the installed ones and the ones shipped with chi, which `install <name>` installs (see [Guardrails](guardrails.md), [Plugins](plugins.md#the-btw-bundle), [the mcp bundle](plugins.md#the-mcp-bundle) [the loop-guard bundle](plugins.md#the-loop-guard-bundle)
|
|
24
|
+
- `chi bundle install|upgrade|uninstall|status|diff|list|build` — manage memory bundles (see [Bundle hooks](hooks.md#bundle-hooks-unified-workflow-bundle)); `list` shows the installed ones and the ones shipped with chi, which `install <name>` installs (see [Guardrails](guardrails.md), [Plugins](plugins.md#the-btw-bundle), [the mcp bundle](plugins.md#the-mcp-bundle) [the loop-guard bundle](plugins.md#the-loop-guard-bundle), [the check-in bundle](plugins.md#the-check-in-bundle) and [the skills bundle](plugins.md#the-skills-bundle))
|
|
24
25
|
|
|
25
26
|
### First setup
|
|
26
27
|
|
|
@@ -71,7 +72,7 @@ known-names 0.1.0 0.1.1 updated
|
|
|
71
72
|
infra_tools 1.0.0 skipped (not from chi)
|
|
72
73
|
Chi Helper 0.2.0 up to date (launch file refreshed)
|
|
73
74
|
workers 2 live on 0.2.0: they move to 0.3.0 at idle exit (30 min) or chi sessions stop 2ea8c1f0 91b0d2aa
|
|
74
|
-
Also shipped, not installed: check-in, source-links (chi bundle install NAME)
|
|
75
|
+
Also shipped, not installed: check-in, skills, source-links (chi bundle install NAME)
|
|
75
76
|
done
|
|
76
77
|
```
|
|
77
78
|
|
|
@@ -148,8 +149,8 @@ flag also works as `--kebab-case VALUE`, e.g. `--server-host`, `--server-port`,
|
|
|
148
149
|
`api: openai` in config.yml is driven through the OpenAI chat API (streamed; a remote
|
|
149
150
|
provider via `url:` and `api_key_env:`); every other host gets chi's own raw-prompt loop. `/model` and `--model host:model` switch hosts, and
|
|
150
151
|
the loop with them. See [Configuration](configuration.md) (`hosts:` and `api:`).
|
|
151
|
-
`--backend`, `SAMAGOTCHI_BACKEND` and a `backend:` key were removed
|
|
152
|
-
|
|
152
|
+
`--backend`, `SAMAGOTCHI_BACKEND` and a `backend:` key were removed (`backend:` warns
|
|
153
|
+
as an unknown key).
|
|
153
154
|
|
|
154
155
|
### Entrypoint scenarios
|
|
155
156
|
|
|
@@ -417,16 +418,54 @@ touch screen), and so does each code block of a rendered answer. An answer
|
|
|
417
418
|
copies its Markdown source, not the rendered text; a code block copies just
|
|
418
419
|
its code; a prompt copies the text as you typed it.
|
|
419
420
|
|
|
420
|
-
### Web
|
|
421
|
+
### Web views
|
|
421
422
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
bubbles: one thinking block, one activity panel and one
|
|
425
|
-
|
|
423
|
+
`web.view` picks how the page draws a turn: `turn` (the default, below),
|
|
424
|
+
`stage` (the running turn pinned above the composer, below) or `chat` (the
|
|
425
|
+
classic row of bubbles: one thinking block, one activity panel and one
|
|
426
|
+
answer bubble per generation).
|
|
427
|
+
|
|
428
|
+
```sh
|
|
429
|
+
chi web --web-view stage # or chat; turn is the default
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
The setting also supports `SAMAGOTCHI_WEB_VIEW=stage` or the global config:
|
|
433
|
+
|
|
434
|
+
```yaml
|
|
435
|
+
web:
|
|
436
|
+
view: stage
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
`?view=turn`, `?view=stage` or `?view=chat` on the page URL picks the view
|
|
440
|
+
for that page load, whatever the config says; the parameter is dropped
|
|
441
|
+
when you switch between the project and all-sessions views. The terminal
|
|
442
|
+
UIs are not affected.
|
|
443
|
+
|
|
444
|
+
**The stage view** pins the running turn above the composer, in its own
|
|
445
|
+
card, so it stays on screen without scrolling: a status row (what it is
|
|
446
|
+
doing, the step, the elapsed time), your prompt on one line, the newest
|
|
447
|
+
narration sentence (else the newest thinking one, in italics; click it for
|
|
448
|
+
the step's reasoning), the running tool with what it does, and the last
|
|
449
|
+
three calls. A card that needs you (a question, an approval, check-in)
|
|
450
|
+
sits in the stage too. The chip under it, `N steps · M tool calls` with one
|
|
451
|
+
tick per call, opens the turn view's block in place (newest step first
|
|
452
|
+
while it runs; a tick opens its step). `▾` folds the stage to its status
|
|
453
|
+
row, remembered in this browser. When the turn ends the answer shows in
|
|
454
|
+
the stage, and the whole turn moves up into the history once you are not
|
|
455
|
+
using the stage (the pointer over it, a touch or scroll in the last 4 s,
|
|
456
|
+
keyboard focus or a selection keep it) for 1.5 s; sending the next message
|
|
457
|
+
moves it at once. The history is never scrolled while a turn runs, and only
|
|
458
|
+
follows the hand-off if you were at its end. The `/` command list opens
|
|
459
|
+
over the stage's lower edge.
|
|
460
|
+
|
|
461
|
+
**The turn view** shows a turn as *one block* where the work
|
|
462
|
+
happens. The running
|
|
426
463
|
generation is the live part at the bottom (its thinking, its narration, its
|
|
427
464
|
tool rows), the earlier ones stack above it collapsed to one line each
|
|
428
|
-
(their narration's first line, else
|
|
429
|
-
count), expandable for inspection.
|
|
465
|
+
(their narration's first line, else their first call's title such as
|
|
466
|
+
`edit lib/a.rb`, and a call count), expandable for inspection. A tool row
|
|
467
|
+
says what the call did: a file's path relative to the session's folder, a
|
|
468
|
+
command without its leading `cd … &&` (the full parameters on hover). The live thinking is one line: the
|
|
430
469
|
newest complete sentence, changing at most once per 1.5 s. Click it for the
|
|
431
470
|
full text; a peek is per step (the next step's thinking starts closed
|
|
432
471
|
again). When a step ends its thinking closes to a plain `thinking` line
|
|
@@ -447,22 +486,6 @@ steps saved before that have none, so they show no thinking. An `edit` or
|
|
|
447
486
|
made (up to 120 lines or 8 KB), live and after a reload (see
|
|
448
487
|
[Guardrails](guardrails.md#ask) for the diff an approval shows first).
|
|
449
488
|
|
|
450
|
-
```sh
|
|
451
|
-
chi web --no-web-turn-view # the classic chat view; --web-turn-view is the default
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
The setting also supports `SAMAGOTCHI_WEB_TURN_VIEW=false` or the global config:
|
|
455
|
-
|
|
456
|
-
```yaml
|
|
457
|
-
web:
|
|
458
|
-
turn_view: false
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
`?view=chat` on the page URL forces the classic chat view for that page load
|
|
462
|
-
and `?view=turn` the turn view, whatever the config says; the parameter is dropped
|
|
463
|
-
when you switch between the project and all-sessions views. The terminal
|
|
464
|
-
UIs are not affected.
|
|
465
|
-
|
|
466
489
|
### Web annotate presets
|
|
467
490
|
|
|
468
491
|
Selecting text in an answer, a thinking block, a tool row or one of your
|
|
@@ -489,6 +512,51 @@ web:
|
|
|
489
512
|
there means the default, not "none": use `""` in the file or on the command
|
|
490
513
|
line. A `chi web` that already runs keeps its list; restart it.
|
|
491
514
|
|
|
515
|
+
### chi web on your phone
|
|
516
|
+
|
|
517
|
+
`chi web` listens on 127.0.0.1 only. `--web-host lan` (or `web.host: lan`
|
|
518
|
+
in config.yml) also opens it on this machine's private IPv4 address, for a
|
|
519
|
+
phone on the same Wi-Fi:
|
|
520
|
+
|
|
521
|
+
```sh
|
|
522
|
+
chi web --web-host lan
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
```
|
|
526
|
+
Chi Web on http://127.0.0.1:4567/?dir=/Users/me/projects/app (public: …)
|
|
527
|
+
LAN: http://192.168.1.55:4567/?token=… ← anyone with this link can run commands as you
|
|
528
|
+
Plain http: the link and your traffic can be read by anyone on this Wi-Fi.
|
|
529
|
+
<the link's QR code>
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
Scan the QR code with the phone's camera. The page trades the token in the
|
|
533
|
+
link for a cookie (kept 400 days) and drops it from the address, so a
|
|
534
|
+
bookmark or a home-screen icon keeps working across restarts. A home-screen
|
|
535
|
+
web app on iOS has cookies of its own: if it opens on "needs chi web's
|
|
536
|
+
access token", paste the token there (the part of the link after
|
|
537
|
+
`token=`), or open the link once in it.
|
|
538
|
+
|
|
539
|
+
- Every request from another machine needs the token (the cookie, or
|
|
540
|
+
`Authorization: Bearer <token>` for curl); this Mac (127.0.0.1) needs none.
|
|
541
|
+
Without it the page says how to get in and the API answers 401.
|
|
542
|
+
- The token lives in `$XDG_STATE_HOME/samagotchi/web-token` (0600).
|
|
543
|
+
`chi web --new-token` replaces it: a running chi web takes the new one at
|
|
544
|
+
once, and every phone has to scan the new QR code.
|
|
545
|
+
- A second `chi web` prints the LAN link and QR code again. A plain
|
|
546
|
+
`chi web --web-host lan` while a chi web without LAN access runs asks you
|
|
547
|
+
to stop that one first. `chi self` says whether chi web runs on the LAN.
|
|
548
|
+
- `lan` picks the first private address (10.x, 172.16–31.x, 192.168.x) on an
|
|
549
|
+
interface that is up, not a VPN tunnel, bridge, VM or container, and names
|
|
550
|
+
the others; `web.host: 10.0.0.3` picks one yourself. An address outside
|
|
551
|
+
those ranges (a Tailscale 100.x one, a public one) works, with a warning.
|
|
552
|
+
After the address changes (a new Wi-Fi), restart chi web. IPv6 isn't
|
|
553
|
+
offered.
|
|
554
|
+
- It is plain http: the token and everything you do travel unencrypted on
|
|
555
|
+
the Wi-Fi. Use it on your home network, never on a shared one (a café, an
|
|
556
|
+
office guest network), and run `chi web --new-token` if a link leaks.
|
|
557
|
+
- On http the browser has no notifications: the bell is hidden on the phone,
|
|
558
|
+
and the tab title still counts what needs you.
|
|
559
|
+
|
|
492
560
|
## Runtime Model Switch (Assist Mode)
|
|
493
561
|
|
|
494
562
|
In interactive assist mode, you can switch the request model without restarting:
|
|
@@ -576,38 +644,23 @@ Behavior details:
|
|
|
576
644
|
|
|
577
645
|
## Status Line
|
|
578
646
|
|
|
579
|
-
|
|
580
|
-
|
|
647
|
+
The REPL and attached mode show one status row under the prompt, drawn when what it says
|
|
648
|
+
changes:
|
|
581
649
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
- During spinner rendering, status details are rendered in the spinner block.
|
|
586
|
-
- When llama.cpp streaming payload includes usage fields, status prefers server-derived token telemetry (`p`, `c`, `t`) and context percent.
|
|
587
|
-
- If server usage fields are absent, status falls back to the `:context_status` estimate telemetry.
|
|
588
|
-
- When a memory is loaded between tool rounds, the spinner line includes a `loaded: <memory>` notification immediately after the spinner frame.
|
|
589
|
-
- After responses, memory details are shown via the same unified `status>` line.
|
|
590
|
-
- The legacy standalone `memories>` summary line is no longer emitted.
|
|
591
|
-
- With `--mute`, the sticky and idle rows add `muted: <names>` after `mem:` (the
|
|
592
|
-
spinner row doesn't). Attached, `mem:` shows the used memories and the
|
|
593
|
-
session's `--memory` list before the first turn records them.
|
|
594
|
-
|
|
595
|
-
Configuration:
|
|
596
|
-
|
|
597
|
-
- `SAMAGOTCHI_STATUS_LINE` (default `on`): set to `off`, `false`, or `0` to disable status-line rendering.
|
|
598
|
-
- `SAMAGOTCHI_STATUS_WIDTH_MODE` (default `terminal_cap`): one of `terminal_cap`, `fixed`.
|
|
599
|
-
- `SAMAGOTCHI_STATUS_MAX_WIDTH` (default `160`): maximum width used by `terminal_cap`.
|
|
600
|
-
- `SAMAGOTCHI_STATUS_FIXED_WIDTH` (default `120`): fixed width used by `fixed` mode.
|
|
601
|
-
|
|
602
|
-
Width mode behavior:
|
|
603
|
-
|
|
604
|
-
- `terminal_cap`: use `min(terminal_columns, SAMAGOTCHI_STATUS_MAX_WIDTH)`, single-line with `+N` overflow indicator.
|
|
605
|
-
- `fixed`: use `SAMAGOTCHI_STATUS_FIXED_WIDTH`, single-line with `+N` overflow indicator.
|
|
606
|
-
|
|
607
|
-
Notes:
|
|
650
|
+
```
|
|
651
|
+
status> model=Qwen3.6-35B | ↳ 3f2a1c9e | ctx=12.3% (under20) | mem: notes, cli_usage | muted: gh-helper
|
|
652
|
+
```
|
|
608
653
|
|
|
609
|
-
-
|
|
610
|
-
|
|
654
|
+
- `model=`: the model in use, `(default: …)` beside it when it isn't the config's default, and
|
|
655
|
+
`model=<served> (served; asked <name>)` when the server said it served another model.
|
|
656
|
+
- `↳ <id>`: the session that delegated this one.
|
|
657
|
+
- `ctx=`: the kernel's context estimate and its bucket, updated during a turn (on hosts that
|
|
658
|
+
report none, `api: openai`, at the turn's end).
|
|
659
|
+
- `mem:`: the memories the session read, with its `--memory` list; `muted:` its `--mute` list.
|
|
660
|
+
Up to 8 names each, then `+N`.
|
|
661
|
+
- The row is cut to the terminal's width. Without a live region (output or input not a terminal,
|
|
662
|
+
`TERM=dumb`) it prints as a line when it changes.
|
|
663
|
+
- `SAMAGOTCHI_STATUS_LINE` / `status.line` (default `on`): `off`, `false` or `0` hides it.
|
|
611
664
|
|
|
612
665
|
## Tool Tally
|
|
613
666
|
|
|
@@ -622,36 +675,45 @@ It lists the top 3 tools by count (ties go to the tool used first), the failed c
|
|
|
622
675
|
(a call a guardrail or an approval blocked counts as a call, not as failed) and the last
|
|
623
676
|
call with its parameters, cut to the terminal width. It starts over with each turn.
|
|
624
677
|
|
|
625
|
-
-
|
|
678
|
+
- The REPL and attached mode: the second row of the activity slot, shown while the slot is (the
|
|
626
679
|
model generating or a tool running). Joining a turn mid-way seeds it from the turn so far.
|
|
627
|
-
- The REPL (`--no-shared`): a row under the spinner row. The spinner stops while tools
|
|
628
|
-
run (the `tool>` lines show them), so the tally shows while the model generates
|
|
629
|
-
between tool rounds; the spinner block is one row taller from then on.
|
|
630
680
|
- The web: the activity panel's summary reads `activity · 12 tool calls (2 failed) · execute ×7 · …`
|
|
631
681
|
(without `last:`: the rows show it).
|
|
632
682
|
|
|
633
|
-
##
|
|
683
|
+
## Activity Row
|
|
684
|
+
|
|
685
|
+
While a turn runs, one row above the prompt says what it is doing, the spinner frame first
|
|
686
|
+
(the REPL and attached mode alike):
|
|
634
687
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
688
|
+
- `| thinking…` while the model starts, then `| thinking · <sentence>`: the newest complete
|
|
689
|
+
sentence of its thinking, or of its answer (`writing ·`), like the web's thinking ticker: the
|
|
690
|
+
same sentence rules (a list number such as `118.` is no sentence end; a newline is one), and the
|
|
691
|
+
row changes at most once every 1.5 s so it doesn't flicker. A long sentence is cut with `…`; a
|
|
692
|
+
Qwen `TURN:` prefix and inline markdown are left out.
|
|
693
|
+
- `| waiting for the first token… 5s` after 2 s with nothing streamed.
|
|
694
|
+
- `| running execute…` while a tool runs (its `tool>` line prints when it ends).
|
|
695
|
+
- `| retrying (1/4 in 0.5s): Errno::ECONNREFUSED` while a network error is retried.
|
|
696
|
+
- `| mcp: starting servers…` while a plugin's slow setup (an init task) runs, between turns too;
|
|
697
|
+
`mcp> ✓ …` prints when it is done.
|
|
641
698
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
699
|
+
The spinner turns with time, so a turn that gets no chunks still looks alive. Without a live
|
|
700
|
+
region (output or input not a terminal, `TERM=dumb`) there is no activity row; the turn's lines
|
|
701
|
+
still print as they end.
|
|
645
702
|
|
|
646
703
|
## Thinking-Phase Cancellation
|
|
647
704
|
|
|
648
|
-
|
|
705
|
+
While a turn runs, you can cancel it without exiting the process:
|
|
649
706
|
|
|
650
707
|
- Press `Ctrl-C` to cancel the active request.
|
|
651
708
|
|
|
652
709
|
Behavior notes:
|
|
653
710
|
|
|
654
711
|
- Cancellation returns control to the prompt immediately; what you typed there stays.
|
|
712
|
+
- The turn ends with one line, `✕ turn canceled (Ctrl-C) · 3.1s`, and for a prompt turn a dim
|
|
713
|
+
`partial progress kept; !rollback restores the pre-turn state` under it (a canceled continue is back where it
|
|
714
|
+
started). A failed turn ends with `✕ turn failed: <summary> · 2.0s` and a dim `prompt restored for retry`. The
|
|
715
|
+
REPL and attached mode say the same; the web says `✕ canceled (Ctrl-C)` (`stopped` for its Stop button,
|
|
716
|
+
`by a hook` for a hook's).
|
|
655
717
|
- Visible text the canceled request had streamed stays in the conversation, marked `[interrupted]`, so the next
|
|
656
718
|
message (or a continue) picks up from the half-finished reply; the canceled request's thinking and any unfinished
|
|
657
719
|
tool call are dropped.
|