v0.9.0
Added
-
Live compilation progress — the compiler now emits structured
CompilationEvents (rote.compiler.events): phase transitions
(driven byprogress.ndjsonmarkers the compiler skill writes at
the start of each phase), per-turn token counts, tool calls, and
artifacts.rote compilerenders them live on stderr; hosts embed
the stream viaCompiler(on_event=...). Works across the Claude
subprocess driver (stream-json) and both in-process API drivers. -
OpenAI-compatible API driver (
--agent openai-api) — the same
in-process compilation loop against any OpenAI-shaped endpoint
(GPT, GLM, Kimi, …), sharing one filesystem-tool surface with the
Anthropic driver. -
Gateway-friendly driver auth — both API drivers accept
base_urlanddefault_headers(through the new
Compiler(driver_kwargs=...)), so compilations can route through
proxies like Cloudflare AI Gateway with no provider key in the
environment. -
Compiler.compile()acceptsextra_instructions, appended to the
compiler skill prompt (e.g. pinning emitted judge calls to a
specific runtime client). -
The Cloudflare adapter emits
manifest.jsonat the runtime-dir
root — machine-readable pipeline identity (name, version, pipeline
hash, class name, node ids, entry) for deploy tooling; regex
fallback retained for older emits. -
rote.eval.build_scorecard_foris now public API (was a CLI
private). -
Cloudflare Workers call MCP tools, authenticated by provisioning
— Workers have no filesystem for the token store, so
rote mcp export <server>turns a completedrote mcp logininto
Worker secrets (dotenv form for.dev.vars,--jsonfor
npx wrangler secret bulk). MCP-bound nodes emit working calls
through a Workers helper that mints access tokens at runtime via the
OAuth refresh grant and caches them — with rotated refresh tokens —
in aROTE_MCP_TOKENSKV namespace declared in the emitted
wrangler.jsonc. The Env interface,.dev.vars.example, and
README document the per-server provisioning surface. Emitted output
typechecks against@cloudflare/workers-typesv5 + the MCP SDK. -
Node TypeScript runtimes call MCP tools, authenticated — the
DBOS-TS and Inngest adapters now emit working bodies for
mcp:-bound nodes (previously always throwing stubs): the module
calls the tool via the official@modelcontextprotocol/sdk(^1.29)
through an emittedsrc/extracted/_roteMcp.tshelper that reads the
same rote registry/token store the CLI writes, refreshes stale access
tokens with a refresh-token grant against the stored
token_endpoint, writes rotated refresh tokens back atomically, and
retries once on 401.--backend apikeeps the direct-vendor-SDK
stubs. Proven end-to-end across languages: Pythonrote mcp login
seeds the store, compiled TS authenticates, refreshes a forced-stale
token, and rotates credentials Python reads back
(tests/test_mcp_ts_e2e.py). -
A full MCP client with OAuth 2.1 (
rote mcp, design in
docs/mcp-client.md) — real streamable-HTTP MCP
servers authenticate with OAuth; without a client that can run the
flow, store tokens durably, and refresh them, MCP-backed workflows
only worked against unauthenticated servers:rote mcp add / list / remove— a user-level server registry
(~/.config/rote/mcp.json, 0600) mapping the logical server names
pipelines carry in theirmcp:bindings to endpoints, with
pre-registeredclient_id/client_secretsupport for servers
without dynamic client registration (Slack/GitHub-class) and static
headers for API-key schemes.rote mcp login— the full spec dance (protected-resource
discovery, PKCE, dynamic client registration, refresh) via
fastmcp's OAuth provider, persisting into a rote-owned token store
(one 0600 JSON file per server,~/.local/share/rote/mcp-tokens/)
whose layout is a documented cross-language contract.
--no-browserprints the authorization URL for SSH boxes.rote mcp headers— mints a currently-valid Authorization header
(auto-refreshing through the stored refresh token), the
machine-facing token API.- Emitted DBOS apps authenticate: MCP-backed steps now open the
client through an emittedextracted/_rote_mcp.pyhelper (the
verbatim source ofrote.mcp._runtime_helper— one tested
implementation) that resolves endpoints (env > registry > IR) and
credentials (OAuth store > static headers > none) at runtime, with
in-place token refresh. Emitted apps still never import rote. eval --runtrials authenticate: the generated--mcp-config
injects registry headers verbatim, or — for logged-in servers — a
headersHelperinvokingrote mcp headers, which Claude Code
re-runs per connection and on 401, so tokens refresh mid-run on
long trials.- Verified end-to-end against a real OAuth-protected server
(tests/test_mcp_oauth_e2e.py): live authorization dance with
dynamic registration, cross-process token reuse, an authenticated
tool call through the emitted helper, and a forced-stale refresh. - New optional extra:
pip install 'rote-cli[mcp]';python -m rote
now works (used by the headersHelper wiring).
Fixed
- The API drivers no longer misread per-turn output truncation
(stop_reason: max_tokens/finish_reason: length) as completion —
the per-turn cap is raised to 32k tokens and the loop continues
automatically with awarningevent. Surfaced by Claude 5 models,
which spend far more of the turn budget on thinking. - The Anthropic driver sets an explicit client timeout sized from the
per-turn token cap (the SDK otherwise refuses non-streaming requests
that may exceed 10 minutes at the new cap). - The Anthropic driver survives
content: nullassistant turns some
gateway endpoints return for all-thinking responses: content is
normalized, empty assistant turns are never replayed into history,
and an empty natural stop nudge-continues with a warning. - Emitted Cloudflare
package.jsonpinned@cloudflare/workers-types
^4, which current wrangler (4.110+) rejects with a peer-dependency
conflict on a fresh install — bumped to ^5.