Agentic memory extension for SillyTavern providing POV-aware memory, witness tracking, relationships, and emotional continuity.
Core Philosophy: Zero external DBs (all state lives in context.chatMetadata.openvault), local RAG first, and LLM-agnostic structured outputs
- Write ESM code without bundlers. Runs directly in-browser. Never use bare specifiers (
import { z } from 'zod') - Import CDN packages exclusively via
cdnImport(). (src/utils/cdn.js) - Pin all CDN versions centrally. Maintain the
CDN_VERSIONSmap insrc/utils/cdn.js. Update bothpackage.jsonandCDN_VERSIONSsimultaneously - Alias CDN URLs for testing. Map all CDN dependencies to
node_modules/invitest.config.js
- Access SillyTavern globals exclusively via
getDeps(). (src/deps.js). Never accessgetContext,eventSource, orfetchdirectly - Access settings exclusively via
src/settings.js. UsegetSettings(path, default)andsetSetting(path, val). Never hardcode fallbacks; pull fromdefaultSettingsinsrc/constants.js - Define all magic strings and thresholds centrally. Place enums (e.g.,
ENTITY_TYPES), thresholds, and API endpoints insrc/constants.jsand freeze them (Object.freeze({...}))
- Validate arrays explicitly. Use
array?.length > 0 ? array : fallback. Empty arrays are truthy and will bypass||fallbacks - Throw
AbortErrorto signal cancellation. Catch it explicitly and do not log it as a failure - Reset session controller before checking extension enabled. In
onChatChanged,resetSessionController()must fire beforeisExtensionEnabled()— otherwise disabling the extension leaks in-flight workers across chat switches. - Yield the main thread in heavy loops. Call
await yieldToMain()to polyfillscheduler.yield()and prevent ST UI freezes - Never edit
src/types.d.tsdirectly. Regenerate it from Zod schemas usingnpm run generate-types - Never use
z.any()in Zod schemas. Usez.unknown(), typed alternatives, or JSDoc@typedeffor complex/interface types that Zod can't model (e.g., function signatures, class instances).z.any()leaks into generatedtypes.d.tsasany
npm run checkruns automatically on every commit (sync-version, generate-types, lint, jsdoc, css, typecheck). The commit is aborted on any failure — fix errors, never skip them
Domain-specific rules live in subdirectory CLAUDE.md files (auto-discovered by Claude):
src/store/— State management, stChanges contract, migrationssrc/store/migrations/— Schema versioning, rollback patternssrc/extraction/— Background worker, turn boundaries, swipe protection, backfillsrc/graph/— Semantic merge, edge consolidation, Louvain communitiessrc/reflection/— Reflection pipeline, accumulator, 3-tier dedupsrc/retrieval/— Context budgeting, world context intent routing, query buildingsrc/services/— ST Vector REST API, CSRF, collection isolationsrc/prompts/— Prompt topology,<think/>tags, bilingual schemassrc/ui/— Progressive disclosure, DOM patterns, payload calculatorsrc/perf/— Metrics store, sync vs async instrumentationsrc/utils/— Codecs, logging, stemmers, AIMD queuetests/— Test pyramid, mocking boundaries, factoriesinclude/DATA_SCHEMA.md— Data schema & retrieval formulas (authoritative)