diff --git a/docs/docs/classes/DatabaseAdapter.md b/docs/docs/classes/DatabaseAdapter.md index f24ccb9..14cbb2b 100644 --- a/docs/docs/classes/DatabaseAdapter.md +++ b/docs/docs/classes/DatabaseAdapter.md @@ -26,6 +26,23 @@ custom_edit_url: null ## Methods +### addParticipantToRoom + +▸ **addParticipantToRoom**(`userId`, `roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +___ + ### countMemoriesByRoomId ▸ **countMemoriesByRoomId**(`room_id`, `unique?`, `tableName?`): `Promise`\<`number`\> @@ -112,6 +129,22 @@ ___ ___ +### createRoom + +▸ **createRoom**(`name`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`\> + +___ + ### getAccountById ▸ **getAccountById**(`userId`): `Promise`\<``null`` \| [`Account`](../interfaces/Account.md)\> @@ -242,6 +275,38 @@ ___ ___ +### getRoomsByParticipant + +▸ **getRoomsByParticipant**(`userId`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +___ + +### getRoomsByParticipants + +▸ **getRoomsByParticipants**(`userIds`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userIds` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[] | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +___ + ### log ▸ **log**(`params`): `Promise`\<`void`\> @@ -262,6 +327,22 @@ ___ ___ +### removeAllGoalsByRoomId + +▸ **removeAllGoalsByRoomId**(`room_id`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `room_id` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +___ + ### removeAllMemoriesByRoomId ▸ **removeAllMemoriesByRoomId**(`room_id`, `tableName`): `Promise`\<`void`\> @@ -279,6 +360,22 @@ ___ ___ +### removeGoal + +▸ **removeGoal**(`goalId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `goalId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +___ + ### removeMemory ▸ **removeMemory**(`memoryId`, `tableName`): `Promise`\<`void`\> @@ -296,6 +393,39 @@ ___ ___ +### removeParticipantFromRoom + +▸ **removeParticipantFromRoom**(`userId`, `roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +___ + +### removeRoom + +▸ **removeRoom**(`roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +___ + ### searchMemories ▸ **searchMemories**(`params`): `Promise`\<[`Memory`](../interfaces/Memory.md)[]\> diff --git a/docs/docs/classes/SqliteDatabaseAdapter.md b/docs/docs/classes/SqliteDatabaseAdapter.md index 526c254..5d9a59c 100644 --- a/docs/docs/classes/SqliteDatabaseAdapter.md +++ b/docs/docs/classes/SqliteDatabaseAdapter.md @@ -34,6 +34,27 @@ custom_edit_url: null ## Methods +### addParticipantToRoom + +▸ **addParticipantToRoom**(`userId`, `roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[addParticipantToRoom](DatabaseAdapter.md#addparticipanttoroom) + +___ + ### countMemoriesByRoomId ▸ **countMemoriesByRoomId**(`room_id`, `unique?`, `tableName?`): `Promise`\<`number`\> @@ -140,6 +161,26 @@ ___ ___ +### createRoom + +▸ **createRoom**(`name`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[createRoom](DatabaseAdapter.md#createroom) + +___ + ### getAccountById ▸ **getAccountById**(`userId`): `Promise`\<``null`` \| [`Account`](../interfaces/Account.md)\> @@ -298,6 +339,46 @@ ___ ___ +### getRoomsByParticipant + +▸ **getRoomsByParticipant**(`userId`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[getRoomsByParticipant](DatabaseAdapter.md#getroomsbyparticipant) + +___ + +### getRoomsByParticipants + +▸ **getRoomsByParticipants**(`userIds`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userIds` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[] | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[getRoomsByParticipants](DatabaseAdapter.md#getroomsbyparticipants) + +___ + ### log ▸ **log**(`params`): `Promise`\<`void`\> @@ -322,6 +403,26 @@ ___ ___ +### removeAllGoalsByRoomId + +▸ **removeAllGoalsByRoomId**(`room_id`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `room_id` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeAllGoalsByRoomId](DatabaseAdapter.md#removeallgoalsbyroomid) + +___ + ### removeAllMemoriesByRoomId ▸ **removeAllMemoriesByRoomId**(`room_id`, `tableName`): `Promise`\<`void`\> @@ -343,6 +444,26 @@ ___ ___ +### removeGoal + +▸ **removeGoal**(`goalId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `goalId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeGoal](DatabaseAdapter.md#removegoal) + +___ + ### removeMemory ▸ **removeMemory**(`memoryId`, `tableName`): `Promise`\<`void`\> @@ -364,6 +485,47 @@ ___ ___ +### removeParticipantFromRoom + +▸ **removeParticipantFromRoom**(`userId`, `roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeParticipantFromRoom](DatabaseAdapter.md#removeparticipantfromroom) + +___ + +### removeRoom + +▸ **removeRoom**(`roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeRoom](DatabaseAdapter.md#removeroom) + +___ + ### searchMemories ▸ **searchMemories**(`params`): `Promise`\<[`Memory`](../interfaces/Memory.md)[]\> diff --git a/docs/docs/classes/SupabaseDatabaseAdapter.md b/docs/docs/classes/SupabaseDatabaseAdapter.md index dbabbe4..2ca7932 100644 --- a/docs/docs/classes/SupabaseDatabaseAdapter.md +++ b/docs/docs/classes/SupabaseDatabaseAdapter.md @@ -35,6 +35,27 @@ custom_edit_url: null ## Methods +### addParticipantToRoom + +▸ **addParticipantToRoom**(`userId`, `roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[addParticipantToRoom](DatabaseAdapter.md#addparticipanttoroom) + +___ + ### countMemoriesByRoomId ▸ **countMemoriesByRoomId**(`room_id`, `unique?`, `tableName`): `Promise`\<`number`\> @@ -141,6 +162,26 @@ ___ ___ +### createRoom + +▸ **createRoom**(`name`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `name` | `string` | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[createRoom](DatabaseAdapter.md#createroom) + +___ + ### getAccountById ▸ **getAccountById**(`userId`): `Promise`\<``null`` \| [`Account`](../interfaces/Account.md)\> @@ -299,6 +340,46 @@ ___ ___ +### getRoomsByParticipant + +▸ **getRoomsByParticipant**(`userId`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[getRoomsByParticipant](DatabaseAdapter.md#getroomsbyparticipant) + +___ + +### getRoomsByParticipants + +▸ **getRoomsByParticipants**(`userIds`): `Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userIds` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[] | + +#### Returns + +`Promise`\<\`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\`[]\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[getRoomsByParticipants](DatabaseAdapter.md#getroomsbyparticipants) + +___ + ### log ▸ **log**(`params`): `Promise`\<`void`\> @@ -323,6 +404,26 @@ ___ ___ +### removeAllGoalsByRoomId + +▸ **removeAllGoalsByRoomId**(`room_id`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `room_id` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeAllGoalsByRoomId](DatabaseAdapter.md#removeallgoalsbyroomid) + +___ + ### removeAllMemoriesByRoomId ▸ **removeAllMemoriesByRoomId**(`room_id`, `tableName`): `Promise`\<`void`\> @@ -344,16 +445,35 @@ ___ ___ +### removeGoal + +▸ **removeGoal**(`goalId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `goalId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeGoal](DatabaseAdapter.md#removegoal) + +___ + ### removeMemory -▸ **removeMemory**(`memoryId`, `tableName`): `Promise`\<`void`\> +▸ **removeMemory**(`memoryId`): `Promise`\<`void`\> #### Parameters | Name | Type | | :------ | :------ | | `memoryId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | -| `tableName` | `string` | #### Returns @@ -365,6 +485,47 @@ ___ ___ +### removeParticipantFromRoom + +▸ **removeParticipantFromRoom**(`userId`, `roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `userId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeParticipantFromRoom](DatabaseAdapter.md#removeparticipantfromroom) + +___ + +### removeRoom + +▸ **removeRoom**(`roomId`): `Promise`\<`void`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `roomId` | \`$\{string}-$\{string}-$\{string}-$\{string}-$\{string}\` | + +#### Returns + +`Promise`\<`void`\> + +#### Overrides + +[DatabaseAdapter](DatabaseAdapter.md).[removeRoom](DatabaseAdapter.md#removeroom) + +___ + ### searchMemories ▸ **searchMemories**(`params`): `Promise`\<[`Memory`](../interfaces/Memory.md)[]\> diff --git a/package.json b/package.json index bfcce52..91a0ef6 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "shell": "node --no-warnings scripts/shell.mjs --dev", "concat": "node ./scripts/concat.mjs", "shell:cloud": "node --no-warnings scripts/shell.mjs", - "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest -f --runInBand", + "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --runInBand", + "test:failed": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest -f --runInBand", "test:coverage": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --coverage", "reset-profile": "rimraf ~/.cjrc", "deploy": "wrangler deploy", diff --git a/scripts/concat.mjs b/scripts/concat.mjs index fba42f6..fd078d2 100644 --- a/scripts/concat.mjs +++ b/scripts/concat.mjs @@ -5,7 +5,7 @@ import { fileURLToPath } from 'url' const instructions = 'The above code was taken from my codebase at https://github.com/jointhealliance/bgent.' // Patterns to ignore -const ignorePatterns = [] +const ignorePatterns = ["evaluator", "action", "context", "provider", "logger"] // __dirname is not defined in ES module scope, so we need to create it const __filename = fileURLToPath(import.meta.url) diff --git a/src/lib/__tests__/actions.test.ts b/src/lib/__tests__/actions.test.ts index fffe5a7..a265428 100644 --- a/src/lib/__tests__/actions.test.ts +++ b/src/lib/__tests__/actions.test.ts @@ -1,13 +1,13 @@ import { type UUID } from "crypto"; import dotenv from "dotenv"; import { createRuntime } from "../../test/createRuntime"; +import { getOrCreateRelationship } from "../../test/getOrCreateRelationship"; import { runAiTest } from "../../test/runAiTest"; import { TEST_ACTION, TEST_ACTION_FAIL } from "../../test/testAction"; import { type User } from "../../test/types"; import { composeContext } from "../context"; import logger from "../logger"; import { embeddingZeroVector } from "../memory"; -import { createRelationship, getRelationship } from "../relationships"; import { type BgentRuntime } from "../runtime"; import { messageHandlerTemplate } from "../templates"; import { Content, State, type Message } from "../types"; @@ -154,25 +154,14 @@ describe("Actions", () => { } // get all relationships for user - let data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user.id as UUID, userB: "00000000-0000-0000-0000-000000000000" as UUID, }); - // if relationship does not exist, create it if (!data) { - await createRelationship({ - runtime, - userA: user.id as UUID, - userB: "00000000-0000-0000-0000-000000000000" as UUID, - }); - - data = await getRelationship({ - runtime, - userA: user.id as UUID, - userB: "00000000-0000-0000-0000-000000000000" as UUID, - }); + throw new Error("Relationship not found"); } room_id = data!.room_id; diff --git a/src/lib/__tests__/evaluation.test.ts b/src/lib/__tests__/evaluation.test.ts index bc6e6bd..9b069a9 100644 --- a/src/lib/__tests__/evaluation.test.ts +++ b/src/lib/__tests__/evaluation.test.ts @@ -1,16 +1,16 @@ -import { type User } from "../../test/types"; import { UUID } from "crypto"; import dotenv from "dotenv"; import { createRuntime } from "../../test/createRuntime"; +import { getOrCreateRelationship } from "../../test/getOrCreateRelationship"; +import { runAiTest } from "../../test/runAiTest"; import { TEST_EVALUATOR, TEST_EVALUATOR_FAIL } from "../../test/testEvaluator"; +import { type User } from "../../test/types"; +import { zeroUuid } from "../constants"; import { composeContext } from "../context"; import { evaluationTemplate } from "../evaluators"; import fact from "../evaluators/fact"; -import { getRelationship } from "../relationships"; import { BgentRuntime } from "../runtime"; import { Message } from "../types"; -import { runAiTest } from "../../test/runAiTest"; -import { zeroUuid } from "../constants"; dotenv.config({ path: ".dev.vars" }); @@ -27,7 +27,7 @@ describe("Evaluation Process", () => { runtime = setup.runtime; user = setup.session.user; - const relationship = await getRelationship({ + const relationship = await getOrCreateRelationship({ runtime, userA: user.id as UUID, userB: zeroUuid, diff --git a/src/lib/__tests__/goals.test.ts b/src/lib/__tests__/goals.test.ts index c4c9d40..3a5955c 100644 --- a/src/lib/__tests__/goals.test.ts +++ b/src/lib/__tests__/goals.test.ts @@ -17,15 +17,15 @@ describe("Goals", () => { }); runtime = result.runtime; user = result.session.user; - await runtime.databaseAdapter.removeAllMemoriesByRoomId(zeroUuid, "goals"); + await runtime.databaseAdapter.removeAllGoalsByRoomId(zeroUuid); }); beforeEach(async () => { - await runtime.databaseAdapter.removeAllMemoriesByRoomId(zeroUuid, "goals"); + await runtime.databaseAdapter.removeAllGoalsByRoomId(zeroUuid); }); afterAll(async () => { - await runtime.databaseAdapter.removeAllMemoriesByRoomId(zeroUuid, "goals"); + await runtime.databaseAdapter.removeAllGoalsByRoomId(zeroUuid); }); test("createGoal - successfully creates a new goal", async () => { @@ -109,5 +109,10 @@ describe("Goals", () => { ); expect(updatedGoalInDb?.status).toEqual(GoalStatus.DONE); + + // Clean up the created goal + if (existingGoal?.id) { + await runtime.databaseAdapter.removeGoal(existingGoal.id); + } }); }); diff --git a/src/lib/__tests__/lore.test.ts b/src/lib/__tests__/lore.test.ts index bdf4886..42f653b 100644 --- a/src/lib/__tests__/lore.test.ts +++ b/src/lib/__tests__/lore.test.ts @@ -1,14 +1,14 @@ -import { type User } from "../../test/types"; import { type UUID } from "crypto"; import dotenv from "dotenv"; import { createRuntime } from "../../test/createRuntime"; +import { getOrCreateRelationship } from "../../test/getOrCreateRelationship"; +import { type User } from "../../test/types"; +import { zeroUuid } from "../constants"; import { composeContext } from "../context"; import { addLore, getLore } from "../lore"; import { BgentRuntime } from "../runtime"; import { messageHandlerTemplate } from "../templates"; import { type Content } from "../types"; -import { zeroUuid } from "../constants"; -import { getRelationship } from "../relationships"; dotenv.config({ path: ".dev.vars" }); describe("Lore", () => { @@ -21,7 +21,7 @@ describe("Lore", () => { }); runtime = result.runtime; const user = result?.session?.user as User; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user?.id as UUID, userB: zeroUuid, diff --git a/src/lib/__tests__/memory.test.ts b/src/lib/__tests__/memory.test.ts index c8ea5a4..45ba7f0 100644 --- a/src/lib/__tests__/memory.test.ts +++ b/src/lib/__tests__/memory.test.ts @@ -1,19 +1,19 @@ -import { type User } from "../../test/types"; import { type UUID } from "crypto"; import dotenv from "dotenv"; +import { getCachedEmbedding, writeCachedEmbedding } from "../../test/cache"; import { createRuntime } from "../../test/createRuntime"; +import { getOrCreateRelationship } from "../../test/getOrCreateRelationship"; +import { type User } from "../../test/types"; +import { zeroUuid } from "../constants"; import { MemoryManager } from "../memory"; -import { getRelationship } from "../relationships"; import { type Content, type Memory } from "../types"; -import { getCachedEmbedding, writeCachedEmbedding } from "../../test/cache"; -import { zeroUuid } from "../constants"; dotenv.config({ path: ".dev.vars" }); describe("Memory", () => { let memoryManager: MemoryManager; let runtime = null; let user: User; - let room_id: UUID; + let room_id: UUID = zeroUuid; beforeAll(async () => { const result = await createRuntime({ @@ -22,7 +22,7 @@ describe("Memory", () => { runtime = result.runtime; user = result.session.user; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user?.id as UUID, userB: zeroUuid, @@ -32,7 +32,9 @@ describe("Memory", () => { throw new Error("Relationship not found"); } - room_id = data?.room_id; + console.log("*** data", data); + + room_id = data.room_id; memoryManager = new MemoryManager({ tableName: "messages", @@ -64,7 +66,7 @@ describe("Memory", () => { const similarMemory = await memoryManager.addEmbeddingToMemory({ user_id: user?.id as UUID, content: { content: similarMemoryContent }, - room_id, + room_id: room_id, embedding, }); if (!embedding) { @@ -100,6 +102,9 @@ describe("Memory", () => { }, ); + console.log("*** room_id", room_id); + console.log("*** searchedMemories", searchedMemories); + // Check that the similar memory is included in the search results and the dissimilar one is not or ranks lower expect( searchedMemories.some( @@ -203,7 +208,7 @@ describe("Memory - Basic tests", () => { runtime = result.runtime; user = result.session.user; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user?.id as UUID, userB: zeroUuid, @@ -290,7 +295,7 @@ describe("Memory - Extended Tests", () => { runtime = result.runtime; user = result.session.user; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user.id as UUID, userB: zeroUuid, @@ -302,6 +307,8 @@ describe("Memory - Extended Tests", () => { room_id = data.room_id; + if (!room_id) throw new Error("Room not found"); + memoryManager = new MemoryManager({ tableName: "messages", runtime, @@ -370,7 +377,7 @@ describe("Memory - Extended Tests", () => { const similarMemory = await memoryManager.addEmbeddingToMemory({ user_id: user?.id as UUID, content: { content: similarMemoryContent }, - room_id, + room_id: room_id, embedding, }); if (!embedding) { diff --git a/src/lib/__tests__/messages.test.ts b/src/lib/__tests__/messages.test.ts index c2dfde5..3f28822 100644 --- a/src/lib/__tests__/messages.test.ts +++ b/src/lib/__tests__/messages.test.ts @@ -1,13 +1,14 @@ -import { type User } from "../../test/types"; import { type UUID } from "crypto"; +import dotenv from "dotenv"; import { createRuntime } from "../../test/createRuntime"; +import { getOrCreateRelationship } from "../../test/getOrCreateRelationship"; +import { type User } from "../../test/types"; +import { zeroUuid } from "../constants"; +import { formatFacts } from "../evaluators/fact"; import { formatActors, formatMessages, getActorDetails } from "../messages"; +import { createRelationship } from "../relationships"; import { type BgentRuntime } from "../runtime"; import { type Actor, type Content, type Memory } from "../types"; -import { formatFacts } from "../evaluators/fact"; -import { createRelationship, getRelationship } from "../relationships"; -import { zeroUuid } from "../constants"; -import dotenv from "dotenv"; dotenv.config({ path: ".dev.vars" }); @@ -37,12 +38,14 @@ describe("Messages Library", () => { userB, }); - const relationship = await getRelationship({ + const relationship = await getOrCreateRelationship({ runtime, userA, userB, }); + console.log("relationship", relationship); + if (!relationship?.room_id) { throw new Error("Room not found"); } diff --git a/src/lib/__tests__/relationships.test.ts b/src/lib/__tests__/relationships.test.ts index 1cc95d9..79eec97 100644 --- a/src/lib/__tests__/relationships.test.ts +++ b/src/lib/__tests__/relationships.test.ts @@ -1,14 +1,11 @@ -import { type User } from "../../test/types"; import { type UUID } from "crypto"; import dotenv from "dotenv"; import { createRuntime } from "../../test/createRuntime"; // Adjust the import path as needed -import { - createRelationship, - getRelationship, - getRelationships, -} from "../relationships"; // Adjust the import path as needed -import { BgentRuntime } from "../runtime"; +import { getOrCreateRelationship } from "../../test/getOrCreateRelationship"; +import { type User } from "../../test/types"; import { zeroUuid } from "../constants"; +import { createRelationship, getRelationships } from "../relationships"; // Adjust the import path as needed +import { BgentRuntime } from "../runtime"; dotenv.config({ path: ".dev.vars" }); @@ -22,19 +19,26 @@ describe("Relationships Module", () => { }); runtime = setup.runtime; user = setup.session.user; + if (!user.id) { + throw new Error("User ID is undefined"); + } }); test("createRelationship creates a new relationship", async () => { - const userA = user?.id as UUID; + console.log("user: ", user); + const userA = user.id as UUID; const userB = zeroUuid; - - const relationship = await createRelationship({ - runtime, - userA, - userB, - }); - - expect(relationship).toBe(true); + if (userA === undefined) throw new Error("userA is undefined"); + try { + const relationship = await createRelationship({ + runtime, + userA, + userB, + }); + expect(relationship).toBe(true); + } catch (error) { + console.log("*** error: ", error); + } }); test("getRelationship retrieves an existing relationship", async () => { @@ -43,7 +47,7 @@ describe("Relationships Module", () => { await createRelationship({ runtime, userA, userB }); - const relationship = await getRelationship({ + const relationship = await getOrCreateRelationship({ runtime, userA, userB, diff --git a/src/lib/__tests__/runtime.test.ts b/src/lib/__tests__/runtime.test.ts index e040415..0348c72 100644 --- a/src/lib/__tests__/runtime.test.ts +++ b/src/lib/__tests__/runtime.test.ts @@ -1,12 +1,12 @@ -import dotenv from "dotenv"; -import { createRuntime } from "../../test/createRuntime"; import { type UUID } from "crypto"; -import { createRelationship, getRelationship } from "../relationships"; +import dotenv from "dotenv"; import { getCachedEmbedding, writeCachedEmbedding } from "../../test/cache"; -import { BgentRuntime } from "../runtime"; +import { createRuntime } from "../../test/createRuntime"; +import { getOrCreateRelationship } from "../../test/getOrCreateRelationship"; import { type User } from "../../test/types"; -import { type Message } from "../types"; import { zeroUuid } from "../constants"; +import { BgentRuntime } from "../runtime"; +import { type Message } from "../types"; dotenv.config({ path: ".dev.vars" }); @@ -58,26 +58,16 @@ describe("Agent Runtime", () => { runtime = result.runtime; user = result.session.user; - let data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user?.id as UUID, userB: zeroUuid, }); if (!data) { - await createRelationship({ - runtime, - userA: user?.id as UUID, - userB: zeroUuid, - }); - data = await getRelationship({ - runtime, - userA: user?.id as UUID, - userB: zeroUuid, - }); + throw new Error("Relationship not found"); } - // TODO: This seems to be defaulting to zeroUuid, but we should be able to get the room_id from the relationship - room_id = (data?.room_id as UUID) || zeroUuid; + room_id = data.room_id; await clearMemories(); // Clear memories before each test }); @@ -114,5 +104,5 @@ describe("Agent Runtime", () => { expect(state.recentMessagesData.length).toBeGreaterThan(1); await clearMemories(); - }); + }, 60000); }); diff --git a/src/lib/actions/__tests__/elaborate.test.ts b/src/lib/actions/__tests__/elaborate.test.ts index ae1c6ba..a43bc04 100644 --- a/src/lib/actions/__tests__/elaborate.test.ts +++ b/src/lib/actions/__tests__/elaborate.test.ts @@ -1,17 +1,17 @@ -import { type User } from "../../../test/types"; import { type UUID } from "crypto"; import dotenv from "dotenv"; import { createRuntime } from "../../../test/createRuntime"; import { Goodbye1 } from "../../../test/data"; +import { getOrCreateRelationship } from "../../../test/getOrCreateRelationship"; import { populateMemories } from "../../../test/populateMemories"; -import { getRelationship } from "../../relationships"; +import { runAiTest } from "../../../test/runAiTest"; +import { type User } from "../../../test/types"; +import { zeroUuid } from "../../constants"; import { type BgentRuntime } from "../../runtime"; import { Content, type Message } from "../../types"; import action from "../elaborate"; import ignore from "../ignore"; -import { zeroUuid } from "../../constants"; import wait from "../wait"; -import { runAiTest } from "../../../test/runAiTest"; dotenv.config({ path: ".dev.vars" }); @@ -59,7 +59,7 @@ describe("User Profile", () => { user = setup.session.user; runtime = setup.runtime; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user.id as UUID, userB: zeroUuid, diff --git a/src/lib/actions/__tests__/ignore.test.ts b/src/lib/actions/__tests__/ignore.test.ts index 654e62e..73d2bad 100644 --- a/src/lib/actions/__tests__/ignore.test.ts +++ b/src/lib/actions/__tests__/ignore.test.ts @@ -6,6 +6,7 @@ import { GetTellMeAboutYourselfConversationTroll2, Goodbye1, } from "../../../test/data"; +import { getOrCreateRelationship } from "../../../test/getOrCreateRelationship"; import { populateMemories } from "../../../test/populateMemories"; import { runAiTest } from "../../../test/runAiTest"; import { type User } from "../../../test/types"; @@ -13,7 +14,6 @@ import { zeroUuid } from "../../constants"; import { composeContext } from "../../context"; import logger from "../../logger"; import { embeddingZeroVector } from "../../memory"; -import { getRelationship } from "../../relationships"; import { type BgentRuntime } from "../../runtime"; import { messageHandlerTemplate } from "../../templates"; import { Content, State, type Message } from "../../types"; @@ -147,7 +147,7 @@ describe("Ignore action tests", () => { user = setup.session.user; runtime = setup.runtime; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user?.id as UUID, userB: zeroUuid, diff --git a/src/lib/actions/__tests__/wait.test.ts b/src/lib/actions/__tests__/wait.test.ts index a7c9f21..3067b5e 100644 --- a/src/lib/actions/__tests__/wait.test.ts +++ b/src/lib/actions/__tests__/wait.test.ts @@ -1,15 +1,15 @@ -import { type User } from "../../../test/types"; import { type UUID } from "crypto"; import dotenv from "dotenv"; import { createRuntime } from "../../../test/createRuntime"; import { GetTellMeAboutYourselfConversation1 } from "../../../test/data"; +import { getOrCreateRelationship } from "../../../test/getOrCreateRelationship"; import { populateMemories } from "../../../test/populateMemories"; -import { getRelationship } from "../../relationships"; +import { runAiTest } from "../../../test/runAiTest"; +import { type User } from "../../../test/types"; +import { zeroUuid } from "../../constants"; import { type BgentRuntime } from "../../runtime"; import { type Message } from "../../types"; import action from "../wait"; // Import the wait action -import { zeroUuid } from "../../constants"; -import { runAiTest } from "../../../test/runAiTest"; dotenv.config({ path: ".dev.vars" }); @@ -34,7 +34,7 @@ describe("Wait Action Behavior", () => { user = setup.session.user; runtime = setup.runtime; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user?.id as UUID, userB: zeroUuid, diff --git a/src/lib/actions/elaborate.ts b/src/lib/actions/elaborate.ts index 67b8c13..714b0c4 100644 --- a/src/lib/actions/elaborate.ts +++ b/src/lib/actions/elaborate.ts @@ -66,8 +66,6 @@ export default { stop: [], }); - console.log("response", response); - runtime.databaseAdapter.log({ body: { message, context, response }, user_id: userId, diff --git a/src/lib/adapters/sqlite.ts b/src/lib/adapters/sqlite.ts index 3f7a069..f5ab6e4 100644 --- a/src/lib/adapters/sqlite.ts +++ b/src/lib/adapters/sqlite.ts @@ -292,6 +292,51 @@ export class SqliteDatabaseAdapter extends DatabaseAdapter { ); } + async removeGoal(goalId: UUID): Promise { + const sql = "DELETE FROM goals WHERE id = ?"; + this.db.prepare(sql).run(goalId); + } + + async removeAllGoalsByRoomId(room_id: UUID): Promise { + const sql = "DELETE FROM goals WHERE room_id = ?"; + this.db.prepare(sql).run(JSON.stringify(room_id)); + } + + async createRoom(name: string): Promise { + const roomId = crypto.randomUUID(); + const sql = "INSERT INTO rooms (id, name) VALUES (?, ?)"; + this.db.prepare(sql).run(roomId, name); + return roomId as UUID; + } + + async removeRoom(roomId: UUID): Promise { + const sql = "DELETE FROM rooms WHERE id = ?"; + this.db.prepare(sql).run(roomId); + } + + async getRoomsByParticipant(userId: UUID): Promise { + const sql = "SELECT room_id FROM participants WHERE user_id = ?"; + const rows = this.db.prepare(sql).all(userId) as { room_id: string }[]; + return rows.map((row) => row.room_id as UUID); + } + + async getRoomsByParticipants(userIds: UUID[]): Promise { + const sql = + "SELECT DISTINCT room_id FROM participants WHERE user_id IN (?)"; + const rows = this.db.prepare(sql).all(userIds) as { room_id: string }[]; + return rows.map((row) => row.room_id as UUID); + } + + async addParticipantToRoom(userId: UUID, roomId: UUID): Promise { + const sql = "INSERT INTO participants (user_id, room_id) VALUES (?, ?)"; + this.db.prepare(sql).run(userId, roomId); + } + + async removeParticipantFromRoom(userId: UUID, roomId: UUID): Promise { + const sql = "DELETE FROM participants WHERE user_id = ? AND room_id = ?"; + this.db.prepare(sql).run(userId, roomId); + } + async createRelationship(params: { userA: UUID; userB: UUID; diff --git a/src/lib/adapters/supabase.ts b/src/lib/adapters/supabase.ts index 425dd52..879d606 100644 --- a/src/lib/adapters/supabase.ts +++ b/src/lib/adapters/supabase.ts @@ -32,7 +32,7 @@ export class SupabaseDatabaseAdapter extends DatabaseAdapter { } async createAccount(account: Account): Promise { - const { error } = await this.supabase.from("accounts").insert([account]); + const { error } = await this.supabase.from("accounts").upsert([account]); if (error) { throw new Error(error.message); } @@ -297,18 +297,146 @@ export class SupabaseDatabaseAdapter extends DatabaseAdapter { await this.supabase.from("goals").upsert(goal); } + async removeGoal(goalId: UUID): Promise { + const { error } = await this.supabase + .from("goals") + .delete() + .eq("id", goalId); + if (error) { + throw new Error(`Error removing goal: ${error.message}`); + } + } + + async removeAllGoalsByRoomId(room_id: UUID): Promise { + const { error } = await this.supabase + .from("goals") + .delete() + .eq("room_id", room_id); + if (error) { + throw new Error(`Error removing goals: ${error.message}`); + } + } + + async getRoomsByParticipant(userId: UUID): Promise { + const { data, error } = await this.supabase + .from("participants") + .select("room_id") + .eq("user_id", userId); + + if (error) { + throw new Error(`Error getting rooms by participant: ${error.message}`); + } + + return data.map((row) => row.room_id as UUID); + } + + async getRoomsByParticipants(userIds: UUID[]): Promise { + const { data, error } = await this.supabase + .from("participants") + .select("room_id") + .in("user_id", userIds); + + if (error) { + throw new Error(`Error getting rooms by participants: ${error.message}`); + } + + return [...new Set(data.map((row) => row.room_id as UUID))]; + } + + async createRoom(name: string): Promise { + const { data, error } = (await this.supabase + .from("rooms") + .upsert({ name }) + .single()) as { data: { id: UUID } | null; error: Error | null }; + + if (error) { + throw new Error(`Error creating room: ${error.message}`); + } + + if (!data) { + throw new Error("No data returned from room creation"); + } + + return data.id; + } + + async removeRoom(roomId: UUID): Promise { + const { error } = await this.supabase + .from("rooms") + .delete() + .eq("id", roomId); + + if (error) { + throw new Error(`Error removing room: ${error.message}`); + } + } + + async addParticipantToRoom(userId: UUID, roomId: UUID): Promise { + const { error } = await this.supabase + .from("participants") + .insert({ user_id: userId, room_id: roomId }); + + if (error) { + throw new Error(`Error adding participant: ${error.message}`); + } + } + + async removeParticipantFromRoom(userId: UUID, roomId: UUID): Promise { + const { error } = await this.supabase + .from("participants") + .delete() + .eq("user_id", userId) + .eq("room_id", roomId); + + if (error) { + throw new Error(`Error removing participant: ${error.message}`); + } + } + async createRelationship(params: { userA: UUID; userB: UUID; }): Promise { - const { data, error: roomsError } = (await this.supabase + // check for room with values name: `Room for ${params.userA} and ${params.userB}`, created_by: params.userA, + const { data: allRoomData, error: allRoomsError } = await this.supabase .from("rooms") - .insert({ name: "test relationship" }) - .single()) as { data: { id: UUID } | null; error: Error | null }; - if (roomsError) { - throw new Error(roomsError.message); + .select("id") + .eq("name", `Room for ${params.userA} and ${params.userB}`) + .eq("created_by", params.userA); + + if (allRoomsError) { + throw new Error("All rooms error: " + allRoomsError.message); + } + + if (!allRoomData || allRoomData.length === 0) { + const { error: roomsError } = await this.supabase + .from("rooms") + .insert({ + name: `Room for ${params.userA} and ${params.userB}`, + created_by: params.userA, + }) + .eq("name", `Room for ${params.userA} and ${params.userB}`); + + if (roomsError) { + throw new Error("Room error: " + roomsError.message); + } + } + + // get the room_id from the room creation + const { data, error: roomError } = await this.supabase + .from("rooms") + .select("id") + .eq("name", `Room for ${params.userA} and ${params.userB}`) + .single(); + + if (roomError) { + throw new Error("Room error: " + roomError.message); + } + + const room_id = data.id as UUID; + if (!room_id) { + throw new Error("Room not found"); } - const room_id = data?.id; const { error: participantsError } = await this.supabase .from("participants") .insert([ @@ -320,15 +448,20 @@ export class SupabaseDatabaseAdapter extends DatabaseAdapter { } // then create a relationship between the two users with the room_id as the relationship's room_id - const { error } = await this.supabase.from("relationships").upsert({ - user_a: params.userA, - user_b: params.userB, - user_id: params.userA, - room_id, - }); + const { error } = await this.supabase + .from("relationships") + .upsert({ + user_a: params.userA, + user_b: params.userB, + user_id: params.userA, + room_id, + status: "FRIENDS", + }) + .eq("user_a", params.userA) + .eq("user_b", params.userB); if (error) { - throw new Error(error.message); + throw new Error("Relationship error: " + error.message); } return true; diff --git a/src/lib/database.ts b/src/lib/database.ts index 0813197..1bb85f5 100644 --- a/src/lib/database.ts +++ b/src/lib/database.ts @@ -99,6 +99,22 @@ export abstract class DatabaseAdapter { abstract createGoal(goal: Goal): Promise; + abstract removeGoal(goalId: UUID): Promise; + + abstract removeAllGoalsByRoomId(room_id: UUID): Promise; + + abstract createRoom(name: string): Promise; + + abstract removeRoom(roomId: UUID): Promise; + + abstract getRoomsByParticipant(userId: UUID): Promise; + + abstract getRoomsByParticipants(userIds: UUID[]): Promise; + + abstract addParticipantToRoom(userId: UUID, roomId: UUID): Promise; + + abstract removeParticipantFromRoom(userId: UUID, roomId: UUID): Promise; + abstract createRelationship(params: { userA: UUID; userB: UUID; diff --git a/src/lib/evaluators/__tests__/fact.test.ts b/src/lib/evaluators/__tests__/fact.test.ts index c3d651a..325ec5a 100644 --- a/src/lib/evaluators/__tests__/fact.test.ts +++ b/src/lib/evaluators/__tests__/fact.test.ts @@ -8,12 +8,12 @@ import { GetTellMeAboutYourselfConversation3, jimFacts, } from "../../../test/data"; +import { getOrCreateRelationship } from "../../../test/getOrCreateRelationship"; import { populateMemories } from "../../../test/populateMemories"; import { runAiTest } from "../../../test/runAiTest"; import { type User } from "../../../test/types"; import { defaultActions } from "../../actions"; import { zeroUuid } from "../../constants"; -import { getRelationship } from "../../relationships"; import { type BgentRuntime } from "../../runtime"; import { type Message } from "../../types"; import evaluator from "../fact"; @@ -23,7 +23,7 @@ dotenv.config({ path: ".dev.vars" }); describe("Facts Evaluator", () => { let user: User; let runtime: BgentRuntime; - let room_id: UUID; + let room_id = zeroUuid; beforeAll(async () => { const setup = await createRuntime({ @@ -34,7 +34,11 @@ describe("Facts Evaluator", () => { user = setup.session.user; runtime = setup.runtime; - const data = await getRelationship({ + if (!user.id) { + throw new Error("User ID is undefined"); + } + + const data = await getOrCreateRelationship({ runtime, userA: user.id as UUID, userB: zeroUuid, diff --git a/src/lib/evaluators/__tests__/goal.test.ts b/src/lib/evaluators/__tests__/goal.test.ts index f931f5e..67a0e6d 100644 --- a/src/lib/evaluators/__tests__/goal.test.ts +++ b/src/lib/evaluators/__tests__/goal.test.ts @@ -1,16 +1,16 @@ -import { type User } from "../../../test/types"; import { type UUID } from "crypto"; import dotenv from "dotenv"; import { createRuntime } from "../../../test/createRuntime"; +import { getOrCreateRelationship } from "../../../test/getOrCreateRelationship"; import { populateMemories } from "../../../test/populateMemories"; +import { runAiTest } from "../../../test/runAiTest"; +import { type User } from "../../../test/types"; +import { defaultActions } from "../../actions"; +import { zeroUuid } from "../../constants"; import { createGoal, getGoals } from "../../goals"; -import { getRelationship } from "../../relationships"; import { type BgentRuntime } from "../../runtime"; -import { Goal, GoalStatus, Objective, type Message, State } from "../../types"; +import { Goal, GoalStatus, Objective, State, type Message } from "../../types"; import evaluator from "../goal"; -import { defaultActions } from "../../actions"; -import { zeroUuid } from "../../constants"; -import { runAiTest } from "../../../test/runAiTest"; dotenv.config({ path: ".dev.vars" }); @@ -28,7 +28,7 @@ describe("Goals Evaluator", () => { user = setup.session.user; runtime = setup.runtime; - const data = await getRelationship({ + const data = await getOrCreateRelationship({ runtime, userA: user.id as UUID, userB: zeroUuid, diff --git a/src/lib/messages.ts b/src/lib/messages.ts index b198cbf..ce0b986 100644 --- a/src/lib/messages.ts +++ b/src/lib/messages.ts @@ -24,7 +24,7 @@ export async function getActorDetails({ */ export function formatActors({ actors }: { actors: Actor[] }) { const actorStrings = actors.map((actor: Actor) => { - const header = `${actor.name}${actor.details.tagline ? ": " + actor.details.tagline : ""}${actor.details?.summary ? "\n" + actor.details?.summary : ""}`; + const header = `${actor.name}${actor.details?.tagline ? ": " + actor.details?.tagline : ""}${actor.details?.summary ? "\n" + actor.details?.summary : ""}`; return header; }); const finalActorStrings = actorStrings.join("\n"); diff --git a/src/test/createRuntime.ts b/src/test/createRuntime.ts index b167199..24447bf 100644 --- a/src/test/createRuntime.ts +++ b/src/test/createRuntime.ts @@ -52,10 +52,6 @@ export async function createRuntime({ case "supabase": default: { - console.log( - "env?.SUPABASE_SERVICE_API_KEY", - env?.SUPABASE_SERVICE_API_KEY, - ); const supabase = createClient( env?.SUPABASE_URL ?? SUPABASE_URL, env?.SUPABASE_SERVICE_API_KEY ?? SUPABASE_ANON_KEY, @@ -75,14 +71,16 @@ export async function createRuntime({ password: TEST_PASSWORD!, }); + console.log("response to signup", response); + // Change the name of the user const { error } = await supabase .from("accounts") .update({ name: "Test User" }) - .eq("id", data?.user?.id); + .eq("id", response.data.user?.id); if (error) { - throw error; + throw new Error("Create runtime error: " + JSON.stringify(error)); } user = response.data.user as User; diff --git a/src/test/getOrCreateRelationship.ts b/src/test/getOrCreateRelationship.ts new file mode 100644 index 0000000..91e2a18 --- /dev/null +++ b/src/test/getOrCreateRelationship.ts @@ -0,0 +1,56 @@ +import { UUID } from "crypto"; +import { BgentRuntime, Relationship, getRelationship } from "../lib"; + +export async function getOrCreateRelationship({ + runtime, + userA, + userB, +}: { + runtime: BgentRuntime; + userA: UUID; + userB: UUID; +}): Promise { + // Check if a relationship already exists between userA and userB + let relationship = await getRelationship({ runtime, userA, userB }); + + if (!relationship) { + try { + // Check if a room already exists for the participants + const rooms = await runtime.databaseAdapter.getRoomsByParticipants([ + userA, + userB, + ]); + + let roomId: UUID; + + if (!rooms || rooms.length === 0) { + // If no room exists, create a new room for the relationship + roomId = await runtime.databaseAdapter.createRoom("Direct Message"); + + // Add participants to the newly created room + await runtime.databaseAdapter.addParticipantToRoom(userA, roomId); + await runtime.databaseAdapter.addParticipantToRoom(userB, roomId); + } else { + // If a room already exists, use the existing room + roomId = rooms[0]; + } + + // Create the relationship + await runtime.databaseAdapter.createRelationship({ + userA, + userB, + }); + + // Fetch the newly created relationship + relationship = await getRelationship({ runtime, userA, userB }); + + if (!relationship) { + throw new Error("Failed to fetch the created relationship"); + } + } catch (error) { + throw new Error(`Error creating relationship: ${JSON.stringify(error)}`); + } + } + + return relationship; +} diff --git a/supabase/migrations/20240318103238_remote_schema.sql b/supabase/migrations/20240318103238_remote_schema.sql index 24b471b..52bc1ce 100644 --- a/supabase/migrations/20240318103238_remote_schema.sql +++ b/supabase/migrations/20240318103238_remote_schema.sql @@ -57,14 +57,17 @@ BEGIN SELECT value INTO newuser_url FROM secrets WHERE key = 'newuser_url'; SELECT value INTO token FROM secrets WHERE key = 'token'; - -- Make the HTTP POST request to the endpoint - SELECT * INTO response FROM http_post( - newuser_url, - jsonb_build_object( - 'token', token, - 'user_id', NEW.id::text - ) - ); + -- Ensure newuser_url and token are both defined and not empty + IF newuser_url IS NOT NULL AND newuser_url <> '' AND token IS NOT NULL AND token <> '' THEN + -- Make the HTTP POST request to the endpoint + SELECT * INTO response FROM http_post( + newuser_url, + jsonb_build_object( + 'token', token, + 'user_id', NEW.id::text + ) + ); + END IF; RETURN NEW; END;