@game-infra/ai-schemas 0.3.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/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/catalog.d.ts +137 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +209 -0
- package/dist/catalog.js.map +1 -0
- package/dist/contracts.d.ts +1073 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +243 -0
- package/dist/contracts.js.map +1 -0
- package/dist/featuredModels.d.ts +95 -0
- package/dist/featuredModels.d.ts.map +1 -0
- package/dist/featuredModels.js +189 -0
- package/dist/featuredModels.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/inference.d.ts +323 -0
- package/dist/inference.d.ts.map +1 -0
- package/dist/inference.js +162 -0
- package/dist/inference.js.map +1 -0
- package/dist/preference.d.ts +49 -0
- package/dist/preference.d.ts.map +1 -0
- package/dist/preference.js +74 -0
- package/dist/preference.js.map +1 -0
- package/dist/preset.d.ts +422 -0
- package/dist/preset.d.ts.map +1 -0
- package/dist/preset.js +212 -0
- package/dist/preset.js.map +1 -0
- package/dist/provider.d.ts +487 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +224 -0
- package/dist/provider.js.map +1 -0
- package/dist/schemaRegistry.d.ts +71 -0
- package/dist/schemaRegistry.d.ts.map +1 -0
- package/dist/schemaRegistry.js +35 -0
- package/dist/schemaRegistry.js.map +1 -0
- package/dist/service.d.ts +143 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +103 -0
- package/dist/service.js.map +1 -0
- package/dist/subscription.d.ts +275 -0
- package/dist/subscription.d.ts.map +1 -0
- package/dist/subscription.js +198 -0
- package/dist/subscription.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Igor Savin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @game-infra/ai-schemas
|
|
2
|
+
|
|
3
|
+
The [`ai-service`](../../../services/ai-service/README.md) API contract: how a
|
|
4
|
+
provider, a coding-plan subscription and a routing preset are described, what an
|
|
5
|
+
inference request and its answer look like, and the endpoint definitions that
|
|
6
|
+
carry them.
|
|
7
|
+
|
|
8
|
+
Published to npm, like the other `*-schemas` packages, because a game repo
|
|
9
|
+
calling ai-service needs the contract without checking out the service.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```jsonc
|
|
14
|
+
// package.json, in a sibling checkout
|
|
15
|
+
{
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@game-infra/ai-schemas": "link:../game-infra/packages/schemas/ai-schemas",
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or from the registry: `pnpm add @game-infra/ai-schemas`.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Contracts carry their own method, path and schemas, so a client never restates a
|
|
27
|
+
path:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { aiGenerateTextContract, aiPresetRoutePlanContract } from "@game-infra/ai-schemas";
|
|
31
|
+
import { sendByApiContract } from "@toad-contracts/frontend-http-client";
|
|
32
|
+
|
|
33
|
+
const { result } = await sendByApiContract(client, aiGenerateTextContract, {
|
|
34
|
+
body: {
|
|
35
|
+
preset: "narrative",
|
|
36
|
+
messages: [{ role: "user", content: "A rusted door in a flooded corridor." }],
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Every answer reports which route served it, which failed on the way, and
|
|
41
|
+
// which were never tried.
|
|
42
|
+
result.body.route?.served.providerId;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
aiPresetRoutePlanContract.pathResolver({ slug: "narrative" }); // '/presets/narrative/route'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## What is in here
|
|
50
|
+
|
|
51
|
+
| Module | What it describes |
|
|
52
|
+
| ------------------- | ------------------------------------------------------------------- |
|
|
53
|
+
| `provider.ts` | Providers, their tiers, dialects and model routes |
|
|
54
|
+
| `subscription.ts` | Coding-plan credentials and the vendor profiles that reach them |
|
|
55
|
+
| `preset.ts` | Routing presets, route candidates, and why a route was excluded |
|
|
56
|
+
| `inference.ts` | Messages, the three inference requests, and what an answer reports |
|
|
57
|
+
| `schemaRegistry.ts` | How a registered response schema is published |
|
|
58
|
+
| `catalog.ts` | Provider blueprints, and model discovery |
|
|
59
|
+
| `featuredModels.ts` | The models surfaced by name, and the id each is reached under |
|
|
60
|
+
| `preference.ts` | The two ordering folds the service and the console must agree about |
|
|
61
|
+
| `contracts.ts` | Every endpoint definition |
|
|
62
|
+
|
|
63
|
+
## The two tables worth knowing
|
|
64
|
+
|
|
65
|
+
**Tiers** (`PROVIDER_TIERS`) are `subscription`, `direct`, `local`, `umbrella`,
|
|
66
|
+
in the order they are tried by default. The axis is who pays: a coding plan is
|
|
67
|
+
flat-rate quota already bought, a direct key is metered by the vendor that
|
|
68
|
+
trained the model, a local server costs whatever the hardware costs, and a
|
|
69
|
+
gateway resells at a markup. Expressing preference over tiers rather than over
|
|
70
|
+
provider ids is what lets a deployment state its policy once instead of per
|
|
71
|
+
model.
|
|
72
|
+
|
|
73
|
+
**Subscription vendors** (`SUBSCRIPTION_VENDOR_PROFILES`) carry each plan's
|
|
74
|
+
dialect, endpoint and auth scheme. Four of the five speak the Anthropic Messages
|
|
75
|
+
dialect, because Claude Code is an Anthropic-API client and Z.ai, Moonshot and
|
|
76
|
+
DeepSeek each publish an Anthropic-compatible endpoint precisely so it can be
|
|
77
|
+
pointed at them; `codex` is the exception and speaks the OpenAI Responses shape.
|
|
78
|
+
Every field is a default rather than a constant, and a stored subscription can
|
|
79
|
+
override any of them: a vendor moving an endpoint should be a console edit
|
|
80
|
+
rather than a release of this package.
|
|
81
|
+
|
|
82
|
+
## Surfaced models
|
|
83
|
+
|
|
84
|
+
`FEATURED_MODELS` names the handful of models worth reaching for a kind of work,
|
|
85
|
+
and the id a gateway serves each under. Today that is creative writing —
|
|
86
|
+
narration, dialogue, in-world prose — and all of it is reached through
|
|
87
|
+
OpenRouter, because none of those four families is worth a direct account on its
|
|
88
|
+
own and one key already reaches all of them.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { featuredModelRoutes, featuredModelsFor } from "@game-infra/ai-schemas";
|
|
92
|
+
|
|
93
|
+
featuredModelsFor("creative-writing").filter((model) => model.flagship);
|
|
94
|
+
// aion, euryale, mistral-large, hermes
|
|
95
|
+
|
|
96
|
+
featuredModelRoutes("openrouter");
|
|
97
|
+
// [{ model: 'aion', providerModelId: 'aion-labs/aion-3.0' }, …] — save these on
|
|
98
|
+
// the provider and a preset naming `aion` plans like any other model.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The list is advisory and reaches routing through exactly one door: an operator
|
|
102
|
+
saves those routes onto a provider. Until then a surfaced model is a
|
|
103
|
+
recommendation with an id attached, which is why nothing in the planner reads
|
|
104
|
+
this table. Consumers should read it from ai-service's `GET /catalog` rather
|
|
105
|
+
than importing it, so a repinned id arrives without a release.
|
|
106
|
+
|
|
107
|
+
## Extension points
|
|
108
|
+
|
|
109
|
+
- **`orderedTierPreference` / `orderedProviderPreference`** are exported because
|
|
110
|
+
the service and the console must not disagree about them: the preset editor
|
|
111
|
+
shows the resulting order as somebody drags rows, and a second copy of the
|
|
112
|
+
rule in Vue is a copy that eventually differs from the one a request takes.
|
|
113
|
+
Both **reorder and never filter**, so a preference stored before a tier
|
|
114
|
+
existed cannot silently make that tier unreachable.
|
|
115
|
+
- **`SUBSCRIPTION_PASSWORD_HEADER`** names the header a request carries a
|
|
116
|
+
subscription unlock in. A header rather than a body field, for the same reason
|
|
117
|
+
the bearer token is one, and exported so a browser client can list it in its
|
|
118
|
+
CORS allowance — without which a preflight drops it and every subscription
|
|
119
|
+
route silently falls through to a metered provider.
|
|
120
|
+
|
|
121
|
+
## What is deliberately not here
|
|
122
|
+
|
|
123
|
+
**A model catalog.** A list of every model id baked into a released package is
|
|
124
|
+
wrong within weeks, and wrong in the direction that hurts: it advertises models
|
|
125
|
+
a deployment cannot actually reach, so the mistake surfaces as a failed request
|
|
126
|
+
rather than as an empty picker. Model routes come from the provider itself,
|
|
127
|
+
through ai-service's discovery endpoint, or from an operator typing them in.
|
|
128
|
+
`PROVIDER_BLUEPRINTS` holds only the parts that do not go stale: which tier a
|
|
129
|
+
provider belongs to, which dialect it speaks, and where it lives.
|
|
130
|
+
|
|
131
|
+
`FEATURED_MODELS` is not that catalog and does not reintroduce it. It claims no
|
|
132
|
+
inventory — it answers "which model should write this", which no `/models` call
|
|
133
|
+
answers and no gateway's refresh changes — and it routes nothing until an
|
|
134
|
+
operator saves it onto a provider.
|
|
135
|
+
|
|
136
|
+
Three of the four dialects are HTTP shapes. `workers-ai` is the exception and
|
|
137
|
+
names a transport rather than a wire format: Cloudflare Workers AI is reached
|
|
138
|
+
through the consuming Worker's own `AI` binding, so a provider on that dialect
|
|
139
|
+
has no base URL and no credential — the platform authorises the call.
|
|
140
|
+
|
|
141
|
+
## Dependencies
|
|
142
|
+
|
|
143
|
+
`@game-infra/api-schemas-core` (the shared response wrappers),
|
|
144
|
+
`@toad-contracts/core` and `@toad-contracts/valibot`. `valibot` is a peer.
|
|
145
|
+
|
|
146
|
+
## Consumers
|
|
147
|
+
|
|
148
|
+
`services/ai-service`, `apps/ai-console`, and any game-repo service calling
|
|
149
|
+
ai-service.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { type InferOutput } from "valibot";
|
|
2
|
+
import { type CredentialKind, type ProviderDialect, type ProviderTier } from "./provider.js";
|
|
3
|
+
/**
|
|
4
|
+
* The out-of-the-box provider blueprints.
|
|
5
|
+
*
|
|
6
|
+
* A blueprint is the part of a provider nobody should have to look up: which
|
|
7
|
+
* tier it belongs to, which dialect it speaks, and where it lives. It is not a
|
|
8
|
+
* configured provider and holds no credential; the console offers these as
|
|
9
|
+
* starting points and writes a real provider record from the one an operator
|
|
10
|
+
* picks, at which point every field becomes editable.
|
|
11
|
+
*
|
|
12
|
+
* What is deliberately NOT here is a list of models. A model list baked into a
|
|
13
|
+
* released package is wrong within weeks and wrong in the direction that
|
|
14
|
+
* matters, because it advertises models a deployment cannot actually reach.
|
|
15
|
+
* Model routes come from the provider itself, through the discovery endpoint,
|
|
16
|
+
* or from an operator typing them in.
|
|
17
|
+
*
|
|
18
|
+
* The surfaced models in `featuredModels.ts` are not that list and do not
|
|
19
|
+
* contradict this one. They claim no inventory: they name the handful of models
|
|
20
|
+
* worth reaching for a kind of work, which is a judgement no `/models` call
|
|
21
|
+
* answers, and they become routable only once an operator saves them onto a
|
|
22
|
+
* provider.
|
|
23
|
+
*/
|
|
24
|
+
export interface ProviderBlueprint {
|
|
25
|
+
/** The `providerId` a created provider gets by default. */
|
|
26
|
+
providerId: string;
|
|
27
|
+
/** Display name. */
|
|
28
|
+
name: string;
|
|
29
|
+
tier: ProviderTier;
|
|
30
|
+
dialect: ProviderDialect;
|
|
31
|
+
credentialKind: CredentialKind;
|
|
32
|
+
/**
|
|
33
|
+
* Where it lives. Absent for the two first-party dialects, whose SDKs carry
|
|
34
|
+
* their own host, and for the self-hosted gateways and local runners, which
|
|
35
|
+
* have no public instance to point at and resolve only once an operator says
|
|
36
|
+
* where theirs is.
|
|
37
|
+
*/
|
|
38
|
+
baseUrl?: string;
|
|
39
|
+
/** One line on what this provider is for, shown under its name in the picker. */
|
|
40
|
+
note: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The blueprints, in the order the console offers them: the model vendors
|
|
44
|
+
* first, then the gateways that resell them, then the servers an operator runs.
|
|
45
|
+
*/
|
|
46
|
+
export declare const PROVIDER_BLUEPRINTS: readonly ProviderBlueprint[];
|
|
47
|
+
/** A blueprint, on the wire. */
|
|
48
|
+
export declare const ProviderBlueprintSchema: import("valibot").ObjectSchema<{
|
|
49
|
+
readonly providerId: import("valibot").StringSchema<undefined>;
|
|
50
|
+
readonly name: import("valibot").StringSchema<undefined>;
|
|
51
|
+
readonly tier: import("valibot").PicklistSchema<readonly ["subscription", "direct", "local", "umbrella"], undefined>;
|
|
52
|
+
readonly dialect: import("valibot").PicklistSchema<readonly ["openai", "anthropic", "openai-compatible", "workers-ai"], undefined>;
|
|
53
|
+
readonly credentialKind: import("valibot").PicklistSchema<readonly ["api-key", "subscription", "none"], undefined>;
|
|
54
|
+
readonly baseUrl: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
55
|
+
readonly note: import("valibot").StringSchema<undefined>;
|
|
56
|
+
}, undefined>;
|
|
57
|
+
/** A subscription vendor the console can offer, with what it takes to store one. */
|
|
58
|
+
export declare const SubscriptionVendorOptionSchema: import("valibot").ObjectSchema<{
|
|
59
|
+
readonly vendor: import("valibot").StringSchema<undefined>;
|
|
60
|
+
readonly label: import("valibot").StringSchema<undefined>;
|
|
61
|
+
readonly baseUrl: import("valibot").StringSchema<undefined>;
|
|
62
|
+
readonly dialect: import("valibot").StringSchema<undefined>;
|
|
63
|
+
/** Where the credential goes: `bearer` or `api-key`. */
|
|
64
|
+
readonly authScheme: import("valibot").StringSchema<undefined>;
|
|
65
|
+
/** Whether the vendor licenses the plan to one named individual. */
|
|
66
|
+
readonly individualOnly: import("valibot").BooleanSchema<undefined>;
|
|
67
|
+
}, undefined>;
|
|
68
|
+
/**
|
|
69
|
+
* Everything the console needs to render its "add a provider" screens without
|
|
70
|
+
* restating this package's tables in Vue.
|
|
71
|
+
*/
|
|
72
|
+
export declare const CatalogResponseSchema: import("valibot").ObjectSchema<{
|
|
73
|
+
readonly success: import("valibot").BooleanSchema<undefined>;
|
|
74
|
+
readonly error: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
75
|
+
} & {
|
|
76
|
+
providers: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
77
|
+
readonly providerId: import("valibot").StringSchema<undefined>;
|
|
78
|
+
readonly name: import("valibot").StringSchema<undefined>;
|
|
79
|
+
readonly tier: import("valibot").PicklistSchema<readonly ["subscription", "direct", "local", "umbrella"], undefined>;
|
|
80
|
+
readonly dialect: import("valibot").PicklistSchema<readonly ["openai", "anthropic", "openai-compatible", "workers-ai"], undefined>;
|
|
81
|
+
readonly credentialKind: import("valibot").PicklistSchema<readonly ["api-key", "subscription", "none"], undefined>;
|
|
82
|
+
readonly baseUrl: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
83
|
+
readonly note: import("valibot").StringSchema<undefined>;
|
|
84
|
+
}, undefined>, undefined>, undefined>;
|
|
85
|
+
subscriptionVendors: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
86
|
+
readonly vendor: import("valibot").StringSchema<undefined>;
|
|
87
|
+
readonly label: import("valibot").StringSchema<undefined>;
|
|
88
|
+
readonly baseUrl: import("valibot").StringSchema<undefined>;
|
|
89
|
+
readonly dialect: import("valibot").StringSchema<undefined>;
|
|
90
|
+
/** Where the credential goes: `bearer` or `api-key`. */
|
|
91
|
+
readonly authScheme: import("valibot").StringSchema<undefined>;
|
|
92
|
+
/** Whether the vendor licenses the plan to one named individual. */
|
|
93
|
+
readonly individualOnly: import("valibot").BooleanSchema<undefined>;
|
|
94
|
+
}, undefined>, undefined>, undefined>;
|
|
95
|
+
tiers: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").PicklistSchema<readonly ["subscription", "direct", "local", "umbrella"], undefined>, undefined>, undefined>;
|
|
96
|
+
/** The built-in tier order, so the preset editor can show what "default" means. */
|
|
97
|
+
defaultTierPreference: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").PicklistSchema<readonly ["subscription", "direct", "local", "umbrella"], undefined>, undefined>, undefined>;
|
|
98
|
+
/**
|
|
99
|
+
* The models this deployment surfaces by name, with the id each is reached
|
|
100
|
+
* under. Served rather than imported for the same reason the blueprints are:
|
|
101
|
+
* a consumer built against an older contract package would otherwise offer a
|
|
102
|
+
* model this service has since repinned, and the mistake would surface as a
|
|
103
|
+
* request that stopped answering.
|
|
104
|
+
*/
|
|
105
|
+
featuredModels: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
106
|
+
readonly model: import("valibot").StringSchema<undefined>;
|
|
107
|
+
readonly label: import("valibot").StringSchema<undefined>;
|
|
108
|
+
readonly purpose: import("valibot").PicklistSchema<readonly ["creative-writing"], undefined>;
|
|
109
|
+
readonly providerId: import("valibot").StringSchema<undefined>;
|
|
110
|
+
readonly providerModelId: import("valibot").StringSchema<undefined>;
|
|
111
|
+
readonly flagship: import("valibot").BooleanSchema<undefined>;
|
|
112
|
+
readonly note: import("valibot").StringSchema<undefined>;
|
|
113
|
+
}, undefined>, undefined>, undefined>;
|
|
114
|
+
}, undefined>;
|
|
115
|
+
export type CatalogResponse = InferOutput<typeof CatalogResponseSchema>;
|
|
116
|
+
/**
|
|
117
|
+
* Model ids a provider says it serves.
|
|
118
|
+
*
|
|
119
|
+
* Read from the provider, never from a table here: an operator adding a gateway
|
|
120
|
+
* wants the models that gateway has today, and the endpoint that answers that
|
|
121
|
+
* question is the gateway's own. A provider whose dialect has no such endpoint
|
|
122
|
+
* reports `supported: false` rather than an empty list, because "this provider
|
|
123
|
+
* serves nothing" and "there is no way to ask" are different facts and only one
|
|
124
|
+
* of them means the operator should type the ids in by hand.
|
|
125
|
+
*/
|
|
126
|
+
export declare const DiscoveredModelsResponseSchema: import("valibot").ObjectSchema<{
|
|
127
|
+
readonly success: import("valibot").BooleanSchema<undefined>;
|
|
128
|
+
readonly error: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
129
|
+
} & {
|
|
130
|
+
providerId: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
131
|
+
supported: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
132
|
+
models: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>, undefined>;
|
|
133
|
+
/** Why discovery could not answer, when it could not. */
|
|
134
|
+
failure: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
135
|
+
}, undefined>;
|
|
136
|
+
export type DiscoveredModelsResponse = InferOutput<typeof DiscoveredModelsResponseSchema>;
|
|
137
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAA4C,MAAM,SAAS,CAAC;AAErF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,iBAAiB,EAgJ3D,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,uBAAuB;;;;;;;;aAQlC,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,8BAA8B;;;;;IAKzC,wDAAwD;;IAExD,oEAAoE;;aAEpE,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;QAVhC,wDAAwD;;QAExD,oEAAoE;;;;IAYpE,mFAAmF;;IAEnF;;;;;;OAMG;;;;;;;;;;aAEH,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B;;;;;;;IAIzC,yDAAyD;;aAEzD,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,WAAW,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { createSuccessResponseSchema } from "@game-infra/api-schemas-core";
|
|
2
|
+
import { array, boolean, object, optional, string } from "valibot";
|
|
3
|
+
import { FeaturedModelSchema } from "./featuredModels.js";
|
|
4
|
+
import { ProviderDialectSchema, CredentialKindSchema, ProviderTierSchema, } from "./provider.js";
|
|
5
|
+
/**
|
|
6
|
+
* The blueprints, in the order the console offers them: the model vendors
|
|
7
|
+
* first, then the gateways that resell them, then the servers an operator runs.
|
|
8
|
+
*/
|
|
9
|
+
export const PROVIDER_BLUEPRINTS = [
|
|
10
|
+
{
|
|
11
|
+
providerId: "openai",
|
|
12
|
+
name: "OpenAI",
|
|
13
|
+
tier: "direct",
|
|
14
|
+
dialect: "openai",
|
|
15
|
+
credentialKind: "api-key",
|
|
16
|
+
note: "OpenAI's own API. Native structured outputs.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
providerId: "anthropic",
|
|
20
|
+
name: "Anthropic",
|
|
21
|
+
tier: "direct",
|
|
22
|
+
dialect: "anthropic",
|
|
23
|
+
credentialKind: "api-key",
|
|
24
|
+
note: "Anthropic's own API. Native tool-schema structured outputs and prompt caching.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
providerId: "google",
|
|
28
|
+
name: "Google Gemini",
|
|
29
|
+
tier: "direct",
|
|
30
|
+
dialect: "openai-compatible",
|
|
31
|
+
credentialKind: "api-key",
|
|
32
|
+
baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
33
|
+
note: "Gemini through Google's OpenAI-compatible endpoint.",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
providerId: "mistral",
|
|
37
|
+
name: "Mistral",
|
|
38
|
+
tier: "direct",
|
|
39
|
+
dialect: "openai-compatible",
|
|
40
|
+
credentialKind: "api-key",
|
|
41
|
+
baseUrl: "https://api.mistral.ai/v1",
|
|
42
|
+
note: "Mistral's own API.",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
providerId: "deepseek",
|
|
46
|
+
name: "DeepSeek",
|
|
47
|
+
tier: "direct",
|
|
48
|
+
dialect: "openai-compatible",
|
|
49
|
+
credentialKind: "api-key",
|
|
50
|
+
baseUrl: "https://api.deepseek.com",
|
|
51
|
+
note: "DeepSeek's own API.",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
providerId: "qwen",
|
|
55
|
+
name: "Qwen (DashScope)",
|
|
56
|
+
tier: "direct",
|
|
57
|
+
dialect: "openai-compatible",
|
|
58
|
+
credentialKind: "api-key",
|
|
59
|
+
baseUrl: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
|
60
|
+
note: "Alibaba's shared DashScope domain. An account with a workspace-dedicated domain " +
|
|
61
|
+
"replaces this base URL with its own.",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
providerId: "moonshot",
|
|
65
|
+
name: "Moonshot (Kimi)",
|
|
66
|
+
tier: "direct",
|
|
67
|
+
dialect: "openai-compatible",
|
|
68
|
+
credentialKind: "api-key",
|
|
69
|
+
baseUrl: "https://api.moonshot.ai/v1",
|
|
70
|
+
note: "Moonshot's own API.",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
providerId: "xai",
|
|
74
|
+
name: "xAI",
|
|
75
|
+
tier: "direct",
|
|
76
|
+
dialect: "openai-compatible",
|
|
77
|
+
credentialKind: "api-key",
|
|
78
|
+
baseUrl: "https://api.x.ai/v1",
|
|
79
|
+
note: "xAI's own API.",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
providerId: "openrouter",
|
|
83
|
+
name: "OpenRouter",
|
|
84
|
+
tier: "umbrella",
|
|
85
|
+
dialect: "openai-compatible",
|
|
86
|
+
credentialKind: "api-key",
|
|
87
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
88
|
+
note: "One key for most vendors' models, at a resale price. The usual first fallback.",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
providerId: "workers-ai",
|
|
92
|
+
name: "Cloudflare Workers AI",
|
|
93
|
+
tier: "umbrella",
|
|
94
|
+
dialect: "workers-ai",
|
|
95
|
+
credentialKind: "none",
|
|
96
|
+
note: "Cloudflare's hosted models through ai-service's own AI binding. No account id, no API " +
|
|
97
|
+
"token and no egress: the call is served inside the runtime. Add it and it works.",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
providerId: "bifrost",
|
|
101
|
+
name: "Bifrost",
|
|
102
|
+
tier: "umbrella",
|
|
103
|
+
dialect: "openai-compatible",
|
|
104
|
+
credentialKind: "api-key",
|
|
105
|
+
note: "A self-hosted gateway. No public instance, so it resolves only once its URL is set.",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
providerId: "litellm",
|
|
109
|
+
name: "LiteLLM",
|
|
110
|
+
tier: "umbrella",
|
|
111
|
+
dialect: "openai-compatible",
|
|
112
|
+
credentialKind: "api-key",
|
|
113
|
+
note: "A self-hosted gateway. Model ids are the operator's own config.yaml aliases.",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
providerId: "vllm",
|
|
117
|
+
name: "vLLM",
|
|
118
|
+
tier: "local",
|
|
119
|
+
dialect: "openai-compatible",
|
|
120
|
+
credentialKind: "none",
|
|
121
|
+
baseUrl: "http://localhost:8000/v1",
|
|
122
|
+
note: "A vLLM server. Serves whatever weights it was started with.",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
providerId: "ollama",
|
|
126
|
+
name: "Ollama",
|
|
127
|
+
tier: "local",
|
|
128
|
+
dialect: "openai-compatible",
|
|
129
|
+
credentialKind: "none",
|
|
130
|
+
baseUrl: "http://localhost:11434/v1",
|
|
131
|
+
note: "An Ollama server. Model ids are the tags it has pulled.",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
providerId: "lmstudio",
|
|
135
|
+
name: "LM Studio",
|
|
136
|
+
tier: "local",
|
|
137
|
+
dialect: "openai-compatible",
|
|
138
|
+
credentialKind: "none",
|
|
139
|
+
baseUrl: "http://localhost:1234/v1",
|
|
140
|
+
note: "An LM Studio server.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
providerId: "llamacpp",
|
|
144
|
+
name: "llama.cpp",
|
|
145
|
+
tier: "local",
|
|
146
|
+
dialect: "openai-compatible",
|
|
147
|
+
credentialKind: "none",
|
|
148
|
+
baseUrl: "http://localhost:8080/v1",
|
|
149
|
+
note: "A llama-server instance.",
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
/** A blueprint, on the wire. */
|
|
153
|
+
export const ProviderBlueprintSchema = object({
|
|
154
|
+
providerId: string(),
|
|
155
|
+
name: string(),
|
|
156
|
+
tier: ProviderTierSchema,
|
|
157
|
+
dialect: ProviderDialectSchema,
|
|
158
|
+
credentialKind: CredentialKindSchema,
|
|
159
|
+
baseUrl: optional(string()),
|
|
160
|
+
note: string(),
|
|
161
|
+
});
|
|
162
|
+
/** A subscription vendor the console can offer, with what it takes to store one. */
|
|
163
|
+
export const SubscriptionVendorOptionSchema = object({
|
|
164
|
+
vendor: string(),
|
|
165
|
+
label: string(),
|
|
166
|
+
baseUrl: string(),
|
|
167
|
+
dialect: string(),
|
|
168
|
+
/** Where the credential goes: `bearer` or `api-key`. */
|
|
169
|
+
authScheme: string(),
|
|
170
|
+
/** Whether the vendor licenses the plan to one named individual. */
|
|
171
|
+
individualOnly: boolean(),
|
|
172
|
+
});
|
|
173
|
+
/**
|
|
174
|
+
* Everything the console needs to render its "add a provider" screens without
|
|
175
|
+
* restating this package's tables in Vue.
|
|
176
|
+
*/
|
|
177
|
+
export const CatalogResponseSchema = createSuccessResponseSchema({
|
|
178
|
+
providers: optional(array(ProviderBlueprintSchema)),
|
|
179
|
+
subscriptionVendors: optional(array(SubscriptionVendorOptionSchema)),
|
|
180
|
+
tiers: optional(array(ProviderTierSchema)),
|
|
181
|
+
/** The built-in tier order, so the preset editor can show what "default" means. */
|
|
182
|
+
defaultTierPreference: optional(array(ProviderTierSchema)),
|
|
183
|
+
/**
|
|
184
|
+
* The models this deployment surfaces by name, with the id each is reached
|
|
185
|
+
* under. Served rather than imported for the same reason the blueprints are:
|
|
186
|
+
* a consumer built against an older contract package would otherwise offer a
|
|
187
|
+
* model this service has since repinned, and the mistake would surface as a
|
|
188
|
+
* request that stopped answering.
|
|
189
|
+
*/
|
|
190
|
+
featuredModels: optional(array(FeaturedModelSchema)),
|
|
191
|
+
});
|
|
192
|
+
/**
|
|
193
|
+
* Model ids a provider says it serves.
|
|
194
|
+
*
|
|
195
|
+
* Read from the provider, never from a table here: an operator adding a gateway
|
|
196
|
+
* wants the models that gateway has today, and the endpoint that answers that
|
|
197
|
+
* question is the gateway's own. A provider whose dialect has no such endpoint
|
|
198
|
+
* reports `supported: false` rather than an empty list, because "this provider
|
|
199
|
+
* serves nothing" and "there is no way to ask" are different facts and only one
|
|
200
|
+
* of them means the operator should type the ids in by hand.
|
|
201
|
+
*/
|
|
202
|
+
export const DiscoveredModelsResponseSchema = createSuccessResponseSchema({
|
|
203
|
+
providerId: optional(string()),
|
|
204
|
+
supported: optional(boolean()),
|
|
205
|
+
models: optional(array(string())),
|
|
206
|
+
/** Why discovery could not answer, when it could not. */
|
|
207
|
+
failure: optional(string()),
|
|
208
|
+
});
|
|
209
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|