84 lines
3.0 KiB
TypeScript
84 lines
3.0 KiB
TypeScript
/** DTOs for the internal bridge API consumed by agent-comms host daemons. */
|
|
|
|
export interface BridgeMessageDto {
|
|
room_id: string;
|
|
/** Agent slug (localpart suffix), e.g. "pi0-web1". */
|
|
agent: string;
|
|
body: string;
|
|
thread_root?: string;
|
|
msgtype?: string;
|
|
/** Optional protocol payload merged into content (e.g. org.uscllc.agent). */
|
|
extra_content?: Record<string, unknown>;
|
|
}
|
|
|
|
export interface BridgeTypingDto {
|
|
room_id: string;
|
|
agent: string;
|
|
typing: boolean;
|
|
}
|
|
|
|
const AGENT_SLUG_RE = /^[a-z0-9][a-z0-9_.-]*$/;
|
|
|
|
const assertAgentSlug = (agent: unknown): void => {
|
|
if (typeof agent !== 'string' || !AGENT_SLUG_RE.test(agent.toLowerCase())) {
|
|
throw new Error('agent must match [a-z0-9][a-z0-9_.-]*');
|
|
}
|
|
};
|
|
|
|
export function validateBridgeMessage(input: unknown): asserts input is BridgeMessageDto {
|
|
const o = input as Partial<BridgeMessageDto> | null | undefined;
|
|
if (!o || typeof o !== 'object') throw new Error('payload must be an object');
|
|
if (typeof o.room_id !== 'string' || !o.room_id.startsWith('!'))
|
|
throw new Error('room_id must be a Matrix room id');
|
|
assertAgentSlug(o.agent);
|
|
if (typeof o.body !== 'string') throw new Error('body must be a string');
|
|
if (o.thread_root !== undefined && typeof o.thread_root !== 'string')
|
|
throw new Error('thread_root must be a string');
|
|
if (
|
|
o.extra_content !== undefined &&
|
|
(typeof o.extra_content !== 'object' || o.extra_content === null)
|
|
) {
|
|
throw new Error('extra_content must be an object');
|
|
}
|
|
}
|
|
|
|
export function validateBridgeTyping(input: unknown): asserts input is BridgeTypingDto {
|
|
const o = input as Partial<BridgeTypingDto> | null | undefined;
|
|
if (!o || typeof o !== 'object') throw new Error('payload must be an object');
|
|
if (typeof o.room_id !== 'string' || !o.room_id.startsWith('!'))
|
|
throw new Error('room_id must be a Matrix room id');
|
|
assertAgentSlug(o.agent);
|
|
if (typeof o.typing !== 'boolean') throw new Error('typing must be a boolean');
|
|
}
|
|
|
|
export interface ProvisionRoomDto {
|
|
name: string;
|
|
alias?: string;
|
|
topic?: string;
|
|
invite?: string[];
|
|
space_id?: string;
|
|
}
|
|
|
|
export function validateProvisionRoom(input: unknown): asserts input is ProvisionRoomDto {
|
|
const o = input as Partial<ProvisionRoomDto> | null | undefined;
|
|
if (!o || typeof o !== 'object') throw new Error('payload must be an object');
|
|
if (typeof o.name !== 'string' || o.name.length === 0) throw new Error('name is required');
|
|
if (o.alias !== undefined && (!/^[a-z0-9_.-]+$/.test(o.alias) || o.alias.length > 200)) {
|
|
throw new Error('alias must match [a-z0-9_.-]+ (max 200 chars)');
|
|
}
|
|
if (o.invite !== undefined) {
|
|
if (
|
|
!Array.isArray(o.invite) ||
|
|
o.invite.some((u) => typeof u !== 'string' || !u.startsWith('@'))
|
|
) {
|
|
throw new Error('invite must be a list of Matrix user ids');
|
|
}
|
|
if (o.invite.length > 50) {
|
|
throw new Error('invite list exceeds maximum of 50');
|
|
}
|
|
}
|
|
if (o.space_id !== undefined && (typeof o.space_id !== 'string' || !o.space_id.startsWith('!'))) {
|
|
throw new Error('space_id must be a Matrix room id');
|
|
}
|
|
}
|