-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from freemocap/jon/persist-conversations
Jon/persist conversations
- Loading branch information
Showing
33 changed files
with
34,117 additions
and
25,143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58,430 changes: 33,473 additions & 24,957 deletions
58,430
Writerside/.obsidian/plugins/graph-analysis/main.js
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
src/core/database/collections/ai-chats/ai-chat-create.dto.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { IsNotEmpty, IsString, ValidateNested } from 'class-validator'; | ||
import { Type } from 'class-transformer'; | ||
import { ContextRoute } from './context-route.provider'; | ||
import { UserIdentifier } from '../users/user-identifiers'; | ||
import { Couplet } from '../couplets/couplet.schema'; | ||
|
||
export class AiChatCreateDto { | ||
@IsString() | ||
@IsNotEmpty() | ||
aiChatId: string; | ||
|
||
@ValidateNested() | ||
@Type(() => UserIdentifier) | ||
ownerUser: UserIdentifier; | ||
|
||
@ValidateNested() | ||
@Type(() => ContextRoute) | ||
contextRoute: ContextRoute; | ||
|
||
@ValidateNested({ each: true }) | ||
@Type(() => Couplet) | ||
couplets: Couplet[]; | ||
} | ||
|
||
export class UpdateAiChatDto { | ||
@ValidateNested({ each: true }) | ||
@Type(() => Couplet) | ||
couplets: Couplet[]; | ||
} | ||
|
||
export class GetAiChatDto { | ||
@IsString() | ||
@IsNotEmpty() | ||
id: string; | ||
} | ||
|
||
export class ListAiChatsDto { | ||
@ValidateNested() | ||
@Type(() => ContextRoute) | ||
contextRoute: ContextRoute; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | ||
import { Document, Types } from 'mongoose'; | ||
import { ContextRoute } from './context-route.provider'; | ||
import { User } from '../users/user.schema'; | ||
import { Couplet } from '../couplets/couplet.schema'; | ||
|
||
export type AiChatDocument = AiChat & Document; | ||
|
||
@Schema({ timestamps: true }) | ||
export class AiChat { | ||
@Prop({ type: ContextRoute, required: true }) | ||
contextRoute: ContextRoute; | ||
|
||
@Prop({ required: true, unique: true }) | ||
aiChatId: string; | ||
|
||
@Prop({ type: Types.ObjectId, ref: 'User', required: true }) | ||
ownerUser: User; | ||
|
||
@Prop({ type: [{ type: Types.ObjectId, ref: 'Couplet' }], required: true }) | ||
couplets: Couplet[]; | ||
} | ||
|
||
export const AiChatSchema = SchemaFactory.createForClass(AiChat); | ||
|
||
AiChatSchema.post( | ||
'save', | ||
function (doc: AiChatDocument, next: (err?: Error) => void) { | ||
const lastIdentifier = | ||
doc.contextRoute.identifiers[doc.contextRoute.identifiers.length - 1]; | ||
if (doc.aiChatId !== lastIdentifier.contextId) { | ||
next( | ||
new Error( | ||
'aiChatId should match the bottom-most identifier in the context route', | ||
), | ||
); | ||
} else { | ||
next(); | ||
} | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { AiChatsService } from './ai-chats.service'; | ||
import { MongooseModule } from '@nestjs/mongoose'; | ||
import { AiChat, AiChatSchema } from './ai-chat.schema'; | ||
|
||
@Module({ | ||
imports: [ | ||
MongooseModule.forFeature([{ name: AiChat.name, schema: AiChatSchema }]), | ||
], | ||
providers: [AiChatsService], | ||
exports: [AiChatsService], | ||
}) | ||
export class AiChatsModule {} |
79 changes: 79 additions & 0 deletions
79
src/core/database/collections/ai-chats/ai-chats.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { InjectModel } from '@nestjs/mongoose'; | ||
import { Model } from 'mongoose'; | ||
|
||
import { AiChatCreateDto, UpdateAiChatDto } from './ai-chat-create.dto'; | ||
import { v4 as uuidv4 } from 'uuid'; | ||
import { AiChat, AiChatDocument } from './ai-chat.schema'; | ||
import { Couplet } from '../couplets/couplet.schema'; | ||
|
||
@Injectable() | ||
export class AiChatsService { | ||
constructor( | ||
@InjectModel(AiChat.name) | ||
private readonly aiChatModel: Model<AiChatDocument>, | ||
) {} | ||
|
||
async findAll(): Promise<AiChatDocument[]> { | ||
return this.aiChatModel.find().exec(); | ||
} | ||
|
||
async findOne(aiChatId: string): Promise<AiChatDocument> { | ||
return this.aiChatModel.findOne({ aiChatId: aiChatId }).exec(); | ||
} | ||
|
||
public async createAiChat( | ||
createAiChatDto: AiChatCreateDto, | ||
): Promise<AiChatDocument> { | ||
const createdAiChat = new this.aiChatModel({ | ||
...createAiChatDto, | ||
uuid: uuidv4(), | ||
}); | ||
return createdAiChat.save(); | ||
} | ||
|
||
public async addCouplets( | ||
aiChatId: string, | ||
couplets: [Couplet], | ||
): Promise<void> { | ||
const existingAiChat = await this.aiChatModel | ||
.findOne({ aiChatId: aiChatId }) | ||
.exec(); | ||
|
||
if (!existingAiChat) { | ||
throw new Error(`AiChat with id ${aiChatId} not found`); | ||
} | ||
|
||
this._updateAiChat(aiChatId, { couplets }); | ||
} | ||
async _updateAiChat( | ||
aiChatId: string, | ||
updateAiChatDto: UpdateAiChatDto, | ||
): Promise<AiChatDocument> { | ||
const existingAiChat = await this.aiChatModel | ||
.findOne({ aiChatId: aiChatId }) | ||
.exec(); | ||
if (!existingAiChat) { | ||
throw new Error(`AiChat with id ${aiChatId} not found`); | ||
} | ||
|
||
// Push the new couplet(s) to the couplet list in the aiChat | ||
return await this.aiChatModel | ||
.findOneAndUpdate( | ||
{ aiChatId: aiChatId }, | ||
{ $push: { couplets: { $each: updateAiChatDto.couplets } } }, | ||
{ new: true }, | ||
) | ||
.exec(); | ||
} | ||
|
||
async remove(aiChatId: string): Promise<AiChatDocument> { | ||
const deletedAiChat = await this.aiChatModel | ||
.findOneAndDelete({ aiChatId: aiChatId }) | ||
.exec(); | ||
if (!deletedAiChat) { | ||
throw new Error(`AiChat with id ${aiChatId} not found`); | ||
} | ||
return deletedAiChat; | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
src/core/database/collections/ai-chats/context-route.provider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { Injectable, Scope } from '@nestjs/common'; | ||
|
||
export class ContextIdentifier { | ||
type: 'server' | 'category' | 'channel' | 'thread' | 'direct-message'; | ||
contextId: string; | ||
contextName: string; | ||
} | ||
|
||
export class ContextRoute { | ||
sourceInterface: 'discord' | 'slack'; | ||
identifiers: ContextIdentifier[]; | ||
isDirectMessage: boolean; | ||
|
||
constructor( | ||
sourceInterface: 'discord' | 'slack', | ||
identifiers: ContextIdentifier[], | ||
isDirectMessage: boolean, | ||
) { | ||
this.sourceInterface = sourceInterface; | ||
this.identifiers = identifiers; | ||
this.isDirectMessage = isDirectMessage; | ||
|
||
// if (!this.validateIdentifiers()) { | ||
// throw new Error('Invalid parent-child relationship in route'); | ||
// } | ||
} | ||
|
||
// private validateIdentifiers(): boolean { | ||
// for (let index = 1; index < this.identifiers.length; index++) { | ||
// const currentIdentifier = this.identifiers[index]; | ||
// const previousIdentifier = this.identifiers[index - 1]; | ||
// | ||
// if ( | ||
// !currentIdentifier.parentIdentifier || | ||
// currentIdentifier.parentIdentifier.id !== previousIdentifier.id | ||
// ) { | ||
// return false; | ||
// } | ||
// } | ||
// return true; | ||
// } | ||
} | ||
|
||
@Injectable({ scope: Scope.REQUEST }) | ||
export class DiscordContextRouteFactory { | ||
static create( | ||
isDirectMessage: boolean, | ||
channel: ContextIdentifier, | ||
server?: ContextIdentifier, | ||
category?: ContextIdentifier, | ||
thread?: ContextIdentifier, | ||
): ContextRoute { | ||
const identifiers: ContextIdentifier[] = [ | ||
server, | ||
category, | ||
channel, | ||
thread, | ||
].filter(Boolean) as ContextIdentifier[]; | ||
const sourceInterface = 'discord'; | ||
return new ContextRoute(sourceInterface, identifiers, isDirectMessage); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { IsOptional, ValidateNested } from 'class-validator'; | ||
import { Message } from '../messages/message.schema'; | ||
import { Prop } from '@nestjs/mongoose'; | ||
import { Types } from 'mongoose'; | ||
import { Context } from '@slack/bolt'; | ||
import { ContextRoute } from '../ai-chats/context-route.provider'; | ||
|
||
export class CreateCoupletDto { | ||
@ValidateNested() | ||
@Prop({ type: Types.ObjectId, ref: 'Message', required: true }) | ||
humanMessage: Message; | ||
|
||
@ValidateNested() | ||
@Prop({ type: Types.ObjectId, ref: 'Message', required: true }) | ||
aiResponse: Message; | ||
|
||
@IsOptional() | ||
@ValidateNested() | ||
@Prop({ type: ContextRoute }) | ||
contextRoute: ContextRoute; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | ||
import { Document, Types } from 'mongoose'; | ||
import { Message } from 'discord.js'; | ||
import { ContextRoute } from '../ai-chats/context-route.provider'; | ||
|
||
export type CoupletDocument = Couplet & Document; | ||
|
||
@Schema({ timestamps: true }) | ||
export class Couplet { | ||
@Prop({ type: Types.ObjectId, ref: 'Message', required: true }) | ||
humanMessage: Message; | ||
|
||
@Prop({ type: Types.ObjectId, ref: 'Message', required: true }) | ||
aiResponse: Message; | ||
|
||
@Prop({ type: ContextRoute }) | ||
contextRoute: ContextRoute; | ||
} | ||
|
||
export const CoupletSchema = SchemaFactory.createForClass(Couplet); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { CoupletsService } from './couplets.service'; | ||
import { MongooseModule } from '@nestjs/mongoose'; | ||
import { Couplet, CoupletSchema } from './couplet.schema'; | ||
|
||
@Module({ | ||
imports: [ | ||
MongooseModule.forFeature([{ name: Couplet.name, schema: CoupletSchema }]), | ||
], | ||
providers: [CoupletsService], | ||
exports: [CoupletsService], | ||
}) | ||
export class CoupletsModule {} |
Oops, something went wrong.