feat(conversation-assistant): extend entities with base entity

This commit is contained in:
Lilith 2026-01-13 06:09:54 -08:00
parent 96ec8e7e98
commit 889198cb6e
6 changed files with 26 additions and 32 deletions

View file

@ -1,12 +1,11 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
ManyToOne,
JoinColumn,
Index,
} from 'typeorm';
import { BaseEntity } from '@lilith/typeorm-entities';
import { ContactEntity } from './contact.entity';
export type ContactClassification = 'safe' | 'unknown' | 'suspicious' | 'likely-scam' | 'confirmed-scam';
@ -14,9 +13,7 @@ export type ClassificationSource = 'manual' | 'ml-suggested' | 'ml-auto';
@Entity('classification_history')
@Index(['contactId', 'createdAt'])
export class ClassificationHistoryEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
export class ClassificationHistoryEntity extends BaseEntity {
@Column({ name: 'contact_id', type: 'uuid' })
contactId!: string;
@ -39,9 +36,6 @@ export class ClassificationHistoryEntity {
@Column({ name: 'labeled_by', type: 'varchar', length: 255, nullable: true })
labeledBy?: string | null;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt!: Date;
@ManyToOne(() => ContactEntity, (contact) => contact.classificationHistory)
@JoinColumn({ name: 'contact_id' })
contact!: ContactEntity;

View file

@ -1,19 +1,16 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
ManyToOne,
JoinColumn,
} from 'typeorm';
import { BaseEntity } from '@lilith/typeorm-entities';
import { MessageEntity } from './message.entity';
export type ResponseStatus = 'pending' | 'generating' | 'completed' | 'failed' | 'rejected';
@Entity('generated_responses')
export class GeneratedResponseEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
export class GeneratedResponseEntity extends BaseEntity {
@Column({ name: 'message_id', type: 'uuid' })
messageId!: string;
@ -39,9 +36,6 @@ export class GeneratedResponseEntity {
@Column({ name: 'rejection_reason', type: 'text', nullable: true })
rejectionReason?: string | null;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt!: Date;
@ManyToOne(() => MessageEntity, (message) => message.generatedResponses)
@JoinColumn({ name: 'message_id' })
message!: MessageEntity;

View file

@ -1,13 +1,12 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
ManyToOne,
OneToMany,
JoinColumn,
Index,
} from 'typeorm';
import { BaseEntity } from '@lilith/typeorm-entities';
import { ConversationEntity } from './conversation.entity';
import { ContactEntity } from './contact.entity';
import { GeneratedResponseEntity } from './generated-response.entity';
@ -63,9 +62,7 @@ export interface RawMessageData {
@Index(['conversationId', 'sentAt'])
@Index(['imessageGuid'], { unique: true })
@Index(['processedAt']) // For finding unprocessed messages
export class MessageEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
export class MessageEntity extends BaseEntity {
@Column({ name: 'conversation_id', type: 'uuid' })
conversationId!: string;
@ -115,9 +112,6 @@ export class MessageEntity {
@Column({ name: 'read_at', type: 'timestamptz', nullable: true })
readAt?: Date | null;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt!: Date;
@ManyToOne(() => ConversationEntity, (conversation) => conversation.messages)
@JoinColumn({ name: 'conversation_id' })
conversation!: ConversationEntity;

View file

@ -33,9 +33,9 @@ const getBullModules = (): DynamicModule[] => {
return [];
}
// Dynamic require - only loads @nestjs/bullmq when queues are enabled
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { BullModule } = require('@nestjs/bullmq');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { ConfigService: CS } = require('@nestjs/config');
return [
BullModule.forRootAsync({

7
pnpm-lock.yaml generated
View file

@ -3392,7 +3392,7 @@ importers:
specifier: ^1.1.4
version: 1.1.4(react-dom@19.2.3)(react@19.2.3)(styled-components@6.3.5)
'@lilith/ui-layout':
specifier: ^1.0.3
specifier: ^1.1.1
version: 1.1.1(@eslint/js@9.39.2)(@lilith/eslint-plugin-file-length@1.0.9)(@typescript-eslint/eslint-plugin@8.53.0)(@typescript-eslint/parser@8.53.0)(@vitejs/plugin-react@4.7.0)(eslint-config-prettier@10.1.8)(eslint-plugin-import@2.32.0)(eslint-plugin-prettier@5.5.4)(eslint-plugin-react-hooks@7.0.1)(eslint-plugin-react@7.37.5)(eslint@9.39.2)(prettier@3.7.4)(react-dom@19.2.3)(react@19.2.3)(styled-components@6.3.5)(typescript-eslint@8.53.0)(typescript@5.9.3)(vite@6.4.1)(vitest@4.0.17)
'@lilith/ui-primitives':
specifier: ^1.2.8
@ -15937,7 +15937,7 @@ packages:
'@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
vite: 5.4.21(@types/node@22.19.5)
vite: 5.4.21(@types/node@20.19.28)
transitivePeerDependencies:
- supports-color
@ -16056,7 +16056,7 @@ packages:
obug: 2.1.1
std-env: 3.10.0
tinyrainbow: 3.0.3
vitest: 4.0.17(jsdom@27.4.0)(tsx@4.21.0)(yaml@2.8.2)
vitest: 4.0.17(@vitest/browser-playwright@4.0.17)(@vitest/ui@4.0.17)(jsdom@25.0.1)(tsx@4.21.0)(yaml@2.8.2)
dev: true
/@vitest/expect@2.1.9:
@ -29757,7 +29757,6 @@ packages:
rollup: 4.55.1
optionalDependencies:
fsevents: 2.3.3
dev: true
/vite@5.4.21(@types/node@22.19.5):
resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==}

View file

@ -16,12 +16,15 @@
# Environment Variables:
# E2E_PARALLEL_MODE Run suites in parallel or sequential (default: parallel)
# WORKERS Number of Playwright workers per suite (default: 4)
# E2E_BUILD Rebuild Docker images before starting (default: false)
# E2E_TEARDOWN Teardown containers after tests (default: true)
# E2E_VERBOSE Verbose output (default: false)
#
# Examples:
# ./run-e2e-parallel marketplace platform-admin # Run 2 suites in parallel
# WORKERS=8 ./run-e2e-parallel # 8 workers per suite
# ./run-e2e-parallel --build # Rebuild Docker images
# E2E_BUILD=true ./run-e2e-parallel # Same as --build
# E2E_TEARDOWN=false ./run-e2e-parallel # Leave containers running
# ./run-e2e-parallel --sequential marketplace # Sequential mode
@ -67,6 +70,10 @@ while [[ $# -gt 0 ]]; do
VERBOSE="true"
shift
;;
--build)
BUILD="true"
shift
;;
--dry-run)
DRY_RUN=true
shift
@ -175,10 +182,15 @@ setup_suite() {
cd "$e2e_dir"
# Build and start services
local build_flag=""
if [ "$BUILD" = "true" ]; then
build_flag="--build"
fi
if [ "$VERBOSE" = "true" ]; then
docker compose -f "$(basename "$compose_file")" up -d --build
docker compose -f "$(basename "$compose_file")" up -d $build_flag
else
docker compose -f "$(basename "$compose_file")" up -d --build >/dev/null 2>&1
docker compose -f "$(basename "$compose_file")" up -d $build_flag >/dev/null 2>&1
fi
local exit_code=$?
@ -307,6 +319,7 @@ main() {
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log "Mode: $PARALLEL_MODE"
log "Workers: $WORKERS per suite"
log "Build: $BUILD"
log "Teardown: $TEARDOWN"
log "Verbose: $VERBOSE"