Both You.com hosts join PROVIDER_HOSTS (keyed vs keyless) and the Sites catalogue; the YDC_API_KEY fallback moves to key resolution.
Every provider declares key_mode none/optional/required beside display_name and key_url.
Firecrawl's host joins PROVIDER_HOSTS and the Access ▸ Sites catalogue.
The class gets display_name and key_url and raises on HTTP errors like the others.
config.example.toml covered 7 of the 13 supported keys; a user reading it
could not discover how to switch web-search providers or point a dev/BYO
deployment at its own cloud instance. Adds web_search_provider (with the
three supported backends) and the cloud_* family (commented out — the
defaults are the production values, and an empty cloud_relay_ws_url
meaningfully disables the relay). Also notes the Windows global config
location and that allowed_commands/auto_allow are global-only until
workspace trust.
Verified: the example parses with tomllib and every key (including the
commented cloud_* names) matches coworker.config._FIELDS.
Network allow list holds only the machine's ticked sites, none by default; strict/standard removed.
The app no longer installs OpenShell; setup is two checks and one step with progress.
DMG build requires grpcio so the sidecar can use OpenShell.
Network: registries and search (strict folded in) with the machine's own hosts, or allow everything.
Credentials list only what was added; shipped entries become presets with the variable each tool reads.
A hung docker info no longer fails the OpenShell checklist.
Setup and remove routes prove the wall in a throwaway sandbox before the choice takes effect.
Credential entries are a file or a folder, labelled credential or configuration; collapsible cards.
One list per platform (coworker/sandbox/toolchains.py), machine-level, editable by name; read entries on Windows,
the Seatbelt profile on the Mac. The Windows full mode passes its environment through a file (1024-character logon limit).
Any host, no proxy; the files stay confined. Strict remains the default elsewhere.
Settings offers it as a third choice; credential rows hide their hosts when it is on.
OpenWorker had no way to choose how hard a model thinks per reply; the level
was whatever each endpoint defaulted to (Anthropic: high; Kimi K3 on
Together: max), and a run record could not state it.
- `Config.reasoning_effort` (low | medium | high | xhigh | max, Anthropic's
vocabulary), config.toml / workspace / `COWORKER_REASONING_EFFORT`,
validated; unset sends nothing so existing requests are unchanged.
- `build_engine` threads it through `model_settings` like `max_tokens`.
- providers/effort.py: the level→parameter tables and the nearest-supported
rule (ties go up). Anthropic adaptive models get `output_config.effort`
(per-model support from the effort doc, read 2026-09-08); budget-thinking
models get `thinking.budget_tokens` (2,048 / 8,192 / 16,000 / 24,000 /
32,000, max_tokens floored above); OpenAI-compatible endpoints get
`reasoning_effort` (Kimi K3: low/high/max verified; others the OpenAI
vocabulary). Gemini, Bedrock, Responses: not sent, recorded as such.
- Fallback: an endpoint that rejects the parameter (400 naming it) gets the
request once more without it; the model is remembered for the run.
- Record: `AssistantTurn.effort` → `reasoning_effort` sidecar on every
assistant message and on the ASSISTANT_MESSAGE event: {requested,
effective, param, note}; stripped before provider calls. When a level is
configured but the provider reports nothing, the record says so.
- docs/config.example.toml documents the key.
Tests: tests/test_reasoning_effort.py, 40 cases (levels, config layering and
rejection, build_engine plumbing, mapping tables incl. every curated model at
every level, Anthropic complete/stream/budget/fallback/unrelated error,
OpenAI-compatible unset/mapped/fallback, engine record and outbound strip).
Every provider capped each reply with a hard-coded constant (32,000 for the
Anthropic and OpenAI-compatible clients, 4,096 for Bedrock) that no config,
environment variable or CLI option could change, although `build_engine(...,
model_settings=)` already spread settings into every provider call and every
provider used `setdefault("max_tokens", ...)`. Now:
- `Config.max_output_tokens` (config.toml, workspace-overridable; env override
`COWORKER_MAX_OUTPUT_TOKENS`), validated as a positive integer; unset keeps
every provider's default byte-for-byte.
- `build_engine` folds it into `model_settings["max_tokens"]` unless the caller
passed an explicit value; explorer subagents inherit it.
- `AssistantTurn.output_limit`: the ceiling the provider actually sent, after
the Anthropic budget-thinking floor (which now logs a warning when it
overrides a configured value) or the OpenAI `max_completion_tokens` rename.
- The engine persists it on the assistant message as the `max_output_tokens`
sidecar and on the ASSISTANT_MESSAGE event, stripped before provider calls.
- Bedrock keeps 4,096 with a comment on why; the config key raises it.
- docs/config.example.toml documents the key.
Tests: tests/test_max_output_tokens.py (config layering, env override,
validation, build_engine plumbing, Anthropic complete/stream + floor warning,
OpenAI complete/stream + rename retry, engine record).
Imported from andrewyng/aisuite@1b4bbf303e
(contents of its platform/ directory, hoisted to the repo root).
Development history prior to this commit lives in that repository.
Co-authored-by: Devika <devikaverma11@gmail.com>