samagotchi 0.12.0 → 0.14.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 +116 -1
- data/README.md +20 -7
- data/bin/chi +9 -9
- data/docs/architecture.md +4 -2
- data/docs/cli.md +34 -10
- data/docs/configuration.md +79 -15
- data/docs/desktop.md +10 -6
- data/docs/guardrails.md +74 -7
- data/docs/hooks.md +13 -9
- data/docs/memory.md +5 -3
- data/docs/plugins.md +31 -16
- data/docs/sessions.md +9 -6
- data/docs/sub-agent.md +128 -0
- data/lib/samagotchi/answer_command.rb +220 -0
- data/lib/samagotchi/bridge/card_store.rb +94 -6
- data/lib/samagotchi/bridge.rb +14 -2
- data/lib/samagotchi/bridge_client.rb +8 -3
- data/lib/samagotchi/bundle_command.rb +18 -10
- data/lib/samagotchi/bundles/check-in/manifest.yml +2 -2
- data/lib/samagotchi/bundles/check-in/plugin.rb +68 -5
- data/lib/samagotchi/bundles/guardrails/guardrails/rules.yml +19 -0
- data/lib/samagotchi/bundles/guardrails/manifest.yml +2 -2
- data/lib/samagotchi/bundles/mcp/manifest.yml +2 -2
- data/lib/samagotchi/bundles/mcp/plugin.rb +166 -34
- data/lib/samagotchi/bundles/system/config_modification_protocol.md +5 -5
- data/lib/samagotchi/bundles/system/manifest.yml +2 -2
- data/lib/samagotchi/cli/command.rb +3 -2
- data/lib/samagotchi/cli/exit.rb +23 -0
- data/lib/samagotchi/cli/parent_wait.rb +82 -0
- data/lib/samagotchi/config.rb +81 -24
- data/lib/samagotchi/context_window.rb +30 -5
- data/lib/samagotchi/desktop_command.rb +5 -3
- data/lib/samagotchi/engine.rb +54 -17
- data/lib/samagotchi/guardrails/parent_approvals.rb +158 -0
- data/lib/samagotchi/hooks/bundle_loader.rb +10 -3
- data/lib/samagotchi/host_registry.rb +31 -7
- data/lib/samagotchi/kernel_loop.rb +1 -1
- data/lib/samagotchi/llm/chat_loop.rb +5 -3
- data/lib/samagotchi/llm/openai_chat.rb +9 -1
- data/lib/samagotchi/llm/turn_settings.rb +7 -5
- data/lib/samagotchi/memory_bundle/installer.rb +12 -0
- data/lib/samagotchi/memory_bundle/status.rb +9 -1
- data/lib/samagotchi/memory_paths.rb +8 -0
- data/lib/samagotchi/model_profile.rb +30 -16
- data/lib/samagotchi/parent_report.rb +213 -0
- data/lib/samagotchi/plugin/api.rb +15 -2
- data/lib/samagotchi/prompt_literal_guard.rb +4 -2
- data/lib/samagotchi/question_desk.rb +29 -2
- data/lib/samagotchi/recap_setup.rb +15 -5
- data/lib/samagotchi/reply_wait.rb +5 -1
- data/lib/samagotchi/send_command.rb +50 -75
- data/lib/samagotchi/session.rb +15 -0
- data/lib/samagotchi/session_manager.rb +40 -7
- data/lib/samagotchi/sessions_command.rb +13 -3
- data/lib/samagotchi/system_prompt.rb +11 -3
- data/lib/samagotchi/terminal_ui/attach_launcher.rb +33 -5
- data/lib/samagotchi/terminal_ui/attached_loop.rb +53 -14
- data/lib/samagotchi/terminal_ui.rb +30 -3
- data/lib/samagotchi/thought_stream_splitter.rb +4 -4
- data/lib/samagotchi/tool_call_parser.rb +5 -6
- data/lib/samagotchi/tools/builtin_calls.rb +14 -3
- data/lib/samagotchi/tools/builtins.rb +14 -2
- data/lib/samagotchi/tools/delegate_wait.rb +32 -13
- data/lib/samagotchi/tools/execute.rb +8 -8
- data/lib/samagotchi/tools/memory.rb +3 -3
- data/lib/samagotchi/tools/task_create.rb +3 -2
- data/lib/samagotchi/tools/task_runtime.rb +7 -2
- data/lib/samagotchi/utf8_default.rb +29 -0
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +22 -10
- data/lib/samagotchi/web/message_parts.rb +2 -1
- data/lib/samagotchi/web/public/activity.js +6 -1
- data/lib/samagotchi/web/public/app.js +39 -6
- data/lib/samagotchi/web/public/index.html +8 -1
- data/lib/samagotchi/web/public/notify.js +16 -3
- data/lib/samagotchi/web/public/question_cards.js +3 -1
- data/lib/samagotchi/web/public/sessions_list.js +37 -0
- data/lib/samagotchi/web/public/turn_view.js +6 -9
- data/lib/samagotchi/web/server.rb +2 -1
- data/lib/samagotchi/web/session_summary.rb +3 -11
- metadata +8 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 760138c7792d414a15c39e074c5a6dc0ad44dfd0937c12707c3e6428a3544d43
|
|
4
|
+
data.tar.gz: d347cc3e3d7433292c40484beb73b95e2e3a9efb48ecd5ba5168b3c562c8d7e2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ae3585c68672ad0b163448b92c83e9f2d60dbc5efd60c47090170d80750ad20a08a5eae97aebf0dbc57629909db228de565a6a3a00ccb40bff9757ea66c3aeff
|
|
7
|
+
data.tar.gz: 4330ef708fe3ebc22f30e4cf249f88fb68a870eb1afd3be9894822e8e819ca25d393b34ffbabf56ef23ee784016b7cdcae9014d709f42db31fac88f501048ddb
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,119 @@ and commands may change between minor versions. How releases are made:
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.14.0] - 2026-10-02
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- The web marks a session that waits for you: its card gets a warn border, a pulsing dot and a `question`,
|
|
16
|
+
`approval` or `needs you` badge, and it moves to the top of the strip and the all-sessions view until answered
|
|
17
|
+
(the order holds while the pointer is over the list).
|
|
18
|
+
- `models.<key>.window_tokens` and `hosts.<name>.window_tokens` in config.yml set a model's or a host's context window
|
|
19
|
+
for when the server and its model list report none (the model's wins over the host's, and both over
|
|
20
|
+
`context.window_tokens`); the server's `n_ctx` still wins over all of them.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- chi starts under `LC_ALL=C` (or another US-ASCII locale): `chi -p` crashed with `Encoding::CompatibilityError` while
|
|
25
|
+
building the system prompt from a memory index with non-ASCII text. chi and its workers read their files as UTF-8
|
|
26
|
+
whatever the locale.
|
|
27
|
+
- The `mcp` bundle (0.4.0, `chi update`) attaches an image an MCP tool names inside its text
|
|
28
|
+
(`Saved screenshot to /tmp/shot.png.`), not only a text that is the bare path; the same checks apply (an image by
|
|
29
|
+
its bytes, under the temp dir or the server's `cwd`).
|
|
30
|
+
- An MCP server that sends `notifications/tools/list_changed` has its tools listed again (`mcp` 0.4.0): its saved list
|
|
31
|
+
and the model's tools are replaced from the next turn on. They were only logged.
|
|
32
|
+
- An MCP server that exits mid-session starts again on its next call (`mcp` 0.4.0), up to 3 times a session; its tools
|
|
33
|
+
failed until chi restarted.
|
|
34
|
+
- A burst of plugin notices no longer pushes cards and questions out of what a reloaded web page or a joining
|
|
35
|
+
`chi --attach` shows: the worker keeps the last 20 of each apart, and never drops a question still waiting for its
|
|
36
|
+
answer.
|
|
37
|
+
- `/checkin off`, `/checkin mode …` and `/checkin 30` last for the session across a worker's restart (an idle exit,
|
|
38
|
+
`chi send` waking it): the `check-in` bundle (0.2.0, `chi update`) saves them per session and reads them back.
|
|
39
|
+
- `printf '2\n' | chi --attach ID` on a session already waiting on a question answers it: the piped line could be read
|
|
40
|
+
before the question arrived and go in as a new prompt, and the attach then hung.
|
|
41
|
+
- A REPL reading its answers from a pipe shows each answer line once (`? 2`), not `? ? 2`, above why it was refused
|
|
42
|
+
or invalid.
|
|
43
|
+
- A plugin's cards and a turn's hook notices (loop-guard's "stopped the turn" card and its `loop: … denied` rows,
|
|
44
|
+
check-in's, any bundle's) stay after the worker goes: the worker saves them in the session's folder
|
|
45
|
+
(`cards.json`, the same last-20 caps), the web shows them in place for a stopped session, and a later worker starts
|
|
46
|
+
from them. They used to vanish with an idle exit, a restart or `chi sessions stop`.
|
|
47
|
+
- The web marks a tool call a guardrail denied (loop-guard, the `guardrails` bundle, a parent's or the user's Deny)
|
|
48
|
+
`blocked` in red, as the TUI does, live and after a reload; it showed a green `done`.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- A host is remote by its address, not by its API key: an `https` url or a public IP address. A llama.cpp on the LAN
|
|
53
|
+
started with `--api-key` (`api_key_env:`) is now local again: chi asks its `/props` for the context window and the
|
|
54
|
+
served model, keeps its model list for 60 s, and gives it no first-token limit. `hosts.<name>.remote: true|false`
|
|
55
|
+
decides it for a host chi gets wrong (an http host named by a public DNS name counts as local).
|
|
56
|
+
- Codex CLI counts as a parent agent: an answer typed into `chi --attach` or the REPL from a command Codex runs
|
|
57
|
+
(`CODEX_THREAD_ID` set) is held to `guardrails.parent_approvals`, as one from Claude Code is.
|
|
58
|
+
- `delegate` and `delegate_result` report a child's wait with the status words of `chi send --wait --format json`:
|
|
59
|
+
`answered` (was `done`), `question` (was `waiting_for_answer`), `failed`, `canceled` or `no_answer` (was `no_reply`),
|
|
60
|
+
and `running` when the parent's turn is canceled (was `canceled`).
|
|
61
|
+
|
|
62
|
+
Update with `chi update` (bundles: mcp 0.4.0, check-in 0.2.0).
|
|
63
|
+
|
|
64
|
+
## [0.13.0] - 2026-10-02
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- `chi send --wait --format json` prints one JSON object on stdout however the wait ends: the reply, a question with its
|
|
69
|
+
options and the `chi answer` command for it, or the status and a detail line, for scripts and parent agents.
|
|
70
|
+
- `chi answer ID --question QID --option N` (or `--text`, `--dismiss`) answers the question a session waits on and
|
|
71
|
+
waits for what comes next, as `chi send --wait` does, so an agent running chi as a sub-agent can answer chi's
|
|
72
|
+
questions itself. `chi send --wait -m` to a session waiting for an answer is refused with the `chi answer` command
|
|
73
|
+
for it.
|
|
74
|
+
- An approval answered with `chi answer` can be denied, not allowed: allowing is the user's (the web, `chi --attach`).
|
|
75
|
+
`guardrails.parent_approvals: once` in config.yml (no environment variable) lets "Allow
|
|
76
|
+
once" through, never a wider scope, and never on a call that changes chi's own config, hooks or guardrail rules; an approval whose offered scopes are missing lets only Deny through. The worker
|
|
77
|
+
checks it again with its own config (`chi answer` marks its answers); the web and `chi --attach` keep every scope.
|
|
78
|
+
- `chi sessions list` shows a session waiting for an answer as `waiting`; `--format json` has `waiting` (`question`,
|
|
79
|
+
`approval` or `hook`) and `waiting_id`, the question's id for `chi answer --question`.
|
|
80
|
+
- docs/sub-agent.md: running chi as another agent's sub-agent, with instructions to paste into its `CLAUDE.md` /
|
|
81
|
+
`AGENTS.md`.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- The `guardrails` bundle (0.3.0) asks before answering chi's questions around `chi answer`: `chi --attach` / `chi -p`
|
|
86
|
+
with stdin from a pipe, a here-string or a file, and `curl`/`wget` to a session's `/answer` route.
|
|
87
|
+
- An answer typed into `chi --attach` or the REPL counts as a parent agent's, held to `guardrails.parent_approvals`,
|
|
88
|
+
when stdin isn't a terminal or `CLAUDECODE`, `AI_AGENT` or `SAMAGOTCHI_PARENT_SESSION` is set: a piped `y` no
|
|
89
|
+
longer allows an approval at any scope. chi's `execute` and `task_create` export `SAMAGOTCHI_PARENT_SESSION` (the
|
|
90
|
+
session's id) into the commands they run, and the model's `task_create` env can't set it.
|
|
91
|
+
- `guardrails.enabled` and `guardrails.small_models` are config.yml only: `SAMAGOTCHI_GUARDRAILS_ENABLED=false` no
|
|
92
|
+
longer switches guardrails off, and a worker unsets every `SAMAGOTCHI_GUARDRAILS_*` it inherits, so a parent agent
|
|
93
|
+
starting or waking a session can't switch its guardrails off. `XDG_CONFIG_HOME` still picks the config dir.
|
|
94
|
+
- `chi send --wait` exits 4 (not 1) when `--timeout` passes with the turn still running.
|
|
95
|
+
- Attached `chi -p` from a script exits 3 (not 1) when it leaves a question or an approval waiting for an answer,
|
|
96
|
+
and prints the whole question on stderr with the `chi answer` command for it, as `chi send --wait` does.
|
|
97
|
+
- For an approval, the question block, `answer_with` and the refusal tell a parent agent to deny it and tell its
|
|
98
|
+
user (`--option Deny --text WHY`), not `--option N` or `chi --attach`; other questions keep their wording.
|
|
99
|
+
- `chi send --wait`'s exit 3 prints the whole question on stderr: its text, numbered options and how to answer it.
|
|
100
|
+
- `delegate` / `delegate_result` on a child waiting for an answer give the whole question: its text, numbered options
|
|
101
|
+
and the `chi answer` command for it.
|
|
102
|
+
- `chi send --image` with a missing file or one that isn't an image exits 1 (not 2, which is for usage errors), and
|
|
103
|
+
with `--wait --format json` prints the JSON error line.
|
|
104
|
+
|
|
105
|
+
### Fixed
|
|
106
|
+
|
|
107
|
+
- The web no longer notifies about, or draws, a question a chi REPL is asking: the web can't answer it there.
|
|
108
|
+
- `delegate_result` on a child whose worker died says `worker_gone` instead of waiting for, or reporting, a question
|
|
109
|
+
nobody can answer; `chi send --wait` and `chi answer` no longer report such a question as waiting either.
|
|
110
|
+
- Answers from Splash no longer start with two blank lines (a workaround until Splash drops them itself).
|
|
111
|
+
- An error in chi's work after a turn's answer no longer also reports the answered turn as failed.
|
|
112
|
+
- A Stop while a turn is still starting (chi asking the model server about the model) now ends the turn there: no before-turn hooks run and a due reminder stays due.
|
|
113
|
+
- `recap.model` set to a model id without a host no longer turns the recap off: it asks the host a bare `--model` goes to.
|
|
114
|
+
- AGENT.md is found at the top of the git work tree when chi runs in a subdirectory (one in the current directory still wins).
|
|
115
|
+
- `execute.timeout_sec` in config.yml (or `--execute-timeout-sec`) sets how long an `execute` command may run, like `SAMAGOTCHI_EXECUTE_TIMEOUT_SEC`; it no longer warns as an unknown key.
|
|
116
|
+
- A bundle's `requires_chi` now applies to its hooks too, not only its plugin: on a too-old chi they don't load, with a notice.
|
|
117
|
+
- `chi bundle install` and `chi bundle status` say when a bundle's hooks won't load because chi is older than its `requires_chi`, also for a bundle without a plugin.
|
|
118
|
+
- A model named with a disabled host's prefix (`box:model` where `hosts.box` has `enabled: false`) is refused with "host 'box' is disabled" instead of going to the default host as a model id.
|
|
119
|
+
- A Stop while a turn is still starting no longer uses up the warning about guardrails or plugins that failed to load: the next turn shows it.
|
|
120
|
+
- A plugin or MCP tool call reads the same in logs, rows and hooks' `content` whatever the model format or Ruby version: its arguments as JSON (Qwen calls showed Ruby's Hash#inspect, which changed in Ruby 3.4). A plugin tool returning a Hash or Array gives the model JSON too.
|
|
121
|
+
|
|
122
|
+
Update with `chi update` (bundles: guardrails 0.3.0).
|
|
123
|
+
|
|
11
124
|
## [0.12.0] - 2026-10-02
|
|
12
125
|
|
|
13
126
|
### Added
|
|
@@ -669,7 +782,9 @@ and long-lived sessions.
|
|
|
669
782
|
- A macOS desktop helper (`chi desktop install`): a "Send to chi" Service and a
|
|
670
783
|
hotkey panel that send selected text or the clipboard to your sessions.
|
|
671
784
|
|
|
672
|
-
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.
|
|
785
|
+
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.14.0...HEAD
|
|
786
|
+
[0.14.0]: https://github.com/dm1try/samagotchi/compare/v0.13.0...v0.14.0
|
|
787
|
+
[0.13.0]: https://github.com/dm1try/samagotchi/compare/v0.12.0...v0.13.0
|
|
673
788
|
[0.12.0]: https://github.com/dm1try/samagotchi/compare/v0.11.0...v0.12.0
|
|
674
789
|
[0.11.0]: https://github.com/dm1try/samagotchi/compare/v0.10.1...v0.11.0
|
|
675
790
|
[0.10.1]: https://github.com/dm1try/samagotchi/compare/v0.10.0...v0.10.1
|
data/README.md
CHANGED
|
@@ -14,9 +14,16 @@ command.
|
|
|
14
14
|
## Requirements
|
|
15
15
|
|
|
16
16
|
- Ruby 3.3+
|
|
17
|
-
- A model server:
|
|
18
|
-
|
|
19
|
-
(
|
|
17
|
+
- A model server: any OpenAI-compatible chat completions server, or
|
|
18
|
+
[llama.cpp](https://github.com/ggml-org/llama.cpp)'s `llama-server` through
|
|
19
|
+
its own API (the native path, and the default)
|
|
20
|
+
|
|
21
|
+
Tested: llama.cpp native (Qwen, Gemma 4), [Splash](https://github.com/incoai/splash)
|
|
22
|
+
over the OpenAI API, and [OpenRouter](https://openrouter.ai) (remote, OpenAI API
|
|
23
|
+
with `api_key_env`). vLLM, LM Studio, Ollama, mlx-lm, oMLX and other
|
|
24
|
+
OpenAI-compatible servers should work over the OpenAI API but are not tested;
|
|
25
|
+
mlx-lm and oMLX also have native transports, see
|
|
26
|
+
[Configuration](docs/configuration.md#model-server-transport).
|
|
20
27
|
|
|
21
28
|
## Install
|
|
22
29
|
|
|
@@ -59,7 +66,7 @@ Point chi at your model server; it works out the rest and writes
|
|
|
59
66
|
|
|
60
67
|
```sh
|
|
61
68
|
chi bootstrap 192.168.1.29:8081 # llama.cpp on another machine
|
|
62
|
-
chi bootstrap localhost:11434 #
|
|
69
|
+
chi bootstrap localhost:11434 # any OpenAI-compatible server
|
|
63
70
|
chi bootstrap https://openrouter.ai/api/v1 --key-env OPENROUTER_API_KEY
|
|
64
71
|
chi bootstrap # look on this machine's usual ports
|
|
65
72
|
```
|
|
@@ -86,9 +93,8 @@ server:
|
|
|
86
93
|
port: 8080
|
|
87
94
|
```
|
|
88
95
|
|
|
89
|
-
`server:` is a llama.cpp `llama-server`. For
|
|
90
|
-
|
|
91
|
-
`api: openai` instead:
|
|
96
|
+
`server:` is a llama.cpp `llama-server`. For an OpenAI-compatible server,
|
|
97
|
+
name it under `hosts:` with `api: openai` instead:
|
|
92
98
|
|
|
93
99
|
```yaml
|
|
94
100
|
default:
|
|
@@ -145,6 +151,12 @@ stdin plus `-m` puts the stdin above the message as a `>` quote. `chi send --new
|
|
|
145
151
|
starts a session with the message instead (it shows in the web at once), and
|
|
146
152
|
`--wait` blocks and prints the answer.
|
|
147
153
|
|
|
154
|
+
Another agent (Claude Code, Codex) can run chi as a sub-agent the same way:
|
|
155
|
+
`chi send --new --wait --format json` returns chi's reply, or the question chi
|
|
156
|
+
stopped on, which the agent answers with `chi answer`. See
|
|
157
|
+
[chi as a sub-agent](docs/sub-agent.md) for a snippet to paste into its
|
|
158
|
+
`CLAUDE.md` / `AGENTS.md`.
|
|
159
|
+
|
|
148
160
|
### Send to chi (macOS)
|
|
149
161
|
|
|
150
162
|
`chi desktop install` builds a small native helper: select text in any app →
|
|
@@ -173,6 +185,7 @@ once, for the session, for the repo, or for the whole rule in the repo.
|
|
|
173
185
|
- [Configuration](docs/configuration.md): `config.yml`, hosts, model server transports, timeouts, retries, logs
|
|
174
186
|
- [Memory](docs/memory.md): scopes and model-specific overlays
|
|
175
187
|
- [Sessions](docs/sessions.md): storage, retention, `chi sessions`
|
|
188
|
+
- [chi as a sub-agent](docs/sub-agent.md): `chi send --wait --format json`, `chi answer`, instructions for a parent agent
|
|
176
189
|
- [Desktop helper](docs/desktop.md): `chi desktop`, the macOS "Send to chi" Service and hotkey
|
|
177
190
|
- [Guardrails](docs/guardrails.md): allow / ask / deny for tool calls, rules, approvals
|
|
178
191
|
- [Hooks](docs/hooks.md): plugin hooks and bundle hooks
|
data/bin/chi
CHANGED
|
@@ -3,13 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
5
5
|
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
ENV["LANG"] = "en_US.UTF-8"
|
|
11
|
-
Encoding.default_external = Encoding::UTF_8
|
|
12
|
-
end
|
|
6
|
+
# LC_ALL=C or no locale at all: files would read as US-ASCII, and chi's
|
|
7
|
+
# memories and sessions are UTF-8 (Utf8Default).
|
|
8
|
+
require "samagotchi/utf8_default"
|
|
9
|
+
Samagotchi::Utf8Default.apply!
|
|
13
10
|
|
|
14
11
|
require "optparse"
|
|
15
12
|
require "samagotchi/config"
|
|
@@ -45,6 +42,8 @@ SUBCOMMANDS = {
|
|
|
45
42
|
"note" => ["samagotchi/note_command", "NoteCommand"],
|
|
46
43
|
# a message into sessions as the user's (-m)
|
|
47
44
|
"send" => ["samagotchi/send_command", "SendCommand"],
|
|
45
|
+
# answer the question a session waits on, then wait (--question, --option)
|
|
46
|
+
"answer" => ["samagotchi/answer_command", "AnswerCommand"],
|
|
48
47
|
# find a model server and write config.yml (--model, --name)
|
|
49
48
|
"bootstrap" => ["samagotchi/bootstrap_command", "BootstrapCommand"],
|
|
50
49
|
# bring an installed chi up to date
|
|
@@ -94,6 +93,7 @@ parser = OptionParser.new do |opts|
|
|
|
94
93
|
chi sessions <list|stop|archive|unarchive|delete|prune|clean>
|
|
95
94
|
chi note [--source NAME] [-m TEXT] ID...|--all background context for sessions
|
|
96
95
|
chi send [-m TEXT] ID...|--new a message into sessions, as if typed there
|
|
96
|
+
chi answer ID --question QID --option N answer a question a session waits on
|
|
97
97
|
chi bundle <install|upgrade|uninstall|status|diff|list|build>
|
|
98
98
|
chi desktop <install|upgrade|uninstall|status> macOS "Send to chi" helper
|
|
99
99
|
chi models [--format json] [TEXT] the models --model takes, from every host
|
|
@@ -106,7 +106,7 @@ parser = OptionParser.new do |opts|
|
|
|
106
106
|
opts.on("--resume SESSION_ID", "Resume a previous session by its ID (or a unique prefix of it)") { |s| options[:resume] = s }
|
|
107
107
|
opts.on("--attach SESSION_ID", "Attach to a session's worker, waking one if it has exited; ID or a unique prefix") { |s| options[:attach] = s }
|
|
108
108
|
opts.on("--[no-]shared", "Run the session in a background worker and attach to it, so `chi web` can share it (the default, config session.shared; with --resume: that session); --no-shared runs a plain in-process REPL") { |v| options[:shared] = v }
|
|
109
|
-
opts.on("--model NAME", "Model
|
|
109
|
+
opts.on("--model NAME", "Model for this run, not saved (overrides --resume's; config default.model) [env SAMAGOTCHI_DEFAULT_MODEL]") { |m| options[:model] = m; cli_overrides["default.model"] = m }
|
|
110
110
|
opts.on("--profile NAME", Samagotchi::ModelProfile::NAMES,
|
|
111
111
|
"Prompt profile for every model in this run (#{Samagotchi::ModelProfile::NAMES.join('|')}) [alias for --model-profile]") { |p| cli_overrides["model.profile"] = p }
|
|
112
112
|
opts.on("--thinking LEVEL", Samagotchi::Thinking::LEVELS.map(&:to_s), "How much the model thinks this run: off|low|medium|high|default (outranks config.yml; " \
|
|
@@ -311,7 +311,7 @@ if launch == :attached
|
|
|
311
311
|
warn "Error: #{e.message}"
|
|
312
312
|
exit 1
|
|
313
313
|
end
|
|
314
|
-
exit(ended
|
|
314
|
+
exit Samagotchi::TerminalUI::AttachLauncher.exit_status(ended)
|
|
315
315
|
end
|
|
316
316
|
|
|
317
317
|
begin
|
data/docs/architecture.md
CHANGED
|
@@ -156,7 +156,7 @@ agent logic and can be used without any terminal rendering; the UI is a thin lay
|
|
|
156
156
|
#### Using the core
|
|
157
157
|
|
|
158
158
|
```ruby
|
|
159
|
-
engine = Samagotchi::Engine.new(
|
|
159
|
+
engine = Samagotchi::Engine.new(model_name: "gemma4", memories: [])
|
|
160
160
|
session = Samagotchi::Session.new_session(mode: "assist", model_name: "gemma4", working_directory: Dir.pwd)
|
|
161
161
|
|
|
162
162
|
engine.run_turn(session, "hello", on_event: nil) # => LLM::ModelResult (`.output`)
|
|
@@ -223,7 +223,9 @@ process that already owns the `Engine`); every worker starts it, and it exposes:
|
|
|
223
223
|
refused connection is `503 not_live`.
|
|
224
224
|
- `POST /session/:id/cancel` — cancel the running turn; `202`, or `409` when none runs.
|
|
225
225
|
- `POST /session/:id/answer` — answer the pending question; `200`, `409` when another client
|
|
226
|
-
answered first or it is gone, `400` for an invalid selection.
|
|
226
|
+
answered first or it is gone, `400` for an invalid selection. With `client_id: "cli:answer"`
|
|
227
|
+
(`chi answer`, a parent agent) an allow on an approval beyond the worker's
|
|
228
|
+
`guardrails.parent_approvals` is `403 parent_approval_refused`, the question still open.
|
|
227
229
|
- `POST /session/:id/question/dismiss` — leave the question unanswered (an approval: denied);
|
|
228
230
|
`200`, or `409` when it is no longer pending.
|
|
229
231
|
- `POST /session/:id/command` — a session command (`/model`, `/models`, `!rollback`, `!cmd`,
|
data/docs/cli.md
CHANGED
|
@@ -17,19 +17,20 @@
|
|
|
17
17
|
- `chi web --web-view turn` — draw turns with the turn view (each turn as one block of steps, the running one at the bottom of the history) instead of the default stage view (the running turn pinned above the composer); `?view=stage|turn` on the page URL overrides it (see [Web views](#web-views))
|
|
18
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)). A usage error (an unknown subcommand or flag, a flag missing its value, `stop` or `delete` with no ids, a bad `list --format` or `--scope`) exits 2; an unknown or refused session exits 1
|
|
19
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))
|
|
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))
|
|
21
|
-
- `chi
|
|
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; `--format json` prints one JSON object instead; exit 3 a question waits, its options on stderr; exit 4 `--timeout` passed with the turn still running; see [Starting a session](sessions.md#starting-a-session))
|
|
21
|
+
- `chi answer ID --question QID (--option N|LABEL)... [--text T] [--timeout S] [--format json]` (or `--dismiss`) — answer the question a session waits on (the one `chi send --wait` exited 3 with), then wait and print what comes next as `chi send --wait` does: the reply (0), the next question (3), still running after `--timeout` (4). `--option` is 1-based or the label, repeated on a multi-select question; `--text` is free text, or a Deny's reason; `--dismiss` leaves it unanswered and the model finishes its reply. A question no longer open (the web answered first) isn't answered again: it waits for that turn's reply. An option the question doesn't offer exits 2; a worker that is gone exits 1 (`send the task again: chi send --wait -m "…" ID`). An approval can be denied, not allowed, unless `guardrails.parent_approvals: once` (a convention, not a security boundary; see [Guardrails](guardrails.md#approvals-from-a-parent-agent))
|
|
22
|
+
- `chi desktop install|upgrade|uninstall|status` — the macOS "Send to chi" helper: a Service and a ⌃⌥⌘N hotkey that send text or images to a session (live, stopped or new) as a message (⏎, a turn runs) or a context note (⌘⏎) (see [Desktop helper](desktop.md))
|
|
22
23
|
- `chi models [--format text|json] [--timeout S] [TEXT]` — list the models every configured host offers, as the names `--model` takes (see [Listing the models](#listing-the-models))
|
|
23
24
|
- `chi self` — print version, source dir (checkout or installed gem), config/memory/session paths, model/host and bundles; `chi self --model` prints only the model a new session starts on, an alias resolved to its target (the desktop helper's hint)
|
|
24
25
|
- `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))
|
|
25
|
-
- `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; `core` and `dev` are profiles that install a set of them (see [Bundle profiles](memory.md#bundle-profiles-core-and-dev), [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)). A usage error (an unknown subcommand or flag, a missing argument, a bad `build --scope`) exits 2, as for
|
|
26
|
+
- `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; `core` and `dev` are profiles that install a set of them (see [Bundle profiles](memory.md#bundle-profiles-core-and-dev), [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)). A usage error (an unknown subcommand or flag, a missing argument, a bad `build --scope`) exits 2, as for the other subcommands. Plain `chi` and `chi web` exit 1 on an unknown flag, a flag missing its value or a stray argument
|
|
26
27
|
|
|
27
28
|
### First setup
|
|
28
29
|
|
|
29
30
|
`chi bootstrap TARGET` names the model server and writes the config for it:
|
|
30
31
|
|
|
31
32
|
```sh
|
|
32
|
-
chi bootstrap 192.168.1.29:8081 # host:port (port 8080 when none)
|
|
33
|
+
chi bootstrap 192.168.1.29:8081 # host:port (an IP or localhost: port 8080 when none; a domain: https 443, then http 80)
|
|
33
34
|
chi bootstrap https://openrouter.ai/api/v1 --key-env OPENROUTER_API_KEY
|
|
34
35
|
chi bootstrap # try localhost 8080, 11434, 1234, 8000
|
|
35
36
|
```
|
|
@@ -179,7 +180,8 @@ controls exit behavior (`--non-interactive`); `--resume` composes with both.
|
|
|
179
180
|
|
|
180
181
|
Every setting in the config registry (`lib/samagotchi/config.rb`) that exposes a CLI
|
|
181
182
|
flag also works as `--kebab-case VALUE`, e.g. `--server-host`, `--server-port`,
|
|
182
|
-
`--read-truncate-at-bytes
|
|
183
|
+
`--read-truncate-at-bytes`; an on/off setting is `--[no-]kebab-case` with no value
|
|
184
|
+
(`--context-status`, `--no-context-status`). `chi --help` lists them all.
|
|
183
185
|
|
|
184
186
|
**Which loop runs.** There is no backend flag: the model's host decides. A host with
|
|
185
187
|
`api: openai` in config.yml is driven through the OpenAI chat API (streamed; a remote
|
|
@@ -204,11 +206,22 @@ as an unknown key).
|
|
|
204
206
|
|
|
205
207
|
Notes:
|
|
206
208
|
|
|
209
|
+
- Attached `chi -p …` with stdin not a terminal (a script, an agent's shell)
|
|
210
|
+
leaves when its input ends and the turn is done. Exit status: 0 the turn
|
|
211
|
+
ended, 3 a question or an approval waits for an answer (stderr gets the
|
|
212
|
+
whole question as `chi send --wait` prints it, with the
|
|
213
|
+
`chi answer ID --question QID --option N` command; the worker keeps it
|
|
214
|
+
open, and `chi answer` or the web answers it), 1 the turn failed or the
|
|
215
|
+
worker went away. For a
|
|
216
|
+
script, `chi send --new --wait` is the better entry point: stdout holds the
|
|
217
|
+
answer alone (see [Starting a session](sessions.md#starting-a-session)).
|
|
207
218
|
- `-p` always feeds **and** runs the prompt; there is no feed-and-edit variant. To
|
|
208
219
|
prefill (edit, not execute) the first REPL line, use the
|
|
209
220
|
`SAMAGOTCHI_DEFAULT_INPUT` environment variable instead.
|
|
210
|
-
- Prompt history is
|
|
211
|
-
|
|
221
|
+
- Prompt history (↑) is one file shared by every session (see [Persistent Prompt
|
|
222
|
+
History](#persistent-prompt-history)); `--resume` preserves the session's prior
|
|
223
|
+
messages as turn context (a `-p` run on a resumed session never clobbers its
|
|
224
|
+
conversation).
|
|
212
225
|
- Non-interactive runs (`-p` with `--non-interactive`, or bare `--non-interactive`)
|
|
213
226
|
print only the final result output — no spinner, status line, or REPL.
|
|
214
227
|
|
|
@@ -357,6 +370,16 @@ file and index line stay as they are; only this session doesn't see it.
|
|
|
357
370
|
- The `read` tool on `memories/<name>.md` is not refused (a guardrails rule
|
|
358
371
|
can protect the path if wanted).
|
|
359
372
|
|
|
373
|
+
### Session commands
|
|
374
|
+
|
|
375
|
+
`/help` lists the commands this session takes, the installed bundles' too, each
|
|
376
|
+
with a line on what it does. `/stats` shows the session's numbers: turns, tool
|
|
377
|
+
calls (by tool, with errors), iterations, tokens in/out summed over every
|
|
378
|
+
request, generation latency, cancellations, retries, context used and window,
|
|
379
|
+
the prompt profile and the model the server says it ran. `/recap` is in
|
|
380
|
+
[Session recap](#session-recap), `/model` and `/models` in [Runtime Model
|
|
381
|
+
Switch](#runtime-model-switch-assist-mode).
|
|
382
|
+
|
|
360
383
|
### Typing during a turn
|
|
361
384
|
|
|
362
385
|
The prompt stays open while a turn runs, in an attached terminal and in the plain
|
|
@@ -368,7 +391,8 @@ REPL alike:
|
|
|
368
391
|
A line that comes after the turn's last step runs as the next turn, and so
|
|
369
392
|
does one sent after Ctrl-C: it doesn't merge into the turn being cancelled.
|
|
370
393
|
Reminder turns take merged lines too.
|
|
371
|
-
- `/stats` and `/recap` answer at once
|
|
394
|
+
- `/stats` and `/recap` answer at once, and in an attached terminal so do `/help`
|
|
395
|
+
and a plugin's anytime command (`/btw`). Other commands (`!cmd`, `/model`, `/models`,
|
|
372
396
|
`!rollback`, `/continue`, `/guardrails`) say `busy: wait for the turn to end`
|
|
373
397
|
and go back into the prompt, so Enter runs them once the turn ends.
|
|
374
398
|
- A question (`ask_user_question`, a guardrails approval) turns the prompt into
|
|
@@ -601,7 +625,7 @@ In interactive assist mode, you can switch the request model without restarting:
|
|
|
601
625
|
|
|
602
626
|
- `/model <name>`: set a session-scoped model override.
|
|
603
627
|
- `/model host:model` or `/model host:alias`: qualified host routing (only `:` names a host; `openai/gpt-4o` is a model id). `host:alias` applies the alias; an alias whose target names another host is refused (`alias 'tiny' names host 'box', not 'openrouter'`). Aliases apply once: an alias pointing to another alias sends that name as written.
|
|
604
|
-
- `/model --default <name>`: set session model and persist as new default in `config.yml`
|
|
628
|
+
- `/model --default <name>`: set session model and persist as new default (`default.model`) in `config.yml` for future sessions (supports `host:model` full ref). It writes only the file: an exported `SAMAGOTCHI_DEFAULT_MODEL` (or `--model`) still wins over it.
|
|
605
629
|
- `/model <name> --alias <alias>`: create alias for current effective model (alias value may be bare or `host:model`).
|
|
606
630
|
- `/model`: show the effective model (and default when diverged: `runtime model: <effective> (default: <default>, profile=<name>, <source>)`, e.g. `profile=qwen36, server (chat_template)`).
|
|
607
631
|
- `/model clear` (or `default`/`none`/`off`): clear the session override, reverting to the configured default.
|
|
@@ -724,7 +748,7 @@ A long, tool-heavy turn says what it has been doing. From the turn's 3rd tool ca
|
|
|
724
748
|
a dim row under the activity row tallies its calls, with no model call:
|
|
725
749
|
|
|
726
750
|
```
|
|
727
|
-
12 tool calls (2 failed) · execute ×7 ·
|
|
751
|
+
12 tool calls (2 failed) · execute ×7 · read ×3 · edit ×2 · last: execute command=bundle exec rspec
|
|
728
752
|
```
|
|
729
753
|
|
|
730
754
|
It lists the top 3 tools by count (ties go to the tool used first), the failed calls
|
data/docs/configuration.md
CHANGED
|
@@ -49,8 +49,9 @@ hosts:
|
|
|
49
49
|
# url:, else http://host:port/v1) with its api_key_env; base_url is an OpenAI API
|
|
50
50
|
# base as given (e.g. http://h:8081/v1). model is a model ref like any other: an
|
|
51
51
|
# alias is applied, and its host:/the alias's host picks the host when host_ref
|
|
52
|
-
# is left out
|
|
53
|
-
#
|
|
52
|
+
# is left out; a model naming no host goes where a bare --model goes (the
|
|
53
|
+
# default host). A model naming another host than host_ref turns recap off with
|
|
54
|
+
# a warning. recap: false turns it off.
|
|
54
55
|
recap:
|
|
55
56
|
# host_ref: small-box
|
|
56
57
|
# model: your-small-model-id
|
|
@@ -114,8 +115,9 @@ any per-run `--memory` values (config baseline first, deduped). A per-run
|
|
|
114
115
|
|
|
115
116
|
### Environment variables
|
|
116
117
|
|
|
117
|
-
Every setting has an environment variable
|
|
118
|
-
name in upper case, with `_`
|
|
118
|
+
Every setting has an environment variable (except the ones the table marks
|
|
119
|
+
config.yml only): `SAMAGOTCHI_` plus its dotted name in upper case, with `_`
|
|
120
|
+
for each dot. `default.model` is
|
|
119
121
|
`SAMAGOTCHI_DEFAULT_MODEL`, `server.read_timeout` is
|
|
120
122
|
`SAMAGOTCHI_SERVER_READ_TIMEOUT`. Use them to override the file for one run or
|
|
121
123
|
one shell (`SAMAGOTCHI_LOG_LEVEL=debug chi`); keep lasting choices in the file.
|
|
@@ -230,6 +232,37 @@ hosts:
|
|
|
230
232
|
api_key_env: BOX_LLAMA_KEY
|
|
231
233
|
```
|
|
232
234
|
|
|
235
|
+
**Remote or local.** chi treats a host as a remote provider by its address, not
|
|
236
|
+
by its key: an `https` url, or an `http` IP address outside the loopback,
|
|
237
|
+
private (`10.*`, `172.16–31.*`, `192.168.*`, IPv6 `fc00::/7`), link-local and
|
|
238
|
+
CGNAT/Tailscale (`100.64.0.0/10`) nets. An `http` host given by a name
|
|
239
|
+
(`localhost`, `box`, `mac.local`) is local: chi doesn't look names up. A remote
|
|
240
|
+
host keeps its model list for 10 minutes, gets a 120-second first-token limit,
|
|
241
|
+
and isn't asked for llama.cpp's `/props` (its context window and served model
|
|
242
|
+
come from its model list and each turn). `remote: true` or `remote: false` on a
|
|
243
|
+
host decides it instead, e.g. for a llama.cpp behind an https proxy on the LAN:
|
|
244
|
+
|
|
245
|
+
```yaml
|
|
246
|
+
hosts:
|
|
247
|
+
lab:
|
|
248
|
+
url: https://llm.lab.example/v1
|
|
249
|
+
api: openai
|
|
250
|
+
api_key_env: LAB_KEY
|
|
251
|
+
remote: false
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
A host without `port:` (and without `url:`) uses port 8080. `enabled: false`
|
|
255
|
+
turns an entry off without deleting it: chi skips it as if it weren't there
|
|
256
|
+
(not in `chi models`, never the default host; `box:model` then counts as an
|
|
257
|
+
unknown host prefix, see [Llama Model Routing](#llama-model-routing)):
|
|
258
|
+
|
|
259
|
+
```yaml
|
|
260
|
+
hosts:
|
|
261
|
+
box:
|
|
262
|
+
host: 192.0.2.20
|
|
263
|
+
enabled: false
|
|
264
|
+
```
|
|
265
|
+
|
|
233
266
|
For models on that host, chi uses the chat loop (its own OpenAI chat adapter): it
|
|
234
267
|
takes the OpenAI base (`url:`, else `http://HOST:PORT/v1`) and streams messages plus
|
|
235
268
|
function schemas from `/v1/chat/completions`; the model's reasoning (`reasoning_content`)
|
|
@@ -467,7 +500,7 @@ hosts:
|
|
|
467
500
|
```
|
|
468
501
|
|
|
469
502
|
`hosts.<name>.first_token_timeout` wins over `server.first_token_timeout` (`SAMAGOTCHI_SERVER_FIRST_TOKEN_TIMEOUT`),
|
|
470
|
-
which applies to every host. With neither set, remote hosts (
|
|
503
|
+
which applies to every host. With neither set, remote hosts (see "Remote or local" above) get 120 seconds and local
|
|
471
504
|
servers no limit: a long prompt evaluation is normal there, and the read timeout catches a dead server.
|
|
472
505
|
|
|
473
506
|
Every chat request carries the session's id as a `Session-Id` header (next to `User-Agent: chi/<version>`). A
|
|
@@ -493,11 +526,33 @@ to the default host. Only exact ids count, never a substring: `/model gemma` on
|
|
|
493
526
|
a box that lists `gemma-3-12b` needs `box:gemma` or the exact id. The lists are
|
|
494
527
|
known only after `/models` ran (nothing is fetched before the first turn), so
|
|
495
528
|
until then an unqualified name goes to the default host; use `host:model` to pin
|
|
496
|
-
one. A **remote** host (
|
|
497
|
-
list for 10 minutes (60s for local hosts).
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
529
|
+
one. A **remote** host (an `https` url or a public address; see "Remote or local") keeps its model
|
|
530
|
+
list for 10 minutes (60s for local hosts).
|
|
531
|
+
|
|
532
|
+
**The context window** (what the context status and `ctx=` count against) comes from,
|
|
533
|
+
first to last:
|
|
534
|
+
|
|
535
|
+
1. the running server (llama.cpp's `/props` `n_ctx`; a remote host isn't asked),
|
|
536
|
+
2. the window the host's model list gives (`context_length`, `context_window`,
|
|
537
|
+
`max_model_len` or llama.cpp's `meta.n_ctx`),
|
|
538
|
+
3. `models.<key>.window_tokens` (the key as `sampling:` looks a model up), else
|
|
539
|
+
`hosts.<name>.window_tokens`,
|
|
540
|
+
4. `context.window_tokens`, else 256000.
|
|
541
|
+
|
|
542
|
+
The settings only fill in when the server and its list report nothing: what the
|
|
543
|
+
server runs with is the window that counts. Set one for a provider whose list has
|
|
544
|
+
no window:
|
|
545
|
+
|
|
546
|
+
```yaml
|
|
547
|
+
hosts:
|
|
548
|
+
work:
|
|
549
|
+
url: https://llm.work.example/v1
|
|
550
|
+
api: openai
|
|
551
|
+
window_tokens: 131072
|
|
552
|
+
models:
|
|
553
|
+
qwen3-8b:
|
|
554
|
+
window_tokens: 32768
|
|
555
|
+
```
|
|
501
556
|
|
|
502
557
|
Only `:` names a host: `/` is part of a model id (`openai/gpt-4o` is an
|
|
503
558
|
OpenRouter id and goes to the default host as written, even with a host named
|
|
@@ -741,6 +796,10 @@ The helper reads these from its launch file: after editing them run
|
|
|
741
796
|
|
|
742
797
|
If an AGENT.md file is present in the project root, samagotchi injects its
|
|
743
798
|
contents into the system prompt under a "Project specific description:" section.
|
|
799
|
+
The project root is the top of the git work tree chi runs in (a linked
|
|
800
|
+
worktree's own checkout), or the current directory outside a repository. An
|
|
801
|
+
AGENT.md in the current directory is read instead when there is one; only one
|
|
802
|
+
file is read.
|
|
744
803
|
|
|
745
804
|
To skip loading AGENT.md, set `skip_agent_md: true` at the top level of
|
|
746
805
|
`config.yml` (env `SAMAGOTCHI_SKIP_AGENT_MD=true`).
|
|
@@ -749,7 +808,8 @@ To skip loading AGENT.md, set `skip_agent_md: true` at the top level of
|
|
|
749
808
|
|
|
750
809
|
Every setting below takes the three forms described in
|
|
751
810
|
[Environment variables](#environment-variables): a nested key in
|
|
752
|
-
`config.yml`, `SAMAGOTCHI_<DOTTED_NAME>` in the environment
|
|
811
|
+
`config.yml`, `SAMAGOTCHI_<DOTTED_NAME>` in the environment (not for one
|
|
812
|
+
marked config.yml only) and, where the CLI
|
|
753
813
|
column says so, a `--kebab-name` flag. The maps (`hosts:`, `models:`,
|
|
754
814
|
`model_aliases:`, `hooks:`, `guardrails:` rules, `bundles:`, `memories:`) are
|
|
755
815
|
described in their own sections.
|
|
@@ -767,7 +827,7 @@ described in their own sections.
|
|
|
767
827
|
| `server.read_timeout` | `600` | yes | Read timeout, seconds. |
|
|
768
828
|
| `server.first_token_timeout` | 120 remote, off local | | Seconds to the first token; `0` = off. `hosts.<name>.first_token_timeout` wins. |
|
|
769
829
|
| `recap.enabled` | on | | `false` (or `recap: false`) turns the idle recap off. |
|
|
770
|
-
| `recap.model` | session's | yes | Model that writes the recap: an id, alias or `host:model` (the host then picks where to ask). |
|
|
830
|
+
| `recap.model` | session's | yes | Model that writes the recap: an id, alias or `host:model` (the host then picks where to ask; a bare id goes where a bare `--model` goes). |
|
|
771
831
|
| `recap.host_ref` | session's | yes | A `hosts:` name to ask (`host:` is accepted too, also a host name, not a model ref). |
|
|
772
832
|
| `recap.base_url` | none | yes | An OpenAI API base to ask instead (`http://h:8081/v1`). |
|
|
773
833
|
| `recap.inactivity` | `180` | yes | Idle seconds before a recap. |
|
|
@@ -785,20 +845,23 @@ described in their own sections.
|
|
|
785
845
|
| `image.max_side` | `1568` | | See "Images". |
|
|
786
846
|
| `image.max_bytes` | `3750000` | | See "Images". |
|
|
787
847
|
| `image.max_per_request` | `20` | | See "Images". |
|
|
788
|
-
| `guardrails.enabled` | `true` | | See [Guardrails](guardrails.md). |
|
|
789
|
-
| `guardrails.small_models` | `auto` | | Which models get the `models: small` rules: `auto` (32B or less by the size in the name, an MoE's active size), a list of globs, or `[]`. See [Guardrails](guardrails.md#rules-for-some-models). |
|
|
848
|
+
| `guardrails.enabled` | `true` | | `false`: no rules, and hooks' asks are dropped (a deny still applies). config.yml only: a worker unsets any `SAMAGOTCHI_GUARDRAILS_*` it inherits. See [Guardrails](guardrails.md). |
|
|
849
|
+
| `guardrails.small_models` | `auto` | | Which models get the `models: small` rules: `auto` (32B or less by the size in the name, an MoE's active size), a list of globs, or `[]`. config.yml only. See [Guardrails](guardrails.md#rules-for-some-models). |
|
|
850
|
+
| `guardrails.parent_approvals` | `off` | | What `chi answer` lets a parent agent allow on an approval: `off` (deny only) or `once` ("Allow once", never a wider scope). config.yml only: no environment variable (a parent can still pick the config dir with `XDG_CONFIG_HOME`). A convention for an honest parent, not a security boundary. See [Guardrails](guardrails.md#approvals-from-a-parent-agent). |
|
|
790
851
|
| `log.file` | state dir | yes | See "Debug Log File". |
|
|
791
852
|
| `log.disable` | `false` | yes | No file logging. |
|
|
792
853
|
| `log.level` | `info` | yes | `debug`, `info`, `warn`, `error`. |
|
|
793
854
|
| `status.line` | `on` | yes | The status row under the prompt (the REPL's and attached mode's), `on` or `off`. |
|
|
794
855
|
| `context.status` | `true` | yes | Context-usage telemetry for the model. See [context telemetry](internals/context-telemetry.md). |
|
|
795
|
-
| `context.window_tokens` | server's, else 256000 | yes | Context window when the server doesn't report one. |
|
|
856
|
+
| `context.window_tokens` | server's, else 256000 | yes | Context window when the server doesn't report one. `models.<key>.window_tokens` and `hosts.<name>.window_tokens` come first; see "The context window". |
|
|
857
|
+
| `models.<key>.window_tokens`, `hosts.<name>.window_tokens` | none | | A model's or host's context window when the server and its model list report none. |
|
|
796
858
|
| `context.chars_per_token` | `4.0` | yes | Estimate ratio when the server reports no usage. |
|
|
797
859
|
| `context.status_thresholds` | `20,40,60,80` | yes | Percentages that trigger a status. |
|
|
798
860
|
| `context.status_cadence` | `0` | yes | Also every N rounds; `0` = thresholds only. |
|
|
799
861
|
| `thinking.turn_preamble` | `true` | yes | Ask a `qwen36` model to open its thinking with a short `TURN:` line (the step label). |
|
|
800
862
|
| `thinking.level` | `default` | `--thinking` | `off`, `low`, `medium`, `high` or `default` for every model; the flag and env outrank the `models:`/`hosts:` entries, the file's value doesn't. See "Thinking". |
|
|
801
863
|
| `models.<key>.thinking`, `hosts.<name>.thinking` | none | | A model's or host's level. See "Thinking". |
|
|
864
|
+
| `hosts.<name>.remote` | by address | | `true`/`false`: treat the host as a remote provider or a local server. See "Remote or local". |
|
|
802
865
|
| `max_tool_output_chars` | `10000` | yes | Tool output kept in the conversation; a top-level key (see below). |
|
|
803
866
|
| `retry.max` | `5` | yes | See "Llama Network Retry Behavior". |
|
|
804
867
|
| `retry.base_delay` | `0.5` | yes | |
|
|
@@ -817,6 +880,7 @@ described in their own sections.
|
|
|
817
880
|
| `execute.truncate_at_bytes` | `65536` | yes | The same for `execute` output. |
|
|
818
881
|
| `execute.preview_bytes` | `12288` | yes | |
|
|
819
882
|
| `execute.telemetry_threshold_pct` | `80` | yes | |
|
|
883
|
+
| `execute.timeout_sec` | `30` | yes | Seconds one `execute` command may run before it is stopped. |
|
|
820
884
|
| `web.port` | `4567` | `--port` | `chi web`'s port. See [CLI](cli.md). |
|
|
821
885
|
| `web.host` | `127.0.0.1` | yes | `127.0.0.1`, `::1` or `localhost`; `lan` (this machine's private IPv4 address) or one of its IPv4 addresses also opens `chi web` to the network, with an access token (`chi web --new-token` replaces it). Anything else binds `127.0.0.1` with a warning. See [CLI: chi web on your phone](cli.md#chi-web-on-your-phone). |
|
|
822
886
|
| `web.markdown` | `false` | yes | Render answers as Markdown in `chi web`. |
|
data/docs/desktop.md
CHANGED
|
@@ -105,8 +105,9 @@ off until you set it up:
|
|
|
105
105
|
`kitty.agents` picks the programs listed (default `claude|codex|gemini|aider|opencode|cursor-agent|amp|goose`, a
|
|
106
106
|
YAML list works too; `"*"` lists every window, shells too), `kitty.binary` the kitty to run (default
|
|
107
107
|
`/Applications/kitty.app/Contents/MacOS/kitty`). See [Configuration](configuration.md#desktop-helper-agents-in-kitty).
|
|
108
|
-
3. Run `chi
|
|
109
|
-
`kitty:`** run it again.
|
|
108
|
+
3. Run `chi update` (or `chi desktop upgrade`): the helper reads these from its launch file, so **after every edit of
|
|
109
|
+
`kitty:`** run it again. `chi update` only rewrites the launch file when only the settings changed (no rebuild);
|
|
110
|
+
`chi desktop upgrade` always rebuilds.
|
|
110
111
|
|
|
111
112
|
The helper finds the sockets itself: kitty adds `-<pid>` to a `listen_on` path from kitty.conf (and fills in
|
|
112
113
|
`{kitty_pid}`), `~` and variables the helper knows are expanded, others (`${KITTY_PID}`) stay as written, as kitty
|
|
@@ -188,12 +189,15 @@ using it. `status` prints the baked dirs.
|
|
|
188
189
|
The helper uses only these commands, so it could ship on its own later:
|
|
189
190
|
|
|
190
191
|
- `chi sessions list --live --scope=all --format json` and `chi sessions list --limit 20 --scope=all --format json` →
|
|
191
|
-
`[{id, short_id, desc, cwd, project, updated_at, live, busy, owner, recap}]` (it uses `id`, `desc`, `cwd`, `busy`, `updated_at`;
|
|
192
|
+
`[{id, short_id, desc, cwd, project, updated_at, live, busy, owner, recap, parent_id, archived, scratch, ctx_pct}]` (it uses `id`, `desc`, `cwd`, `busy`, `updated_at`;
|
|
192
193
|
"recent" = rows of the second call that aren't live and have `owner: null`; only UUID-shaped ids go on to chi).
|
|
193
|
-
- `chi send [-m LINE] ID...`
|
|
194
|
-
|
|
194
|
+
- `chi send [-m LINE] [--image PATH]... ID...` and `chi send --new --dir DIR [--model NAME] [-m LINE] [--image PATH]...`
|
|
195
|
+
with the text on stdin (or none), and `chi note [--source NAME] ID...` with the text on stdin → one line per session
|
|
196
|
+
on stdout; exit 0 means all sent or queued, 1 means some were refused or failed.
|
|
197
|
+
- `chi self --model` → the model a new session starts on (the panel's hint).
|
|
198
|
+
- `chi models --format json` → the models the hosts offer (the new-session model picker).
|
|
195
199
|
|
|
196
|
-
Each call is stopped after 10 s. A stopped `chi note` says the note may be partly delivered.
|
|
200
|
+
Each call is stopped after 10 s, a send with images after 30 s. A stopped `chi note` says the note may be partly delivered.
|
|
197
201
|
|
|
198
202
|
## Troubleshooting
|
|
199
203
|
|