b164ef945c
- MailInternalDto accepts attachments[]; deposit() stores each as a media part (image/video→MEDIA_REF, audio→VOICE_REF, else FILE_REF) - ingest now persists part sizeBytes; contract + DTO carry it - threads.getMessages returns mimeType + sizeBytes so mail readers can render inline images / file chips - test: internal mail stores an image attachment as a MEDIA_REF part Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { Type } from 'class-transformer';
|
|
import {
|
|
IsArray,
|
|
IsInt,
|
|
IsISO8601,
|
|
IsObject,
|
|
IsOptional,
|
|
IsString,
|
|
ValidateNested,
|
|
} from 'class-validator';
|
|
|
|
class ScopeDto {
|
|
@IsString() orgId!: string;
|
|
@IsString() appId!: string;
|
|
@IsOptional() @IsString() buId?: string;
|
|
@IsOptional() @IsString() tenantId?: string;
|
|
@IsOptional() @IsString() workspaceId?: string;
|
|
@IsOptional() @IsString() projectId?: string;
|
|
@IsOptional() @IsString() userScopeId?: string;
|
|
}
|
|
|
|
class ChannelDto {
|
|
@IsString() type!: string;
|
|
@IsOptional() @IsString() externalChannelId?: string;
|
|
@IsOptional() @IsObject() capabilityContract?: Record<string, unknown>;
|
|
}
|
|
|
|
class SourceDto {
|
|
@IsString() handleKind!: string;
|
|
@IsString() externalId!: string;
|
|
@IsOptional() @IsString() displayName?: string;
|
|
}
|
|
|
|
class ThreadDto {
|
|
@IsOptional() @IsString() externalThreadId?: string;
|
|
@IsOptional() @IsString() subject?: string;
|
|
}
|
|
|
|
class PartDto {
|
|
@IsString() kind!: string;
|
|
@IsOptional() @IsString() bodyText?: string;
|
|
@IsOptional() @IsString() contentRef?: string;
|
|
@IsOptional() @IsString() mimeType?: string;
|
|
@IsOptional() @IsInt() sizeBytes?: number;
|
|
}
|
|
|
|
/** Validates the POST /v1/interactions/ingest body (conforms to IngestInteractionRequest). */
|
|
export class IngestRequestDto {
|
|
@ValidateNested() @Type(() => ScopeDto) scope!: ScopeDto;
|
|
@ValidateNested() @Type(() => ChannelDto) channel!: ChannelDto;
|
|
@ValidateNested() @Type(() => SourceDto) source!: SourceDto;
|
|
@IsOptional() @IsString() kind?: string;
|
|
@IsOptional() @ValidateNested() @Type(() => ThreadDto) thread?: ThreadDto;
|
|
@IsArray() @ValidateNested({ each: true }) @Type(() => PartDto) parts!: PartDto[];
|
|
@IsISO8601() occurredAt!: string;
|
|
@IsOptional() @IsString() providerEventId?: string;
|
|
@IsOptional() @IsObject() metadata?: Record<string, unknown>;
|
|
}
|