export class AgentRoster<
Id extends string,
Definitions extends Readonly<Record<string, AgentRuntimeLike>>,
> {
readonly [agentRosterTypeId] = agentRosterTypeId;
readonly definitionId: Id;
readonly definitions: Definitions;
readonly validatedDefinitions: ReadonlyArray<
ValidatedAgentDefinition<Definitions>
>;
readonly startedAgents: Context.Tag<
AgentsService<Id, Definitions>,
StartedAgents<Definitions>
>;
private constructor(
definitionId: Id,
definitions: Definitions,
validatedDefinitions: ReadonlyArray<ValidatedAgentDefinition<Definitions>>,
startedAgents: Context.Tag<
AgentsService<Id, Definitions>,
StartedAgents<Definitions>
>,
) {
this.definitionId = definitionId;
this.definitions = definitions;
this.validatedDefinitions = validatedDefinitions;
this.startedAgents = startedAgents;
}
static make<
const Id extends string,
const Definitions extends Readonly<Record<string, AgentRuntimeLike>>,
>(
definitionId: Id,
runtimes: Definitions,
): AgentRoster<Id, Definitions> {
const entries = Object.entries(runtimes);
const validatedDefinitions =
/* Safe because each own record entry retains its key and indexed runtime value. */ Object.freeze(
entries.map(([name, runtime]) =>
Object.freeze({
name,
agentName: Schema.decodeUnknownSync(agentName)(name),
runtime,
}),
),
) as ReadonlyArray<ValidatedAgentDefinition<Definitions>>;
nextRosterServiceId += 1;
const definitions =
/* Safe because the surrounding invariant establishes this asserted shape. */ Object.freeze(
Object.fromEntries(entries),
) as Definitions;
const agentsValue = Context.GenericTag<
AgentsService<Id, Definitions>,
StartedAgents<Definitions>
>(`@moltzap/simulator/Agents/${definitionId}/${nextRosterServiceId}`);
return Object.freeze(
new AgentRoster(
definitionId,
definitions,
validatedDefinitions,
agentsValue,
),
);
}
}