This commit is contained in:
163
README.md
Normal file
163
README.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# BoxBrain
|
||||
|
||||
BoxBrain is a TypeScript framework for designing LLM harnesses that make a persona feel like a real person, backed by IdentityDB memory spaces.
|
||||
|
||||
This repository was reset from scratch. The current implementation focuses on a clean framework core rather than a concrete chatbot product.
|
||||
|
||||
## Goals
|
||||
|
||||
BoxBrain helps API users build an LLM-driven persona with:
|
||||
|
||||
- persona initialization into an isolated IdentityDB-backed space
|
||||
- realistic schedule generation
|
||||
- schedule-derived availability (`online`, `do-not-disturb`, `offline`)
|
||||
- reply and proactive conversation APIs
|
||||
- sleep-time memory extraction into durable facts
|
||||
- debug hooks that expose the framework flow and persona reasoning pipeline
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
## Core API
|
||||
|
||||
```ts
|
||||
import { Persona, createSqliteIdentityMemoryStore } from 'boxbrain';
|
||||
|
||||
const memory = await createSqliteIdentityMemoryStore('.data/mina.sqlite');
|
||||
|
||||
const persona = new Persona(
|
||||
'Mina',
|
||||
'Mina is a careful student who likes quiet cafes and is preparing for exams.',
|
||||
{
|
||||
memory,
|
||||
models: {
|
||||
conversation: yourConversationModel,
|
||||
memoryExtraction: yourMemoryExtractionModel,
|
||||
},
|
||||
debug: (event) => console.log(event),
|
||||
},
|
||||
);
|
||||
|
||||
const space = await persona.ready();
|
||||
```
|
||||
|
||||
A persona can also be loaded from an existing space:
|
||||
|
||||
```ts
|
||||
const persona = new Persona(space.id, { memory, models });
|
||||
await persona.ready();
|
||||
```
|
||||
|
||||
## Persona initialization
|
||||
|
||||
`new Persona(displayName, message, options)` creates a new isolated persona space. The seed message is the single freeform place for personality, history, likes, dislikes, relationships, and other facts about the persona.
|
||||
|
||||
`new Persona(spaceId, options)` loads an existing persona space.
|
||||
|
||||
If `models.initialization` is provided, BoxBrain asks it for initial facts. If no initialization model is provided, BoxBrain stores a minimal seed fact about the persona. If the model intentionally returns an empty list, no fallback fact is stored.
|
||||
|
||||
## Schedule API
|
||||
|
||||
```ts
|
||||
await persona.createDailySchedule(now, 'Keep a normal work day.');
|
||||
await persona.createMonthlySchedule(now, 'Mostly study, with occasional rest.');
|
||||
await persona.deleteSchedulesBefore(cutoff);
|
||||
await persona.deleteSchedulesOlderThan(cutoff);
|
||||
```
|
||||
|
||||
`createDailySchedule(datetime, message)` creates tomorrow's schedule in 10-minute blocks. For example, if `datetime` is May 1, the generated daily schedule covers May 2 00:00 through May 3 00:00.
|
||||
|
||||
`createMonthlySchedule(datetime, message)` creates day-level schedule outlines for the next 30 days.
|
||||
|
||||
Schedules are stored through the configured memory store. The IdentityDB store records schedule entries as facts under schedule-related topics.
|
||||
|
||||
## Availability API
|
||||
|
||||
```ts
|
||||
const availability = await persona.getTodayScheduledAvailability(now);
|
||||
```
|
||||
|
||||
Availability is derived from schedule entries and kept in memory rather than persisted separately. The window covers today 00:00 through tomorrow 24:00. When the date changes, BoxBrain rebuilds the snapshot from schedule entries in memory.
|
||||
|
||||
Schedule activities map to availability roughly as:
|
||||
|
||||
- `sleep` → `offline`
|
||||
- `work`, `study`, `job-search`, `travel`, `commute` → `do-not-disturb`
|
||||
- rest, meals, exercise, errands, social time, free time → `online`
|
||||
|
||||
## Conversation API
|
||||
|
||||
```ts
|
||||
const reply = await persona.sendMessage({
|
||||
datetime: now,
|
||||
messageHistory: [
|
||||
{ sender: 'persona', time: yesterday, content: 'See you later.' },
|
||||
{ sender: 'user', time: now, content: 'What are you doing?' },
|
||||
],
|
||||
});
|
||||
|
||||
const opener = await persona.startConversation({
|
||||
datetime: now,
|
||||
messageHistory: [],
|
||||
});
|
||||
```
|
||||
|
||||
Before generating a reply, BoxBrain always loads mandatory context:
|
||||
|
||||
- formatted yesterday/today message history supplied by the API user
|
||||
- yesterday, today, and tomorrow schedule entries
|
||||
- current schedule-derived availability
|
||||
- IdentityDB facts related to the persona and the user
|
||||
|
||||
If no relevant mandatory memory is found, the model context explicitly says `기억이 없음` so the persona can react naturally instead of pretending to remember.
|
||||
|
||||
Conversation models return one or more outgoing messages. The framework instruction tells the model to behave like a `send_message` tool and, unless the persona prefers otherwise, keep each message to at most one sentence.
|
||||
|
||||
If `getLatestMessageHistory` and `models.rewrite` are provided, BoxBrain can detect messages that arrived while a draft was being generated and ask the rewrite model whether to discard and regenerate the stale draft.
|
||||
|
||||
## sleepMemory
|
||||
|
||||
```ts
|
||||
await persona.sleepMemory({
|
||||
datetime: '2026-05-02T00:00:00.000Z',
|
||||
messageHistory: messagesFromMay1,
|
||||
});
|
||||
```
|
||||
|
||||
`sleepMemory` asks `models.memoryExtraction` to inspect the provided message history, objectivize durable facts, and persist them through the memory store. The recommended cadence is daily around midnight, passing the previous day's messages.
|
||||
|
||||
## Debug hooks
|
||||
|
||||
Every major pipeline step can emit a debug event:
|
||||
|
||||
```ts
|
||||
const persona = new Persona('Mina', seed, {
|
||||
debug(event) {
|
||||
// Write to a file, messenger, trace UI, etc.
|
||||
console.log(event.name, event.data);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Examples include:
|
||||
|
||||
- `persona.initialized`
|
||||
- `persona.loaded`
|
||||
- `persona.schedule.daily.generated`
|
||||
- `persona.availability.refreshed`
|
||||
- `persona.conversation.context.loaded`
|
||||
- `persona.conversation.rewrite.checked`
|
||||
- `persona.memory.sleep.persisted`
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
bun run test
|
||||
bun run check
|
||||
bun run build
|
||||
```
|
||||
|
||||
The current test suite covers persona creation/loading, schedule generation/pruning, availability derivation, conversation context assembly, stale-draft rewrite checks, proactive conversation starts, and sleep-memory persistence.
|
||||
Reference in New Issue
Block a user