diff --git a/bun.lock b/bun.lock index 1a58f1f..9a279ac 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,7 @@ "": { "name": "boxbrain", "dependencies": { - "identitydb": "^0.4.0", + "identitydb": "^0.5.0", }, "devDependencies": { "@types/bun": "latest", @@ -249,7 +249,7 @@ "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], - "identitydb": ["identitydb@0.4.0", "", { "dependencies": { "kysely": "^0.28.8", "mysql2": "^3.15.3", "pg": "^8.16.0" } }, "sha512-DAyipdrApjmI1HoHfhT9zuMfNLiWaYe7/k/FrUa55h7WUUASGV192AhrC6KUiMTS55dfYKDBWi0AcS7crSw+bA=="], + "identitydb": ["identitydb@0.5.0", "", { "dependencies": { "kysely": "^0.28.8", "mysql2": "^3.15.3", "pg": "^8.16.0" } }, "sha512-3cp14fb5nDKFakRqHdJrOBOgpDWLlvJ/K2q8405muAfqcJja9ds2tS9ksoaEiMgGU5r+mIz6lADZ3DYNpGqHVQ=="], "is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], diff --git a/package.json b/package.json index dd87df9..00321f4 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "prepublishOnly": "bun run check && bun run test && bun run build && bun run pack:check" }, "dependencies": { - "identitydb": "^0.4.0" + "identitydb": "^0.5.0" }, "devDependencies": { "@types/bun": "latest", diff --git a/src/persona.ts b/src/persona.ts index fe7142d..018c6b9 100644 --- a/src/persona.ts +++ b/src/persona.ts @@ -10,7 +10,7 @@ import { startOfUtcDay, toIso, } from "./schedule"; -import { extractFact } from "identitydb"; +import { ExtractedFact, extractFacts } from "identitydb"; import { buildMandatoryConversationContext, conversationInstruction, @@ -331,6 +331,20 @@ export class Persona { return draft; } + private extractedToDraft(fact: ExtractedFact, statement: string): FactDraft { + return { + statement: fact.statement ?? statement, + topics: [...fact.topics.map((t) => t.name), "sleepMemory"], + source: fact.source ?? "boxbrain.sleepMemory", + ...(typeof fact.confidence === "number" + ? { confidence: fact.confidence } + : {}), + ...(fact.metadata !== undefined && fact.metadata !== null + ? { metadata: fact.metadata as Record } + : {}), + }; + } + async sleepMemory(input: { datetime: DateTimeInput; messageHistory: PersonaMessage[]; @@ -360,26 +374,17 @@ export class Persona { messages: input.messageHistory, }), ].join("\n"); - const extracted = await extractFact( - statement, - this.options.models.factExtractor, - ); - const draft: FactDraft = { - statement: extracted.statement ?? statement, - topics: [...extracted.topics.map((t) => t.name), "sleepMemory"], - source: extracted.source ?? "boxbrain.sleepMemory", - ...(typeof extracted.confidence === 'number' - ? { confidence: extracted.confidence } - : {}), - ...(extracted.metadata !== undefined && extracted.metadata !== null - ? { metadata: extracted.metadata as Record } - : {}), - }; - await this.memory.addFact(persona.id, draft); + const extractedFacts = ( + await extractFacts(statement, this.options.models.factExtractor) + ).map((fact) => this.extractedToDraft(fact, statement)); + + for (const fact of extractedFacts) { + await this.memory.addFact(persona.id, fact); + } await this.emit("persona.memory.sleep.persisted", { - factCount: 1, + factCount: extractedFacts.length, }); - return [draft]; + return extractedFacts; } private async initialize(): Promise { @@ -400,29 +405,24 @@ export class Persona { }); if (this.options.models?.factExtractor) { const statement = `Persona: ${this.mode.displayName}\nSeed: ${this.mode.seedMessage}`; - const extracted = await extractFact( - statement, - this.options.models.factExtractor, - ); - const draft: FactDraft = { - statement: extracted.statement ?? statement, - topics: extracted.topics.map((t) => t.name), - source: extracted.source ?? "boxbrain.persona.initialization", - ...(typeof extracted.confidence === 'number' - ? { confidence: extracted.confidence } - : {}), - ...(extracted.metadata !== undefined && extracted.metadata !== null - ? { metadata: extracted.metadata as Record } - : {}), - }; - await this.memory.addFact(space.id, draft); + const extracteds = ( + await extractFacts(statement, this.options.models.factExtractor) + ).map((fact) => this.extractedToDraft(fact, statement)); + + for (const fact of extracteds) { + await this.memory.addFact(space.id, fact); + } + await this.emit( "persona.initialized", - { displayName: space.displayName, factCount: 1 }, + { displayName: space.displayName, factCount: extracteds.length }, space.id, ); } else { - const fact = defaultInitialFact(this.mode.displayName, this.mode.seedMessage); + const fact = defaultInitialFact( + this.mode.displayName, + this.mode.seedMessage, + ); await this.memory.addFact(space.id, fact); await this.emit( "persona.initialized",