/** * hmem configuration — loaded from hmem.config.json in the project directory. * All values have sensible defaults; the config file is optional. * * Place hmem.config.json in HMEM_PROJECT_DIR (next to your .hmem files). * * ## Character limits * * Option A — just set the two endpoints, levels in between are interpolated linearly: * { * "maxL1Chars": 500, * "maxLnChars": 50000 * } * * Option B — specify all levels explicitly: * { * "maxCharsPerLevel": [500, 5000, 15000, 30000, 50000] * } * * Option A and B can be combined; explicit array takes precedence. * */ export interface HmemConfig { /** * Max characters per level, indexed by depth (0=L1, 1=L2, …, maxDepth-1=Ln). * Computed from maxL1Chars + maxLnChars via linear interpolation if not set explicitly. */ maxCharsPerLevel: number[]; /** Max tree depth (1 = L1 only, 5 = full depth). Default: 5 */ maxDepth: number; /** Max entries returned by a default bulk read(). Default: 100 */ defaultReadLimit: number; /** * Memory category prefixes. Keys are single uppercase letters, values are human-readable names. * Default: P=Project, L=Lesson, T=Task, E=Error, D=Decision, M=Milestone, S=Skill, N=Navigator. * Users can add custom prefixes (e.g. "R": "Research") in hmem.config.json. */ prefixes: Record; /** * Number of top-accessed entries that are automatically promoted to L2 depth in bulk reads. * These are entries with the highest access_count (excluding zero) — "organic favorites". * Set to 0 to disable. Default: 5. */ accessCountTopN: number; /** * Descriptions for prefix category headers (X0000 entries). * Used as L1 text for abstract header entries in grouped bulk reads. * Users can override or add descriptions in hmem.config.json. */ prefixDescriptions: Record; /** * Max characters for auto-extracted titles. Default: 30. * Titles are short labels for navigation (like chapter titles in a book). */ maxTitleChars: number; /** * Max characters for a single L2–L5 node (title + body combined). * A flat sanity-check against bloat — not a depth-based escalation curve. * Default: 100_000. */ maxNodeChars: number; /** * V2 bulk-read algorithm tuning parameters. * Controls how many entries receive expanded treatment in default reads. */ bulkReadV2: { /** Number of top-accessed entries to expand — legacy fixed fallback (default: 3) */ topAccessCount: number; /** Number of newest entries to expand — legacy fixed fallback (default: 5) */ topNewestCount: number; /** Number of obsolete entries to keep visible (default: 3) */ topObsoleteCount: number; /** Number of entries with the most sub-nodes to always expand (default: 3) */ topSubnodeCount: number; /** Percentage-based selection (overrides fixed counts when set) */ newestPercent?: number; newestMin?: number; newestMax?: number; accessPercent?: number; accessMin?: number; accessMax?: number; }; /** * Number of messages between automatic save reminders (checkpoint hook). * Set to 0 to disable. Default: 20. */ checkpointInterval: number; /** * Checkpoint mode: "remind" = inject additionalContext reminder (default), * "auto" = spawn a Haiku subagent that saves directly (no user interaction). */ checkpointMode: "remind" | "auto"; /** LLM provider for auto-checkpoint agent. Default: "anthropic". */ checkpointProvider: "anthropic" | "openai"; /** Model ID for checkpoint agent. Default: "claude-haiku-4-5-20251001". */ checkpointModel: string; /** Base URL for OpenAI-compatible APIs (DeepSeek, Groq, etc.). */ checkpointBaseUrl?: string; /** Env var name to read API key from. Default: ANTHROPIC_API_KEY / OPENAI_API_KEY. */ checkpointApiKeyEnv?: string; /** * Number of recent O-entries (session logs) to inject on load_project. * Set to 0 to disable. Default: 10. */ recentOEntries: number; /** * Number of recent O-entries to inject in bulk reads (read_memory without id/prefix). * Separate from recentOEntries so load_project can show history while bulk reads stay clean. * Default: 0 (no O-entries in bulk read — they are noise when selecting a project). */ bulkReadOEntries: number; /** * Token threshold for context clear recommendation. * When cumulative hmem output exceeds this, the agent is told to flush + /clear. * Set to 0 to disable. Default: 100000. */ contextTokenThreshold: number; /** * Per-response token limit. Tool responses exceeding this are rejected with an error. * Prevents runaway tool output (e.g. read_memory with expand on a huge database). * Measured in chars (≈ 4 chars per real token). Default: 36000 (≈ 9k tokens). * Set to 0 to disable. */ maxToolResponseChars: number; /** * load_project display configuration: which L2 sections to expand. * withBody: L2 seq numbers whose L3 children show title + body (e.g. Overview) * withChildren: L2 seq numbers whose L3 children are all listed as titles (e.g. Bugs, Open Tasks) * Default: withBody=[1], withChildren=[6,8] */ loadProjectExpand: { withBody: number[]; withChildren: number[]; }; /** Per-prefix entry schemas. Keys are prefix letters ("P", "E", etc.). */ schemas?: Record; /** * Global context injected into every load_project response. * Each item specifies a prefix and how deep to render its entries. * Default (when not set): R at depth 2 + C#universal at depth 2. */ globalLoad?: GlobalLoadItem[]; /** Sync configuration — single server or array for multi-server redundancy. */ sync?: SyncConfigBlock | SyncConfigBlock[]; } export interface SchemaSection { name: string; loadDepth: number; defaultChildren?: string[]; /** Short convention describing what belongs in this section and how to structure it. * Consumed by the checkpoint agent (Task #4 routing) and can be shown as placeholder * body in empty sections. Kept to ~100 chars; longer descriptions belong in prose docs. */ description?: string; /** * Controls what the checkpoint agent may write to this section. * readonly — checkpoint may not write to this section at all * pointer — checkpoint may only add short pointer lines (e.g. "→ E00XX Title"), no full content * append — normal appends allowed (default if omitted) */ checkpointPolicy?: "readonly" | "pointer" | "append"; } export interface EntrySchema { sections: SchemaSection[]; createLinkedO?: boolean; } /** * One item in the globalLoad list — a prefix to inject into every load_project response. * loadDepth: 1=title only, 2=title+body, 3=title+body+children * tagFilter: only inject entries that carry this tag (e.g. "#universal") */ export interface GlobalLoadItem { prefix: string; loadDepth: number; tagFilter?: string; } export interface SyncConfigBlock { /** Display name for this server (optional, for multi-server identification) */ name?: string; serverUrl: string; userId: string; salt: string; token?: string; syncSecrets?: boolean; lastPushAt?: string | null; lastPullAt?: string | null; } /** Normalize sync config to always return an array. */ export declare function getSyncServers(config: HmemConfig): SyncConfigBlock[]; export declare const DEFAULT_PREFIXES: Record; /** * Default descriptions for prefix category headers (X0000 entries). * These are used as L1 text for abstract header entries that group * entries by category in bulk reads. */ export declare const DEFAULT_PREFIX_DESCRIPTIONS: Record; export declare const DEFAULT_CONFIG: HmemConfig; /** * Format prefix map as "P=Project, L=Lesson, ..." for tool descriptions. */ export declare function formatPrefixList(prefixes: Record): string; /** * Compute a linearly interpolated char-limit array between l1 and ln for `depth` levels. * depth=1 → [l1], depth=2 → [l1, ln], depth=5 → [l1, …, ln] */ export declare function linearLimits(l1: number, ln: number, depth: number): number[]; /** * Persist an {@link HmemConfig} to `hmem.config.json` in `projectDir`. * Writes `maxCharsPerLevel` directly (no reverse-computing from L1/Ln). * If a sync token is present the file is chmod 600. * @param projectDir Directory that contains (or will contain) `hmem.config.json`. * @param config Configuration to write. */ export declare function saveHmemConfig(projectDir: string, config: HmemConfig): void; /** * Load `hmem.config.json` from `projectDir`. * Unknown keys are ignored; missing keys fall back to {@link DEFAULT_CONFIG}. * @param projectDir Directory that contains `hmem.config.json`. * @returns Merged config with all defaults applied. */ export declare function loadHmemConfig(projectDir: string): HmemConfig;