docs: refresh wiki for current runtime structure
193
API-Reference.md
193
API-Reference.md
@@ -1,32 +1,41 @@
|
||||
# API Reference
|
||||
|
||||
This page documents the current public surface exported from the BoxBrain package root.
|
||||
This page documents the **current public surface exported from the BoxBrain package root**.
|
||||
|
||||
```ts
|
||||
export * from './adapters';
|
||||
export * from './core/adapters';
|
||||
export * from './core/types';
|
||||
export * from './availability';
|
||||
export * from './conversation';
|
||||
export * from './grok';
|
||||
export * from './memory';
|
||||
export * from './persona';
|
||||
export * from './providers/grok';
|
||||
export * from './schedule';
|
||||
export * from './timing';
|
||||
export * from './types';
|
||||
```
|
||||
|
||||
## Public API shape
|
||||
|
||||
The package root exposes both:
|
||||
|
||||
- **functional helpers** for direct use in applications
|
||||
- **class-based service entrypoints** for clearer domain grouping in stateful integrations
|
||||
|
||||
## `persona`
|
||||
|
||||
### `PersonaService`
|
||||
|
||||
Class-based entrypoint for persona initialization.
|
||||
|
||||
### `initializePersona(db, input)`
|
||||
|
||||
Creates and persists a new persona runtime profile.
|
||||
|
||||
**Signature**
|
||||
|
||||
```ts
|
||||
initializePersona(db: IdentityDB, input: InitializePersonaInput): Promise<InitializedPersona>
|
||||
```
|
||||
|
||||
**Important input fields**
|
||||
Important input fields:
|
||||
|
||||
- `displayName: string`
|
||||
- `seedText?: string`
|
||||
@@ -42,36 +51,18 @@ initializePersona(db: IdentityDB, input: InitializePersonaInput): Promise<Initia
|
||||
- `generateProfileImage?: boolean`
|
||||
- `reuseExistingSpace?: boolean`
|
||||
|
||||
`seedText` is the preferred initialize input shape: a single long freeform string that may already include personality, history, values, preferences, dislikes, and relationships. Structured fields remain available as optional supplemental hints and for backward compatibility.
|
||||
|
||||
**Behavior**
|
||||
|
||||
- generates a biography through `structuredModel`, using `seedText` as the primary source when provided
|
||||
- extracts fact drafts through `structuredModel`
|
||||
- writes biography facts into the persona space
|
||||
- optionally generates a profile image and writes a profile-image fact
|
||||
- creates a collision-resistant persona ID if one is not provided
|
||||
|
||||
**Returns**
|
||||
|
||||
```ts
|
||||
interface InitializedPersona {
|
||||
id: string;
|
||||
spaceName: string;
|
||||
displayName: string;
|
||||
biography: string;
|
||||
profileImageUrl?: string;
|
||||
}
|
||||
```
|
||||
`seedText` is the preferred initialization input shape: one long freeform string containing the persona's personality, history, values, preferences, and relationships when available.
|
||||
|
||||
## `schedule`
|
||||
|
||||
### `ScheduleService`
|
||||
|
||||
Class-based entrypoint for schedule generation, listing, and pruning.
|
||||
|
||||
### `generateSchedule(db, input)`
|
||||
|
||||
Generates and persists schedule events, then derives schedule-backed availability entries.
|
||||
|
||||
**Signature**
|
||||
|
||||
```ts
|
||||
generateSchedule(
|
||||
db: IdentityDB,
|
||||
@@ -79,38 +70,18 @@ generateSchedule(
|
||||
): Promise<{ events: BoxBrainScheduleEvent[]; availabilityEntries: BoxBrainAvailabilityEntry[] }>
|
||||
```
|
||||
|
||||
**Important input fields**
|
||||
|
||||
- `spaceName: string`
|
||||
- `displayName?: string`
|
||||
- `currentDate: string`
|
||||
- `scope: 'day' | 'week' | 'month'`
|
||||
- `timezone?: string`
|
||||
- `structuredModel: StructuredModelAdapter`
|
||||
- `specialDateProvider?: SpecialDateProvider`
|
||||
|
||||
### `listScheduleEvents(db, input)`
|
||||
|
||||
Lists persisted schedule events, excluding ones hidden by deletion markers.
|
||||
|
||||
**Signature**
|
||||
|
||||
```ts
|
||||
listScheduleEvents(db: IdentityDB, input: ListScheduleEventsInput): Promise<BoxBrainScheduleEvent[]>
|
||||
```
|
||||
|
||||
**Filters**
|
||||
|
||||
- `spaceName`
|
||||
- optional `from`
|
||||
- optional `until`
|
||||
|
||||
### `pruneExpiredSchedule(db, input)`
|
||||
|
||||
Marks schedule events as deleted when they ended before `referenceTime` minus an optional grace window.
|
||||
|
||||
**Signature**
|
||||
|
||||
```ts
|
||||
pruneExpiredSchedule(db: IdentityDB, input: PruneExpiredScheduleInput): Promise<SchedulePruneResult>
|
||||
```
|
||||
@@ -119,58 +90,27 @@ pruneExpiredSchedule(db: IdentityDB, input: PruneExpiredScheduleInput): Promise<
|
||||
|
||||
Marks schedule events as deleted when they start before a cutoff timestamp.
|
||||
|
||||
**Signature**
|
||||
|
||||
```ts
|
||||
pruneScheduleBefore(db: IdentityDB, input: PruneScheduleBeforeInput): Promise<SchedulePruneResult>
|
||||
```
|
||||
|
||||
**Common types**
|
||||
|
||||
```ts
|
||||
type BoxBrainScheduleScope = 'day' | 'week' | 'month';
|
||||
type BoxBrainScheduleEventKind = 'routine' | 'special';
|
||||
|
||||
interface BoxBrainScheduleEvent {
|
||||
id: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
startAt: string;
|
||||
endAt: string;
|
||||
availabilityMode: BoxBrainAvailabilityMode;
|
||||
availabilityReason?: string;
|
||||
kind: BoxBrainScheduleEventKind;
|
||||
topics: BoxBrainTopicDraft[];
|
||||
metadata?: JsonValue | null;
|
||||
}
|
||||
```
|
||||
|
||||
## `availability`
|
||||
|
||||
### `AvailabilityService`
|
||||
|
||||
Class-based entrypoint for availability writes, listing, and snapshot queries.
|
||||
|
||||
### `setAvailabilityStatus(db, input)`
|
||||
|
||||
Persists an explicit availability entry.
|
||||
|
||||
**Signature**
|
||||
|
||||
```ts
|
||||
setAvailabilityStatus(db: IdentityDB, input: SetAvailabilityStatusInput): Promise<BoxBrainAvailabilityEntry>
|
||||
```
|
||||
|
||||
**Important input fields**
|
||||
|
||||
- `spaceName: string`
|
||||
- `mode: 'online' | 'do_not_disturb' | 'offline'`
|
||||
- `reason?: string`
|
||||
- `effectiveFrom: string`
|
||||
- `until?: string`
|
||||
- `sourceType?: 'schedule' | 'manual' | 'tool'`
|
||||
- `eventId?: string`
|
||||
- `metadata?: JsonValue | null`
|
||||
|
||||
### `listAvailabilityEntries(db, input)`
|
||||
|
||||
Lists explicit availability entries in chronological order.
|
||||
Lists availability entries in chronological order.
|
||||
|
||||
```ts
|
||||
listAvailabilityEntries(db: IdentityDB, input: ListAvailabilityEntriesInput): Promise<BoxBrainAvailabilityEntry[]>
|
||||
@@ -184,32 +124,19 @@ Returns the active availability state at a timestamp plus the next transition.
|
||||
getAvailabilitySnapshot(db: IdentityDB, input: GetAvailabilitySnapshotInput): Promise<BoxBrainAvailabilitySnapshot>
|
||||
```
|
||||
|
||||
**Important types**
|
||||
Important types:
|
||||
|
||||
```ts
|
||||
type BoxBrainAvailabilityMode = 'online' | 'do_not_disturb' | 'offline';
|
||||
type BoxBrainAvailabilitySourceType = 'default' | 'schedule' | 'manual' | 'tool';
|
||||
|
||||
interface BoxBrainAvailabilityEntry {
|
||||
id: string;
|
||||
mode: BoxBrainAvailabilityMode;
|
||||
reason?: string;
|
||||
effectiveFrom: string;
|
||||
until?: string;
|
||||
sourceType: BoxBrainAvailabilitySourceType;
|
||||
eventId?: string;
|
||||
createdAt?: string;
|
||||
metadata?: JsonValue | null;
|
||||
}
|
||||
|
||||
interface BoxBrainAvailabilitySnapshot {
|
||||
current: BoxBrainAvailabilityEntry;
|
||||
next: BoxBrainAvailabilityEntry | null;
|
||||
}
|
||||
```
|
||||
|
||||
## `conversation`
|
||||
|
||||
### `ConversationService`
|
||||
|
||||
Class-based entrypoint for inbound replies, proactive openings, and entry listing.
|
||||
|
||||
### `replyToConversation(db, input)`
|
||||
|
||||
Persists an inbound message and generates a DM-style response turn.
|
||||
@@ -234,41 +161,29 @@ Lists stored conversation entries for a persona, optionally filtered by counterp
|
||||
listConversationEntries(db: IdentityDB, input: ListConversationEntriesInput): Promise<BoxBrainConversationEntry[]>
|
||||
```
|
||||
|
||||
**Required model roles for turn generation**
|
||||
|
||||
Both `replyToConversation` and `startConversation` require:
|
||||
Required model roles for turn generation:
|
||||
|
||||
- `mandatoryMemoryModel: StructuredModelAdapter`
|
||||
- `contextualMemoryModel: StructuredModelAdapter`
|
||||
- `responseModel: StructuredModelAdapter`
|
||||
|
||||
**Turn result**
|
||||
## `memory`
|
||||
|
||||
### `FactDraftMemoryStore`
|
||||
|
||||
Class-based entrypoint for persisting extracted fact drafts into IdentityDB.
|
||||
|
||||
### `persistFactDrafts(db, input)`
|
||||
|
||||
Low-level helper for writing BoxBrain fact drafts into IdentityDB.
|
||||
|
||||
```ts
|
||||
interface ConversationTurnResult {
|
||||
blocked: boolean;
|
||||
blockedReason?: string;
|
||||
blockedUntil?: string;
|
||||
messages: BoxBrainMessage[];
|
||||
usedMemories: BoxBrainMemoryReference[];
|
||||
toolCallsExecuted: ConversationToolCall[];
|
||||
}
|
||||
```
|
||||
|
||||
**Message type**
|
||||
|
||||
```ts
|
||||
interface BoxBrainMessage {
|
||||
text: string;
|
||||
typingDelaySeconds: number;
|
||||
replyDelaySeconds: number;
|
||||
totalDelaySeconds: number;
|
||||
}
|
||||
persistFactDrafts(db: IdentityDB, input: PersistFactDraftsInput): Promise<Fact[]>
|
||||
```
|
||||
|
||||
## `timing`
|
||||
|
||||
### Availability constants
|
||||
### Constants
|
||||
|
||||
```ts
|
||||
ONLINE_AVAILABILITY
|
||||
@@ -276,6 +191,10 @@ DND_AVAILABILITY
|
||||
OFFLINE_AVAILABILITY
|
||||
```
|
||||
|
||||
### `TimingProfile`
|
||||
|
||||
Class-based entrypoint for timing calculations.
|
||||
|
||||
### `createTypingDelay(message, options?)`
|
||||
|
||||
Computes a per-message typing delay based on message length.
|
||||
@@ -346,6 +265,10 @@ interface SpecialDateProvider {
|
||||
|
||||
## `grok`
|
||||
|
||||
### `GrokApiClient`
|
||||
|
||||
Class-based xAI runtime client used by the Grok adapter helpers.
|
||||
|
||||
### `createGrokTextModelAdapter(options)`
|
||||
|
||||
Creates a `TextModelAdapter` that uses xAI chat completions.
|
||||
@@ -370,21 +293,9 @@ createGrokAdapters(options: GrokAdapterBundleOptions): {
|
||||
}
|
||||
```
|
||||
|
||||
## `memory`
|
||||
|
||||
### `persistFactDrafts(db, input)`
|
||||
|
||||
Low-level helper for writing BoxBrain fact drafts into IdentityDB.
|
||||
|
||||
```ts
|
||||
persistFactDrafts(db: IdentityDB, input: PersistFactDraftsInput): Promise<Fact[]>
|
||||
```
|
||||
|
||||
Useful when extending BoxBrain with your own runtime modules.
|
||||
|
||||
## `types`
|
||||
|
||||
Selected important domain types:
|
||||
Selected important domain types include:
|
||||
|
||||
```ts
|
||||
type BoxBrainFactDomain =
|
||||
|
||||
@@ -1,48 +1,50 @@
|
||||
# Getting Started
|
||||
|
||||
## Current setup assumptions
|
||||
## Setup options
|
||||
|
||||
At the current stage, BoxBrain is a local TypeScript/Bun framework that depends on a sibling checkout of IdentityDB.
|
||||
BoxBrain now consumes the published `identitydb` package from npm, so **a sibling checkout of IdentityDB is no longer required** for normal usage or local verification.
|
||||
|
||||
The package configuration currently points to:
|
||||
### Use BoxBrain in your own project
|
||||
|
||||
```json
|
||||
"identitydb": "file:../IdentityDB"
|
||||
```bash
|
||||
bun add boxbrain identitydb
|
||||
```
|
||||
|
||||
So a practical local setup looks like this:
|
||||
### Work on the BoxBrain repository itself
|
||||
|
||||
```bash
|
||||
git clone https://git.psw.kr/p-sw/BoxBrain.git
|
||||
git clone https://git.psw.kr/p-sw/IdentityDB.git
|
||||
```
|
||||
|
||||
with both repositories living next to each other.
|
||||
|
||||
## Install and verify
|
||||
|
||||
```bash
|
||||
cd BoxBrain
|
||||
bun install
|
||||
```
|
||||
|
||||
## Verify the repository
|
||||
|
||||
```bash
|
||||
bun run test
|
||||
bun run check
|
||||
bun run build
|
||||
```
|
||||
|
||||
## Minimal dependencies
|
||||
If you hit a `better-sqlite3` native module / `NODE_MODULE_VERSION` mismatch after environment changes, reset the install so Bun can re-run trusted lifecycle scripts:
|
||||
|
||||
```bash
|
||||
rm -rf node_modules bun.lock
|
||||
bun install
|
||||
```
|
||||
|
||||
## Runtime requirements
|
||||
|
||||
You need:
|
||||
|
||||
- Node.js 20+
|
||||
- Bun
|
||||
- IdentityDB available at `../IdentityDB`
|
||||
- an initialized IdentityDB database connection at runtime
|
||||
|
||||
## Create an IdentityDB instance
|
||||
|
||||
BoxBrain uses IdentityDB as the persistence layer.
|
||||
|
||||
A minimal in-memory setup:
|
||||
|
||||
```ts
|
||||
import { IdentityDB } from 'identitydb';
|
||||
|
||||
@@ -58,7 +60,7 @@ For a persistent local database, replace `':memory:'` with a file path.
|
||||
|
||||
## Create model adapters
|
||||
|
||||
BoxBrain runtime code expects provider adapters instead of hard-coding a specific vendor inside the core functions.
|
||||
BoxBrain expects provider adapters instead of hard-coding a vendor into the core runtime.
|
||||
|
||||
### Provider-agnostic contracts
|
||||
|
||||
@@ -84,7 +86,9 @@ const grok = createGrokAdapters({
|
||||
|
||||
## Initialize a persona
|
||||
|
||||
This is the first major BoxBrain workflow.
|
||||
You can use either the functional helper or the class-based service entrypoint.
|
||||
|
||||
### Functional helper
|
||||
|
||||
```ts
|
||||
import { IdentityDB } from 'identitydb';
|
||||
@@ -109,18 +113,32 @@ const persona = await initializePersona(db, {
|
||||
imageModel: grok.image,
|
||||
generateProfileImage: true,
|
||||
});
|
||||
|
||||
console.log(persona);
|
||||
```
|
||||
|
||||
### What initialization does
|
||||
### Class-based service
|
||||
|
||||
- generates a detailed biography
|
||||
- can start from a single long freeform persona seed string
|
||||
- extracts IdentityDB-ready facts
|
||||
- creates or reuses an IdentityDB space (depending on options)
|
||||
- optionally generates a profile image
|
||||
- persists biography and image facts
|
||||
```ts
|
||||
import { IdentityDB } from 'identitydb';
|
||||
import { createGrokAdapters, PersonaService } from 'boxbrain';
|
||||
|
||||
const db = await IdentityDB.connect({ client: 'sqlite', filename: ':memory:' });
|
||||
await db.initialize();
|
||||
|
||||
const grok = createGrokAdapters({
|
||||
apiKey: process.env.XAI_API_KEY!,
|
||||
textModel: 'grok-4.3-mini',
|
||||
structuredModel: 'grok-4.3',
|
||||
imageModel: 'grok-imagine-image-quality',
|
||||
});
|
||||
|
||||
const personas = new PersonaService(db);
|
||||
|
||||
const persona = await personas.initialize({
|
||||
displayName: 'Mina',
|
||||
seedText: 'Mina is a thoughtful, witty Seoul product designer who loves quiet cafés.',
|
||||
structuredModel: grok.structured,
|
||||
});
|
||||
```
|
||||
|
||||
## Generate a schedule
|
||||
|
||||
@@ -151,14 +169,6 @@ console.log(schedule.events);
|
||||
console.log(schedule.availabilityEntries);
|
||||
```
|
||||
|
||||
### What schedule generation does
|
||||
|
||||
- reads persona facts and recent schedule continuity
|
||||
- optionally loads external special-date context
|
||||
- generates realistic events for a day/week/month window
|
||||
- stores schedule facts in IdentityDB
|
||||
- automatically emits schedule-derived availability entries
|
||||
|
||||
## Read or override availability
|
||||
|
||||
```ts
|
||||
@@ -226,8 +236,6 @@ console.log(reply.toolCallsExecuted);
|
||||
|
||||
## Timing helpers
|
||||
|
||||
If you want to inspect or reuse BoxBrain’s timing rules directly:
|
||||
|
||||
```ts
|
||||
import {
|
||||
ONLINE_AVAILABILITY,
|
||||
@@ -245,9 +253,9 @@ const typingDelay = createTypingDelay('지금 뭐해?', {
|
||||
});
|
||||
```
|
||||
|
||||
## Caveats
|
||||
## Important caveats
|
||||
|
||||
### 1. BoxBrain is currently a library, not an HTTP service
|
||||
### 1. BoxBrain is a library, not an HTTP service
|
||||
|
||||
You call the exported TypeScript APIs directly.
|
||||
|
||||
@@ -255,10 +263,10 @@ You call the exported TypeScript APIs directly.
|
||||
|
||||
The framework assumes IdentityDB is available and initialized.
|
||||
|
||||
### 3. Current local development uses a sibling checkout
|
||||
### 3. Internal source folders are a repository concern
|
||||
|
||||
Because the package currently depends on `file:../IdentityDB`, a standalone `npm install boxbrain` style flow is not the current development path yet.
|
||||
The repository is organized by domain folders under `src/`, but the published package is still consumed through the package root exports.
|
||||
|
||||
### 4. `better-sqlite3` native rebuilds may be needed in local dev
|
||||
### 4. Clean Bun installs depend on trusted lifecycle scripts
|
||||
|
||||
If you hit a native module mismatch through the local IdentityDB dependency, rebuilding `better-sqlite3` from the IdentityDB workspace may be required.
|
||||
The repository keeps `trustedDependencies` for `better-sqlite3` and `esbuild` so native/runtime build steps succeed during clean installs.
|
||||
|
||||
120
Home.md
120
Home.md
@@ -2,85 +2,79 @@
|
||||
|
||||
BoxBrain is an IdentityDB-backed TypeScript framework for building **synthetic personas that feel like real DM contacts**.
|
||||
|
||||
It is not a finished chatbot product. It is a **framework for persona runtime design**: a reusable harness for turning long-term memory, schedules, availability, and multi-step LLM orchestration into believable human-like messaging behavior.
|
||||
It is not a finished chatbot product. It is a **framework-first runtime library** for composing persona memory, schedules, availability, and multi-step LLM orchestration into believable messaging behavior.
|
||||
|
||||
## Why BoxBrain exists
|
||||
|
||||
Most LLM chat systems are optimized for correctness, utility, or task completion. BoxBrain exists for a different goal:
|
||||
|
||||
- make a persona feel like a **specific person**, not a generic assistant
|
||||
- preserve continuity through **IdentityDB facts** instead of a short rolling prompt only
|
||||
- let that persona have a **life outside the chat**
|
||||
- make conversation timing and availability feel **human**, not instant and mechanical
|
||||
- keep the whole system **framework-first**, so applications can compose their own transports and product UX on top
|
||||
|
||||
In short: BoxBrain is a harness for building personas that have memory, history, schedules, contactability, and DM-style messaging behavior.
|
||||
|
||||
## What the framework currently provides
|
||||
## What BoxBrain currently provides
|
||||
|
||||
- provider-agnostic adapter contracts for text, structured-output, image, and special-date retrieval
|
||||
- a ready-made xAI Grok adapter set for text, structured-output, and image generation
|
||||
- one IdentityDB **space** per persona as the primary isolation boundary
|
||||
- persona initialization from a long freeform seed string that the LLM breaks into biography-ready detail and IdentityDB facts
|
||||
- LLM-generated biography creation followed by fact extraction into IdentityDB
|
||||
- a ready-made xAI Grok adapter set
|
||||
- one IdentityDB space per persona as the main isolation boundary
|
||||
- persona initialization from a long freeform seed string, with optional supplemental structured hints
|
||||
- biography generation and fact extraction into IdentityDB
|
||||
- optional profile image generation during persona initialization
|
||||
- realistic schedule generation for day, week, and month scopes
|
||||
- schedule generation for `day`, `week`, and `month` scopes
|
||||
- schedule persistence, listing, and pruning
|
||||
- availability state persistence with schedule, manual, and tool-driven overrides
|
||||
- availability snapshots with current and next transition resolution
|
||||
- availability persistence with schedule/manual/tool overrides
|
||||
- availability snapshots with current and next-transition resolution
|
||||
- DM-style conversation orchestration for inbound replies and proactive openings
|
||||
- two-stage memory retrieval for conversation turns: mandatory memories first, contextual memories second
|
||||
- human-like first-reply delay and per-message typing delay helpers
|
||||
- refusal / farewell flows that can trigger an availability-changing tool call
|
||||
- human-like first-reply and typing delay helpers
|
||||
|
||||
## What is still planned
|
||||
|
||||
These are **not** implemented as part of the core library yet:
|
||||
|
||||
- HTTP/RPC wrappers around the runtime APIs
|
||||
- additional ready-made vendor adapter packages beyond Grok
|
||||
- production-focused runtime/persistence integrations beyond the in-process core library
|
||||
- additional ready-made provider adapter packages beyond Grok
|
||||
- production-focused runtime integrations beyond the in-process core library
|
||||
|
||||
## Recommended reading order
|
||||
|
||||
1. [Purpose and Architecture](Purpose-and-Architecture)
|
||||
2. [Getting Started](Getting-Started)
|
||||
3. [API Reference](API-Reference)
|
||||
4. [xAI Grok Adapter](xAI-Grok-Adapter)
|
||||
|
||||
## BoxBrain mental model
|
||||
|
||||
A BoxBrain persona works like this:
|
||||
|
||||
1. **Initialize a persona** from a long freeform seed string, optionally with extra structured hints.
|
||||
2. Generate a detailed biography.
|
||||
3. Extract biography facts and store them in the persona's IdentityDB space.
|
||||
4. Generate schedules anchored to time and external special dates.
|
||||
5. Derive availability from schedule or explicit overrides.
|
||||
6. Run conversations by retrieving mandatory/contextual memories, generating a turn plan, and emitting DM-style messages with delays.
|
||||
|
||||
## Current code surface
|
||||
|
||||
The package root currently exports:
|
||||
|
||||
- `./adapters`
|
||||
- `./availability`
|
||||
- `./conversation`
|
||||
- `./grok`
|
||||
- `./memory`
|
||||
- `./persona`
|
||||
- `./schedule`
|
||||
- `./timing`
|
||||
- `./types`
|
||||
|
||||
## Development status
|
||||
|
||||
Repository status at the time of writing:
|
||||
## Current project status
|
||||
|
||||
- package/runtime: **Bun**
|
||||
- language: **TypeScript**
|
||||
- tests: **Vitest**
|
||||
- build: **tsup**
|
||||
- storage/memory dependency: **IdentityDB**
|
||||
- persistence dependency: published **`identitydb@0.2.0`** from npm
|
||||
- release automation: tag-triggered **Gitea Actions** workflow for npm publishing
|
||||
|
||||
See [Getting Started](Getting-Started) for a working local setup pattern.
|
||||
## Recommended reading order
|
||||
|
||||
1. [Purpose and Architecture](Purpose-and-Architecture)
|
||||
2. [Getting Started](Getting-Started)
|
||||
3. [Source Layout](Source-Layout)
|
||||
4. [API Reference](API-Reference)
|
||||
5. [Release Workflow](Release-Workflow)
|
||||
6. [xAI Grok Adapter](xAI-Grok-Adapter)
|
||||
|
||||
## Mental model
|
||||
|
||||
A BoxBrain persona works like this:
|
||||
|
||||
1. **Initialize a persona** from a long freeform seed string.
|
||||
2. Generate a detailed biography.
|
||||
3. Extract biography facts and store them in the persona's IdentityDB space.
|
||||
4. Generate schedules anchored to time and optional special-date context.
|
||||
5. Derive availability from schedule or explicit overrides.
|
||||
6. Run conversations by retrieving memories, planning a turn, and emitting DM-style messages with delays.
|
||||
|
||||
## Public surface at a glance
|
||||
|
||||
The package root currently re-exports:
|
||||
|
||||
```ts
|
||||
export * from './core/adapters';
|
||||
export * from './core/types';
|
||||
export * from './availability';
|
||||
export * from './conversation';
|
||||
export * from './memory';
|
||||
export * from './persona';
|
||||
export * from './providers/grok';
|
||||
export * from './schedule';
|
||||
export * from './timing';
|
||||
```
|
||||
|
||||
That means consumers can use both:
|
||||
|
||||
- functional helpers like `initializePersona`, `generateSchedule`, and `replyToConversation`
|
||||
- class-based entrypoints like `PersonaService`, `ScheduleService`, `AvailabilityService`, `ConversationService`, `FactDraftMemoryStore`, `TimingProfile`, and `GrokApiClient`
|
||||
|
||||
See [Getting Started](Getting-Started) for local setup and [API Reference](API-Reference) for the current exported runtime surface.
|
||||
|
||||
85
Release-Workflow.md
Normal file
85
Release-Workflow.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Release Workflow
|
||||
|
||||
BoxBrain uses a **tag-triggered Gitea Actions workflow** to publish the package to npm.
|
||||
|
||||
## Trigger
|
||||
|
||||
Creating and pushing either of these tag forms starts the release workflow:
|
||||
|
||||
- `vX.Y.Z`
|
||||
- `X.Y.Z`
|
||||
|
||||
The workflow file lives at:
|
||||
|
||||
```text
|
||||
.gitea/workflows/npm-release.yml
|
||||
```
|
||||
|
||||
## Verify stage
|
||||
|
||||
Before publishing, the workflow performs a full verification pass on the tagged source.
|
||||
|
||||
At a high level it:
|
||||
|
||||
1. installs release tooling in the CI container
|
||||
2. clones the tagged BoxBrain source
|
||||
3. verifies that the tag name matches `package.json` version
|
||||
4. runs the full verify pipeline:
|
||||
- `bun install --frozen-lockfile`
|
||||
- `bun run test`
|
||||
- `bun run check`
|
||||
- `bun run build`
|
||||
|
||||
## Publish stage
|
||||
|
||||
Only after verify succeeds, the workflow:
|
||||
|
||||
1. clones the tagged source again
|
||||
2. installs dependencies with Bun
|
||||
3. builds the package
|
||||
4. publishes to npm with `NODE_AUTH_TOKEN`
|
||||
|
||||
## IdentityDB dependency model
|
||||
|
||||
BoxBrain now depends on the published npm package:
|
||||
|
||||
```json
|
||||
"identitydb": "0.2.0"
|
||||
```
|
||||
|
||||
That means the release workflow **does not need a sibling IdentityDB checkout** anymore.
|
||||
|
||||
## Trusted Bun dependencies
|
||||
|
||||
The repository keeps these entries in `trustedDependencies`:
|
||||
|
||||
- `better-sqlite3`
|
||||
- `esbuild`
|
||||
|
||||
This matters because clean Bun installs must allow the necessary lifecycle scripts for native/runtime build steps.
|
||||
|
||||
## Local verification before tagging
|
||||
|
||||
A normal local verification pass is:
|
||||
|
||||
```bash
|
||||
bun run test
|
||||
bun run check
|
||||
bun run build
|
||||
```
|
||||
|
||||
If you want to simulate a clean release-style clone:
|
||||
|
||||
```bash
|
||||
rm -rf /tmp/boxbrain-release-check
|
||||
git clone https://git.psw.kr/p-sw/BoxBrain.git /tmp/boxbrain-release-check
|
||||
cd /tmp/boxbrain-release-check
|
||||
bun install
|
||||
bun run test && bun run check && bun run build
|
||||
```
|
||||
|
||||
## Current published version
|
||||
|
||||
At the time of writing, BoxBrain has already been published as:
|
||||
|
||||
- `boxbrain@0.1.0`
|
||||
52
Source-Layout.md
Normal file
52
Source-Layout.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Source Layout
|
||||
|
||||
The repository is now organized by **domain folders** under `src/` instead of a flat list of top-level runtime files.
|
||||
|
||||
## Current `src/` structure
|
||||
|
||||
- `src/core/` — shared adapter interfaces, common types, and fact helpers
|
||||
- `src/persona/` — persona initialization runtime
|
||||
- `src/schedule/` — schedule generation, listing, and pruning
|
||||
- `src/availability/` — availability persistence and snapshot resolution
|
||||
- `src/conversation/` — DM-style conversation orchestration
|
||||
- `src/memory/` — fact-draft persistence into IdentityDB
|
||||
- `src/timing/` — timing constants, delay helpers, and timing profile class
|
||||
- `src/providers/grok/` — xAI-specific runtime client and adapter helpers
|
||||
|
||||
## Why the structure changed
|
||||
|
||||
The repository moved to domain folders to make the runtime easier to navigate as BoxBrain grew beyond a few flat modules.
|
||||
|
||||
This structure now makes it clearer where to look for:
|
||||
|
||||
- public entrypoints for a domain
|
||||
- internal helpers related to that domain
|
||||
- class-based service abstractions for stateful integrations
|
||||
- provider-specific code that should stay separate from the provider-agnostic core
|
||||
|
||||
## Class-oriented runtime surface
|
||||
|
||||
The current repository also leans more heavily on class-based entrypoints while still keeping the existing functional helpers.
|
||||
|
||||
Notable exported classes:
|
||||
|
||||
- `PersonaService`
|
||||
- `ScheduleService`
|
||||
- `AvailabilityService`
|
||||
- `ConversationService`
|
||||
- `FactDraftMemoryStore`
|
||||
- `TimingProfile`
|
||||
- `GrokApiClient`
|
||||
|
||||
That means consumers can choose between:
|
||||
|
||||
- **functional usage** for quick direct calls
|
||||
- **service-class usage** for cleaner composition inside larger applications
|
||||
|
||||
## Important packaging note
|
||||
|
||||
The folder layout described on this page is the **repository source structure**.
|
||||
|
||||
The published package is still consumed through the **package root exports**, not through documented public subpath exports.
|
||||
|
||||
See [API Reference](API-Reference) for the supported root-level public surface.
|
||||
@@ -3,5 +3,7 @@
|
||||
- [Home](Home)
|
||||
- [Purpose and Architecture](Purpose-and-Architecture)
|
||||
- [Getting Started](Getting-Started)
|
||||
- [Source Layout](Source-Layout)
|
||||
- [API Reference](API-Reference)
|
||||
- [Release Workflow](Release-Workflow)
|
||||
- [xAI Grok Adapter](xAI-Grok-Adapter)
|
||||
|
||||
Reference in New Issue
Block a user