Files
BoxBrain/README.md
Shinwoo PARK c047c5a23d
Some checks failed
CI / verify (push) Failing after 3s
feat: bootstrap BoxBrain framework
2026-05-14 19:30:34 +09:00

164 lines
5.5 KiB
Markdown

# 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.