pi-lemonade-link 1.1.0 → 2.0.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.
package/README.md CHANGED
@@ -10,16 +10,19 @@ No hardcoded endpoints, no manual model lists. One extension, five capabilities:
10
10
  1. **Live model discovery** — every chat model your lemonade box advertises shows
11
11
  up in `/model` automatically, annotated with whether it's loaded right now.
12
12
  2. **Nine agent tools** — transcription, image generation/editing/upscaling,
13
- text-to-speech, music/SFX, 3D meshes, and text classification, all callable
13
+ text-to-speech (incl. voice cloning + voice design), music/SFX, 3D meshes,
14
+ and text classification (fixed-label + zero-shot), all callable
14
15
  by the LLM, all model-aware.
15
16
  3. **A setup menu** — `/lemonade-setup` opens a navigable TUI for status,
16
- discovery, configuration, model management (live-progress pulls, Hugging
17
- Face installs), and live log streaming.
17
+ discovery, configuration, a live model browser (inline status, type-to-
18
+ search, contextual actions, animated busy markers with Esc-to-detach),
19
+ download-job management, recipe-backend installs, model updates, Hugging
20
+ Face installs, and live log streaming.
18
21
  4. **A lemonade status bar** — while a lemonade model is active, an extra
19
22
  below-editor row appears (your footer is never touched): instance name,
20
23
  tok/s and prefix-cache hit % derived locally from the session's own
21
- messages, plus polled busy/queue, CPU/GPU/NPU and VRAM from the active
22
- instance.
24
+ messages, plus polled busy/queue, whole-box active requests + live tok/s,
25
+ CPU/GPU/NPU and VRAM from the active instance.
23
26
  Switching to a non-lemonade model removes the row.
24
27
  5. **Harness self-awareness** — every chat, including virgin ones, is told
25
28
  where its lemonade machinery lives, so the agent can operate it directly.
@@ -186,7 +189,7 @@ Per tool:
186
189
  | `upscale_image` | Image → 4x PNG | arg → `defaultUpscaleModel` (RealESRGAN-x4plus) | PNG on disk + path | needs an upscale model pulled on the server; `-anime` variant exists for art. Sends the image as base64 JSON, not multipart |
187
190
  | `text_to_speech` | Text → spoken audio | arg → first model labeled `tts` (OpenMOSS-TTS on current builds) | mp3/wav on disk + path | if the TTS model isn't pulled, the request can trigger a slow auto-pull that outlasts the request — pull it via the setup menu first. `voice`/`speed`/`response_format` supported |
188
191
  | `generate_audio` | Prompt → music / SFX | arg → first model labeled `music`/`sfx`/`audio` | wav on disk + path | ACE-Step for music (optional `lyrics` with `[verse]`/`[chorus]` tags = sung vocals; omit = instrumental), ThinkSound for SFX. Not downloaded by default — pull first |
189
- | `classify_text` | Text → ranked label confidences | arg → `defaultClassifierModel` → first catalog model with the `onnxruntime` recipe | inline text readout | encoder classifiers (phishing, PII, prompt-injection...) — millisecond inference in its own classification slot; scores returned highest-first, so the top line is the verdict. Pull classifiers via the setup menu or HF install |
192
+ | `classify_text` | Text → ranked label confidences | arg → `defaultClassifierModel` → first catalog model with the `onnxruntime` recipe (or a `zero-shot` decision model when `labels` is passed) | inline text readout | fixed-label encoder classifiers (phishing, PII, prompt-injection — their label set is baked in) and zero-shot decision models (labels sent per request); scores returned highest-first, so the top line is the verdict. Pull classifiers via the setup menu or HF install |
190
193
  | `generate_3d_model` | Image → textured `.glb` | arg → first model labeled `3d` (TRELLIS-3D) | .glb on disk + path | minutes per mesh; `resolution` 512/1024/1536; needs TRELLIS pulled. TUI cannot render it — open the file in a 3D viewer |
191
194
 
192
195
  **How `classify_text` handles multiple classifiers and modalities.** Each
@@ -278,8 +281,9 @@ and the normal menu takes over once the first instance exists.
278
281
  | Menu | What you can do |
279
282
  |---|---|
280
283
  | **Server status** | The complete state of the box, grouped by the endpoint each metric came from — every server metric flat on one **live** panel that re-fetches every `statusPollMs` (default 2 s) while open, with each snapshot timestamped in the header; a transient fetch failure keeps the last good snapshot. Scrollable (wrap-aware `↑↓/j/k/pgup/pgdn/home/end` scrolling + mouse wheel, `q`/`esc`/`enter` return; position indicator in the footer). With multiple instances configured, `n`/`p` cycles between boxes without leaving the view — the title names the instance shown, and the menu's active instance follows it on exit. Sections: `/v1/health` (loaded models with busy/streaming/backend-health/pid/slot-pool, per-type slot limits, pinned counts, telemetry state), `/v1/system-stats` (CPU/RAM used-total-%, GPU, VRAM, NPU), `/v1/stats` (last-request tok/s, TTFT, in/out tokens, prefix-cache hit rate, lifetime token/request counters, routing decisions), `/v1/system-info` (CPU cores/threads, OS, GPU/NPU inventory incl. NPU power mode and TOPS, model-storage drive usage), and `/metrics` (llama.cpp backend: request queue depth, busy slots per decode, peak sequence length). Each section degrades to an "(unreachable)" line independently — one dead endpoint never blanks the panel |
281
- | **Server settings** | Discover servers (UDP beacon + HTTP fallback), edit base URL, edit API key, test connection |
282
- | **Model management** | List catalog (including not-yet-downloaded registry entries), load / unload, pull (download) with live progress + esc-to-cancel, install from Hugging Face (search → pick variant → install as `user.*`), delete, change context size (unload → reload with `ctx_size`, saved), toggle chat-only filter, refresh provider |
284
+ | **Server settings** | Discover servers (UDP beacon + HTTP fallback), edit base URL, edit API key, edit admin key (for `/internal/*`: pin, bulk model sync), test connection |
285
+ | **Model management** | **Model browser**: one live list of every model — downloaded or not — with inline status (`●` loaded · `○` downloaded · `◌` not on disk · `↓` downloading % · `⤴` update available · `★` featured); **type to search** (substring over name + description, `⌫` edits, `esc` clears the filter first), `ctrl+t` toggles all ⇄ downloaded-only, and the list refreshes underneath you every ~2 s. Selecting a model opens its **contextual actions**: view details (checkpoints, launch command, load state), load (animated busy marker with live server-side load status, `esc` continues in background), unload, pin/unpin, pull / update (live progress + esc-cancel), recipe-options editor, delete (typed phrase). Plus: **Downloads** (server-owned job list — live, cancel/pause/remove/retry, bulk-clear stopped jobs; terminal jobs are auto-removed so they never linger), **Install from Hugging Face** (search → pick variant → install as `user.*`), **Check for model updates** (report, then bulk sync via the admin key or update one-by-one with plain pulls), chat-only filter toggle, refresh provider |
286
+ | **Backends** | The recipe × backend inventory from system-info (installed / installable / unsupported, tier, version) — install with dry-run preview + live download progress, uninstall, `ctrl`-free type-to-search across every recipe:backend. Guest-tier note: models whose recipe has only guest backends stay hidden from the catalog until one is installed |
283
287
  | **Transcription settings** | Default Whisper model, endpoint path, smoke-test a file |
284
288
  | **Live server logs** | WebSocket stream of the server's log: full snapshot backlog (up to 5000 entries) then live entries as they happen; Esc to close |
285
289
  | **Spec & version check** | The three drift tiers, interactive: docs-vs-upstream status (TUI-only), live per-instance server versions beside the verified build and the latest upstream release, re-check now, one-keystroke docs re-sync (re-downloads upstream docs into the extension's docs/ folder — the code is not updated), `specCheck` / `serverVersionCheck` / `upstreamVersionCheck` toggles |
@@ -289,9 +293,14 @@ Notes on the destructive and slow paths:
289
293
  - **Delete** requires two gates: a confirm dialog, then typing the exact phrase
290
294
  `i want to delete <model-id>` — three attempts allowed, each prompt shows
291
295
  chances remaining, and Esc aborts immediately.
292
- - **Change context size** prefills the model's *current* context (from live
293
- health), accepts `32k`, `1m`, or raw token counts, and warns that the model
294
- is unloaded and reloaded (the new `ctx_size` is saved for future loads).
296
+ - **Change context size / recipe options** is a per-model editor over
297
+ `GET/POST/DELETE /v1/models/{id}/options`: every option key with its
298
+ saved/effective/default values side by side; edits save immediately
299
+ (merge — untouched keys keep their values; empty/`auto` clears a key,
300
+ `ctx_size: -1` = auto-size, backend keys get a menu of what this system
301
+ supports), and a loaded model is offered a reload to apply. Works on
302
+ unloaded models too — the options take effect at the next load. The old
303
+ unload → reload-with-ctx hack is retired; this is strictly more capable.
295
304
  - **Pull** uses lemonade's server-owned download jobs: a live progress view
296
305
  (percent, bytes, per-file status, updated every second) with **Esc to cancel**
297
306
  (via `/v1/downloads/control`). Blocking pull is kept only as a fallback for
@@ -402,17 +411,18 @@ The full shape (values shown are the built-in defaults):
402
411
  |---|---|
403
412
  | `servers` | **Required** — the only instance store: `[{ "name", "baseUrl", "apiKey"?, "description"? }]`. May be empty on a fresh install (the first `/lemonade-setup` run offers a wizard); the FIRST entry is the default instance (targeted when tools' `server` argument is omitted); reordering changes the default. Each registers as a `lemonade-<name>` provider. |
404
413
  | `apiKey` | Shared fallback `Authorization: Bearer …` for instances without their own. A dummy value works for auth-less servers (pi requires non-empty auth to list models). |
405
- | `*Path` | API endpoint paths, in case a future lemonade changes them. |
414
+ | `adminApiKey` | Key for `/internal/*` endpoints (pin/unpin, bulk model sync) on servers that set `LEMONADE_ADMIN_API_KEY`. Empty = fall back to `apiKey`. Per-instance override lives on the server entry, same fallback chain. |
415
+ | `*Path` | API endpoint paths, in case a future lemonade changes them (incl. `modelOptionsPath` with its `{id}` placeholder). |
406
416
  | `chatOnly` | Filter the provider down to chat-capable models. |
407
417
  | `cacheOnOutage` | **Outage cache**: when a probe can't reach an instance, `/model` lists its last good catalog — persisted on every successful probe, provenance-marked `(cached <time>)`, warned at session start, and re-synced automatically (prompt submits, model selections, session starts, plus the status bar's own health poll) with a `+new −gone` diff notice once the box answers. Once an instance is known down (durable flag from the last failed probe), the next startup serves the cached listing **instantly — no probe wait** and reconciles in the background, so the down-box stall only ever bites once per outage, at the transition into it. `false` (default) keeps the fully-honest empty listing. Manage via `/lemonade-setup` → *Catalog cache*; force a re-probe with *Refresh connection*. |
408
- | `defaultTranscriptionModel` / `defaultImageModel` / `defaultUpscaleModel` / `defaultClassifierModel` | Fixed model ids for the tools. Empty = auto-pick from the live catalog (by label, or by `onnxruntime` recipe for classifiers). |
418
+ | `defaultTranscriptionModel` / `defaultImageModel` / `defaultUpscaleModel` / `defaultClassifierModel` | Fixed model ids for the tools. Empty = auto-pick from the live catalog (by label; classifiers prefer `onnxruntime` encoders, or `zero-shot`-labeled decision models when `labels` is passed). |
409
419
  | `outputDir` | Where generated files (images, audio, meshes) are saved. Empty = agent's working directory. |
410
420
  | `*TimeoutMs` | Per-operation timeouts. `pullTimeoutMs` only caps the *blocking* pull fallback — normal pulls use download jobs with live progress. |
411
421
  | `statusPollMs` | How often the setup-menu status panel re-fetches while open (live refresh). `0` = static snapshot. |
412
422
  | `statusBar` | Show the below-editor lemonade status bar while a lemonade model is active (see *Lemonade status bar*). |
413
423
  | `barPollMs` | Server-poll cadence for the status bar's busy/queue + CPU/GPU/NPU/VRAM segments. `0` = local metrics only (instance, tok/s, cache-hit %). |
414
424
  | `specCheck` / `specCheckCooldownMs` / `specCheckTimeoutMs` | Docs-freshness check: the `docs/` snapshot is compared against upstream `lemonade-sdk/lemonade` by git blob SHA — **TUI-only status, no startup warning** (extension ↔ server agreement is what matters; see *Keeping the specs honest*); the verdict is durable for `specCheckCooldownMs` (default 24 h, also the upstream-release probe's throttle). |
415
- | `serverVersionCheck` | **Tier 1, startup warning**: `/v1/health` self-reports the server version; any instance reporting a version other than the build this extension was verified against (`v11.7.0` — a constant in the extension code, not a setting) warns **with direction**: server newer → check for an extension update; server older → update the server. |
425
+ | `serverVersionCheck` | **Tier 1, startup warning**: `/v1/health` self-reports the server version; any instance reporting a version other than the build this extension was verified against (`v2026.46.2` — a constant in the extension code, not a setting; dev builds like `2026.46.2~1719.034d3f52` count as their release) warns **with direction**: server newer → check for an extension update; server older → update the server. |
416
426
  | `upstreamVersionCheck` | **Tier 2, info notice**: servers older than the latest published lemonade release (probed via GitHub, throttled) get a one-line "a server update is available" notice — **deduplicated to once per (instance, release)**, so it never re-fires on every session for the same release; the TUI always shows current state. Default on; separately toggleable. |
417
427
 
418
428
  ## Offline & unreachable networks
@@ -545,6 +555,8 @@ uses:
545
555
  | [`docs/README.md`](./docs/README.md) | Spec index and design philosophy |
546
556
  | [`docs/openai.md`](./docs/openai.md) | OpenAI-compatible surface: chat/completions, embeddings, audio (transcription, speech, generations), images (generation/edit/variation/upscale), realtime, `/v1/models` + labels taxonomy |
547
557
  | [`docs/lemonade.md`](./docs/lemonade.md) | Lemonade-specific surface: load/unload/pull/delete, download jobs + control, registry search + pull variants, health/stats/system-stats/system-info, classify, audio/3D generation, log streaming, job engine, install/uninstall |
558
+ | [`docs/router.md`](./docs/router.md) | Router API: `collection.router` models and routing policies |
559
+ | [`docs/internal.md`](./docs/internal.md) | Internal API: aliases, model sync, telemetry — used by the desktop app; versioned separately from the public surface |
548
560
  | [`docs/mcp.md`](./docs/mcp.md) | The MCP gateway (lemonade as an MCP server) |
549
561
  | [`docs/ollama.md`](./docs/ollama.md), [`docs/anthropic.md`](./docs/anthropic.md), [`docs/llamacpp.md`](./docs/llamacpp.md) | Other compatibility surfaces (rerank, slots, etc.) |
550
562
 
@@ -562,7 +574,7 @@ Drift is watched **in tiers, ordered by what actually matters at runtime**:
562
574
 
563
575
  1. **Extension ↔ server sync (startup warning).** Every registration and
564
576
  refresh compares each instance's live `/v1/health` version against the
565
- build this extension was verified against (`v11.7.0` — a constant in the
577
+ build this extension was verified against (`v2026.46.2` — a constant in the
566
578
  extension code, **not a user setting**: it is a property of the code,
567
579
  updated with each extension release). A mismatch is the one signal that
568
580
  means *endpoints may have changed for this pairing*, so it warns —
@@ -573,7 +585,7 @@ Drift is watched **in tiers, ordered by what actually matters at runtime**:
573
585
  default, separately toggleable).** The latest published lemonade release
574
586
  is probed via GitHub (throttled, durable, silent on network failure); any
575
587
  server older than it gets a single info line — *"instance 'x' runs
576
- lemonade v11.7.0; the latest published release is v11.9.0 — a server
588
+ lemonade v2026.44.1; the latest published release is v2026.46.2 — a server
577
589
  update is available."* Much lower tier: an older server isn't broken,
578
590
  it's just behind. The notice is **deduplicated to once per (instance,
579
591
  release)** — it fires when a new upstream release first appears, never
@@ -599,7 +611,7 @@ release.
599
611
  ## Extension version & provider API
600
612
 
601
613
  This extension's version (`version` in `package.json`) and the lemonade
602
- server build it was verified against (`11.7.0`) are recorded together in
614
+ server build it was verified against (`2026.46.2`) are recorded together in
603
615
  the `provider` block of `package.json` and in the
604
616
  `EXTENSION_CONFIRMED_SERVER_VERSION` constant in `index.ts` (which drives
605
617
  the startup version-drift warning). The server status panel and the
@@ -623,8 +635,10 @@ and server-version checks (see *Keeping the specs honest*) are what catch
623
635
 
624
636
  ## Lemonade behavior reference
625
637
 
626
- Empirically confirmed against lemonade 11.7.0 (cross-checked with the
627
- [official endpoint spec](https://lemonade-server.ai/docs/api/)):
638
+ Empirically confirmed against lemonade 2026.46.2 (cross-checked with the
639
+ [official endpoint spec](https://lemonade-server.ai/docs/api/) — which the
640
+ server now also serves itself at `GET /v1/docs`, so the running build's
641
+ reference is always one curl away):
628
642
 
629
643
  - **Auto-loading.** A request for an unloaded model triggers an automatic load
630
644
  attempt. If the model's slot is free or holds an unpinned model, lemonade
@@ -634,8 +648,27 @@ Empirically confirmed against lemonade 11.7.0 (cross-checked with the
634
648
  - **Per-type slots.** The server holds one slot per model type (llm,
635
649
  transcription, image, embedding, …), so Whisper can be loaded alongside your
636
650
  chat model.
637
- - **change-ctx.** Implemented as unload → reload with `ctx_size` +
638
- `save_options: true`, which persists the choice for future loads.
651
+ - **change-ctx & friends.** Per-model recipe options (ctx size, backend,
652
+ args, evict timeouts) are edited through `/v1/models/{id}/options` — saved
653
+ without loading, merged per key, applied to a loaded model by a plain
654
+ reload (`POST /v1/load` reloads a model whose load-time options changed).
655
+ - **Pinning.** `POST /internal/pin` flips a loaded model's pinned flag in
656
+ place (no reload); it demands `LEMONADE_ADMIN_API_KEY` when the server sets
657
+ one — configure `adminApiKey` or every pin attempt fails with an actionable
658
+ admin-key message.
659
+ - **Model updates.** `POST /v1/models/check-updates` reports newer upstream
660
+ commits (plain key); updating is either a bulk `/internal/models/sync`
661
+ (admin key) or plain per-model re-pulls. Re-pulling a model with a stale
662
+ errored job RESUMES the job (status flips back to `downloading`) — verified
663
+ live.
664
+ - **Download-job hygiene.** The server keeps errored/cancelled jobs in
665
+ `GET /v1/downloads` until a client removes them; this extension now removes
666
+ the ones it drove to a terminal outcome (and offers bulk-clear in the
667
+ Downloads view), so dead jobs no longer linger forever.
668
+ - **Backends.** `GET /v1/system-info` reports the full recipe × backend matrix
669
+ (state: installed/installable/unsupported, tier, version, format);
670
+ `POST /v1/install` (+`/dry-run`) and `/v1/uninstall` manage them, and
671
+ installs flow through the same `/v1/downloads` job machinery as pulls.
639
672
  - **Status panel sources.** All five metric endpoints are live-confirmed:
640
673
  `/v1/health` (incl. per-model `is_busy`/`is_streaming`/`backend_health`/
641
674
  `slot_pool`/`residency_class`/`last_use`/`pid` and `pinned_models` counters),
package/docs/README.md CHANGED
@@ -18,5 +18,28 @@ This spec details all supported endpoints. It is organized into pages that corre
18
18
  | [MCP Gateway](./mcp.md) | Use this to expose Lemonade as a Model Context Protocol server (POST /mcp). |
19
19
  | [llama.cpp-Specific API](./llamacpp.md) | Reference for llama.cpp-specific compatibility and conventions. |
20
20
  | [Lemonade-Specific API](./lemonade.md) | Local-first API for managing lifecycle, configuration, backends, etc. |
21
+ | [Router API](./router.md) | How `collection.router` models route requests, and how to test a routing policy. |
22
+ | [Internal API](./internal.md) | Control endpoints for clients bundled with the server, secured by `LEMONADE_ADMIN_API_KEY`. |
21
23
 
22
24
  A running server also serves these pages itself: [`GET /v1/docs`](./lemonade.md#get-v1docs) lists what it has and [`GET /v1/docs/{page}`](./lemonade.md#get-v1docspage) returns one, so the reference always matches the installed version and stays available offline.
25
+
26
+ ## Authentication
27
+
28
+ When `LEMONADE_API_KEY` is set, clients send it in the `Authorization` header as a Bearer token:
29
+
30
+ ```bash
31
+ curl http://localhost:13305/v1/models -H "Authorization: Bearer $LEMONADE_API_KEY"
32
+ ```
33
+
34
+ Each route says whether it needs a key. The internal routes take `LEMONADE_ADMIN_API_KEY` when it is set, and `LEMONADE_API_KEY` otherwise; the admin key also works on every other route. Lemonade reads no other header, so an Anthropic SDK client passes the key as `auth_token`, not `api_key`. The WebSocket APIs take the key as an `api_key` query parameter instead. See [API Key and Security](../guide/configuration/README.md#api-key-and-security) for every combination of the two keys.
35
+
36
+ ## Errors
37
+
38
+ Each route lists the errors it answers with in its Errors table. These come from the server before a request reaches a route, so no route lists them:
39
+
40
+ | Status | Body | When |
41
+ |--------|------|------|
42
+ | `401` | `{"error": "Invalid or missing API key"}`, or `"Invalid or missing admin API key"` for an internal route | The request lacks the key its route needs |
43
+ | `403` | `{"error": "Origin not allowed"}` | The `Origin` header names an origin that [`allowed_origins`](../guide/configuration/README.md) does not allow |
44
+ | `404` | `{"error": {"message": "The requested endpoint does not exist", "type": "not_found", "path"}}` | No route matches the path |
45
+ | `405` | `{"error": "Method Not Allowed. Use POST for this endpoint"}` | A `GET` reaches a `POST`-only route under `/v0/`, `/v1/`, `/api/v0/` or `/api/v1/` |
package/docs/anthropic.md CHANGED
@@ -1,11 +1,188 @@
1
1
  # Anthropic-Compatible API
2
2
 
3
- Lemonade supports an initial Anthropic Messages compatibility endpoint for applications that call Claude-style APIs.
3
+ Lemonade serves the Anthropic Messages API for applications that call Claude-style APIs.
4
4
 
5
- | Endpoint | Status | Notes |
6
- |----------|--------|-------|
7
- | `POST /v1/messages` | Supported | Supports both streaming and non-streaming. Query params like `?beta=true` are accepted. |
5
+ <!-- BEGIN GENERATED: anthropic.summary -->
6
+ | Method | Endpoint | Description |
7
+ |--------|----------|-------------|
8
+ | `POST` | [`/v1/messages`](#post-v1messages) | Generate the next assistant message |
9
+ <!-- END GENERATED: anthropic.summary -->
8
10
 
9
- Current scope focuses on message generation parity for common fields (`model`, `messages`, `system`, `max_tokens`, `temperature`, `stream`, and basic `tools`). Unsupported or unimplemented Anthropic-specific fields are ignored and surfaced via warning logs/headers.
11
+ <!-- BEGIN GENERATED: anthropic.messages -->
12
+ ## `POST /v1/messages`
13
+ <sub>![Status](https://img.shields.io/badge/status-partially_available-yellow)</sub>
10
14
 
11
- Those limits apply only where Lemonade converts to and from the OpenAI shape. A cloud provider registered with `--wire-format anthropic` is relayed unconverted, so no field is dropped — see [Cloud Offload](../guide/configuration/cloud.md#providers-that-speak-the-anthropic-messages-format).
15
+ Generates the next assistant message for a conversation in the Anthropic Messages format.
16
+
17
+ Requires `LEMONADE_API_KEY` when it is set.
18
+
19
+ ### Parameters
20
+
21
+ | Parameter | Required | Description | Status |
22
+ |-----------|----------|-------------|--------|
23
+ | `model` | Yes | The model to run; loaded on first use. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
24
+ | `messages` | Yes | Conversation so far, as `user` and `assistant` messages. `content` is a string or an array of `text`, `image` (base64 source), `tool_use` and `tool_result` blocks. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
25
+ | `system` | No | System prompt, as a string or an array of `text` blocks. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
26
+ | `max_tokens` | No | Upper bound on generated tokens. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
27
+ | `temperature` | No | Sampling temperature. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
28
+ | `top_p` | No | Cumulative probability of the top tokens to consider during nucleus sampling, from `0.0` to `1.0`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
29
+ | `top_k` | No | Number of top tokens to consider during sampling. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
30
+ | `stop_sequences` | No | Sequences where generation stops. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
31
+ | `stream` | No | `true` sends the response as server-sent events as it progresses; `false` sends one response once complete. Defaults to `false`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
32
+ | `tools` | No | Tools the model may call, each with a `name`, `description` and `input_schema`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
33
+ | `tool_choice` | No | `{"type": "auto"}`, `any`, `none`, or `tool` with a `name`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
34
+ | `output_config` | No | `format` of type `json_schema` (with a `schema`) or `json_object` constrains the reply. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
35
+ | `thinking` | No | Not applied to local models: reasoning models think regardless. Qwen3 models skip their reasoning when the prompt ends with `/no_think`. | <sub>![Status](https://img.shields.io/badge/not_available-red)</sub> |
36
+ | `metadata` | No | Ignored for local models, with a warning. | <sub>![Status](https://img.shields.io/badge/not_available-red)</sub> |
37
+ | `context_management` | No | Ignored for local models, with a warning. | <sub>![Status](https://img.shields.io/badge/not_available-red)</sub> |
38
+ | `ctx_size` | No | Lemonade extension: context size to load the model with, when this request loads it. Ignored when the model is already loaded. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
39
+ | `beta` (query) | No | Accepted for Anthropic SDK compatibility. Values other than `true` add a warning; `true` is passed on to providers that are relayed. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
40
+
41
+ Lemonade runs the request as an OpenAI chat completion and converts both ways. Some values it cannot convert, such as an unsupported content block type or `metadata`, are ignored and reported in the `X-Lemonade-Warning` header (joined with ` | `) and in a `warnings` array. Unknown fields are ignored without a warning. A cloud provider registered with `--wire-format anthropic` is relayed unconverted, so nothing is dropped; see [Cloud Offload](../guide/configuration/cloud.md#providers-that-speak-the-anthropic-messages-format).
42
+
43
+ Errors use Anthropic's shape, `{"type": "error", "error": {"type", "message"}}`.
44
+
45
+ ### Examples
46
+
47
+ #### Non-streaming
48
+
49
+ === "PowerShell"
50
+
51
+ ```powershell
52
+ Invoke-WebRequest `
53
+ -Uri "http://localhost:13305/v1/messages" `
54
+ -Method POST `
55
+ -Headers @{ "Content-Type" = "application/json" } `
56
+ -Body '{
57
+ "model": "Qwen3-0.6B-GGUF",
58
+ "max_tokens": 64,
59
+ "temperature": 0,
60
+ "messages": [{"role": "user", "content": "What is the capital of France? /no_think"}]
61
+ }'
62
+ ```
63
+
64
+ === "Bash"
65
+
66
+ ```bash
67
+ curl http://localhost:13305/v1/messages \
68
+ -H "Content-Type: application/json" \
69
+ -d '{
70
+ "model": "Qwen3-0.6B-GGUF",
71
+ "max_tokens": 64,
72
+ "temperature": 0,
73
+ "messages": [{"role": "user", "content": "What is the capital of France? /no_think"}]
74
+ }'
75
+ ```
76
+
77
+ **Response:** `200 OK`
78
+
79
+ ```json
80
+ {
81
+ "id": "chatcmpl-e1cbsIyQh8RNvDa8IFa7hUsiL7xxgEmv",
82
+ "type": "message",
83
+ "role": "assistant",
84
+ "model": "Qwen3-0.6B-GGUF",
85
+ "content": [{"type": "text", "text": "The capital of France is **Paris**."}],
86
+ "stop_reason": "end_turn",
87
+ "stop_sequence": null,
88
+ "usage": {"input_tokens": 19, "output_tokens": 14}
89
+ }
90
+ ```
91
+
92
+ #### Streaming
93
+
94
+ === "PowerShell"
95
+
96
+ ```powershell
97
+ Invoke-WebRequest `
98
+ -Uri "http://localhost:13305/v1/messages" `
99
+ -Method POST `
100
+ -Headers @{ "Content-Type" = "application/json" } `
101
+ -Body '{
102
+ "model": "Qwen3-0.6B-GGUF",
103
+ "max_tokens": 64,
104
+ "temperature": 0,
105
+ "messages": [{"role": "user", "content": "What is the capital of France? /no_think"}],
106
+ "stream": true
107
+ }'
108
+ ```
109
+
110
+ === "Bash"
111
+
112
+ ```bash
113
+ curl http://localhost:13305/v1/messages \
114
+ -H "Content-Type: application/json" \
115
+ -d '{
116
+ "model": "Qwen3-0.6B-GGUF",
117
+ "max_tokens": 64,
118
+ "temperature": 0,
119
+ "messages": [{"role": "user", "content": "What is the capital of France? /no_think"}],
120
+ "stream": true
121
+ }'
122
+ ```
123
+
124
+ **Response:** `200 OK`
125
+
126
+ ```text
127
+ event: message_start
128
+ data: {"type": "message_start", "message": {"content": [], "id": "chatcmpl-VoeIi1EHhQg4HDI3S7ehBxKOoUCjX2DI", "model": "Qwen3-0.6B-GGUF", "role": "assistant", "stop_reason": null, "stop_sequence": null, "type": "message", "usage": {"input_tokens": 0, "output_tokens": 0}}}
129
+ event: content_block_start
130
+ data: {"type": "content_block_start", "index": 0, "content_block": {"text": "", "type": "text"}}
131
+ event: content_block_delta
132
+ data: {"type": "content_block_delta", "index": 0, "delta": {"text": "The", "type": "text_delta"}}
133
+ ...
134
+ event: message_delta
135
+ data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence": null}, "usage": {"input_tokens": 0, "output_tokens": 0}}
136
+ event: message_stop
137
+ data: {"type": "message_stop"}
138
+ ```
139
+
140
+ ### Response format
141
+
142
+ #### JSON
143
+
144
+ - `id` - The message's ID.
145
+ - `type` - Always `message`.
146
+ - `role` - Always `assistant`.
147
+ - `model` - The model that generated the message.
148
+ - `content` - The message's content blocks.
149
+ - `type` - `text` or `tool_use`. A relayed provider can add its own block types, such as `thinking`.
150
+ - `text` - In a `text` block: the text.
151
+ - `id` - In a `tool_use` block: the tool call's ID.
152
+ - `name` - In a `tool_use` block: the tool's name.
153
+ - `input` - In a `tool_use` block: the call's arguments.
154
+ - `stop_reason` - `end_turn`, `max_tokens` or `tool_use`.
155
+ - `stop_sequence` - The stop sequence that ended the message; always `null` for local models.
156
+ - `usage` - Token counts.
157
+ - `input_tokens` - Prompt tokens.
158
+ - `output_tokens` - Generated tokens.
159
+ - `warnings` - What Lemonade ignored or changed while converting; present only when there is something to report.
160
+
161
+ #### Event stream
162
+
163
+ - `type` - Matches the event's name: `message_start`, `content_block_start`, `content_block_delta`, `content_block_stop`, `message_delta`, `message_stop` or `error`. A relayed provider can also send `ping`.
164
+ - `message` - In `message_start`: the message, with empty `content` and zero `usage`.
165
+ - `index` - In `content_block_start`, `content_block_delta` and `content_block_stop`: the block's position in the message's `content`.
166
+ - `content_block` - In `content_block_start`: the block, with empty `text` or `input`.
167
+ - `delta` - In `content_block_delta`: the block's next `text_delta` text or `input_json_delta` partial JSON. In `message_delta`: the `stop_reason` and `stop_sequence`.
168
+ - `usage` - In `message_delta`: token counts. Both are `0` when the backend's stream carries no usage, as with llama.cpp.
169
+ - `warnings` - In `message_delta`: what Lemonade ignored while converting; present only when there is something to report.
170
+ - `error` - In `error`, sent when the backend or provider fails after the stream started: the error's `type` and `message`.
171
+
172
+ ### Errors
173
+
174
+ | Status | Code | When |
175
+ |--------|------|------|
176
+ | `400` | `invalid_json` | The body is not a JSON object |
177
+ | `400` | `missing_argument` | A required argument is missing |
178
+ | `400` | `invalid_argument` | An argument or a value nested in it has the wrong JSON type, or a value its schema does not list |
179
+ | `400` | | `model` is a cloud model whose `--wire-format anthropic` provider has an `http://` base URL and was not installed with `--allow-insecure-http` |
180
+ | `401` | | `model` is a cloud model whose `--wire-format anthropic` provider has no API key |
181
+ | `404` | | `model` fails to load for any reason other than a residency conflict, such as naming no model or a failed download |
182
+ | `409` | `router_residency_conflict` | Loading the requested model would evict a model that a `collection.router` model needs resident on the same NPU |
183
+ | `500` | | `model` is a cloud model whose `--wire-format anthropic` provider has no base URL |
184
+ | `500` | | `model` is a `--wire-format anthropic` cloud model with no `checkpoint` |
185
+ | `500` | | The backend reports an error; the backend's own status replaces this one when it sends one |
186
+ | `500` | | The request fails unexpectedly |
187
+ | `502` | | Without `stream`, the relayed cloud request fails or the provider answers with an error; the provider's own status and body replace this one when it answers |
188
+ <!-- END GENERATED: anthropic.messages -->