@soulcraft/anima (0.91.0)
Installation
@soulcraft:registry=npm install @soulcraft/anima@0.91.0"@soulcraft/anima": "0.91.0"About this package
@soulcraft/anima
Soulcraft Anima (formerly Muse) — AI assistant component library for the Soulcraft platform — chat, plans, skills, tool-use, viewer/editor, and pluggable memory UI. One component, one endpoint.
Documentation
- Integration Guide — Step-by-step setup: endpoint, component, tools, billing, viewer, Memory integration
- Architecture — System prompt layers, tool system, viewer modes, explore views, billing flow
- Tool Authoring — How to define and implement tools the LLM can call
Quick Start
bun add @soulcraft/anima@latest
The served road: besides npm,
anima.soulcraft.comserves the complete chat surface as a script-tag web component —<anima-line>— plus<anima-discussion>as its own entry, so sibling products adopt Anima with two lines of HTML and no install. Seestudy/ops/ADOPTION.mdfor the adoption contract.
Server — one endpoint handles everything
// routes/api/anima/chat/+server.ts
import {
createAnimaChatHandler,
createOpenAICompatAdapter,
createLicenseClient,
} from '@soulcraft/anima/server'
const fleet = createOpenAICompatAdapter({
url: process.env['FLEET_CHAT_URL']!, // OpenAI-compatible engine door (vLLM)
model: 'qwen3-next-80b',
})
const handler = createAnimaChatHandler({
// 0.60.0+ — pass the adapter directly for zero-config smart routing
// (mode → tier+effort), or a selector `(request) => ({ adapter, tier,
// effort })` to route by user plan, workspace tier, feature flag, etc.
llm: fleet,
// 0.63.0+ — Memory is CONFIG, not an instance. Anima mints a short-lived
// per-user JWT per request and builds a typed @soulcraft/memory/client
// internally. Requires @soulcraft/memory >= 0.18.1 (peer).
memory: {
url: process.env['MEMORY_URL']!,
productOrigin: 'your-product',
serviceSecret: process.env['SOULCRAFT_SERVICE_SECRET']!,
},
license: createLicenseClient({ url: 'https://soulcraft.com', productOrigin: 'your-product' }),
defaultKit: YOUR_KIT,
tools: yourToolDefinitions,
executeTool: yourToolExecutor,
})
export const POST = async ({ request, locals }) => {
const body = await request.json()
// REQUIRED for memory: the JWT subject + per-user brain resolution.
// Without userEmail, Anima skips memory entirely (graceful, by design).
if (locals.user?.email) body.userEmail = locals.user.email
return handler(body)
}
Migrating from ≤ 0.62.x? The
memoryoption changed from an instance (createMemoryServiceClient({...}), now removed) to a config object ({ url, productOrigin, serviceSecret }). Bump the@soulcraft/memorypeer to>= 0.18.1, drop thecreateMemoryServiceClientimport, and pass the config literal. ThreaduserEmailon every request. Memory degrades cleanly when omitted — chat never blocks on a Memory hiccup.
Client — one component renders the chat, the consumer owns the panel
<script>
import AnimaInterface from '@soulcraft/anima/components/AnimaInterface'
import '@soulcraft/memory/panel' // registers <memory-panel> custom element
</script>
<AnimaInterface
endpoint="/api/anima/chat"
greeting="What are we working on?"
oncanopyrequestopen={openCanopy}
>
{#snippet panel({ activityEvents })}
<memory-panel
api-url={MEMORY_URL}
api-token={memoryToken}
oncanopyrequestopen={openCanopy}
></memory-panel>
{/snippet}
</AnimaInterface>
The panel snippet is consumer-owned — Memory ships the panel + canopy as Shadow-DOM custom elements in @soulcraft/memory, and Anima exposes the slot. If you don't pass a panel snippet, the panel column is absent from the DOM and the chat reflows to 100% width.
Environment Variables
| Variable | Required | Purpose |
|---|---|---|
FLEET_CHAT_URL |
One engine door required | OpenAI-compatible engine base URL (vLLM door) — serves every tier when set |
OLLAMA_URL |
One engine door required | Ollama base URL — the engine when the vLLM door is absent |
MEMORY_URL |
No | Memory service URL (e.g. http://localhost:5010) |
SOULCRAFT_SERVICE_SECRET |
When using Memory cross-origin | Unified service-to-service auth (Memory, Portal, Auth, …) |
PORTAL_URL |
No | Portal URL for token billing |
Public Exports
| Import path | What |
|---|---|
@soulcraft/anima/server |
Chat handler, LLM adapters, Memory service client, license client, prompt builder, built-in skills |
@soulcraft/anima/types |
TypeScript interfaces (messages, tools, plans, modes, context) |
@soulcraft/anima/components/AnimaInterface |
Complete chat + viewer UI with pluggable panel snippet |
@soulcraft/anima/components/AnimaViewer |
Document viewer/editor (TipTap + Monaco) |
@soulcraft/anima/components/AnimaInput |
Chat input with mode/tier selectors |
@soulcraft/anima/components/AnimaMessage |
Message rendering |
@soulcraft/anima/components/AnimaRenderer |
Markdown rendering |
@soulcraft/anima/components/AnimaTipTapEditor |
TipTap wrapper (wdoc, wslide, markdown) |
@soulcraft/anima/components/AnimaMonacoEditor |
Monaco wrapper (code files, 50+ languages) |
@soulcraft/anima/components/AnimaEditorToolbar |
Formatting toolbar for TipTap edit mode |
@soulcraft/anima/components/AnimaPaymentModal |
Stripe Payment Element for billing |
@soulcraft/anima/discussion |
<anima-discussion> element + discussion rail/thread components |
@soulcraft/anima/views |
All explore view renderers |
@soulcraft/anima/views/* |
Individual view renderers (Graph, Board, Timeline, etc.) |
Memory's <memory-panel> / <memory-canopy> custom elements live in @soulcraft/memory — not in Anima. Anima provides the chat surface + the panel slot; the consumer wires Memory's components in.
Server Exports
import {
// Chat handler
createAnimaChatHandler,
// LLM adapters
createOpenAICompatAdapter,
createOllamaAdapter,
createLLMRouter,
resolveAdapterCapability, // cross-LLM tier (native/best-effort/none)
// Memory integration (0.63.0+ — pass AnimaMemoryConfig to the handler;
// these helpers are for advanced/custom auth flows)
createAnimaMemoryClient, // mint a per-user MemoryClient directly
animaMemoryRPC, // typed bridge for history/breakpoint RPCs
// Memory write tools (ADR-009 writer-first — compose into your tool list)
memoryToolDefinitions,
executeMemoryTool,
MEMORY_GRAMMAR_PROMPT, // cross-LLM fallback for weak-tool models
parseMemoryDirective,
validateClassifierPayload,
// Billing
createLicenseClient,
createMockLicenseClient,
// Prompt building
buildAnimaPrompt,
DEFAULT_WELCOME_CARDS,
// Utilities
collectStream,
// Built-in skills (auto-registered)
memorySkillDefinition,
conversationSkillDefinition,
fileSkillDefinition,
fileToolDefinitions,
} from '@soulcraft/anima/server'
Key Concepts
Single Endpoint
One POST route handles: chat (SSE), conversation history (list / save / load), license checks, memory seed, breakpoint persistence, file rendering. Products need zero extra routes.
Built-in Tools
Auto-registered when their dependency is provided:
- Memory tools (when
memoryprovided): writer-first writes per ADR-009 —remember_fact,forget_memory,add_user_rule,remove_user_rule— plus readsrecallMemories,getUserProfile,updateProfile,getMemoryInsights,getMemoryStats. For adapters that can't call tools, the same write surface rides inline[REMEMBER:]/[FORGET:]/[RULE:]directives (MEMORY_GRAMMAR_PROMPT+parseMemoryDirective, grammar shared via@soulcraft/sdk). - File tools (always):
openFile,editFile. - Conversation tools (always):
presentOptions.
Viewer/Editor
AnimaViewer takes over the chat area to display files. Four modes:
- View — TipTap read-only (documents) or Monaco read-only (code)
- Edit — TipTap WYSIWYG with toolbar (documents) or Monaco editable (code)
- Code — Monaco raw source for any file type
- Explore — Visualization views (graph, board, timeline, etc.)
Three Tiers
| Tier | Purpose | Fleet | Auto-select |
|---|---|---|---|
fast |
Quick tasks | qwen3-next-80b | Task mode |
balanced |
General chat | qwen3-next-80b | Chat mode |
powerful |
Planning, reasoning | qwen3-next-80b | Plan mode |
Billing
Anima talks to Portal directly for token budgets. Products pass license option — zero billing logic in products. Token bar in Model section with upgrade/top-up buttons. Stripe Payment Element for in-app payments.
Theme Support
Uses @soulcraft/theme CSS variables (64 tokens as of 2.7.0, including interactive / secondary action roles, info semantic, and the chart-1..6 categorical palette). Supports all 40 catalog themes and 6 surface modes (glass / flat / raised / gradient / minimal / outline). Products wire buildSurfaceModeStyles() in their layout for full surface-mode support — Memory's web components inherit those tokens through Shadow DOM automatically.
Dev Shell
The dev shell at dev/ mounts the full Anima experience locally with a live Memory integration (a rail of <memory-plans> from npm plus the service-served <self-flow> element), a "Memory" toggle that gates the integration end-to-end (rail UI + chat-handler memory config), and the full theme / kit / LLM / interface-mode controls.
# Terminal 1 — Memory is its own project; clone + run separately
git clone https://github.com/soulcraftlabs/memory.git ~/Projects/memory
cd ~/Projects/memory && bun install && bun run dev # :5010
# Terminal 2 — Anima dev shell
cd dev && bun install && bun run dev # :5173
Then open http://localhost:5173 and click the Memory button in the nav to toggle the integration on/off. With the toggle on, the rail renders and chat uses the with-memory handler; with it off, no rail renders and zero Memory RPCs fire — exercising Anima's graceful degradation path live in the browser.
Peer Dependencies
svelte >=5.0.0@soulcraft/formats >=1.8.0— portable file-format schemas (host keeps formats + brainy aligned; brainy >=9.0.0 since Anima 0.88.0's namespace law)@soulcraft/sdk >=3.27.1— shared memory-directive parser (extractMemoryDirectivesfrom/client)@soulcraft/theme >=2.7.0@soulcraft/memory >=0.18.1(optional — required when thememoryconfig is passed to the chat handler)maplibre-gl >=4.0.0(optional — for the Map explore view)@stripe/stripe-js >=2.0.0(optional — for payment modal)
Dependencies
Dependencies
| ID | Version |
|---|---|
| @tiptap/core | ^3.20.1 |
| @tiptap/extension-collaboration | ^3.20.1 |
| @tiptap/extension-collaboration-caret | ^3.20.1 |
| @tiptap/extension-color | ^3.20.1 |
| @tiptap/extension-font-family | ^3.20.1 |
| @tiptap/extension-highlight | ^3.20.1 |
| @tiptap/extension-image | ^3.20.1 |
| @tiptap/extension-link | ^3.20.1 |
| @tiptap/extension-placeholder | ^3.20.1 |
| @tiptap/extension-table | ^3.20.1 |
| @tiptap/extension-task-item | ^3.20.1 |
| @tiptap/extension-task-list | ^3.20.1 |
| @tiptap/extension-text-align | ^3.20.1 |
| @tiptap/extension-text-style | ^3.20.1 |
| @tiptap/extension-underline | ^3.20.1 |
| @tiptap/pm | ^3.20.1 |
| @tiptap/starter-kit | ^3.20.1 |
| d3 | ^7.9.0 |
| dompurify | ^3.4.11 |
| marked | ^16.4.2 |
| monaco-editor | ^0.54.0 |
| shiki | ^3.21.0 |
| tiptap-extension-code-block-shiki | ^1.0.0 |
| tiptap-markdown | ^0.9.0 |
| y-protocols | ^1.0.6 |
| yjs | ^13.6.30 |
Development dependencies
| ID | Version |
|---|---|
| @soulcraft/brainy | 9.0.0 |
| @soulcraft/cor | 3.1.0 |
| @soulcraft/formats | ^1.9.0 |
| @soulcraft/memory | 0.19.0 |
| @soulcraft/sdk | ^4.23.0 |
| @soulcraft/theme | 2.29.0 |
| @stripe/stripe-js | ^9.0.1 |
| @sveltejs/package | ^2.5.7 |
| @types/d3 | ^7.4.3 |
| ajv | ^8.20.0 |
| jsdom | ^29.1.1 |
| maplibre-gl | ^5.24.0 |
| pdf-lib | ^1.17.1 |
| stripe | ^22.2.0 |
| svelte | ^5.0.0 |
| svelte-check | ^4.1.0 |
| ts-json-schema-generator | ^2.9.0 |
| typescript | ^5.7.0 |
| vitest | ^4.1.2 |
Peer dependencies
| ID | Version |
|---|---|
| @soulcraft/formats | >=1.8.0 |
| @soulcraft/memory | >=0.18.1 |
| @soulcraft/sdk | >=3.27.1 |
| @soulcraft/theme | >=2.7.0 |
| @stripe/stripe-js | >=2.0.0 |
| maplibre-gl | >=4.0.0 |
| svelte | >=5.0.0 |