From 3a78db2b596717edc6725b140c019f1197b46474 Mon Sep 17 00:00:00 2001 From: Shinwoo PARK Date: Mon, 11 May 2026 19:50:13 +0900 Subject: [PATCH] docs: refresh wiki for current runtime structure --- API-Reference.md | 193 ++++++++++++-------------------------------- Getting-Started.md | 98 +++++++++++----------- Home.md | 120 +++++++++++++-------------- Release-Workflow.md | 85 +++++++++++++++++++ Source-Layout.md | 52 ++++++++++++ _Sidebar.md | 2 + 6 files changed, 301 insertions(+), 249 deletions(-) create mode 100644 Release-Workflow.md create mode 100644 Source-Layout.md diff --git a/API-Reference.md b/API-Reference.md index 07273f7..ec6bd46 100644 --- a/API-Reference.md +++ b/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 ``` -**Important input fields** +Important input fields: - `displayName: string` - `seedText?: string` @@ -42,36 +51,18 @@ initializePersona(db: IdentityDB, input: InitializePersonaInput): Promise ``` -**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 ``` -**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 ``` @@ -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 ``` -**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 ``` -**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 @@ -184,32 +124,19 @@ Returns the active availability state at a timestamp plus the next transition. getAvailabilitySnapshot(db: IdentityDB, input: GetAvailabilitySnapshotInput): Promise ``` -**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 ``` -**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 ``` ## `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 -``` - -Useful when extending BoxBrain with your own runtime modules. - ## `types` -Selected important domain types: +Selected important domain types include: ```ts type BoxBrainFactDomain = diff --git a/Getting-Started.md b/Getting-Started.md index 6266a60..4faeb44 100644 --- a/Getting-Started.md +++ b/Getting-Started.md @@ -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. diff --git a/Home.md b/Home.md index 8e7da76..7ff4eee 100644 --- a/Home.md +++ b/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. diff --git a/Release-Workflow.md b/Release-Workflow.md new file mode 100644 index 0000000..d73ec98 --- /dev/null +++ b/Release-Workflow.md @@ -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` diff --git a/Source-Layout.md b/Source-Layout.md new file mode 100644 index 0000000..ef9672c --- /dev/null +++ b/Source-Layout.md @@ -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. diff --git a/_Sidebar.md b/_Sidebar.md index ac1cfff..0bcbf48 100644 --- a/_Sidebar.md +++ b/_Sidebar.md @@ -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)