make xhigh the sandbox's thinking, and stop settings.json freezing
Two changes, one bug found through the other.
Thinking is policy now: defaultThinkingLevel is xhigh unless you say otherwise
(thinking / --thinking / AISB_THINKING, with pi's levels plus 'host' to decline
and 'off' meaning pi's own no-reasoning level). It is written into the bridged
settings and re-applied by the entrypoint on every run, so a run cannot set its
own reasoning down for the runs after it. Unknown levels are refused with the
list to pick from. Nothing is written for codex, claude or a command after --,
and --no-pi-config declines it along with the bridge, because pi's own defaults
are what that flag asks for.
The reason xhigh had never reached a sandbox is worse than a missing default:
settings.json was managed as one whole file, and pi rewrites its own settings
(a theme change, "seen the changelog"), so the first such write matched nothing
and froze every host preference out permanently -- provider, model, thinking
budgets and level included, a real session left holding just
{"lastChangelogVersion": "1.4.0"}. It is merged per key instead, against a copy
of what we last wrote: a key edited in the sandbox stays edited, a key never
touched follows the host again, an untouched key the host dropped is dropped, a
key pi invented survives, and a file with no base copy takes the host values --
which repairs the volumes already frozen. Unparseable JSON is re-seeded with a
warning since pi cannot use it either; a file the container cannot read is
reported with the fix, because nothing inside the sandbox can repair one.
One trap worth remembering: the seeding script is passed to bash -c in single
quotes, so a single quote inside it closes the argument early and the rest runs
in the outer shell -- valid bash, wrong program, clean bash -n and clean
shellcheck. tests/unit/06_entrypoint.sh extracts the seeding script and asserts
it is quote-free, and extracts the merge program to test its semantics without
a container; tests/e2e/12_sandbox.sh does the same in a real run, including
forcing the level back after the sandbox sets it to off.
LLM-Generated: true
This commit is contained in:
@@ -154,14 +154,41 @@ purpose is to be unable to use it:
|
||||
| `apiKey: "sk-..."` or `apiKey: "!pass show ..."` | `apiKey: "$AI_API_TOKEN"` -- pi resolves it itself, no value is written to disk |
|
||||
| a header like `X-Trace: "!date +%s"` | dropped, and reported: a host command is not run in the sandbox |
|
||||
| `baseUrl: "https://aipi.reeseapps.com/v1"` | unchanged, along with every model, limit and thinking level |
|
||||
| settings: provider, model, theme, thinking budgets, telemetry | unchanged |
|
||||
| settings: provider, model, theme, thinking budgets, telemetry | unchanged, merged per key |
|
||||
| a settings value pointing into `~` | dropped, and reported: that path is not mounted |
|
||||
| `auth.json`, `models-store.json`, sessions, extensions | never touched |
|
||||
|
||||
The rewritten pair is seeded into `/home/sandbox/.pi/agent` at container start, owned by
|
||||
your uid, mode `600`. It is a managed file: a change on the host is picked up on the
|
||||
next run, an edit made *inside* the sandbox is left alone, and deleting it inside
|
||||
re-seeds from the host.
|
||||
your uid, mode `600`. The two files are managed differently, because they are different
|
||||
kinds of thing:
|
||||
|
||||
| file | rule | why |
|
||||
|---|---|---|
|
||||
| `models.json` | replaced when missing or unchanged, left alone once you edit it in the sandbox | it is a catalog; a partial merge of a provider list is worse than either choice |
|
||||
| `settings.json` | **merged per key** | pi rewrites its own settings — a theme change, "seen the changelog" — and managing the file whole meant that one write froze *every* host preference out of the sandbox permanently |
|
||||
|
||||
So in `settings.json`: a key you change inside the sandbox stays yours, a key you never
|
||||
touched follows the host again, a key the host drops disappears unless you had changed
|
||||
it, and a key pi added (`lastChangelogVersion`) survives.
|
||||
|
||||
### Thinking is xhigh, and it is policy
|
||||
|
||||
`defaultThinkingLevel` is the one setting `ai-sandbox` insists on, because pi's own
|
||||
default is `medium` and a sandbox run is usually the kind of work you want reasoned
|
||||
about hard:
|
||||
|
||||
```bash
|
||||
pi --allow aipi.reeseapps.com # xhigh, whatever your host settings.json says
|
||||
pi --thinking max ... # this run only
|
||||
pi --thinking off ... # no reasoning, e.g. a mechanical refactor at scale
|
||||
pi --thinking host ... # stop forcing it; your settings.json decides
|
||||
```
|
||||
|
||||
`--thinking` is a policy, not a preference: it is written over the merged settings on
|
||||
every run, so a run cannot set its own thinking level down for the runs after it. It is
|
||||
`pi`-only — codex, claude and anything you put after `--` read their own config, and
|
||||
ai-sandbox leaves that alone. `--no-pi-config` declines the policy too, since "pi starts
|
||||
with its own defaults" is what that flag is for.
|
||||
|
||||
The token itself follows the normal rule -- it is the one variable the bridged config
|
||||
names, so it is passed by name (never by value, and never into `ps`):
|
||||
|
||||
Reference in New Issue
Block a user