File size: 2,296 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 | import type { AgentId } from '../model/ids';
import { AgentTranscript, type Disposable } from './agentTranscript';
export interface AgentDescriptor {
readonly agentId: AgentId;
readonly type?: 'main' | 'sub' | 'independent';
readonly parentAgentId?: AgentId;
readonly label?: string;
readonly createdAt?: string;
readonly disposedAt?: string;
}
export type RosterListener = (agents: readonly AgentDescriptor[]) => void;
export class TranscriptStore {
readonly #agents = new Map<AgentId, AgentTranscript>();
readonly #descriptors = new Map<AgentId, AgentDescriptor>();
readonly #rosterListeners = new Set<RosterListener>();
constructor(readonly sessionId: string) { }
ensureAgent(agentId: AgentId, descriptor?: AgentDescriptor): AgentTranscript {
let transcript = this.#agents.get(agentId);
if (!transcript) {
transcript = new AgentTranscript(agentId);
this.#agents.set(agentId, transcript);
}
if (descriptor && this.#descriptors.get(agentId) !== descriptor) {
this.#descriptors.set(agentId, descriptor);
this.#emitRoster();
}
return transcript;
}
getAgent(agentId: AgentId): AgentTranscript | undefined {
return this.#agents.get(agentId);
}
removeAgent(agentId: AgentId): boolean {
const removed = this.#agents.delete(agentId);
if (this.#descriptors.delete(agentId) || removed) this.#emitRoster();
return removed;
}
describeAgent(descriptor: AgentDescriptor): void {
if (this.#descriptors.get(descriptor.agentId) !== descriptor) {
this.#descriptors.set(descriptor.agentId, descriptor);
this.#emitRoster();
}
}
markDisposed(agentId: AgentId, disposedAt: string): void {
const descriptor = this.#descriptors.get(agentId);
if (descriptor === undefined || descriptor.disposedAt !== undefined) return;
this.describeAgent({ ...descriptor, disposedAt });
}
agents(): readonly AgentDescriptor[] {
return [...this.#descriptors.values()];
}
onRosterChange(listener: RosterListener): Disposable {
this.#rosterListeners.add(listener);
return { dispose: () => void this.#rosterListeners.delete(listener) };
}
#emitRoster(): void {
const agents = this.agents();
for (const listener of this.#rosterListeners) listener(agents);
}
}
|