import { Interface, Namespace, Program } from "@typespec/compiler"; import { TypeNode } from "./ast.js"; import type { PolymorphicDispatchDecl } from "./declarations.js"; import { CallableVector } from "./vector.js"; export type CallableContractSourceKind = "legacy-protocol-model" | "typespec-interface"; export interface CallableSource { kind: CallableContractSourceKind; namespace: string; symbol: string; group: string; } export interface CallableHydrationSeam { seamKind: "protocol-adapter"; implementation: "handwritten"; generatedBoundary: "interface"; } /** * Behavioral polymorphic dispatch metadata attached to a seam interface by * `@dispatch`. The interface is resolved at runtime by the value of the * discriminator field, read at a deterministic access path from the seam * methods' parameters. This carries the mechanism only — never a roster of * concrete implementations, which stay runtime-registered. */ export interface CallableDispatch { /** The discriminator ModelProperty, identified by its owning model + field. */ discriminator: { /** Name of the model that declares the discriminator field. */ model: string; /** Name of the discriminator field. */ field: string; }; /** * Deterministic field-access path from a seam parameter to the discriminator * field, e.g. `agent.template.format.kind`. Uniquely reachable from the * parameter set — an unreachable or ambiguous field is a diagnostic, not a * guessed path. */ path: string; /** * The SAME lowered `PolymorphicDispatchDecl` that drives the discriminator * model's shape `Load` switch, resolved from `discriminator.model`. This is * the Part III IR edge: it lets every emitter render the behavioral resolver * as the twin of the shape switch (same `variants`, `isClosed`, * `defaultVariant`) instead of interpreting a stringly-typed runtime path. * Absent only when the discriminator model is not polymorphic (no * discriminator + child types), which keeps undispatched-adjacent shapes * byte-identical. */ decl?: PolymorphicDispatchDecl; } export interface CallableOperation { name: string; returns: string; description: string; params: Record; optional: boolean; sync: boolean; runtimeCancellable: boolean; atomic: boolean; nonFatal: boolean; vectors?: CallableVector[]; source: CallableSource; } export interface CallableContract { name: string; namespace: string; group: string; description: string; source: CallableSource; hydration: CallableHydrationSeam; operations: CallableOperation[]; /** * Present when the interface is decorated with `@dispatch`. Absent for plain * seam interfaces, keeping the shape byte-identical for undecorated contracts. */ dispatch?: CallableDispatch; } export declare function lowerLegacyCallableContracts(nodes: TypeNode[]): CallableContract[]; export declare function lowerLegacyCallableContract(node: TypeNode): CallableContract; export declare function collectNamespaceCallableInterfaces(namespace: Namespace, interfaces?: Interface[]): Interface[]; export declare function lowerTypeSpecCallableContracts(program: Program, namespace: Namespace, rootNamespace: string, rootAlias: string): CallableContract[]; export declare function lowerTypeSpecCallableContract(program: Program, iface: Interface, rootNamespace: string, rootAlias: string): CallableContract; export declare function callableContractToProtocolNode(contract: CallableContract): TypeNode;