1import * as Effect from "effect/Effect";
2import * as Schema from "effect/Schema";
3import * as SchemaTransformation from "effect/SchemaTransformation";
4
5import { TrimmedNonEmptyString } from "./baseSchemas.ts";
6import { ProviderOptionSelections } from "./model.ts";
7import { ProviderInstanceId } from "./providerInstance.ts";
8
9/**
10 * Selection of a model on a configured provider instance.
11 *
12 * `instanceId` is the routing key. The provider driver, credentials,
13 * environment, and continuation identity are resolved by the provider
14 * instance registry rather than encoded into the selection itself.
15 */
16const ModelSelectionWire = Schema.Struct({
17 instanceId: ProviderInstanceId,
18 model: TrimmedNonEmptyString,
19 options: Schema.optionalKey(ProviderOptionSelections),
20});
21
22const ModelSelectionSource = Schema.Struct({
23 provider: Schema.optional(Schema.Unknown),
24 instanceId: Schema.optional(Schema.Unknown),
25 model: Schema.Unknown,
26 options: Schema.optional(Schema.Unknown),
27});
28
29/**
30 * The decoder still accepts the historical `{ provider, model }` shape while
31 * V1 persistence remains readable. Runtime code only receives the canonical
32 * instance-based representation.
33 */
34export const ModelSelection = ModelSelectionSource.pipe(
35 Schema.decodeTo(
36 ModelSelectionWire,
37 SchemaTransformation.transformEffect({
38 decode: (raw) => {
39 const instanceIdSource =
40 raw.instanceId !== undefined
41 ? raw.instanceId
42 : typeof raw.provider === "string"
43 ? raw.provider
44 : undefined;
45 const base: Record<string, unknown> = {
46 instanceId: instanceIdSource,
47 model: raw.model,
48 };
49 if (raw.options !== undefined) base.options = raw.options;
50 return Effect.succeed(base as typeof ModelSelectionWire.Encoded);
51 },
52 encode: (value) => {
53 const base: Record<string, unknown> = {
54 instanceId: value.instanceId,
55 model: value.model,
56 };
57 if (value.options !== undefined) base.options = value.options;
58 return Effect.succeed(base as typeof ModelSelectionSource.Encoded);
59 },
60 }),
61 ),
62);
63export type ModelSelection = typeof ModelSelection.Type;