Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions contracts/model-price-ranges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Exact advertised price range discovery

GET /api/v1/models accepts optional min_price/max_price for base prompt prices and min_output_price/max_output_price for base completion prices, in USD per million tokens. Bounds are inclusive and conjunctive. Published pricing.prompt/completion strings are per-token values; compare exactly after shifting each query bound down six decimal positions. Never use floating-point money arithmetic, average prompt/output prices for these filters, apply discounts/conditional overrides/optional charges or infer a request bill.

The accepted local query syntax is `(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?`, bounded to 128 UTF-16 units and finite Number conversion. Number conversion checks the existing finite-input restriction only; exact comparisons and continuations retain the string, including positive underflow and zero with enormous exponents. Reject negative values (including -0), leading signs/zeroes, whitespace, incomplete decimals, nonnumeric/null/empty values, duplicates, oversized/nonfinite input and exactly reversed pairs. Local restrictions are not invented OpenAPI constraints. SDK number serialization may already lose precision before a request reaches the gateway.

Reuse bounded sparse decimal digits with BigInt positions. Query bounds are prepared once per request, with no exponent-sized zero runs/powers or cross-request cache. Equivalent spellings compare equal. Models without pricing metadata cannot match any selected range; known zero remains a valid free base price. Omitted ranges preserve existing listing order and behavior.

Authenticate first, reject invalid queries before catalog access, validate/capture the complete catalog, authorize enabled models/final providers with explicit Deny precedence, then filter captured metadata before sorting/paging. Preserve all selected filters and original accepted price-bound spelling in fixed relative continuations; each page reloads catalog and policy. Required audit precedes output without bound/price/query data in operational events or errors. Hidden/disabled malformed pricing and catalog/audit failures return safe unavailable responses. Audit-time mutation cannot change captured prices or output. No routing, inference, secrets, limits or usage ports are invoked. Legacy /v1 queries and /api/v1/models/count price queries remain rejected.

Query pin v4 selects the four complete official parameter objects in addition to the previous fourteen targets. Each is optional, in query, with minimum:0 and type:[number,null], and has no source maximum/default/unit extension. Retain all prior targets, nullable markers and normalization semantics. Removing precisely these four parameters reproduces the complete v3 projection digest d985275c9d19ea77b69ce525117e05c6c0dd62ccfba807abff15725268bec77a; older migration digests remain verified. Stale versions/rehashed invalid exact maps reject. Controlled CLI fixtures cover each new field's drift, private atomic failures, one credential-free download and no pin writes. All other pins remain byte-identical.

Source: [official OpenAPI](https://openrouter.ai/openapi.json), retrieved 2026-10-18. Canonical source SHA-256 e14bcc1e02453bff8807cc79d03170ce7d229a9d0836e253ff49b764b8aa811d; query v4 projection SHA-256 aa9f1298d0c56d6d786499f859c3ee9062b2bc01407e2c9926bff1e85921ff62. Administrator prices may be stale/inaccurate; filtering does not refresh prices, select inference providers or certify live capability/cost. Full #116 and unresolved #7 remain open. See [plan](../docs/plans/512-model-price-ranges.md).
6 changes: 4 additions & 2 deletions contracts/model-query-schema.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Supported discovery-query schema drift contract

A separate version-3 pin selects official GET /models operation identity and exactly offset, limit, output_modalities, supported_parameters, context, input_modalities, q, sort and min/max intelligence/coding/agentic index parameter objects. Capture query name/location, explicit or omitted required status, schema and all structural serialization/extension fields. Select OpenAPI/document versions. Read inline operation parameters only; missing/duplicate supported names, invalid containers, wrong location, parameter references/content instead of schema, and supported-name inherited parameters fail safely for review. Unselected queries, inherited unrelated parameters, operation editorial metadata and other endpoints are outside detection.
Version4 (#512) adds four complete optional nonnegative number/null price-bound objects without changing previous targets. The USD-per-million unit comes from official prose and is implemented separately; no local 128-unit syntax, exact arithmetic or pair-order rule is inserted into the pin. Removing those four objects reproduces complete v3, and older v2/v1 reconstruction remains checked. Each new field has independent shape/drift and malformed/missing target coverage; stale v3 rejects before any CLI fetch. Fresh source/projection digests and runtime limits are recorded in the [price range contract](model-price-ranges.md) and [plan](../docs/plans/512-model-price-ranges.md).

A separate version-4 pin selects official GET /models operation identity and exactly offset, limit, output_modalities, supported_parameters, context, input_modalities, q, sort, min/max intelligence/coding/agentic index and min_price/max_price/min_output_price/max_output_price parameter objects. Capture query name/location, explicit or omitted required status, schema and all structural serialization/extension fields. Select OpenAPI/document versions. Read inline operation parameters only; missing/duplicate supported names, invalid containers, wrong location, parameter references/content instead of schema, and supported-name inherited parameters fail safely for review. Unselected queries, inherited unrelated parameters, operation editorial metadata and other endpoints are outside detection.

The pin has an exact envelope and exact parameter map, fixed official URL, date, canonical source SHA-256 and canonical structural projection SHA-256. Offline integrity validates shape/selected identities/canonical normalized projection/digest and rejects stale or rehashed malformed maps. It cannot independently authenticate the recorded source digest without that source. Structural source changes compare unequal; selected inline schema references/extensions remain in the projection, while referenced targets are not traversed.

Editorial description/title/example/examples/externalDocs/$comment annotations are ignored. Annotation-named schema properties and literal default/const/enum data remain structural. Parameter array and object-key order are normalized; schema arrays retain their order. The source has optional parameters, offset integer/null minimum0/default0, limit integer minimum1/maximum1000/default500, context integer minimum1, and plain non-null strings for both capability filters. No modality enum/text default, comma-list semantics, identifier length or safe-integer bound is manufactured from prose/local runtime policy.

Existing offline and explicit live compatibility commands check both chat and discovery pins. Both pins validate before a single fixed official HTTPS retrieval, reusing credential omission, redirect rejection, bounded time/body and fixed errors. Check results are separate, nonzero for drift/invalid/unavailable data, content-free, and never write pins. The chat version-30 pin is unchanged. Existing discovery IAM/metadata/continuation, limits/audit/usage and SDK behavior are unaffected.
Existing offline and explicit live compatibility commands validate all four pins before a single fixed official HTTPS retrieval, reusing credential omission, redirect rejection, bounded time/body and fixed errors. Check results are separate, nonzero for drift/invalid/unavailable data, content-free, and never write pins. Request, model-response and count pins remain byte-identical in #512. Existing discovery IAM/metadata/continuation, limits/audit/usage and SDK behavior remain shared.

This guard is partial structural change detection. It does not validate instances/responses, implement new query fields, refresh metadata, infer provider capabilities or certify full external-tool compatibility. Newly required unselected queries and structural changes only in referenced targets remain outside detection. Release #116 and unresolved #7 remain open. See [plan](../docs/plans/458-model-query-schema.md).

Expand Down
52 changes: 50 additions & 2 deletions contracts/openrouter-model-query-schema.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"version": 3,
"version": 4,
"source": "https://openrouter.ai/openapi.json",
"retrievedAt": "2026-10-18",
"sourceSha256": "e14bcc1e02453bff8807cc79d03170ce7d229a9d0836e253ff49b764b8aa811d",
"projectionSha256": "d985275c9d19ea77b69ce525117e05c6c0dd62ccfba807abff15725268bec77a",
"projectionSha256": "aa9f1298d0c56d6d786499f859c3ee9062b2bc01407e2c9926bff1e85921ff62",
"projection": {
"openapi": "3.1.0",
"documentVersion": "1.0.0",
Expand Down Expand Up @@ -171,6 +171,54 @@
"null"
]
}
},
"min_price": {
"in": "query",
"name": "min_price",
"required": false,
"schema": {
"minimum": 0,
"type": [
"number",
"null"
]
}
},
"max_price": {
"in": "query",
"name": "max_price",
"required": false,
"schema": {
"minimum": 0,
"type": [
"number",
"null"
]
}
},
"min_output_price": {
"in": "query",
"name": "min_output_price",
"required": false,
"schema": {
"minimum": 0,
"type": [
"number",
"null"
]
}
},
"max_output_price": {
"in": "query",
"name": "max_output_price",
"required": false,
"schema": {
"minimum": 0,
"type": [
"number",
"null"
]
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions docs/PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ LLM subscriptions and API keys spread across teams make it difficult to revoke a

Success means unauthorized principals cannot obtain provider credentials or invoke models; administrators can inspect permissions and usage by principal, role, and model; and auditors can trace permission changes and denied calls.

## Compatible advertised price ranges (#512)

Compatible model discovery accepts inclusive input/output minimum/maximum base-price filters in USD per million tokens. Apply exact decimal comparison to trusted per-token metadata, excluding unknown prices and retaining current IAM, audit, filters and paging. This does not estimate a bill or refresh prices. See [plan](plans/512-model-price-ranges.md) and [contract](../contracts/model-price-ranges.md).

## 2. Users

| User | Primary task |
Expand Down
4 changes: 4 additions & 0 deletions docs/acceptance.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ Verify independently specified query/envelope/nested-count shapes and exact prov

The request v32 and model-response v2 pins must match reviewed official structures without broad normalization changes. Assert exact new optional fields, both deferred-tool booleans, seven retained nullable type arrays, stale-version rejection and reconstructed prior projection digests. Controlled CLI probes must report only the changed subset, download once without credentials, reject stale pins before download and preserve all pin bytes. New target bodies remain explicitly unselected; no runtime field support or complete compatibility is inferred. See [plan](plans/509-reviewed-schema-drift.md) and [contracts](../contracts/openrouter-schema-drift.md).

## Exact discovery price ranges (#512)

Verify raw and installed SDK four-field filters, inclusive/one-sided/zero bounds, exact per-million conversion, high precision/underflow/huge exponents, ignored discounts/overrides and missing-price exclusion. Use an independent bounded integer oracle. Verify combined filters/sorting, original spelling in relative continuations, fresh catalog/model/provider IAM, hidden malformed data, auth-before-query/catalog, private required failures and immutable audit-time snapshots. Count/legacy queries reject price bounds. Query v4 exact shapes, stale/maps/structural drift and historical projection digests must pass; all other pins remain unchanged. See [plan](plans/512-model-price-ranges.md) and [contract](../contracts/model-price-ranges.md).

## Harness connection

The PostgreSQL migration runner applies versions `001` through `008` in order, records their checksums, and skips unchanged history on a second run. It refuses edited, missing, duplicate, skipped, and out-of-order versions before applying new SQL. A failing migration leaves neither its schema changes nor its history row, and driver errors expose no SQL text. Deployment connection provisioning and concurrent migrator coordination remain separate release work.
Expand Down
4 changes: 4 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Status: Internal authorization, portable deployment, dual upstream modes, initia

OpenGranter does **not** call AWS IAM to decide access. Its policy engine adopts default denial, explicit Deny precedence, and principal/action/resource concepts. It does not reproduce every AWS IAM policy type, STS, AssumeRole, SigV4, or cross-account semantics. A role is an assignable policy grouping, not a temporary role session in the first release.

## Exact advertised price filtering (#512)

Capture bounded price-query strings and immutable range objects, reject exactly reversed pairs before catalog access and prepare sparse decimal bound keys with a minus-six position shift for per-million units. After full catalog validation and model/final-provider IAM, filter captured base prices before existing sort/paging and required audit. Reuse exact ordering digit logic without floating-point money operations, exponent-sized allocation, provider calls or routing authority. Query pin v4 adds four raw parameter objects; other pins are unchanged. See [plan](plans/512-model-price-ranges.md) and [contract](../contracts/model-price-ranges.md).

## Request path

```mermaid
Expand Down
6 changes: 5 additions & 1 deletion docs/openrouter-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Tracking issue: [#116](https://github.com/Theorvane/OpenGranter/issues/116).

## Exact advertised price query ranges (#512)

Compatible discovery supports min_price/max_price/min_output_price/max_output_price with inclusive USD-per-million semantics and exact decimal comparison against captured base per-token prices. Unknown prices cannot match selected ranges; omitted ranges preserve existing listing behavior. Bounded local syntax, exact reversed-pair rejection, original continuation spelling, shared model/provider IAM/private audit and installed SDK socket cases apply. Query pin v4 adds four complete official parameter objects and preserves previous/historical projections; other pins remain byte-identical. Prices may be stale/inaccurate, and SDK numeric serialization can lose precision before transmission. This does not certify billed cost, refresh data, choose routes or complete #116. See [plan](plans/512-model-price-ranges.md) and [contract](../contracts/model-price-ranges.md).

## Reviewed official source drift (#509)

Request pin v32 records new optional alignment/safeguard response references and both optional boolean defer_loading declarations. Model-response pin v2 removes only seven legacy nullable:true markers while retaining explicit nullable number/integer arrays. Independent shapes, old-version rejection, exact prior-digest reconstruction and controlled CLI drift cases cover the refresh; query/count pins remain unchanged. Alignment/AlignmentCallRecord/ArmorSafeguardResult bodies were inspected but remain outside the fixed target selection. Structural tracking does not implement these runtime fields or plugins, certify safeguards or change IAM/audit/usage. Full #116 and unresolved #7 remain open. See [plan](plans/509-reviewed-schema-drift.md), [chat contract](../contracts/openrouter-schema-drift.md) and [response contract](../contracts/model-response-schema.md).
Expand Down Expand Up @@ -29,7 +33,7 @@ Tools with a hardcoded openrouter.ai host need a configurable endpoint or an int
| Area | Current state | Remaining acceptance gate |
| --- | --- | --- |
| Base paths and Bearer token | /api/v1 chat/models aliases and IAM-filtered /models/count; shared proxy authorization; pinned OpenAI SDK smoke tests | Broader direct streaming and named-client workflows; OpenCode 1.18.5 explicit custom-provider registration/text is verified on delegated and managed OpenAI/Anthropic/Gemini fixture routes |
| Model discovery | IAM-filtered aliases; optional administrator-published SDK-required and bounded descriptive/date/identifier metadata, bounded offset/limit paging and bounded all-member input/parameter lists, minimum-context filters and any-member output lists, literal name/slug/alias search, inclusive Artificial Analysis index ranges and creation/context/benchmark/exact-price ordering on /api/v1; separate supported-query structural pin | Metadata provisioning/refresh, remaining filters/sorts, broader optional fields and complete discovery workflows |
| Model discovery | IAM-filtered aliases; optional administrator-published SDK-required and bounded descriptive/date/identifier metadata, bounded offset/limit paging and bounded all-member input/parameter lists, minimum-context filters and any-member output lists, literal name/slug/alias search, inclusive exact base-price and Artificial Analysis index ranges and creation/context/benchmark/exact-price ordering on /api/v1; separate supported-query structural pin | Metadata provisioning/refresh, remaining filters/sorts, broader optional fields and complete discovery workflows |
| Non-streaming text chat | One normalized choice with portable output/sampling controls, provider-bounded verbosity/effort, delegated min_p/top_a/repetition_penalty, bounded OpenAI/OpenRouter logprobs/top_logprobs with content/refusal token alternatives and bytes, and Gemini chosen/alternative probabilities with unavailable bytes | Anthropic probability mapping, remaining request/response schema, sampling and capability metadata |
| Streaming | Managed OpenAI/delegated OpenRouter nullable probability controls and bounded choice-level content/refusal token alternatives/bytes, including private final usage-choice probabilities after required handoffs; managed Gemini HTTP text/function streams with exact initial version identity, complete objects with bounded same-part signatures through raw HTTP/OpenAI SDK and explicitly configured OpenCode, dense call indices, clean framed EOF, final reported totals and actual SDK/persisted direct/dual checks on both bases; managed Anthropic HTTP text/function streams with bounded JSON arguments, generated persisted direct/dual wiring, cumulative aggregate usage and actual OpenAI/OpenRouter SDK checks on both bases; managed OpenAI HTTP text/refusal/indexed function streams with per-attempt usage/audit, generated persisted direct/dual wiring and actual SDK checks on both bases; delegated HTTP text/refusal/scalar/detail reasoning and indexed function streams with bounded validation, awaited delivery, cancellation, final usage metadata and interruption audit; both installed SDKs exercise function workflows on both bases; OpenCode 1.18.5 reads a fixture through a streamed function and completes correlated results on delegated and managed OpenAI/Anthropic/Gemini fixture routes | Gemini partial-argument streams and Anthropic/Gemini thinking/server-tool streams, native custom/multimodal and other tool variants, unselected schema targets, additional stream option fields and full named external-client conformance |
| Tool calling | Validated function-tool requests and complete text-only result histories; delegated OpenRouter nonstream/stream assistant calls and direct OpenAI nonstream/stream calls and bounded managed Anthropic nonstream/stream declarations/choices/calls/correlated results; bounded managed Gemini nonstream/stream declarations/choices/calls/results with thinking disabled, plus official nonstream/stream same-part tool-call signature replay through raw HTTP/OpenAI SDK and explicitly configured OpenCode; SDK socket tests cover two-function continuations and fresh IAM | Server/custom tools, rich content, other native mappings and broader named external-tool workflows and application configurations |
Expand Down
Loading
Loading