Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: basic message pthid/thid support #1381

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(core): basic message thread id
Signed-off-by: Ariel Gentile <gentilester@gmail.com>
  • Loading branch information
genaris committed Mar 10, 2023
commit 3f52a41483c5d3c65c3adbd15d0ffa029650f3cf
Original file line number Diff line number Diff line change
@@ -41,13 +41,14 @@ export class BasicMessagesApi {
* @throws {MessageSendingError} If message is undeliverable
* @returns the created record
*/
public async sendMessage(connectionId: string, message: string) {
public async sendMessage(connectionId: string, message: string, threadId?: string) {
const connection = await this.connectionService.getById(this.agentContext, connectionId)

const { message: basicMessage, record: basicMessageRecord } = await this.basicMessageService.createMessage(
this.agentContext,
message,
connection
connection,
threadId
)
const outboundMessageContext = new OutboundMessageContext(basicMessage, {
agentContext: this.agentContext,
Original file line number Diff line number Diff line change
@@ -11,13 +11,15 @@ import { getAgentOptions, makeConnection, waitForBasicMessage } from '../../../.
import testLogger from '../../../../tests/logger'
import { Agent } from '../../../agent/Agent'
import { MessageSendingError, RecordNotFoundError } from '../../../error'
import { ConsoleLogger, LogLevel } from '../../../logger'
import { BasicMessage } from '../messages'
import { BasicMessageRecord } from '../repository'

const faberConfig = getAgentOptions(
'Faber Basic Messages',
{
endpoints: ['rxjs:faber'],
logger: new ConsoleLogger(LogLevel.debug),
},
getIndySdkModules()
)
@@ -26,6 +28,7 @@ const aliceConfig = getAgentOptions(
'Alice Basic Messages',
{
endpoints: ['rxjs:alice'],
logger: new ConsoleLogger(LogLevel.debug),
},
getIndySdkModules()
)
@@ -84,6 +87,41 @@ describe('Basic Messages E2E', () => {
})
})

test.only('Alice and Faber exchange messages using threadId', async () => {
testLogger.test('Alice sends message to Faber')
const helloRecord = await aliceAgent.basicMessages.sendMessage(aliceConnection.id, 'Hello')

expect(helloRecord.content).toBe('Hello')

testLogger.test('Faber waits for message from Alice')
const helloMessage = await waitForBasicMessage(faberAgent, {
content: 'Hello',
})

testLogger.test('Faber sends message to Alice')
const replyRecord = await faberAgent.basicMessages.sendMessage(faberConnection.id, 'How are you?', helloMessage.id)
expect(replyRecord.content).toBe('How are you?')
expect(replyRecord.threadId).toBe(helloMessage.id)

testLogger.test('Alice waits until she receives message from faber')
const replyMessage = await waitForBasicMessage(aliceAgent, {
content: 'How are you?',
})
expect(replyMessage.content).toBe('How are you?')
expect(replyMessage.threadId).toBe(helloMessage.id)

// Both sender and recipient shall be able to find the threaded message
const aliceThreadedMessages = await aliceAgent.basicMessages.findAllByQuery({ threadId: helloMessage.id })
const faberThreadedMessages = await faberAgent.basicMessages.findAllByQuery({ threadId: helloMessage.id })

for (const msg of faberThreadedMessages) {
console.log(`${JSON.stringify(msg)}`)
}
expect(aliceThreadedMessages.length).toBe(1)
expect(faberThreadedMessages.length).toBe(1)
expect(faberThreadedMessages[0]).toEqual(replyRecord)
})

test('Alice is unable to send a message', async () => {
testLogger.test('Alice sends message to Faber that is undeliverable')

Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ export type CustomBasicMessageTags = TagsBase
export type DefaultBasicMessageTags = {
connectionId: string
role: BasicMessageRole
threadId?: string
}

export type BasicMessageTags = RecordTags<BasicMessageRecord>
@@ -18,7 +19,7 @@ export interface BasicMessageStorageProps {
connectionId: string
role: BasicMessageRole
tags?: CustomBasicMessageTags

threadId?: string
content: string
sentTime: string
}
@@ -28,6 +29,7 @@ export class BasicMessageRecord extends BaseRecord<DefaultBasicMessageTags, Cust
public sentTime!: string
public connectionId!: string
public role!: BasicMessageRole
public threadId?: string

public static readonly type = 'BasicMessageRecord'
public readonly type = BasicMessageRecord.type
@@ -43,6 +45,7 @@ export class BasicMessageRecord extends BaseRecord<DefaultBasicMessageTags, Cust
this.connectionId = props.connectionId
this._tags = props.tags ?? {}
this.role = props.role
this.threadId = props.threadId
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a problem in old exchanges not having a threadId?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, besides the fact that it will not be possible for query for them.

}
}

@@ -51,6 +54,7 @@ export class BasicMessageRecord extends BaseRecord<DefaultBasicMessageTags, Cust
...this._tags,
connectionId: this.connectionId,
role: this.role,
threadId: this.threadId,
}
}
}
Original file line number Diff line number Diff line change
@@ -22,16 +22,26 @@ export class BasicMessageService {
this.eventEmitter = eventEmitter
}

public async createMessage(agentContext: AgentContext, message: string, connectionRecord: ConnectionRecord) {
public async createMessage(
agentContext: AgentContext,
message: string,
connectionRecord: ConnectionRecord,
threadId?: string
) {
const basicMessage = new BasicMessage({ content: message })

const basicMessageRecord = new BasicMessageRecord({
sentTime: basicMessage.sentTime.toISOString(),
content: basicMessage.content,
connectionId: connectionRecord.id,
role: BasicMessageRole.Sender,
threadId,
})

if (threadId) {
basicMessage.setThread({ threadId })
}

await this.basicMessageRepository.save(agentContext, basicMessageRecord)
this.emitStateChangedEvent(agentContext, basicMessageRecord, basicMessage)

@@ -47,6 +57,7 @@ export class BasicMessageService {
content: message.content,
connectionId: connection.id,
role: BasicMessageRole.Receiver,
threadId: message.id !== message.threadId ? message.threadId : undefined,
})

await this.basicMessageRepository.save(agentContext, basicMessageRecord)