mirror of
https://github.com/sortedcord/omnia.git
synced 2026-07-22 03:52:48 +05:30
FEAT!(voice): Implement intent hydration, dehydration system fixes: #29
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
"@omnia/core": "workspace:*",
|
||||
"@omnia/intent": "workspace:*",
|
||||
"@omnia/llm": "workspace:*",
|
||||
"@omnia/voice": "workspace:*",
|
||||
"zod": "^4.4.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Database from "better-sqlite3";
|
||||
import { Entity, resolveAlias } from "@omnia/core";
|
||||
import { Intent } from "@omnia/intent";
|
||||
import { hydrate } from "@omnia/voice";
|
||||
|
||||
export interface BufferEntry {
|
||||
id: string;
|
||||
@@ -23,32 +24,14 @@ export function serializeSubjectiveBufferEntry(
|
||||
entry: BufferEntry,
|
||||
viewer: Entity,
|
||||
): string {
|
||||
const isSelf = viewer.id === entry.intent.actorId;
|
||||
|
||||
if (isSelf) {
|
||||
let details = (
|
||||
entry.intent.selfDescription ||
|
||||
entry.intent.description ||
|
||||
entry.intent.originalText
|
||||
).trim();
|
||||
if (details.length > 0) {
|
||||
details = details.charAt(0).toUpperCase() + details.slice(1);
|
||||
}
|
||||
if (entry.intent.type === "action" && entry.outcome) {
|
||||
details += ` (Outcome: ${entry.outcome.isValid ? "Succeeded" : `Failed - ${entry.outcome.reason}`})`;
|
||||
}
|
||||
return details;
|
||||
let details = hydrate(entry.intent.content, viewer).trim();
|
||||
if (details.length > 0) {
|
||||
details = details.charAt(0).toUpperCase() + details.slice(1);
|
||||
}
|
||||
|
||||
const actorAlias = resolveAlias(viewer, entry.intent.actorId);
|
||||
const subjectStr = actorAlias.charAt(0).toUpperCase() + actorAlias.slice(1);
|
||||
|
||||
let details = (entry.intent.description || entry.intent.originalText).trim();
|
||||
if (entry.intent.type === "action" && entry.outcome) {
|
||||
details += ` (Outcome: ${entry.outcome.isValid ? "Succeeded" : `Failed - ${entry.outcome.reason}`})`;
|
||||
}
|
||||
|
||||
return `${subjectStr} ${details}`;
|
||||
return details;
|
||||
}
|
||||
|
||||
export class BufferRepository {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { describe, test, expect } from "vitest";
|
||||
import Database from "better-sqlite3";
|
||||
import { describe, test, expect } from "vitest";
|
||||
import { Entity } from "@omnia/core";
|
||||
import { MockLLMProvider, MockEmbeddingProvider } from "@omnia/llm";
|
||||
import {
|
||||
BufferEntry,
|
||||
BufferRepository,
|
||||
LedgerRepository,
|
||||
checkHandoffTrigger,
|
||||
splitBufferForHandoff,
|
||||
HandoffEngine,
|
||||
splitBufferForHandoff,
|
||||
checkHandoffTrigger,
|
||||
} from "@omnia/memory";
|
||||
|
||||
describe("Memory Handoff Tests (Tier 1)", () => {
|
||||
const now = new Date("2026-07-07T12:00:00.000Z");
|
||||
const now = new Date("2026-07-09T08:00:00.000Z");
|
||||
|
||||
test("splitBufferForHandoff correctly splits based on watermark and fresh buckets", () => {
|
||||
describe("Memory Handoff Tests (Tier 1)", () => {
|
||||
test("splitBufferForHandoff identifies candidate entries based on recency", () => {
|
||||
const entries: BufferEntry[] = [];
|
||||
|
||||
// Add 12 older entries (older than 30 minutes)
|
||||
@@ -30,8 +30,7 @@ describe("Memory Handoff Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: "dialogue",
|
||||
originalText: `Old event ${i}`,
|
||||
description: `does old thing ${i}`,
|
||||
content: `entity@alice[I] do old thing ${i}`,
|
||||
actorId: "alice",
|
||||
targetIds: ["bob"],
|
||||
},
|
||||
@@ -54,8 +53,7 @@ describe("Memory Handoff Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: "dialogue",
|
||||
originalText: `Fresh event ${idx}`,
|
||||
description: `does fresh thing ${idx}`,
|
||||
content: `entity@alice[I] do fresh thing ${idx}`,
|
||||
actorId: "alice",
|
||||
targetIds: ["bob"],
|
||||
},
|
||||
@@ -84,8 +82,7 @@ describe("Memory Handoff Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: "dialogue",
|
||||
originalText: "hello",
|
||||
description: "says hello",
|
||||
content: "entity@alice[I] say hello",
|
||||
actorId: "alice",
|
||||
targetIds: [],
|
||||
},
|
||||
@@ -100,8 +97,7 @@ describe("Memory Handoff Tests (Tier 1)", () => {
|
||||
locationId: "room-2",
|
||||
intent: {
|
||||
type: "monologue",
|
||||
originalText: "think",
|
||||
description: "thinks",
|
||||
content: "entity@alice[I] think",
|
||||
actorId: "alice",
|
||||
targetIds: [],
|
||||
},
|
||||
@@ -138,8 +134,7 @@ describe("Memory Handoff Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: i % 2 === 0 ? "dialogue" : "action",
|
||||
originalText: `Event ${i}`,
|
||||
description: `does thing ${i}`,
|
||||
content: `entity@alice[I] do thing ${i}`,
|
||||
actorId: "alice",
|
||||
targetIds: ["bob"],
|
||||
},
|
||||
|
||||
@@ -1,24 +1,14 @@
|
||||
import { describe, test, expect } from "vitest";
|
||||
import Database from "better-sqlite3";
|
||||
import { describe, test, expect } from "vitest";
|
||||
import { Entity, SQLiteRepository } from "@omnia/core";
|
||||
import { Intent } from "@omnia/intent";
|
||||
import {
|
||||
BufferEntry,
|
||||
BufferRepository,
|
||||
serializeSubjectiveBufferEntry,
|
||||
resolveAlias,
|
||||
} from "@omnia/memory";
|
||||
|
||||
describe("Subjective Buffer Entry Serializer Tests (Tier 1)", () => {
|
||||
test("resolveAlias correctly handles self and fallbacks", () => {
|
||||
const viewer = new Entity("alice");
|
||||
viewer.aliases.set("bob", "the hooded figure");
|
||||
|
||||
expect(resolveAlias(viewer, "alice")).toBe("you");
|
||||
expect(resolveAlias(viewer, "bob")).toBe("the hooded figure");
|
||||
expect(resolveAlias(viewer, "charlie")).toBe("an unfamiliar figure");
|
||||
});
|
||||
|
||||
test("serializes dialogue intent substituting target/actor aliases", () => {
|
||||
const viewer = new Entity("alice");
|
||||
viewer.aliases.set("bob", "the hooded figure");
|
||||
@@ -31,9 +21,8 @@ describe("Subjective Buffer Entry Serializer Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: "dialogue",
|
||||
originalText: '"Hello there," Bob said to Charlie.',
|
||||
description: "says, 'Hello there' to the bartender",
|
||||
selfDescription: "You say, 'Hello there' to the bartender.",
|
||||
content:
|
||||
"entity@bob[I] say 'Hello there' to entity@charlie[the bartender]",
|
||||
actorId: "bob",
|
||||
targetIds: ["charlie"],
|
||||
modifiers: [],
|
||||
@@ -42,7 +31,7 @@ describe("Subjective Buffer Entry Serializer Tests (Tier 1)", () => {
|
||||
|
||||
const result = serializeSubjectiveBufferEntry(entry, viewer);
|
||||
expect(result).toBe(
|
||||
"The hooded figure says, 'Hello there' to the bartender",
|
||||
"The hooded figure says 'Hello there' to the bartender",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -57,9 +46,7 @@ describe("Subjective Buffer Entry Serializer Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: "action",
|
||||
originalText: "Bob tried to break the latch.",
|
||||
description: "attempts to break the lock latch",
|
||||
selfDescription: "You attempt to break the lock latch.",
|
||||
content: "entity@bob[I] attempt to break the lock latch",
|
||||
actorId: "bob",
|
||||
targetIds: [],
|
||||
modifiers: [],
|
||||
@@ -86,9 +73,7 @@ describe("Subjective Buffer Entry Serializer Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: "action",
|
||||
originalText: "I opened the window.",
|
||||
description: "open the window",
|
||||
selfDescription: "You open the window.",
|
||||
content: "entity@alice[I] open the window",
|
||||
actorId: "alice",
|
||||
targetIds: [],
|
||||
modifiers: [],
|
||||
@@ -96,7 +81,7 @@ describe("Subjective Buffer Entry Serializer Tests (Tier 1)", () => {
|
||||
};
|
||||
|
||||
const resultSelf = serializeSubjectiveBufferEntry(entrySelf, viewer);
|
||||
expect(resultSelf).toBe("You open the window.");
|
||||
expect(resultSelf).toBe("I open the window");
|
||||
|
||||
const entryUnfamiliar: BufferEntry = {
|
||||
id: "entry-unfamiliar",
|
||||
@@ -105,9 +90,7 @@ describe("Subjective Buffer Entry Serializer Tests (Tier 1)", () => {
|
||||
locationId: "room-1",
|
||||
intent: {
|
||||
type: "action",
|
||||
originalText: "Someone knocked.",
|
||||
description: "knocks on the door",
|
||||
selfDescription: "You knock on the door.",
|
||||
content: "entity@stranger-1[I] knock on the door",
|
||||
actorId: "stranger-1",
|
||||
targetIds: [],
|
||||
modifiers: [],
|
||||
@@ -136,9 +119,7 @@ describe("BufferRepository Persistence Tests (Tier 1)", () => {
|
||||
|
||||
const intent: Intent = {
|
||||
type: "action",
|
||||
originalText: "Alice picked up a stick.",
|
||||
description: "Alice gathers a stick",
|
||||
selfDescription: "You gather a stick.",
|
||||
content: "entity@alice[I] gather a stick",
|
||||
actorId: "alice",
|
||||
targetIds: [],
|
||||
modifiers: [],
|
||||
@@ -196,8 +177,7 @@ describe("BufferRepository Persistence Tests (Tier 1)", () => {
|
||||
locationId: "forest",
|
||||
intent: {
|
||||
type: "action",
|
||||
originalText: "Alice sneezed.",
|
||||
description: "Alice sneezes",
|
||||
content: "entity@alice[I] sneeze",
|
||||
actorId: "alice",
|
||||
targetIds: [],
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"references": [
|
||||
{ "path": "../core" },
|
||||
{ "path": "../intent" },
|
||||
{ "path": "../llm" }
|
||||
{ "path": "../llm" },
|
||||
{ "path": "../voice" }
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user