File size: 2,424 Bytes
4e23b01 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | /**
* `modelService` — model configuration registry. Mirrors
* `agent-core-v2/llm-adapter/model/model.ts` (`ModelRecordSchema`, including its
* passthrough of unknown keys) and `agent-core-v2/llm-adapter/protocol/protocol.ts`
* (`ProtocolSchema` — the four real wire protocols; `kimi` is a provider
* `type`, not a protocol, and Vertex AI is a `providerOptions` mode of
* `google-genai`). The schema name stays `modelConfigSchema` while the
* engine type is `ModelRecord` — the contract-parity test pins that pairing.
*/
import { z } from 'zod';
import { maybe, noResult } from '../helpers.js';
import type { ServiceContract } from '../types.js';
const protocolSchema = z.enum([
'anthropic',
'openai',
'openai_responses',
'google-genai',
]);
const oAuthRefSchema = z.object({
storage: z.enum(['file', 'keyring']),
key: z.string().min(1),
oauthHost: z.string().min(1).optional(),
});
const modelBaseSchema = z.object({
providerId: z.string().optional(),
baseUrl: z.string().optional(),
apiKey: z.string().optional(),
oauth: oAuthRefSchema.optional(),
protocol: protocolSchema.optional(),
name: z.string().optional(),
aliases: z.array(z.string()).optional(),
provider: z.string().optional(),
model: z.string().optional(),
maxContextSize: z.number().int().min(1).optional(),
maxOutputSize: z.number().int().min(1).optional(),
capabilities: z.array(z.string()).optional(),
displayName: z.string().optional(),
reasoningKey: z.string().optional(),
adaptiveThinking: z.boolean().optional(),
betaApi: z.boolean().optional(),
supportEfforts: z.array(z.string()).optional(),
defaultEffort: z.string().optional(),
});
const modelOverrideSchema = modelBaseSchema
.omit({
providerId: true,
baseUrl: true,
apiKey: true,
oauth: true,
protocol: true,
name: true,
aliases: true,
provider: true,
model: true,
betaApi: true,
})
.partial();
export const modelConfigSchema = modelBaseSchema
.extend({ overrides: modelOverrideSchema.optional() })
.passthrough();
export const modelsContract = {
get: { input: z.tuple([z.string()]), output: maybe(modelConfigSchema) },
list: { input: z.tuple([]), output: z.record(z.string(), modelConfigSchema) },
set: { input: z.tuple([z.string(), modelConfigSchema]), output: noResult },
delete: { input: z.tuple([z.string()]), output: noResult },
} satisfies ServiceContract;
|