samagotchi 0.99.0 → 0.100.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -1
- data/README.md +2 -2
- data/docs/architecture.md +9 -3
- data/docs/bundle-authoring.md +1 -1
- data/docs/cli.md +1 -1
- data/docs/guardrails.md +2 -2
- data/docs/hooks.md +6 -1
- data/docs/memory.md +1 -1
- data/docs/plugins.md +67 -2
- data/docs/releasing.md +1 -1
- data/docs/sessions.md +1 -1
- data/docs/sub-agent.md +7 -2
- data/lib/samagotchi/bundles/core/manifest.yml +4 -3
- data/lib/samagotchi/bundles/system/manifest.yml +1 -1
- data/lib/samagotchi/bundles/work-cap/manifest.yml +13 -0
- data/lib/samagotchi/bundles/work-cap/plugin.rb +401 -0
- data/lib/samagotchi/engine.rb +2 -1
- data/lib/samagotchi/hooks/loader.rb +34 -6
- data/lib/samagotchi/plugin/api.rb +2 -1
- data/lib/samagotchi/plugin/context.rb +10 -2
- data/lib/samagotchi/session_metrics/usage.rb +31 -0
- data/lib/samagotchi/session_metrics.rb +48 -5
- data/lib/samagotchi/testing/host.rb +30 -1
- data/lib/samagotchi/testing/recorder.rb +5 -1
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/public/app.js +44 -8
- data/lib/samagotchi/web/public/chains.js +24 -0
- data/lib/samagotchi/web/public/index.html +7 -1
- data/lib/samagotchi/web/public/markdown_place.js +47 -1
- data/lib/samagotchi/web/public/send_turn.js +6 -2
- data/lib/samagotchi/web/public/session_actions.js +10 -5
- data/lib/samagotchi/web/public/turn_view.js +21 -7
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 47dbac4f107af7d9c7d9d571b907a1e9e777326732614ed34986f2dce954168a
|
|
4
|
+
data.tar.gz: 4335f033596dc75f3db80b754a347e36862d0fd07f1d72bafcc7a5c50ed539ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2454b93c9271b14ba0349c2991f6b0312dfdee76fd6a90005feb38726025dad71b6b4f1701bcbb2622c3db786d86fe2e58636668aa2f7d43d0ac289cae36e5a
|
|
7
|
+
data.tar.gz: 8fef8d270b58719f286b57c840f1a5fc3a53de10fec01fdcc08ea3de1315de17d267a834759b05ae09c05ca80b8f27009329eb38ff0aaf9a7b6ab59585b3e1d3
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,39 @@ and commands may change between minor versions. How releases are made:
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.100.1] - 2026-10-22
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- The web's `continue →` no longer takes a draft left over from another session (or the start page) as the new
|
|
16
|
+
link's first message: the opener goes in, and the toast's **Restore draft** brings the draft back. A draft written
|
|
17
|
+
in the continued session still stays.
|
|
18
|
+
- work-cap 0.1.1: a changed `bundles: work-cap:` setting reaches a running session (the caps are resolved again when the
|
|
19
|
+
settings change; the state file still wins per meter), and an empty key (`tool_calls:` with no value) falls through to
|
|
20
|
+
`child:` / `default:` instead of reading as "off"; `off`, `false` and `0` stay an explicit no cap.
|
|
21
|
+
- Web: a closed step's text in the history renders as markdown (with `web.markdown` on) and keeps its source refs,
|
|
22
|
+
live and after a reload, as the answer does.
|
|
23
|
+
- A hook entry in config.yml's `hooks:` that isn't a mapping, or has no `path:`, warns naming it
|
|
24
|
+
(`hooks.before_turn[0]`) instead of vanishing; the event's other entries still load.
|
|
25
|
+
|
|
26
|
+
## [0.100.0] - 2026-10-22
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Plugins can read the session's work so far with `ctx.usage`: turns, tool calls (by tool), steps and active time
|
|
31
|
+
(generations plus tool calls, never a wait on a question), across workers, the same numbers `/stats` shows. The
|
|
32
|
+
bundle test kit sets it with `bundle.set(usage: {...})`. See [docs/plugins.md](docs/plugins.md).
|
|
33
|
+
- The `work-cap` bundle (in the `core` profile; `chi update` installs it): an optional per-session cap on tool calls
|
|
34
|
+
and active minutes across turns, the bound a session whose step-limit Continue keeps being answered otherwise
|
|
35
|
+
lacks. At a cap the turn pauses on Continue / Stop, the question naming the session's totals; `/workcap` shows or
|
|
36
|
+
sets it, `chi send --new --set work-cap.tool_calls=400` caps a child. Inert until a cap is set. See
|
|
37
|
+
[docs/plugins.md](docs/plugins.md#the-work-cap-bundle).
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- An empty `hooks:` key in config.yml no longer crashes chi, and a malformed `hooks:` section (or one event's
|
|
42
|
+
entry) warns instead of being dropped without a word.
|
|
43
|
+
|
|
11
44
|
## [0.99.0] - 2026-10-22
|
|
12
45
|
|
|
13
46
|
### Added
|
|
@@ -3774,7 +3807,9 @@ and long-lived sessions.
|
|
|
3774
3807
|
- A macOS desktop helper (`chi desktop install`): a "Send to chi" Service and a
|
|
3775
3808
|
hotkey panel that send selected text or the clipboard to your sessions.
|
|
3776
3809
|
|
|
3777
|
-
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.
|
|
3810
|
+
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.100.1...HEAD
|
|
3811
|
+
[0.100.1]: https://github.com/dm1try/samagotchi/compare/v0.100.0...v0.100.1
|
|
3812
|
+
[0.100.0]: https://github.com/dm1try/samagotchi/compare/v0.99.0...v0.100.0
|
|
3778
3813
|
[0.99.0]: https://github.com/dm1try/samagotchi/compare/v0.98.0...v0.99.0
|
|
3779
3814
|
[0.98.0]: https://github.com/dm1try/samagotchi/compare/v0.97.0...v0.98.0
|
|
3780
3815
|
[0.97.0]: https://github.com/dm1try/samagotchi/compare/v0.96.0...v0.97.0
|
data/README.md
CHANGED
|
@@ -78,8 +78,8 @@ Messages API, picks the
|
|
|
78
78
|
model (or asks, when there are several), sends one test request and writes
|
|
79
79
|
the config. With a config already there, it adds a `hosts:` entry and keeps
|
|
80
80
|
the rest of the file. Then it installs the `core` bundles (loop-guard,
|
|
81
|
-
check-in, guardrails, slow-commands, agents-md, cost-cap: the safety set for a
|
|
82
|
-
small local model, the cost
|
|
81
|
+
check-in, guardrails, slow-commands, agents-md, cost-cap, work-cap: the safety set for a
|
|
82
|
+
small local model, the cost and work caps inert until you set one) and, on a terminal, offers `dev` (known-names, mcp, btw, skills,
|
|
83
83
|
source-links, github-pr, coordinator, claude-peer, codex-peer, ruby, model-notes; see
|
|
84
84
|
[Bundle profiles](docs/memory.md#bundle-profiles-core-and-dev)). Edit the
|
|
85
85
|
file later as in [Configure](#configure); `chi bootstrap --help` has the
|
data/docs/architecture.md
CHANGED
|
@@ -411,7 +411,10 @@ stay the turns' only. `SessionMetrics#persist` is serialized (its own mutex, tak
|
|
|
411
411
|
threads' saves land in snapshot order.
|
|
412
412
|
A bundle's `ctx.cost` reads the same sums (`SessionMetrics#cost`, a frozen `SessionMetrics::Cost`): the `tokens`
|
|
413
413
|
block's `cost_sum` and `cost_estimate_sum` with the running turn's finished generations folded in, plus the `side`
|
|
414
|
-
block's, so it counts what earlier workers spent too ([plugins.md](plugins.md)).
|
|
414
|
+
block's, so it counts what earlier workers spent too ([plugins.md](plugins.md)). Its `ctx.usage` reads the work
|
|
415
|
+
(`SessionMetrics#usage`, a frozen `SessionMetrics::Usage`): the snapshot's `turns`, `tool_calls_total` /
|
|
416
|
+
`tool_calls_by_tool` and `iterations_total`, and `active_ms`, the generations' `gen_ms` plus the finished tool
|
|
417
|
+
records' `duration_ms` (tallied per tool as they are counted; `ask_user_question`'s, a wait on the user, left out).
|
|
415
418
|
|
|
416
419
|
The page's frequent reads of `GET /api/sessions/:id` stay light too:
|
|
417
420
|
- `?tail=1&recent=1` (each turn's end, a cancel, an answer display): `{tail, session: {id, status,
|
|
@@ -428,7 +431,10 @@ The page's frequent reads of `GET /api/sessions/:id` stay light too:
|
|
|
428
431
|
`drawAsking(text, refs)`) pairs them on its raw draw and again after its markdown swap; the card pairs its
|
|
429
432
|
question text and its kept reply (`question_cards.js`); the step's closed `.gen-text` takes them
|
|
430
433
|
(`turn_view.js`; on a reload its `data-answer-at`, the message's `display_refs`) and `linkTextRefs` pairs it at
|
|
431
|
-
the turn's end and after a reload. A
|
|
434
|
+
the turn's end and after a reload. A closed step's text is markdown too with `web.markdown` on: a reload's
|
|
435
|
+
from its message's `html` (`turn_view.js` `textTemplate`), a live turn's from `POST /api/render` on its step's
|
|
436
|
+
first open after the turn's end (`markdown_place.js` `renderStepTexts`, which pairs its refs again after the
|
|
437
|
+
swap); the text as written stays on it as `data-copy-source` (`stepText`, a reloaded card's kept reply). A file ref outside the
|
|
432
438
|
session's folder is dropped, as a reload drops it: the folder `/tail` names, else (an older worker) the hub's
|
|
433
439
|
session list entry's, else (refs to check, no hub entry) the session file's; with no folder known at all, every
|
|
434
440
|
file ref is dropped rather than shown unchecked.
|
|
@@ -609,7 +615,7 @@ A map of the parts the overview above doesn't name (paths under `lib/samagotchi/
|
|
|
609
615
|
| Attached context | `context_sources.rb` (`ContextSources`), `context_poller.rb`, `context_absorber.rb`, `peer_sources.rb` (`PeerSources`: the sources peer bundles declare) | External sources a session keeps fresh, and the peer loop's wakes ([context.md](context.md)). |
|
|
610
616
|
| LLM context strategies | `llm_context_strategy.rb`, `llm_context_view.rb`, `llm_context_stale.rb`, `llm_context_forget.rb` | What a request sends of the history (none, stale, forget) ([internals/llm-context-forget.md](internals/llm-context-forget.md)). |
|
|
611
617
|
| Session chains | `session_continue.rb` (`SessionContinue`), `session_chain.rb` (`SessionChain`) | A session that continues an earlier one. `SessionChain.opener_for` gives the text web `continue →` prefills in the new link: the previous link's own first typed message when that link continues one itself, else nil (the 201's `opener`; not saved) ([sessions.md](sessions.md)). |
|
|
612
|
-
| Analytics | `analytics_file.rb` (`AnalyticsFile`), `session_metrics/totals.rb` (`SessionMetrics::Totals`), `session_metrics/model_segment.rb` (`SessionMetrics::ModelSegment`) | A session's `analytics.json` (`SessionMetrics#persist`); the sums over its turn records (`Totals`: tokens, cost, speeds, kept as running counters) and their split per model after a `/model` switch (`ModelSegment`: a run of turns on one model, the `model_segments` rows); `session_metrics/cost.rb` (`SessionMetrics::Cost`): the spend `ctx.cost` reads. `session_metrics/side_totals.rb` (`SessionMetrics::SideTotals`) and `side_usage.rb` (`SideUsage`): the side requests' sums, apart from the turns'. |
|
|
618
|
+
| Analytics | `analytics_file.rb` (`AnalyticsFile`), `session_metrics/totals.rb` (`SessionMetrics::Totals`), `session_metrics/model_segment.rb` (`SessionMetrics::ModelSegment`) | A session's `analytics.json` (`SessionMetrics#persist`); the sums over its turn records (`Totals`: tokens, cost, speeds, kept as running counters) and their split per model after a `/model` switch (`ModelSegment`: a run of turns on one model, the `model_segments` rows); `session_metrics/cost.rb` (`SessionMetrics::Cost`): the spend `ctx.cost` reads; `session_metrics/usage.rb` (`SessionMetrics::Usage`): the work `ctx.usage` reads. `session_metrics/side_totals.rb` (`SessionMetrics::SideTotals`) and `side_usage.rb` (`SideUsage`): the side requests' sums, apart from the turns'. |
|
|
613
619
|
| Images / vision | `image_store.rb` (`ImageStore`), `vision_support.rb`, `vision_context.rb` | Stored prompt images and whether a model takes them. |
|
|
614
620
|
| Toolkits | `toolkit.rb` (`Toolkit`), `toolkit_binding.rb` (`ToolkitBinding`, the Engine's seam), `toolkit_command.rb` (`/toolkit`), `tools/registry.rb` (`Registry#toolkit`, `#left_out_names`), `web/public/toolkit_chip.js` | Which registered tools a session's prompts declare: saved in the session, resolved at a turn's start (`Engine#apply_toolkit!`), named in the prompt's not-loaded line, a kit's prompt text after the appended files; `chi.toolkit` and `ctx.use_toolkit` for plugins ([configuration.md](configuration.md#toolkits)). |
|
|
615
621
|
| Tool index | `tools/tool_index.rb` (`Tools::ToolIndex`), `tools/deferred_tools.rb` | `find_tools` and `call_tool`: the tools a session knows but doesn't declare one by one (an mcp bundle's servers through `chi.tool_source`, the built-ins its toolkit leaves out), searched and called by name ([plugins.md](plugins.md)). On `api: anthropic` they also go out deferred, a hit loads its matches and the model calls them by name ([internals/anthropic.md](internals/anthropic.md)). |
|
data/docs/bundle-authoring.md
CHANGED
|
@@ -129,7 +129,7 @@ class, a hand-built `ctx`), that is a gap in the kit: say so to the user rather
|
|
|
129
129
|
of a checksum mismatch, and a line with no sha installs unchecked. `chi bundle check --fix` rewrites them; run it
|
|
130
130
|
after the last edit.
|
|
131
131
|
- **requires_chi.** Use the chi the user runs (`chi --version`). `check` warns when the plugin calls something
|
|
132
|
-
newer than the floor (`ctx.http` needs 0.80.0, `ctx.cost` 0.83.0, `ctx.sessions.children` 0.34.0). A keyword added
|
|
132
|
+
newer than the floor (`ctx.http` needs 0.80.0, `ctx.cost` 0.83.0, `ctx.usage` 0.100.0, `ctx.sessions.children` 0.34.0). A keyword added
|
|
133
133
|
later it can't see: `ctx.ask_model(model:)` needs 0.80.0, `ctx.sessions.send(delivery:)` 0.64.0.
|
|
134
134
|
- **trust_level.** Leave it out. `reviewed` / `trusted` are for someone who reviewed the bundle, not its author.
|
|
135
135
|
- **Restart.** A session loads bundles when it starts: after an install or a settings change, the user starts a
|
data/docs/cli.md
CHANGED
|
@@ -84,7 +84,7 @@ chi bootstrap # try localhost 8080, 11434, 1234, 8000
|
|
|
84
84
|
or with anchors gets the lines printed to paste instead. `--dry-run` shows
|
|
85
85
|
what it would write.
|
|
86
86
|
- **The bundles.** Unless writing the config failed, it installs the system
|
|
87
|
-
bundle and the `core` profile (loop-guard, check-in, guardrails, slow-commands, agents-md, cost-cap), one line
|
|
87
|
+
bundle and the `core` profile (loop-guard, check-in, guardrails, slow-commands, agents-md, cost-cap, work-cap), one line
|
|
88
88
|
each; on a terminal it then asks `Also install dev (known-names, mcp, btw,
|
|
89
89
|
skills, source-links, github-pr, coordinator, claude-peer, codex-peer, ruby, model-notes)? [y/N]`. Run again, it installs nothing new: a bundle
|
|
90
90
|
you uninstalled stays out ([Bundle profiles](memory.md#bundle-profiles-core-and-dev)).
|
data/docs/guardrails.md
CHANGED
|
@@ -125,7 +125,7 @@ answers it. Every question's options carry an **effect**, set by whoever asks:
|
|
|
125
125
|
- `deny`: Deny on an approval, Stop on the step-limit question or a plugin's
|
|
126
126
|
stop option;
|
|
127
127
|
- `spend`: more time and tokens, no new permission (Continue on the step-limit
|
|
128
|
-
question, cost-cap's Continue);
|
|
128
|
+
question, cost-cap's and work-cap's Continue);
|
|
129
129
|
- `permit`: one tool call (an approval's "Allow once");
|
|
130
130
|
- `permit_wide`: more than one call (this session, this repo or directory,
|
|
131
131
|
the rule).
|
|
@@ -140,7 +140,7 @@ guardrails:
|
|
|
140
140
|
- `hard`: `deny` and `answer` only. A parent can deny an approval
|
|
141
141
|
(`--option Deny --text "why"`, `--text` alone or `--dismiss`), Stop a
|
|
142
142
|
step-limit question and answer plain questions.
|
|
143
|
-
- `standard`: also `spend`: a parent may Continue a turn (or cost-cap's cap).
|
|
143
|
+
- `standard`: also `spend`: a parent may Continue a turn (or cost-cap's or work-cap's cap).
|
|
144
144
|
- `soft` (the default): also `permit`: `chi answer --option "Allow once"`
|
|
145
145
|
goes through, picked by the option's scope, not its label.
|
|
146
146
|
|
data/docs/hooks.md
CHANGED
|
@@ -26,6 +26,11 @@ hooks:
|
|
|
26
26
|
on_error: skip
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
Each event key holds a list of entries. A `hooks:` that isn't a mapping, or an event key that isn't a list
|
|
30
|
+
(`before_turn: guard.rb`), warns at each start and loads nothing for it; an empty key loads nothing, silently.
|
|
31
|
+
An entry that isn't a mapping (`- guard.rb`) or has no `path:` warns the same way, naming it
|
|
32
|
+
(`hooks.before_turn[0]`, counted from 0), and is skipped alone: the key's other entries load.
|
|
33
|
+
|
|
29
34
|
## Plugin Format
|
|
30
35
|
|
|
31
36
|
Each plugin is a `.rb` file in the hooks directory. The class name must match
|
|
@@ -672,7 +677,7 @@ Notes:
|
|
|
672
677
|
- Ordering: bundle hooks fire by `(priority, bundle_name, hook_name)` (lower priority first), then plain `config.yml` hooks in registration order.
|
|
673
678
|
- Settings: a hook class with `initialize(settings = {})` gets the bundle's section of `config.yml` `bundles:` (see [Settings](#settings)).
|
|
674
679
|
- A bundle can also ship a `plugin.rb` whose `chi.on(event)` blocks are bundle hooks too, next to commands and tools; see [Plugins](plugins.md). There `ctx.notify`, `ctx.steer` and the other `ctx` helpers act as this page's `event[:notify]`… do for the event the block runs for.
|
|
675
|
-
- Shipped bundles (each in a profile: `core` or `dev`, see [Bundle profiles](memory.md#bundle-profiles-core-and-dev)): `chi bundle install guardrails` (rules, see [Guardrails](guardrails.md#the-guardrails-bundle)) and `chi bundle install known-names` (a hook, see [Guardrails](guardrails.md#the-known-names-bundle)), `chi bundle install source-links` (a hook: announces source refs, see [The source-links bundle](#the-source-links-bundle)), `chi bundle install btw` (a plugin: `/btw`, see [Plugins](plugins.md#the-btw-bundle)), `chi bundle install mcp` (a plugin: tools from MCP servers, see [Plugins](plugins.md#the-mcp-bundle)) `chi bundle install loop-guard` (a plugin: breaks tool-call loops, see [Plugins](plugins.md#the-loop-guard-bundle)), `chi bundle install check-in` (a plugin: checks on a long turn, see [Plugins](plugins.md#the-check-in-bundle)), `chi bundle install slow-commands` (a plugin: commands that ran past the execute limit are run as tasks next time, see [Plugins](plugins.md#the-slow-commands-bundle)), `chi bundle install agents-md` (a plugin: a nested AGENTS.md is steered into the conversation on the first touch under its directory, see [Plugins](plugins.md#the-agents-md-bundle)), `chi bundle install cost-cap` (a plugin: a per-session $ cap, `/cap`, see [Plugins](plugins.md#the-cost-cap-bundle)), `chi bundle install ruby` (a plugin: an RSpec run with no examples at all, a hint, see [Plugins](plugins.md#the-ruby-bundle)) `chi bundle install skills` (a plugin: `/skill`, versions of skills, see [Plugins](plugins.md#the-skills-bundle)), `chi bundle install github-pr` (attached context: the branch's open PR, see [Plugins](plugins.md#the-github-pr-bundle)), `chi bundle install coordinator` (a plugin: parallel work in worktrees and child sessions, see [Plugins](plugins.md#the-coordinator-bundle)), `chi bundle install claude-peer` / `codex-peer` (a plugin: talk to a Claude Code or Codex session, see [Plugins](plugins.md#the-claude-peer-bundle)) and `chi bundle install model-notes` (memories: reviewed model notes, see [Plugins](plugins.md#the-model-notes-bundle)).
|
|
680
|
+
- Shipped bundles (each in a profile: `core` or `dev`, see [Bundle profiles](memory.md#bundle-profiles-core-and-dev)): `chi bundle install guardrails` (rules, see [Guardrails](guardrails.md#the-guardrails-bundle)) and `chi bundle install known-names` (a hook, see [Guardrails](guardrails.md#the-known-names-bundle)), `chi bundle install source-links` (a hook: announces source refs, see [The source-links bundle](#the-source-links-bundle)), `chi bundle install btw` (a plugin: `/btw`, see [Plugins](plugins.md#the-btw-bundle)), `chi bundle install mcp` (a plugin: tools from MCP servers, see [Plugins](plugins.md#the-mcp-bundle)) `chi bundle install loop-guard` (a plugin: breaks tool-call loops, see [Plugins](plugins.md#the-loop-guard-bundle)), `chi bundle install check-in` (a plugin: checks on a long turn, see [Plugins](plugins.md#the-check-in-bundle)), `chi bundle install slow-commands` (a plugin: commands that ran past the execute limit are run as tasks next time, see [Plugins](plugins.md#the-slow-commands-bundle)), `chi bundle install agents-md` (a plugin: a nested AGENTS.md is steered into the conversation on the first touch under its directory, see [Plugins](plugins.md#the-agents-md-bundle)), `chi bundle install cost-cap` (a plugin: a per-session $ cap, `/cap`, see [Plugins](plugins.md#the-cost-cap-bundle)), `chi bundle install work-cap` (a plugin: a per-session cap on tool calls and active minutes, `/workcap`, see [Plugins](plugins.md#the-work-cap-bundle)), `chi bundle install ruby` (a plugin: an RSpec run with no examples at all, a hint, see [Plugins](plugins.md#the-ruby-bundle)) `chi bundle install skills` (a plugin: `/skill`, versions of skills, see [Plugins](plugins.md#the-skills-bundle)), `chi bundle install github-pr` (attached context: the branch's open PR, see [Plugins](plugins.md#the-github-pr-bundle)), `chi bundle install coordinator` (a plugin: parallel work in worktrees and child sessions, see [Plugins](plugins.md#the-coordinator-bundle)), `chi bundle install claude-peer` / `codex-peer` (a plugin: talk to a Claude Code or Codex session, see [Plugins](plugins.md#the-claude-peer-bundle)) and `chi bundle install model-notes` (memories: reviewed model notes, see [Plugins](plugins.md#the-model-notes-bundle)).
|
|
676
681
|
- Installing a bundle executes its hook code at `Engine` startup. Only install bundles you trust, as you would a gem. Hooks are **not** executed at install time (copy-only); they are `module_eval`'d at `Engine.new` inside per-bundle `Samagotchi::Bundles::<name>` namespaces (no top-level `require` collisions). Keep hook files side-effect-free at load time; do work in `#call` — top-level side effects (require, IO, `at_exit`, global assignment) run once per `Engine.new` (class redefinition is idempotent).
|
|
677
682
|
|
|
678
683
|
Lifecycle:
|
data/docs/memory.md
CHANGED
|
@@ -387,7 +387,7 @@ profiles, meta bundles that install a set of them:
|
|
|
387
387
|
|
|
388
388
|
| profile | bundles |
|
|
389
389
|
|---|---|
|
|
390
|
-
| `core` | loop-guard, check-in, guardrails, slow-commands, agents-md, cost-cap: the recommended safety set |
|
|
390
|
+
| `core` | loop-guard, check-in, guardrails, slow-commands, agents-md, cost-cap, work-cap: the recommended safety set |
|
|
391
391
|
| `dev` | known-names, mcp, btw, skills, source-links, github-pr, coordinator, claude-peer, codex-peer, ruby, model-notes |
|
|
392
392
|
|
|
393
393
|
`chi bootstrap` installs `core` and, on a terminal, offers `dev`. An existing
|
data/docs/plugins.md
CHANGED
|
@@ -751,6 +751,7 @@ full label, `plugin.rb (bundle my-bundle)`.
|
|
|
751
751
|
| `ctx.model` | the model the session runs on now: its resolved ref (`host:id`), right after `/model` too |
|
|
752
752
|
| `ctx.model_key` | that model's memory overlay key (`<name>.<key>.md`, what `memory_write current_model_only` writes) |
|
|
753
753
|
| `ctx.cost` | the session's spend so far, read now, as a frozen value: `total` (USD, reported + estimated, side requests included; 0.0 before any), `reported` (by providers, `usage.cost`), `estimated` (from `hosts.<name>.models` prices; a generation is one or the other, never both), `side` (recap, `/btw`, `ask_model`: their share of `total`) and `known?` (false while generations or side requests ran but none was reported or priced, so a limit on it can't be enforced; a session with some priced generations reads known, the unpriced ones counting 0). It includes the running turn's finished generations and what earlier workers of the session spent. Use its methods, not its class. Needs chi 0.83.0 |
|
|
754
|
+
| `ctx.usage` | the session's work so far, read now, as a frozen value: `turns` (finished ones and the running one), `tool_calls` and `tool_calls_by_tool` (every call, running ones included; canonical names: an alias counts under its tool, a `call_tool` call under the inner tool), `steps` (the loop rounds that dispatched tools, `/stats`' iterations) and `active_ms` (`active_minutes` too): work time, the generations' time plus the finished tool calls' time, never the waits between them (a question, an approval, the user's answer to `ask_user_question`), with `tool_ms_by_tool` its tool part by tool, so a waiting tool's time (`task_wait`) can be left out. Its counts are the ones `/stats` and `chi sessions stats` show, earlier workers' included. Use its methods, not its class. Needs chi 0.100.0 (guard it with `ctx.respond_to?(:usage)`) |
|
|
754
755
|
| `ctx.settings` | the bundle's settings, frozen: config.yml's `bundles: <bundle>:` with the session's own `--set` values laid over it ([Per-session settings](#per-session-settings)); the config alone until the session is bound (in `register` and `chi.ctx`) |
|
|
755
756
|
| `ctx.data_dir` | `$XDG_STATE_HOME/samagotchi/plugins/<bundle>/`, created on first use. A session's own state goes in `sessions/<id>.json` or `sessions/<id>/` there: chi removes it when the session is deleted, discarded or pruned |
|
|
756
757
|
| `ctx.log` | `ctx.log.info(:event, key: value)`: debug-log records tagged `plugins`, with `bundle=<bundle>` |
|
|
@@ -1120,7 +1121,7 @@ CHANGELOG line and bumps the shipped bundles that use it. Anything else under
|
|
|
1120
1121
|
|
|
1121
1122
|
**Stable**
|
|
1122
1123
|
|
|
1123
|
-
1. `Samagotchi::Plugin::Api` / `chi.*` and `ctx` as documented above (`ctx.cost`'s
|
|
1124
|
+
1. `Samagotchi::Plugin::Api` / `chi.*` and `ctx` as documented above (`ctx.cost`'s and `ctx.usage`'s values by their methods), including
|
|
1124
1125
|
`Samagotchi::Plugin::ToolResult`, `Samagotchi::Plugin::ModelError` (and its
|
|
1125
1126
|
subclass `Samagotchi::Plugin::ModelCancelled`),
|
|
1126
1127
|
`Samagotchi::Plugin::Service::Stopped`, `Samagotchi::Plugin::Sessions::Error`
|
|
@@ -1187,6 +1188,7 @@ bundle.sessions.on(:children) { |all:| [] } # ctx.sessions, scripte
|
|
|
1187
1188
|
bundle.http.stub(:post, "http://127.0.0.1:9000/classify", json: { label: "safe" }) # ctx.http, never the network
|
|
1188
1189
|
bundle.set(running: false) # the session's values: cwd:, messages:, cancelled: …
|
|
1189
1190
|
bundle.set(cost: 2.5) # ctx.cost: reported USD, or { reported:, estimated:, side:, known: }
|
|
1191
|
+
bundle.set(usage: { tool_calls: 40, active_ms: 600_000 }) # ctx.usage: { turns:, tool_calls:, tool_calls_by_tool:, steps:, active_ms:, tool_ms_by_tool: }
|
|
1190
1192
|
bundle.set(session_settings: { "cap" => 1 }) # the session's --set values (Bundle.load takes session_settings: too)
|
|
1191
1193
|
bundle.tool_loads.last.names # ctx.load_tools calls; set(load_tools_staged: [...]) limits what they stage
|
|
1192
1194
|
bundle.shutdown
|
|
@@ -1222,6 +1224,10 @@ bundle.shutdown
|
|
|
1222
1224
|
- **`ctx.cost`** is zero and known unless the test sets it: `bundle.set(cost: 2.5)` (reported USD), a Hash of the
|
|
1223
1225
|
parts (`reported:`, `estimated:`, `side:`, `known:`; `total` is reported + estimated) or a callable giving either,
|
|
1224
1226
|
called at each read (a counting lambda shows whether the bundle read it).
|
|
1227
|
+
- **`ctx.usage`** is zero unless the test sets it: `bundle.set(usage: {...})`, a Hash of the parts (`turns:`,
|
|
1228
|
+
`tool_calls:`, `tool_calls_by_tool:`, `steps:`, `active_ms:`, `tool_ms_by_tool:`; zeros for the rest, an unknown
|
|
1229
|
+
part raises; `tool_calls` defaults to the sum of `tool_calls_by_tool`, `active_ms` to the sum of
|
|
1230
|
+
`tool_ms_by_tool`) or a callable giving one, called at each read.
|
|
1225
1231
|
- **`session_settings:`** (on `Bundle.load` and `bundle.set`) are the session's own `--set` values for the bundle,
|
|
1226
1232
|
keys its manifest lists in `session_settings:` (another key, or a value of another type than the manifest gives
|
|
1227
1233
|
it, raises `ArgumentError`, as chi refuses it). `ctx.settings`
|
|
@@ -1680,6 +1686,64 @@ its own card and doesn't wake its parent ([sessions.md](sessions.md#delegating))
|
|
|
1680
1686
|
The state is one file per session, `<data_dir>/sessions/<session id>.json` (`{"cap": 3.0, "step": 3.0}`), removed
|
|
1681
1687
|
with the session.
|
|
1682
1688
|
|
|
1689
|
+
Its sibling for work instead of money, tool calls and active minutes across the session's turns, is
|
|
1690
|
+
[the work-cap bundle](#the-work-cap-bundle): the cap a local model (no cost) can have.
|
|
1691
|
+
|
|
1692
|
+
## The work-cap bundle
|
|
1693
|
+
|
|
1694
|
+
`chi bundle install work-cap` installs the bundle shipped with chi (`chi bootstrap` installs it with the `core`
|
|
1695
|
+
profile; an existing install gets it with `chi update`). It caps the work one session does across its turns: tool
|
|
1696
|
+
calls and active minutes. The per-turn meters reset every turn (the step limit, check-in, loop-guard), and a
|
|
1697
|
+
Continue on the step-limit question starts the next 300 steps; a parent agent may answer that Continue itself
|
|
1698
|
+
(`chi answer`), so a child it keeps continuing has no overall bound but cost-cap's `$`, and on a local model none.
|
|
1699
|
+
work-cap is that bound, with cost-cap's shape: the harness watches, the model never sees any of it. It is inert
|
|
1700
|
+
without a cap, and there is none by default.
|
|
1701
|
+
|
|
1702
|
+
```yaml
|
|
1703
|
+
# config.yml
|
|
1704
|
+
bundles:
|
|
1705
|
+
work-cap:
|
|
1706
|
+
child: {tool_calls: 500, minutes: 90} # delegate children with no own value
|
|
1707
|
+
default: {} # every other session (and a delegate without child:); empty: no cap
|
|
1708
|
+
warn_at: 0.8 # tell the user (only) once at this share of a cap; 0/off: no warning
|
|
1709
|
+
ignore_tools: [task_wait, task_get, delegate, delegate_result] # not counted: waiting
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
- **What counts** (`ctx.usage`): **tool calls**, the session's own across its turns and workers, less
|
|
1713
|
+
`ignore_tools` (the waiting tools by default, `delegate` among them since it blocks on its child, so a session
|
|
1714
|
+
waiting on a long task or a child isn't capped for waiting); and **active minutes**, work time: the generations' time plus the finished tool calls' time (less
|
|
1715
|
+
`ignore_tools`' time), never a wait (a question, its own included, an approval, the user's answer to
|
|
1716
|
+
`ask_user_question`), so idle time and a Continue answered hours later don't count.
|
|
1717
|
+
- **When it checks:** before each generation, like cost-cap: the overshoot is at most one generation's tool calls.
|
|
1718
|
+
When the step limit and a work cap fall in the same turn, the work cap asks first, and its Stop ends the turn.
|
|
1719
|
+
- **At `warn_at` of a cap** you get one notice per meter, `work-cap> 320 of 400 tool calls (80%)`; a raised cap
|
|
1720
|
+
warns again.
|
|
1721
|
+
- **At a cap** the turn pauses on a question (header "Work cap") that names the session's totals, so a parent
|
|
1722
|
+
answering it decides on the whole picture: `Work cap reached: 412 tool calls of 400 (6 turns, 47 min active,
|
|
1723
|
+
$1.20). Continue raises it to 800.` **Continue** raises the cap by another cap's worth (as many steps as it
|
|
1724
|
+
takes to pass the work, saved for the session), **Stop** stops the turn (`canceled` with `stopped_by: work-cap`)
|
|
1725
|
+
with a card showing the totals. Both meters at once: one question naming both, Continue raises each. With no one
|
|
1726
|
+
to ask (`--non-interactive`) it stops. Continue is tagged `:spend`, as cost-cap's: a parent agent may Continue
|
|
1727
|
+
under `guardrails.parent_answers: soft` or `standard`, only Stop under `hard` (see
|
|
1728
|
+
[Guardrails](guardrails.md#answers-from-a-parent-agent)).
|
|
1729
|
+
- **The caps of a session**, each meter on its own: the one `/workcap` or a Continue set, else its own value (`chi
|
|
1730
|
+
--set work-cap.tool_calls=400`, `work-cap.minutes=60`, `chi send --new --set …`; `off`, `0` or a negative number
|
|
1731
|
+
for none), else `child:`'s for a delegate child, else `default:`'s. Minutes in config.yml read `90`, `90m` or
|
|
1732
|
+
`1.5h`. A value that doesn't read (`tool_calls: many`, a `default:` that isn't a mapping) gets one notice,
|
|
1733
|
+
`work-cap: tool_calls: "many" isn't a number or off; using default.tool_calls: (400)`, and the next value is used,
|
|
1734
|
+
never a silent no cap.
|
|
1735
|
+
|
|
1736
|
+
**`/workcap`** (works while a turn runs; the next generation reads it):
|
|
1737
|
+
|
|
1738
|
+
- `/workcap`: `work-cap: 320 of 400 tool calls (6 turns, 47 min active, $1.20)`, or `work-cap: no cap (…)` with the
|
|
1739
|
+
totals.
|
|
1740
|
+
- `/workcap 400`: the tool-call cap (and what Continue adds) becomes 400 for this session; `/workcap 90m` or
|
|
1741
|
+
`/workcap 2h`: the active-minutes cap.
|
|
1742
|
+
- `/workcap off` (or `/workcap 0`): no work cap for this session, over the config.
|
|
1743
|
+
|
|
1744
|
+
The state is one file per session, `<data_dir>/sessions/<session id>.json` (`{"tool_calls": {"cap": 800, "step":
|
|
1745
|
+
400}}`, a meter's `"cap": null` for off).
|
|
1746
|
+
|
|
1683
1747
|
## The check-in bundle
|
|
1684
1748
|
|
|
1685
1749
|
`chi bundle install check-in` installs the bundle shipped with chi (`chi
|
|
@@ -1712,7 +1776,8 @@ what it has found. check-in counts the turn's tool calls, and when there are
|
|
|
1712
1776
|
- **`mode: notify`**: a notice line only.
|
|
1713
1777
|
|
|
1714
1778
|
The count is per turn: a new turn (a prompt, a continue, a reminder) starts
|
|
1715
|
-
from zero; steering merged into the running turn doesn't reset it
|
|
1779
|
+
from zero; steering merged into the running turn doesn't reset it (a cap
|
|
1780
|
+
across the session's turns is [the work-cap bundle](#the-work-cap-bundle)). The polling
|
|
1716
1781
|
tools are not counted. A nudge that arrives after the model's final answer is
|
|
1717
1782
|
dropped (logged), never restarting a turn that is done; the card's "Nudged the
|
|
1718
1783
|
model at N tool calls" then becomes "The answer came first; nudge not sent."
|
data/docs/releasing.md
CHANGED
|
@@ -13,7 +13,7 @@ can run the whole release; the user approves the notes before the tag and the
|
|
|
13
13
|
and `rake release:check` enforce it). The system bundle upgrades itself when
|
|
14
14
|
chi starts.
|
|
15
15
|
- **Every other shipped bundle** (btw, check-in, guardrails, known-names,
|
|
16
|
-
loop-guard, mcp, skills, slow-commands, agents-md, cost-cap, source-links, github-pr, coordinator, claude-peer, codex-peer, ruby, model-notes, and the profiles core and dev) has its own semver in its
|
|
16
|
+
loop-guard, mcp, skills, slow-commands, agents-md, cost-cap, work-cap, source-links, github-pr, coordinator, claude-peer, codex-peer, ruby, model-notes, and the profiles core and dev) has its own semver in its
|
|
17
17
|
`manifest.yml` and, when it needs a newer chi, a `requires_chi:` line. They never upgrade by themselves: users run
|
|
18
18
|
`chi update` (all of them, with the gem) or `chi bundle upgrade NAME`. So:
|
|
19
19
|
- a change to a bundle's files bumps that bundle's `version:`
|
data/docs/sessions.md
CHANGED
|
@@ -237,7 +237,7 @@ A session can **continue** an earlier one: "the next run of the same routine" (a
|
|
|
237
237
|
- **If the continue fails part-way:** a new link that fails to start gives its moved delegates back before it is deleted (each gets a note saying so; its worker is stopped first, if one started, and a worker that won't stop is reported, the link left), with any report one of them rang it with meanwhile; the previous link, back in the lists, is woken for reports waiting. A continue that dies in the middle leaves a `move.json` in the new link's folder: the new link's next worker finishes that move (only the delegates it names, and without a second note to one already told) as it starts. Until the new link's own worker holds it, a ring from a moved delegate doesn't start another (a `starting` marker in its folder, which that worker removes; a stale one, over 60 s old or from a process that is gone, is ignored). An open delegate below an archived delegate refuses the continue (`under archived …`): unarchive that one, or archive this one.
|
|
238
238
|
- **Refused too:** a link that is continued already (naming the link that continues it; continue that one, or `last:<id>`), a previous link whose folder is gone, and one whose model's host can't run it when no default model is configured to fall back to. A refusal starts nothing and archives nothing; a new link that fails to start puts back what was archived. Every refusal that can be known up front (the archive's ones included) comes before the recap wait. One continue of a session runs at a time (a lock in its folder; other chains don't wait), so a double click finds the first one's link and is refused, while a `last:<id>` continue that waited follows the chain to its new end.
|
|
239
239
|
- **Web:** `POST /api/sessions` takes `continues: "<id, prefix or last:id>"`, with `idle: true` (a new link waiting for its first message, previewed by the previous link's, or `preview`) or a `prompt`, and `model` (or `model_name`) for the new link's model, but not `dir`, `llm_context` or `thinking` (400 `invalid_continues`: the previous link's are taken). 201 is the new session's summary, `continues` set, with `moved`: the ids of the delegates that moved to it (`[]` for none), and `model_warning`: the default-model fallback's warning, then any about the model id, joined by `; ` (`null` for none), and `opener`: the previous link's first typed message, in full, when that link continues one itself (`null` otherwise: a chain's first link's first message is its task); 404 `not_found`; 400 `ambiguous_id` for a prefix of several sessions, `invalid_model` for a given model whose host config.yml doesn't have (or a fallback with no default model); 409 `continued` with `next_id` (the link that continues it already, which the page opens instead), `open_children` with `ids` (open delegates that can't move), `folder_gone`, `busy`, `scratch` or `owned_by_tui`. Every session summary carries `continues`.
|
|
240
|
-
- **The page:** the info bar's `continue →` continues the open session (`continues: <id>, idle: true`; it reads `continuing…` through the recap wait) and opens the new link with an opener in the composer, not sent (a draft
|
|
240
|
+
- **The page:** the info bar's `continue →` continues the open session (`continues: <id>, idle: true`; it reads `continuing…` through the recap wait) and opens the new link with an opener in the composer, not sent (a draft written in this session stays instead; one carried over from another session or the start page gives way to the opener, and the toast's **Restore draft** brings it back): the previous link's own first typed message when that link continues one (the 201's `opener`; a `!shell` line isn't taken), else `Continue where we left off.`. So whatever you sent on the last link comes back on the next one, and editing it once changes it for every later link; the previous link is archived, a toast says so (`Continued 3fa2c1d0 in 4b7e9a01; 3fa2c1d0 is archived; 1 open delegate moved`), and a moved delegate's card folds under the new link. When the previous link's model's host is gone the link starts on the default model and the toast carries the server's `model_warning` too, and then stays until closed. A fresh link (one with no turn yet, however it was made: `continue →`, `chi send --new --continues`, a reload) shows the model picker in its composer with the link's model, until its first turn starts (a failed or canceled first turn ends it too); a pick runs `/model <name>` in the link (a command bubble; the info bar follows) and changes neither the start page's remembered model nor its Recent list, and a Send right after it waits for the `/model` to be taken. A link a chi REPL owns, or one continued already, shows none. A link continued already has no `continue →`: its `→` link goes to the next link (a stale page's continue answered 409 `continued` opens `next_id`). A continue refused for open delegates that can't move shows a toast that names each one (its preview and what the server says to do: `older chi worker 0.46.1; restart it`, `open in a chi REPL; close it there`), each a link to its page; any other refusal shows the server's words. The info bar of a link carries `← 2026-10-08` (the previous link's day) and, on an earlier link, `2026-10-10 →`, each a link with its id, its full start (`2026-10-10 14:32`) and its preview in the tooltip; a neighbour that started on the open link's own day shows its time instead (`← 09:12`, `14:32 →`). A link made by `continue →` inherits the previous link's preview (and its title, if it has one) when it is created, so its card keeps its chain's title whatever opener it is sent, and its top bar and browser tab show its card's title. A link whose title is the opener and nothing else (a `chi send --new --continues` link whose first message is `Continue where we left off.`) shows its chain's first link's title instead, on its card, in the popover and in its info bar's title line, display only (its messages and data keep the opener; its own title when the first link is gone). The lists fold a chain into the card of its latest listed link, whatever the earlier links' archived state (typing in an archived link brings it back, folded there still), their delegates with them: the card's `↩ #N` chip (`#N of M` when later links aren't listed; its tooltip `Session chain: link N of M`) opens a popover of the other links, newest first (`#N`, its date, with its time (`2026-10-17 14:32`) when another link of the chain started the same day, its own title when it differs from the card's (a link inherits its chain's, so mostly it doesn't), else its recap's first sentence, else its preview, `archived`), a click opens one; the chip shows a live dot or `waiting` for a link that has a worker or waits on the user, and a waiting link puts its chain's card first. All sessions folds nothing while a search is typed or "include archived" is on: every link is a card of its own then, its chip `#N of M`, with its own delegates folded in, so a search finds an earlier link and its delegates.
|
|
241
241
|
- **CLI:** `chi send --new --continues (ID|PREFIX|last:ID) [--model M] [-m TEXT]` (see *Starting a session*).
|
|
242
242
|
- **Which link:** an id, a unique prefix, or `last:<id or prefix>`, the latest link of the chain that session is in. It walks the links that still exist: a deleted link in the middle (`chi sessions delete`, the retention sweep of an unarchived one) ends the walk before it, so `last:` of an earlier link then names that earlier link, and continuing it starts a second line beside the links after the gap; name a link after the gap instead. A trigger names the chain this way: `chi send` to an archived link would bring it back (a human's input), not continue the chain.
|
|
243
243
|
|
data/docs/sub-agent.md
CHANGED
|
@@ -47,7 +47,9 @@ chi answer ID --question QID --dismiss [--timeout S] [--format json]
|
|
|
47
47
|
|
|
48
48
|
A child with a bundle setting of its own, such as a $ cap (the [cost-cap bundle](plugins.md#the-cost-cap-bundle)):
|
|
49
49
|
`chi send --new --wait --format json --set cost-cap.cap=3 -m "task"`. At the cap the wait exits 3 with the cost-cap
|
|
50
|
-
question; `chi answer ID --question QID --option Continue` (or `Stop`) answers it.
|
|
50
|
+
question; `chi answer ID --question QID --option Continue` (or `Stop`) answers it. A cap on the child's work across
|
|
51
|
+
its turns (the [work-cap bundle](plugins.md#the-work-cap-bundle)), the bound a parent that keeps answering the step
|
|
52
|
+
limit's Continue doesn't otherwise have: `--set work-cap.tool_calls=400` (or `work-cap.minutes=60`, active minutes).
|
|
51
53
|
|
|
52
54
|
`chi answer` waits after answering, the same way `chi send --wait` does, so the
|
|
53
55
|
next question comes back as exit 3 again. What it waits for is the answered
|
|
@@ -122,7 +124,10 @@ relayed to the parent's user the way approvals are.
|
|
|
122
124
|
|
|
123
125
|
A session at its cost cap (the [cost-cap bundle](plugins.md#the-cost-cap-bundle)) waits the same way, as a
|
|
124
126
|
question of kind `hook` with header "Cost cap" and options `Continue` and `Stop`: `--option Continue` raises the cap
|
|
125
|
-
by another cap's worth and the turn goes on, `--option Stop` ends it `canceled` with `stopped_by: cost-cap`.
|
|
127
|
+
by another cap's worth and the turn goes on, `--option Stop` ends it `canceled` with `stopped_by: cost-cap`. A session at its work cap (the
|
|
128
|
+
[work-cap bundle](plugins.md#the-work-cap-bundle)) asks the same, header "Work cap", the question naming the
|
|
129
|
+
session's totals (`Work cap reached: 412 tool calls of 400 (6 turns, 47 min active, $1.20). Continue raises it to
|
|
130
|
+
800.`); `stopped_by: work-cap` on Stop.
|
|
126
131
|
|
|
127
132
|
## Approvals
|
|
128
133
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: core
|
|
3
|
-
version: 0.
|
|
3
|
+
version: 0.4.0
|
|
4
4
|
scope: system
|
|
5
5
|
description: "Recommended safety set"
|
|
6
6
|
trust_level: reviewed
|
|
7
|
-
# Its members' highest floor (
|
|
8
|
-
requires_chi: ">= 0.
|
|
7
|
+
# Its members' highest floor (work-cap's: ctx.usage, raised at the release)
|
|
8
|
+
requires_chi: ">= 0.100.0"
|
|
9
9
|
includes:
|
|
10
10
|
- loop-guard
|
|
11
11
|
- check-in
|
|
@@ -13,3 +13,4 @@ includes:
|
|
|
13
13
|
- slow-commands
|
|
14
14
|
- agents-md
|
|
15
15
|
- cost-cap
|
|
16
|
+
- work-cap
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: work-cap
|
|
3
|
+
version: 0.1.1
|
|
4
|
+
scope: system
|
|
5
|
+
description: "A per-session work cap (tool calls, active minutes) across turns: at a cap the turn pauses on Continue (another cap's worth) / Stop with the session's totals, a warning at 80% goes to the user only; /workcap shows or sets it"
|
|
6
|
+
trust_level: reviewed
|
|
7
|
+
plugin:
|
|
8
|
+
file: plugin.rb
|
|
9
|
+
sha256: sha256:f4ce7ea7f5801490a29e232c41c7bca2007c140d21f1a78bbfb60e6b6fd4f64b
|
|
10
|
+
# ask_user's effects: are in chi 0.92.0; ctx.usage is new in the next chi
|
|
11
|
+
requires_chi: ">= 0.100.0"
|
|
12
|
+
# chi --set work-cap.tool_calls=400 / work-cap.minutes=60: the session's own caps, a number or off
|
|
13
|
+
session_settings: {tool_calls: number, minutes: number}
|