# provider-github-copilot

> GitHub Copilot subscription provider worker; sign in with GitHub once and the models the plan grants appear in the picker. Implements provider::github-copilot::stream, refresh_models, and a device-flow login surface behind llm-router.

| field | value |
|-------|-------|
| version | 0.1.5-rc.3 |
| type | binary |
| license | Apache-2.0 |
| repo | https://github.com/iii-hq/workers |
| supported_targets | x86_64-apple-darwin, aarch64-apple-darwin, x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-unknown-linux-musl, armv7-unknown-linux-gnueabihf |
| author | iii |

## installation

```sh
iii trigger compose::add worker=provider-github-copilot@0.1.5-rc.3
```

## dependencies

- `state` @ `^0.22.2`
- `llm-router` @ `^1.4.12`

## readme

# provider-github-copilot

GitHub Copilot subscription provider worker behind
[llm-router](https://github.com/iii-hq/workers/tree/main/llm-router): sign in with GitHub once and the
models the subscription grants appear in the model picker. The wire is
OpenAI Chat Completions against the Copilot API endpoint; what makes this
provider different from the api_key providers is the credential lifecycle,
which it owns end to end.

Implements the provider protocol from
`tech-specs/2026-06-agentic/llm-router.md`: `provider::github-copilot::stream`
(SSE chunks → `AssistantMessageEvent` frames into a router-owned channel),
`provider::github-copilot::refresh_models` (live `GET /models`, admitted rows
mapped to catalog records → `router::models::reconcile`), plus a device-flow
sign-in surface (`login::start` / `login::poll`).

## Signing in

```bash
iii trigger provider::github-copilot::login::start
# → { user_code, verification_uri, device_code, interval }
# enter the code at the verification URL, then:
iii trigger provider::github-copilot::login::poll device_code=<device_code>
# → { status: "ok" } — the catalog fills within seconds
```

Machines already signed in through an editor need no login at all: the worker
imports (read-only) `~/.config/github-copilot/apps.json` or pi's auth store.
`GITHUB_COPILOT_NO_LOCAL_IMPORT=1` opts out of that import;
`GITHUB_COPILOT_OAUTH_TOKEN` supplies the GitHub OAuth token directly; and
`GITHUB_COPILOT_TOKEN` supplies a ready Copilot bearer (tests, short-lived
dev sessions).

## Behavior

- **Credential lifecycle:** the long-lived GitHub OAuth token (login, env,
  or editor import) is exchanged at `copilot_internal/v2/token` for a
  short-lived Copilot bearer (~25 minutes) that also names the API endpoint.
  The bearer is cached in-memory, refreshed proactively inside a 2-minute
  margin, and invalidated when a stream dies with an auth error — the next
  call re-exchanges instead of failing again. The GitHub token persists in
  iii-state (scope `provider-github-copilot`, key `oauth_token`).
- **Catalog ids are prefixed:** Copilot serves several vendors' models under
  bare ids (`gpt-5.2`, `claude-sonnet-4.6`) that would collide with the
  sibling single-vendor providers. Catalog ids are `copilot/<id>`; the
  prefix is stripped on every upstream call.
- **Admission:** a listing row must be `type: chat`, support `tool_calls`,
  carry a non-`disabled` `policy.state`, and declare `/chat/completions`
  among its endpoints. The editor's internal feature models (preview rows
  with no picker category — search, compaction, exec agents) are dropped
  too. Windows, ceilings, and capability flags come from the listing's
  `capabilities` tree; there is no pricing — a subscription meters in
  premium requests, so records carry no per-token cost and
  `usage.cost_usd` stays unset.
- **Verified, not guessed:** which models a plan may actually call is *not*
  in the listing. Two models can be identical across every field the API
  exposes — same vendor, same `policy: enabled`, same picker category — and
  one answers while the other returns `model_not_supported` (a free or
  educational plan carries the base families but no premium requests).
  Discovery therefore probes each admitted model with a one-token request,
  four at a time, and reconciles only what answered. Verdicts persist for
  24 hours, so a model is probed once and answered from cache after that —
  a refresh runs at boot, on every `router::ready` rebind, and after each
  sign-in, and a probe that *succeeds* on a premium model spends a premium
  request, not just a token. When the TTL lapses everything is re-checked,
  so enabling more models upstream (or changing plan) needs no code change.
- **Self-healing:** if a model refuses between refreshes, the stream returns
  an actionable permanent error, the row is removed from the catalog, and
  the verdict is recorded — so the picker never offers the same dead model
  twice and no further probe is spent on it.
- **`model_picker_enabled` is deliberately ignored.** It reflects an
  editor-side picker preference and reads `false` for every row on accounts
  that have never toggled models in an editor — gating on it admits nothing.
- **Registration:** self-declares via `router::provider::register` with
  backoff until acked, and re-declares on the `router::ready` trigger type.
  The declaration carries no static `models` slice; a refresh fires right
  after registration and after every successful login.
- **Client identity:** the token exchange, discovery, and every chat call
  carry the integration headers the Copilot gateway requires
  (`Copilot-Integration-Id`, `Editor-Version`, plugin version, user agent),
  plus `X-Initiator: agent` so agent-initiated turns are billed per
  Copilot's convention and never misattributed as user keystrokes.
- **Reasoning:** the wire has no reasoning-effort parameter — thinking
  models decide for themselves and stream reasoning back as `reasoning`
  deltas (surfaced as thinking blocks; the older `reasoning_content` field
  from compatible gateways is honored too). A requested `thinking_level` is
  reported as ignored via a report-and-continue warning.
- **Structured output:** strict `json_schema` mode on models whose listing
  declares `structured_outputs`; a schema requested for any other model
  degrades to `json_object` with a warning.
- **Token counting:** none. The Copilot API exposes no tokenizer endpoint
  and its models span several vendors' vocabularies — `router::count_tokens`
  reports `no_token_counter` for this provider and the harness falls back
  to its own estimate.
- **Liveness:** `ping` at least every 30s of upstream silence; a failed
  channel write (caller gone / `router::abort`) drops the SSE receiver and
  aborts the in-flight HTTP request.
- **Errors:** statuses carry subscription semantics on the shared taxonomy:
  401 (bearer or login died) → `auth_expired` and the cached bearer is
  dropped; 403 (no Copilot access / model not authorized) → `permanent`;
  429 → `rate_limited`; 5xx and network failures → `transient`;
  context-length errors → `context_overflow`. The numeric `error.code`
  envelope wins over the transport status. No transport retries here — the
  router owns retry policy.
- **api_url precedence:** operator override in the `llm-router` entry →
  the endpoint the exchange reply names (GitHub Enterprise tenants land
  here automatically) → the public default.

## Tests

```bash
cargo test                                            # unit (pure modules + TCP stubs)
III_ENGINE_BIN=$(which iii) cargo test --test integration -- --test-threads=1
```

The integration suite spawns a real engine, the real router (path dep), this
provider, and a local stub upstream; the ready-bearer env path short-circuits
the token exchange so no external API is called. A suite-wide lock
serializes the tests (they manage credential env vars), so plain
`cargo test` is safe too.

## Running

The binary takes the standard worker CLI flags: `--url` (engine WebSocket,
default `ws://127.0.0.1:49134`, falls back to the `III_URL` environment
variable), `--manifest` (print the registry manifest and exit), and
`--config` (accepted but ignored with a warning — provider config comes
from the `llm-router` configuration entry).

## api reference

```json
{
  "functions": [
    {
      "description": "Cancel the in-flight upstream stream for a request_id (router::abort fan-out), stopping billed generation immediately.",
      "metadata": {
        "internal": true
      },
      "name": "provider::github-copilot::abort",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Input of a provider's `provider::<id>::abort`: actively cancel the in-flight upstream stream for `request_id` (the router's `request_id`, delivered to the provider as `resolution_key`) so billed generation stops immediately instead of waiting for the provider to notice the closed channel on its next write.",
        "properties": {
          "request_id": {
            "type": "string"
          }
        },
        "required": [
          "request_id"
        ],
        "title": "ProviderAbortRequest",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Output of `provider::<id>::abort`. `aborted: false` means the request was unknown — already finished, never started, or aborted before (idempotent).",
        "properties": {
          "aborted": {
            "type": "boolean"
          }
        },
        "required": [
          "aborted"
        ],
        "title": "ProviderAbortResponse",
        "type": "object"
      }
    },
    {
      "description": "Complete the device-flow sign-in: exchanges the device_code once the operator has entered the user_code; on success the GitHub credential is stored and discovery runs. Returns ok | pending | expired | denied.",
      "metadata": {},
      "name": "provider::github-copilot::login::poll",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "device_code": {
            "description": "The `device_code` from `login::start`.",
            "type": "string"
          }
        },
        "required": [
          "device_code"
        ],
        "title": "LoginPollRequest",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "LoginStatus": {
            "description": "Outcome of one poll. `SlowDown` is kept distinct from `Pending` because GitHub asks callers to lengthen their interval when it appears; the requested wait rides along in `retry_after_seconds`.",
            "oneOf": [
              {
                "description": "Signed in; the credential is stored and discovery has been kicked.",
                "enum": [
                  "ok"
                ],
                "type": "string"
              },
              {
                "description": "The operator has not finished at the verification URL yet.",
                "enum": [
                  "pending"
                ],
                "type": "string"
              },
              {
                "description": "Polling too fast — wait `retry_after_seconds` longer before retrying.",
                "enum": [
                  "slow_down"
                ],
                "type": "string"
              },
              {
                "description": "The device code expired; start again.",
                "enum": [
                  "expired"
                ],
                "type": "string"
              },
              {
                "description": "The operator rejected the request.",
                "enum": [
                  "denied"
                ],
                "type": "string"
              }
            ]
          }
        },
        "properties": {
          "retry_after_seconds": {
            "description": "Seconds to add to the poll interval; set when `status` is `slow_down`.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "status": {
            "$ref": "#/definitions/LoginStatus"
          }
        },
        "required": [
          "status"
        ],
        "title": "LoginPollResponse",
        "type": "object"
      }
    },
    {
      "description": "Begin the GitHub device-flow sign-in: returns the user_code to enter at the verification URL plus the device_code for login::poll. Operator-only.",
      "metadata": {},
      "name": "provider::github-copilot::login::start",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "LoginStartRequest",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "device_code": {
            "description": "Opaque device code to pass to `login::poll`.",
            "type": "string"
          },
          "expires_in": {
            "description": "Seconds until the device code expires.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "interval": {
            "description": "Seconds to wait between polls (GitHub's requested cadence).",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "user_code": {
            "description": "Code the operator types at `verification_uri`.",
            "type": "string"
          },
          "verification_uri": {
            "description": "Where to type it (github.com/login/device).",
            "type": "string"
          }
        },
        "required": [
          "device_code",
          "expires_in",
          "interval",
          "user_code",
          "verification_uri"
        ],
        "title": "LoginStartResponse",
        "type": "object"
      }
    },
    {
      "description": "Internal: router::ready subscriber that re-declares this provider and refreshes its catalog.",
      "metadata": {
        "internal": true
      },
      "name": "provider::github-copilot::on_router_ready",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Event delivered to a provider's `provider::<id>::on_router_ready` (the `router::ready` trigger payload, currently `{}`). Unknown fields are ignored.",
        "title": "RouterReadyEvent",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Ack returned by a provider's `provider::<id>::on_router_ready`.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "ProviderReadyAck",
        "type": "object"
      }
    },
    {
      "description": "Refresh the Copilot catalog slice from GET /models — ids, windows, and capability flags come from the live listing the subscription enables — and reconcile it through the router; returns the model count written.",
      "metadata": {},
      "name": "provider::github-copilot::refresh_models",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Input of a provider's `provider::<id>::refresh_models` — takes no arguments. A struct (not `Value`) keeps the request schema concrete; unknown fields (e.g. the engine-injected `_caller_worker_id`) are ignored.",
        "title": "RefreshModelsRequest",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Output of `provider::<id>::refresh_models`.",
        "properties": {
          "count": {
            "format": "uint",
            "minimum": 0,
            "type": "integer"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "count",
          "ok"
        ],
        "title": "RefreshModelsResponse",
        "type": "object"
      }
    },
    {
      "description": "Stream a GitHub Copilot chat completion: exchange the GitHub credential for a Copilot bearer, call the Chat Completions API, and relay AssistantMessageEvent frames to writer_ref.",
      "metadata": {},
      "name": "provider::github-copilot::stream",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "AgentFunction": {
            "description": "Function invocation schema — what a provider sees as a `tools` array entry (README § Function invocation schema; adapter boundary). These describe iii functions exposed to the model, not provider-native tools.",
            "properties": {
              "description": {
                "type": "string"
              },
              "execution_mode": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": "string"
              },
              "parameters": true
            },
            "required": [
              "description",
              "name",
              "parameters"
            ],
            "type": "object"
          },
          "AgentMessage": {
            "anyOf": [
              {
                "$ref": "#/definitions/AssistantMessage"
              },
              {
                "$ref": "#/definitions/FunctionResultMessage"
              },
              {
                "$ref": "#/definitions/CustomMessage"
              },
              {
                "$ref": "#/definitions/UserMessage"
              }
            ],
            "description": "The canonical transcript message union. Untagged: the single-variant role tags disambiguate deserialization."
          },
          "AssistantMessage": {
            "properties": {
              "content": {
                "items": {
                  "$ref": "#/definitions/ContentBlock"
                },
                "type": "array"
              },
              "error_kind": {
                "anyOf": [
                  {
                    "$ref": "#/definitions/ErrorKind"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "error_message": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "model": {
                "type": "string"
              },
              "native_stop_reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "provider": {
                "type": "string"
              },
              "role": {
                "$ref": "#/definitions/AssistantRoleTag"
              },
              "stop_reason": {
                "$ref": "#/definitions/StopReason"
              },
              "timestamp": {
                "format": "int64",
                "type": "integer"
              },
              "usage": {
                "anyOf": [
                  {
                    "$ref": "#/definitions/Usage"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "warnings": {
                "items": {
                  "type": "string"
                },
                "type": [
                  "array",
                  "null"
                ]
              }
            },
            "required": [
              "content",
              "model",
              "provider",
              "role",
              "stop_reason",
              "timestamp"
            ],
            "type": "object"
          },
          "AssistantRoleTag": {
            "enum": [
              "assistant"
            ],
            "type": "string"
          },
          "ChannelDirection": {
            "enum": [
              "read",
              "write"
            ],
            "type": "string"
          },
          "ContentBlock": {
            "description": "Content blocks — the atomic units of message content (README § Content blocks).",
            "oneOf": [
              {
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "type": {
                    "enum": [
                      "text"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "text",
                  "type"
                ],
                "type": "object"
              },
              {
                "properties": {
                  "data": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "type": {
                    "enum": [
                      "image"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "data",
                  "mime",
                  "type"
                ],
                "type": "object"
              },
              {
                "properties": {
                  "signature": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "text": {
                    "type": "string"
                  },
                  "type": {
                    "enum": [
                      "thinking"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "text",
                  "type"
                ],
                "type": "object"
              },
              {
                "description": "Opaque redacted thinking payload — replayed verbatim on the Anthropic wire.",
                "properties": {
                  "data": {
                    "type": "string"
                  },
                  "type": {
                    "enum": [
                      "redacted_thinking"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "data",
                  "type"
                ],
                "type": "object"
              },
              {
                "properties": {
                  "arguments": true,
                  "function_id": {
                    "type": "string"
                  },
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "enum": [
                      "function_call"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "arguments",
                  "function_id",
                  "id",
                  "type"
                ],
                "type": "object"
              },
              {
                "properties": {
                  "content": {
                    "items": {
                      "$ref": "#/definitions/ContentBlock"
                    },
                    "type": "array"
                  },
                  "function_call_id": {
                    "type": "string"
                  },
                  "is_error": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "type": {
                    "enum": [
                      "function_result"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "content",
                  "function_call_id",
                  "type"
                ],
                "type": "object"
              }
            ]
          },
          "CustomMessage": {
            "properties": {
              "content": {
                "items": {
                  "$ref": "#/definitions/ContentBlock"
                },
                "type": "array"
              },
              "custom_type": {
                "type": "string"
              },
              "details": true,
              "display": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "role": {
                "$ref": "#/definitions/CustomRoleTag"
              },
              "timestamp": {
                "format": "int64",
                "type": "integer"
              }
            },
            "required": [
              "content",
              "custom_type",
              "role",
              "timestamp"
            ],
            "type": "object"
          },
          "CustomRoleTag": {
            "enum": [
              "custom"
            ],
            "type": "string"
          },
          "ErrorKind": {
            "enum": [
              "auth_expired",
              "rate_limited",
              "context_overflow",
              "transient",
              "permanent"
            ],
            "type": "string"
          },
          "FunctionResultMessage": {
            "properties": {
              "content": {
                "items": {
                  "$ref": "#/definitions/ContentBlock"
                },
                "type": "array"
              },
              "details": true,
              "function_call_id": {
                "type": "string"
              },
              "function_id": {
                "type": "string"
              },
              "is_error": {
                "type": "boolean"
              },
              "role": {
                "$ref": "#/definitions/FunctionResultRoleTag"
              },
              "timestamp": {
                "format": "int64",
                "type": "integer"
              }
            },
            "required": [
              "content",
              "details",
              "function_call_id",
              "function_id",
              "is_error",
              "role",
              "timestamp"
            ],
            "type": "object"
          },
          "FunctionResultRoleTag": {
            "enum": [
              "function_result"
            ],
            "type": "string"
          },
          "Model": {
            "description": "The capability record (README § Model descriptor).",
            "properties": {
              "context_window": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "display_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "input_limit": {
                "format": "uint64",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              },
              "max_output_tokens": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "pricing": {
                "anyOf": [
                  {
                    "$ref": "#/definitions/Pricing"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "provider": {
                "type": "string"
              },
              "reasoning_efforts": {
                "items": {
                  "$ref": "#/definitions/ReasoningEffort"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "supports_cache": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "supports_structured_output": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "supports_thinking": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "supports_tools": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "supports_vision": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "supports_xhigh": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "thinking_budgets": {
                "additionalProperties": {
                  "format": "uint64",
                  "minimum": 0,
                  "type": "integer"
                },
                "type": [
                  "object",
                  "null"
                ]
              }
            },
            "required": [
              "context_window",
              "id",
              "max_output_tokens",
              "provider"
            ],
            "type": "object"
          },
          "Pricing": {
            "properties": {
              "cache_read": {
                "format": "double",
                "type": [
                  "number",
                  "null"
                ]
              },
              "cache_write": {
                "format": "double",
                "type": [
                  "number",
                  "null"
                ]
              },
              "input": {
                "format": "double",
                "type": [
                  "number",
                  "null"
                ]
              },
              "output": {
                "format": "double",
                "type": [
                  "number",
                  "null"
                ]
              }
            },
            "type": "object"
          },
          "ReasoningEffort": {
            "description": "One provider-native reasoning effort advertised for a specific model.\n\nValues intentionally remain strings: provider catalogs can add efforts without requiring a router-wide enum release first.",
            "properties": {
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "effort": {
                "type": "string"
              }
            },
            "required": [
              "effort"
            ],
            "type": "object"
          },
          "ResponseFormat": {
            "properties": {
              "schema": true,
              "type": {
                "type": "string"
              }
            },
            "required": [
              "type"
            ],
            "type": "object"
          },
          "StopReason": {
            "enum": [
              "end",
              "length",
              "function_call",
              "aborted",
              "error"
            ],
            "type": "string"
          },
          "StreamChannelRef": {
            "properties": {
              "access_key": {
                "type": "string"
              },
              "channel_id": {
                "type": "string"
              },
              "direction": {
                "$ref": "#/definitions/ChannelDirection"
              }
            },
            "required": [
              "access_key",
              "channel_id",
              "direction"
            ],
            "type": "object"
          },
          "ThinkingLevel": {
            "description": "\"minimal\" requests the lowest reasoning effort and needs only `thinking` support; levels map to provider-native knobs via `Model::thinking_budgets`.",
            "enum": [
              "minimal",
              "low",
              "medium",
              "high",
              "xhigh"
            ],
            "type": "string"
          },
          "Usage": {
            "properties": {
              "cache_read": {
                "format": "uint64",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              },
              "cache_write": {
                "format": "uint64",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              },
              "cost_usd": {
                "format": "double",
                "type": [
                  "number",
                  "null"
                ]
              },
              "input": {
                "format": "uint64",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              },
              "output": {
                "format": "uint64",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              },
              "reasoning": {
                "format": "uint64",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              }
            },
            "type": "object"
          },
          "UserMessage": {
            "properties": {
              "content": {
                "items": {
                  "$ref": "#/definitions/ContentBlock"
                },
                "type": "array"
              },
              "role": {
                "$ref": "#/definitions/UserRoleTag"
              },
              "timestamp": {
                "format": "int64",
                "type": "integer"
              }
            },
            "required": [
              "content",
              "role",
              "timestamp"
            ],
            "type": "object"
          },
          "UserRoleTag": {
            "description": "Single-variant role tags: exact-match on deserialize, correct wire string on serialize, and they let `AgentMessage` be an untagged union.",
            "enum": [
              "user"
            ],
            "type": "string"
          }
        },
        "description": "Input of a provider worker's `provider::<id>::stream` iii function — what the router forwards per attempt. (No `PartialEq`: `iii_sdk::StreamChannelRef` doesn't implement it.)",
        "properties": {
          "max_output_tokens": {
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "messages": {
            "items": {
              "$ref": "#/definitions/AgentMessage"
            },
            "type": "array"
          },
          "model": {
            "type": "string"
          },
          "model_meta": {
            "anyOf": [
              {
                "$ref": "#/definitions/Model"
              },
              {
                "type": "null"
              }
            ]
          },
          "provider_options": true,
          "resolution_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "response_format": {
            "anyOf": [
              {
                "$ref": "#/definitions/ResponseFormat"
              },
              {
                "type": "null"
              }
            ]
          },
          "session_id": {
            "description": "Stable conversation identity for provider cache affinity.",
            "type": [
              "string",
              "null"
            ]
          },
          "system_prompt": {
            "type": [
              "string",
              "null"
            ]
          },
          "thinking_level": {
            "anyOf": [
              {
                "$ref": "#/definitions/ThinkingLevel"
              },
              {
                "type": "null"
              }
            ]
          },
          "tools": {
            "items": {
              "$ref": "#/definitions/AgentFunction"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "writer_ref": {
            "$ref": "#/definitions/StreamChannelRef"
          }
        },
        "required": [
          "messages",
          "model",
          "writer_ref"
        ],
        "title": "ProviderStreamInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Output of a provider's `provider::<id>::stream` (spec § stream contract): the function streams frames to `writer_ref` and returns this ack.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "ProviderStreamOutput",
        "type": "object"
      }
    }
  ],
  "triggers": []
}
```
