tracelattice 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/core/HistoryManager.dag.test.d.ts +0 -7
- package/dist/__tests__/core/HistoryManager.dag.test.d.ts.map +1 -1
- package/dist/__tests__/errors.types.test-d.d.ts +16 -0
- package/dist/__tests__/errors.types.test-d.d.ts.map +1 -0
- package/dist/__tests__/eval/fixtures/scenarios.d.ts.map +1 -1
- package/dist/__tests__/evaluator/EvaluatorBackwardCompat.test.d.ts +0 -13
- package/dist/__tests__/evaluator/EvaluatorBackwardCompat.test.d.ts.map +1 -1
- package/dist/__tests__/helpers/factories.d.ts +5 -4
- package/dist/__tests__/helpers/factories.d.ts.map +1 -1
- package/dist/__tests__/integration/CompressionAutoTrigger.test.d.ts +0 -9
- package/dist/__tests__/integration/CompressionAutoTrigger.test.d.ts.map +1 -1
- package/dist/__tests__/integration/CompressionPersistence.test.d.ts +0 -15
- package/dist/__tests__/integration/CompressionPersistence.test.d.ts.map +1 -1
- package/dist/__tests__/integration/StrategyIntegration.test.d.ts +0 -8
- package/dist/__tests__/integration/StrategyIntegration.test.d.ts.map +1 -1
- package/dist/__tests__/integration/ToTStrategyIntegration.test.d.ts +0 -16
- package/dist/__tests__/integration/ToTStrategyIntegration.test.d.ts.map +1 -1
- package/dist/__tests__/integration/dag-edges.test.d.ts +0 -15
- package/dist/__tests__/integration/dag-edges.test.d.ts.map +1 -1
- package/dist/__tests__/reasoning-integration.test.d.ts +0 -9
- package/dist/__tests__/reasoning-integration.test.d.ts.map +1 -1
- package/dist/__tests__/strategies/StrategyContract.test.d.ts +0 -16
- package/dist/__tests__/strategies/StrategyContract.test.d.ts.map +1 -1
- package/dist/__tests__/thought-processor.test.d.ts +0 -6
- package/dist/__tests__/thought-processor.test.d.ts.map +1 -1
- package/dist/cli.js +21 -17
- package/dist/cli.js.map +1 -1
- package/dist/config/ConfigLoader.d.ts +14 -14
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +8 -8
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/contracts/PersistenceBackend.d.ts +4 -3
- package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
- package/dist/contracts/ids.d.ts +4 -0
- package/dist/contracts/ids.d.ts.map +1 -1
- package/dist/contracts/ids.js +4 -1
- package/dist/contracts/ids.js.map +1 -1
- package/dist/contracts/interfaces.d.ts +2 -2
- package/dist/contracts/interfaces.d.ts.map +1 -1
- package/dist/contracts/strategy.d.ts +2 -1
- package/dist/contracts/strategy.d.ts.map +1 -1
- package/dist/contracts/summary.d.ts +2 -1
- package/dist/contracts/summary.d.ts.map +1 -1
- package/dist/core/HistoryManager.d.ts +6 -5
- package/dist/core/HistoryManager.d.ts.map +1 -1
- package/dist/core/HistoryManager.js +3 -1
- package/dist/core/HistoryManager.js.map +1 -1
- package/dist/core/IHistoryManager.d.ts +5 -4
- package/dist/core/IHistoryManager.d.ts.map +1 -1
- package/dist/core/InputNormalizer.d.ts +2 -1
- package/dist/core/InputNormalizer.d.ts.map +1 -1
- package/dist/core/InputNormalizer.js +7 -3
- package/dist/core/InputNormalizer.js.map +1 -1
- package/dist/core/PersistenceBuffer.d.ts.map +1 -1
- package/dist/core/PersistenceBuffer.js +2 -1
- package/dist/core/PersistenceBuffer.js.map +1 -1
- package/dist/core/SessionLock.d.ts +2 -1
- package/dist/core/SessionLock.d.ts.map +1 -1
- package/dist/core/SessionLock.js +3 -2
- package/dist/core/SessionLock.js.map +1 -1
- package/dist/core/ThoughtFormatter.d.ts.map +1 -1
- package/dist/core/ThoughtFormatter.js +2 -2
- package/dist/core/ThoughtFormatter.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js +15 -14
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/core/compression/CompressionService.d.ts +2 -1
- package/dist/core/compression/CompressionService.d.ts.map +1 -1
- package/dist/core/compression/CompressionService.js +3 -2
- package/dist/core/compression/CompressionService.js.map +1 -1
- package/dist/core/compression/DehydrationPolicy.d.ts.map +1 -1
- package/dist/core/compression/DehydrationPolicy.js.map +1 -1
- package/dist/core/compression/InMemorySummaryStore.d.ts +2 -1
- package/dist/core/compression/InMemorySummaryStore.d.ts.map +1 -1
- package/dist/core/compression/InMemorySummaryStore.js.map +1 -1
- package/dist/core/compression/Summary.d.ts +2 -2
- package/dist/core/compression/Summary.d.ts.map +1 -1
- package/dist/core/evaluator/Calibrator.d.ts +4 -3
- package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
- package/dist/core/evaluator/Calibrator.js +2 -1
- package/dist/core/evaluator/Calibrator.js.map +1 -1
- package/dist/core/graph/EdgeEmitter.d.ts +2 -1
- package/dist/core/graph/EdgeEmitter.d.ts.map +1 -1
- package/dist/core/graph/EdgeEmitter.js.map +1 -1
- package/dist/core/graph/EdgeStore.d.ts +6 -5
- package/dist/core/graph/EdgeStore.d.ts.map +1 -1
- package/dist/core/graph/EdgeStore.js.map +1 -1
- package/dist/core/graph/GraphView.d.ts +7 -6
- package/dist/core/graph/GraphView.d.ts.map +1 -1
- package/dist/core/graph/GraphView.js.map +1 -1
- package/dist/core/reasoning/strategies/totScoring.d.ts +2 -1
- package/dist/core/reasoning/strategies/totScoring.d.ts.map +1 -1
- package/dist/core/reasoning/strategies/totScoring.js.map +1 -1
- package/dist/core/reasoning.d.ts +29 -29
- package/dist/core/reasoning.d.ts.map +1 -1
- package/dist/core/thought.d.ts +62 -170
- package/dist/core/thought.d.ts.map +1 -1
- package/dist/di/Container.d.ts +9 -5
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/Container.js +3 -0
- package/dist/di/Container.js.map +1 -1
- package/dist/di/ServiceRegistry.d.ts +3 -2
- package/dist/di/ServiceRegistry.d.ts.map +1 -1
- package/dist/lib.d.ts +2 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +2 -1
- package/dist/lib.js.map +1 -1
- package/dist/logger/StructuredLogger.d.ts +6 -6
- package/dist/logger/StructuredLogger.d.ts.map +1 -1
- package/dist/logger/StructuredLogger.js.map +1 -1
- package/dist/persistence/FilePersistence.d.ts +4 -3
- package/dist/persistence/FilePersistence.d.ts.map +1 -1
- package/dist/persistence/FilePersistence.js +2 -1
- package/dist/persistence/FilePersistence.js.map +1 -1
- package/dist/persistence/MemoryPersistence.d.ts +4 -3
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
- package/dist/persistence/MemoryPersistence.js +2 -1
- package/dist/persistence/MemoryPersistence.js.map +1 -1
- package/dist/persistence/SqlitePersistence.d.ts +4 -3
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.js +3 -2
- package/dist/persistence/SqlitePersistence.js.map +1 -1
- package/dist/registry/SkillRegistry.d.ts +0 -2
- package/dist/registry/SkillRegistry.d.ts.map +1 -1
- package/dist/registry/SkillRegistry.js +0 -3
- package/dist/registry/SkillRegistry.js.map +1 -1
- package/dist/sanitize.d.ts +31 -0
- package/dist/sanitize.d.ts.map +1 -1
- package/dist/sanitize.js +12 -2
- package/dist/sanitize.js.map +1 -1
- package/dist/schema.d.ts +2 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js.map +1 -1
- package/dist/transport/BaseTransport.d.ts +9 -9
- package/dist/transport/BaseTransport.d.ts.map +1 -1
- package/dist/transport/BaseTransport.js.map +1 -1
- package/dist/transport/HttpTransport.d.ts.map +1 -1
- package/dist/transport/HttpTransport.js +7 -5
- package/dist/transport/HttpTransport.js.map +1 -1
- package/dist/transport/SseTransport.d.ts.map +1 -1
- package/dist/transport/SseTransport.js +6 -4
- package/dist/transport/SseTransport.js.map +1 -1
- package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
- package/dist/transport/StreamableHttpTransport.js +6 -4
- package/dist/transport/StreamableHttpTransport.js.map +1 -1
- package/dist/utils.d.ts +27 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +6 -0
- package/dist/utils.js.map +1 -0
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config/ConfigLoader.js","sources":["../../src/config/ConfigLoader.ts"],"sourcesContent":["/**\n * Configuration file loading with environment variable override support.\n *\n * This module provides the `ConfigLoader` class which handles loading configuration\n * from YAML and JSON files in standard locations, with automatic environment variable\n * overrides for all settings.\n *\n * @module config\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { PersistenceConfig } from '../contracts/PersistenceBackend.js';\nimport { getErrorMessage } from '../errors.js';\nimport type { FeatureFlags } from '../contracts/features.js';\n\n/**\n * Configuration options loaded from config files.\n *\n * These options represent the structure of configuration files (JSON or YAML)\n * that can be loaded from standard locations. All values can be overridden\n * by environment variables.\n *\n * @example\n * ```yaml\n * # .claude/config.yaml\n * maxHistorySize: 500\n * maxBranches: 25\n * logLevel: debug\n * prettyLog: true\n * skillDirs:\n * - ./custom-skills\n * discoveryCache:\n * ttl: 600000\n * maxSize: 200\n * persistence:\n * enabled: true\n * backend: sqlite\n * options:\n * dbPath: ./data/history.db\n * ```\n */\nexport interface ConfigFileOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * Can be overridden by `MAX_HISTORY_SIZE` environment variable.\n\t */\n\tmaxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * Can be overridden by `MAX_BRANCHES` environment variable.\n\t */\n\tmaxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * Can be overridden by `MAX_BRANCH_SIZE` environment variable.\n\t */\n\tmaxBranchSize?: number;\n\n\t/**\n\t * Logging level for the application.\n\t * Can be overridden by `LOG_LEVEL` environment variable.\n\t */\n\tlogLevel?: 'debug' | 'info' | 'warn' | 'error';\n\n\t/**\n\t * Whether to enable pretty (formatted) logging output.\n\t * Can be overridden by `PRETTY_LOG` environment variable (set to \"false\" to disable).\n\t */\n\tprettyLog?: boolean;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * Can be overridden by `SKILL_DIRS` environment variable (colon-separated).\n\t */\n\tskillDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t * Can be overridden by `DISCOVERY_CACHE_TTL` and `DISCOVERY_CACHE_MAX_SIZE` environment variables.\n\t */\n\tdiscoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * Environment variable `DISCOVERY_CACHE_TTL` accepts seconds.\n\t\t */\n\t\tttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t */\n\t\tmaxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\tpersistence?: PersistenceConfig;\n\n\t/**\n\t * Feature flag overrides. Each field can be set independently.\n\t * Can be overridden by `TRACELATTICE_FEATURES_*` environment variables.\n\t */\n\tfeatures?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` environment variable.\n\t */\n\ttoolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` environment variable.\n\t */\n\ttoolInterleaveSweepMs?: number;\n\n\t/**\n\t * Maximum sessions per owner. Per-owner LRU bucket prevents one user from\n\t * consuming all session slots.\n\t * Can be overridden by `SESSION_MAX_PER_OWNER` environment variable.\n\t */\n\tmaxSessionsPerOwner?: number;\n}\n\n/**\n * Loads configuration from files with environment variable overrides.\n *\n * This class searches for configuration files in standard locations and applies\n * environment variable overrides. Files are searched in priority order, with the\n * first match being used. Environment variables always take precedence over file values.\n *\n * @remarks\n * **Config File Search Order (priority):**\n * 1. Custom path (if provided to constructor)\n * 2. `.claude/config.json` (project-local)\n * 3. `.claude/config.yaml` (project-local)\n * 4. `.claude/config.yml` (project-local)\n * 5. `~/.claude/config.json` (user-global)\n * 6. `~/.claude/config.yaml` (user-global)\n * 7. `~/.claude/config.yml` (user-global)\n *\n * **Environment Variable Overrides:**\n * | Variable | Type | Description |\n * |----------|------|-------------|\n * | `MAX_HISTORY_SIZE` | number | Max thoughts in history |\n * | `MAX_BRANCHES` | number | Max number of branches |\n * | `MAX_BRANCH_SIZE` | number | Max size of each branch |\n * | `LOG_LEVEL` | string | Logging level (debug/info/warn/error) |\n * | `PRETTY_LOG` | string | \"false\" to disable pretty logging |\n * | `SKILL_DIRS` | string | Colon-separated directory paths |\n * | `DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |\n * | `DISCOVERY_CACHE_MAX_SIZE` | number | Max cache entries |\n *\n * @example\n * ```typescript\n * // Use default search paths\n * const loader1 = new ConfigLoader();\n * const config1 = loader1.load();\n *\n * // Use custom config path\n * const loader2 = new ConfigLoader('./my-config.yaml');\n * const config2 = loader2.load();\n *\n * // Convert to ServerConfig options\n * const serverOptions = loader2.toServerConfigOptions(config2);\n * ```\n */\nexport class ConfigLoader {\n\t/** Array of config file paths to search, in priority order. */\n\tprivate _configPaths: string[];\n\n\t/**\n\t * Creates a new ConfigLoader instance.\n\t *\n\t * @param customPath - Optional custom config file path. If provided, only this path will be checked.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Use default search paths\n\t * const loader1 = new ConfigLoader();\n\t *\n\t * // Use a specific config file\n\t * const loader2 = new ConfigLoader('./custom-config.json');\n\t * ```\n\t */\n\tconstructor(customPath?: string) {\n\t\tthis._configPaths = customPath\n\t\t\t? [customPath]\n\t\t\t: [\n\t\t\t\t\t'.claude/config.json',\n\t\t\t\t\t'.claude/config.yaml',\n\t\t\t\t\t'.claude/config.yml',\n\t\t\t\t\tjoin(homedir(), '.claude/config.json'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yaml'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yml'),\n\t\t\t\t];\n\t}\n\n\t/**\n\t * Loads configuration from files and applies environment overrides.\n\t *\n\t * Searches for config files in the configured paths (in priority order),\n\t * parses the first match, and applies environment variable overrides.\n\t * Returns null if no config file is found and no environment overrides are set.\n\t *\n\t * @returns The loaded configuration with environment overrides applied, or null if no config found\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t *\n\t * if (config) {\n\t * console.log('Max history size:', config.maxHistorySize);\n\t * console.log('Log level:', config.logLevel);\n\t * }\n\t * ```\n\t */\n\tload(): ConfigFileOptions | null {\n\t\tlet config: ConfigFileOptions | null = null;\n\n\t\tfor (const configPath of this._configPaths) {\n\t\t\tif (existsSync(configPath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconfig = this.parseConfig(configPath);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Failed to load config from ${configPath}:`,\n\t\t\t\t\t\tgetErrorMessage(error)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.applyEnvironmentOverrides(config || {});\n\t}\n\n\t/**\n\t * Applies environment variable overrides to the configuration.\n\t *\n\t * Environment variables take precedence over file-based configuration.\n\t * Supported environment variables:\n\t * - `MAX_HISTORY_SIZE`, `MAX_BRANCHES`, `MAX_BRANCH_SIZE` (numbers)\n\t * - `LOG_LEVEL` (debug/info/warn/error)\n\t * - `PRETTY_LOG` (\"false\" to disable)\n\t * - `SKILL_DIRS` (colon-separated paths)\n\t * - `DISCOVERY_CACHE_TTL` (in seconds, converted to ms)\n\t * - `DISCOVERY_CACHE_MAX_SIZE` (number)\n\t *\n\t * @param config - The configuration to apply overrides to\n\t * @returns A new configuration object with environment overrides applied\n\t * @private\n\t */\n\tprivate applyEnvironmentOverrides(config: ConfigFileOptions): ConfigFileOptions {\n\t\tconst result: ConfigFileOptions = { ...config };\n\n\t\tif (process.env.MAX_HISTORY_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_HISTORY_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxHistorySize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCHES) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCHES, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranches = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCH_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCH_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranchSize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (\n\t\t\tprocess.env.LOG_LEVEL &&\n\t\t\t['debug', 'info', 'warn', 'error'].includes(process.env.LOG_LEVEL)\n\t\t) {\n\t\t\tresult.logLevel = process.env.LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error';\n\t\t}\n\t\tif (process.env.PRETTY_LOG === 'false') {\n\t\t\tresult.prettyLog = false;\n\t\t}\n\t\tif (process.env.SKILL_DIRS) {\n\t\t\tresult.skillDirs = process.env.SKILL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_TTL) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_TTL, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = result.discoveryCache || {};\n\t\t\t\tresult.discoveryCache.ttl = parsed * 1000;\n\t\t\t}\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_MAX_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_MAX_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = result.discoveryCache || {};\n\t\t\t\tresult.discoveryCache.maxSize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveTtlMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveSweepMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.SESSION_MAX_PER_OWNER) {\n\t\t\tconst parsed = parseInt(process.env.SESSION_MAX_PER_OWNER, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxSessionsPerOwner = parsed;\n\t\t\t}\n\t\t}\n\n\t\tthis.applyFeatureFlagOverrides(result);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Applies TRACELATTICE_FEATURES_* environment variable overrides for feature flags.\n\t * Booleans accept 'true'/'false'/'1'/'0' (case-insensitive).\n\t * Invalid reasoningStrategy values are warned and ignored (fall back to default).\n\t *\n\t * @param result - Configuration object to mutate with feature flag overrides\n\t * @private\n\t */\n\tprivate applyFeatureFlagOverrides(result: ConfigFileOptions): void {\n\t\tconst boolMap: Record<string, Exclude<keyof FeatureFlags, 'reasoningStrategy'>> = {\n\t\t\tTRACELATTICE_FEATURES_DAG_EDGES: 'dagEdges',\n\t\t\tTRACELATTICE_FEATURES_CALIBRATION: 'calibration',\n\t\t\tTRACELATTICE_FEATURES_COMPRESSION: 'compression',\n\t\t\tTRACELATTICE_FEATURES_TOOL_INTERLEAVE: 'toolInterleave',\n\t\t\tTRACELATTICE_FEATURES_NEW_THOUGHT_TYPES: 'newThoughtTypes',\n\t\t\tTRACELATTICE_FEATURES_OUTCOME_RECORDING: 'outcomeRecording',\n\t\t};\n\t\tfor (const [envVar, key] of Object.entries(boolMap)) {\n\t\t\tconst raw = process.env[envVar];\n\t\t\tif (raw === undefined) continue;\n\t\t\tconst parsed = this.parseBoolean(raw);\n\t\t\tif (parsed === undefined) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid boolean value for ${envVar}: \"${raw}\" (expected true/false/1/0). Ignoring.`\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\tresult.features ?? {};\n\t\t\tfeatures[key] = parsed;\n\t\t\tresult.features = features;\n\t\t}\n\n\t\tconst strategyRaw = process.env.TRACELATTICE_FEATURES_REASONING_STRATEGY;\n\t\tif (strategyRaw !== undefined) {\n\t\t\tconst allowed = ['sequential', 'tot'] as const;\n\t\t\tif ((allowed as readonly string[]).includes(strategyRaw)) {\n\t\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\t\tresult.features ?? {};\n\t\t\t\tfeatures.reasoningStrategy = strategyRaw as 'sequential' | 'tot';\n\t\t\t\tresult.features = features;\n\t\t\t} else {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid value for TRACELATTICE_FEATURES_REASONING_STRATEGY: \"${strategyRaw}\" ` +\n\t\t\t\t\t\t`(expected one of ${allowed.join(', ')}). Falling back to 'sequential'.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parses a boolean from an environment variable string.\n\t * Accepts 'true'/'false'/'1'/'0' case-insensitively.\n\t *\n\t * @param raw - Raw environment variable string\n\t * @returns Parsed boolean, or undefined if the value is invalid\n\t * @private\n\t */\n\tprivate parseBoolean(raw: string): boolean | undefined {\n\t\tconst v = raw.trim().toLowerCase();\n\t\tif (v === 'true' || v === '1') return true;\n\t\tif (v === 'false' || v === '0') return false;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Parses a configuration file (JSON or YAML).\n\t *\n\t * Detects the file type by extension and uses the appropriate parser.\n\t * Supports `.json`, `.yaml`, and `.yml` file extensions.\n\t *\n\t * @param filePath - Path to the configuration file to parse\n\t * @returns The parsed configuration object\n\t * @throws {Error} If the file cannot be parsed\n\t * @private\n\t */\n\tprivate parseConfig(filePath: string): ConfigFileOptions {\n\t\tconst content = readFileSync(filePath, 'utf-8');\n\t\tconst ext = filePath.split('.').pop()?.toLowerCase();\n\n\t\tif (ext === 'yaml' || ext === 'yml') {\n\t\t\treturn parseYaml(content) as ConfigFileOptions;\n\t\t}\n\n\t\treturn JSON.parse(content) as ConfigFileOptions;\n\t}\n\n\t/**\n\t * Converts file-based configuration to ServerConfig options.\n\t *\n\t * This is a convenience method for extracting the ServerConfig-relevant\n\t * options from a file-based configuration.\n\t *\n\t * @param config - The configuration to convert\n\t * @returns An object with ServerConfig-compatible options\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t * if (config) {\n\t * const serverOpts = loader.toServerConfigOptions(config);\n\t * const serverConfig = new ServerConfig(serverOpts);\n\t * }\n\t * ```\n\t */\n\ttoServerConfigOptions(config: ConfigFileOptions): {\n\t\tmaxHistorySize?: number;\n\t\tmaxBranches?: number;\n\t\tmaxBranchSize?: number;\n\t\tfeatures?: Partial<FeatureFlags>;\n\t\ttoolInterleaveTtlMs?: number;\n\t\ttoolInterleaveSweepMs?: number;\n\t\tmaxSessionsPerOwner?: number;\n\t} {\n\t\treturn {\n\t\t\tmaxHistorySize: config.maxHistorySize,\n\t\t\tmaxBranches: config.maxBranches,\n\t\t\tmaxBranchSize: config.maxBranchSize,\n\t\t\tfeatures: config.features,\n\t\t\ttoolInterleaveTtlMs: config.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: config.toolInterleaveSweepMs,\n\t\t\tmaxSessionsPerOwner: config.maxSessionsPerOwner,\n\t\t};\n\t}\n}\n"],"names":["ConfigLoader","customPath","join","homedir","config","configPath","existsSync","error","console","getErrorMessage","result","process","parsed","parseInt","Number","boolMap","envVar","key","Object","raw","undefined","features","strategyRaw","allowed","v","filePath","content","readFileSync","ext","parseYaml","JSON"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config/ConfigLoader.js","sources":["../../src/config/ConfigLoader.ts"],"sourcesContent":["/**\n * Configuration file loading with environment variable override support.\n *\n * This module provides the `ConfigLoader` class which handles loading configuration\n * from YAML and JSON files in standard locations, with automatic environment variable\n * overrides for all settings.\n *\n * @module config\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { PersistenceConfig } from '../contracts/PersistenceBackend.js';\nimport { getErrorMessage } from '../errors.js';\nimport type { FeatureFlags } from '../contracts/features.js';\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\n/**\n * Configuration options loaded from config files.\n *\n * These options represent the structure of configuration files (JSON or YAML)\n * that can be loaded from standard locations. All values can be overridden\n * by environment variables.\n *\n * @example\n * ```yaml\n * # .claude/config.yaml\n * maxHistorySize: 500\n * maxBranches: 25\n * logLevel: debug\n * prettyLog: true\n * skillDirs:\n * - ./custom-skills\n * discoveryCache:\n * ttl: 600000\n * maxSize: 200\n * persistence:\n * enabled: true\n * backend: sqlite\n * options:\n * dbPath: ./data/history.db\n * ```\n */\nexport interface ConfigFileOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * Can be overridden by `MAX_HISTORY_SIZE` environment variable.\n\t */\n\treadonly maxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * Can be overridden by `MAX_BRANCHES` environment variable.\n\t */\n\treadonly maxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * Can be overridden by `MAX_BRANCH_SIZE` environment variable.\n\t */\n\treadonly maxBranchSize?: number;\n\n\t/**\n\t * Logging level for the application.\n\t * Can be overridden by `LOG_LEVEL` environment variable.\n\t */\n\treadonly logLevel?: 'debug' | 'info' | 'warn' | 'error';\n\n\t/**\n\t * Whether to enable pretty (formatted) logging output.\n\t * Can be overridden by `PRETTY_LOG` environment variable (set to \"false\" to disable).\n\t */\n\treadonly prettyLog?: boolean;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * Can be overridden by `SKILL_DIRS` environment variable (colon-separated).\n\t */\n\treadonly skillDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t * Can be overridden by `DISCOVERY_CACHE_TTL` and `DISCOVERY_CACHE_MAX_SIZE` environment variables.\n\t */\n\treadonly discoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * Environment variable `DISCOVERY_CACHE_TTL` accepts seconds.\n\t\t */\n\t\treadonly ttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t */\n\t\treadonly maxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\treadonly persistence?: PersistenceConfig;\n\n\t/**\n\t * Feature flag overrides. Each field can be set independently.\n\t * Can be overridden by `TRACELATTICE_FEATURES_*` environment variables.\n\t */\n\treadonly features?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` environment variable.\n\t */\n\treadonly toolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` environment variable.\n\t */\n\treadonly toolInterleaveSweepMs?: number;\n\n\t/**\n\t * Maximum sessions per owner. Per-owner LRU bucket prevents one user from\n\t * consuming all session slots.\n\t * Can be overridden by `SESSION_MAX_PER_OWNER` environment variable.\n\t */\n\treadonly maxSessionsPerOwner?: number;\n}\n\n/**\n * Loads configuration from files with environment variable overrides.\n *\n * This class searches for configuration files in standard locations and applies\n * environment variable overrides. Files are searched in priority order, with the\n * first match being used. Environment variables always take precedence over file values.\n *\n * @remarks\n * **Config File Search Order (priority):**\n * 1. Custom path (if provided to constructor)\n * 2. `.claude/config.json` (project-local)\n * 3. `.claude/config.yaml` (project-local)\n * 4. `.claude/config.yml` (project-local)\n * 5. `~/.claude/config.json` (user-global)\n * 6. `~/.claude/config.yaml` (user-global)\n * 7. `~/.claude/config.yml` (user-global)\n *\n * **Environment Variable Overrides:**\n * | Variable | Type | Description |\n * |----------|------|-------------|\n * | `MAX_HISTORY_SIZE` | number | Max thoughts in history |\n * | `MAX_BRANCHES` | number | Max number of branches |\n * | `MAX_BRANCH_SIZE` | number | Max size of each branch |\n * | `LOG_LEVEL` | string | Logging level (debug/info/warn/error) |\n * | `PRETTY_LOG` | string | \"false\" to disable pretty logging |\n * | `SKILL_DIRS` | string | Colon-separated directory paths |\n * | `DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |\n * | `DISCOVERY_CACHE_MAX_SIZE` | number | Max cache entries |\n *\n * @example\n * ```typescript\n * // Use default search paths\n * const loader1 = new ConfigLoader();\n * const config1 = loader1.load();\n *\n * // Use custom config path\n * const loader2 = new ConfigLoader('./my-config.yaml');\n * const config2 = loader2.load();\n *\n * // Convert to ServerConfig options\n * const serverOptions = loader2.toServerConfigOptions(config2);\n * ```\n */\nexport class ConfigLoader {\n\t/** Array of config file paths to search, in priority order. */\n\tprivate _configPaths: string[];\n\n\t/**\n\t * Creates a new ConfigLoader instance.\n\t *\n\t * @param customPath - Optional custom config file path. If provided, only this path will be checked.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Use default search paths\n\t * const loader1 = new ConfigLoader();\n\t *\n\t * // Use a specific config file\n\t * const loader2 = new ConfigLoader('./custom-config.json');\n\t * ```\n\t */\n\tconstructor(customPath?: string) {\n\t\tthis._configPaths = customPath\n\t\t\t? [customPath]\n\t\t\t: [\n\t\t\t\t\t'.claude/config.json',\n\t\t\t\t\t'.claude/config.yaml',\n\t\t\t\t\t'.claude/config.yml',\n\t\t\t\t\tjoin(homedir(), '.claude/config.json'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yaml'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yml'),\n\t\t\t\t];\n\t}\n\n\t/**\n\t * Loads configuration from files and applies environment overrides.\n\t *\n\t * Searches for config files in the configured paths (in priority order),\n\t * parses the first match, and applies environment variable overrides.\n\t * Returns null if no config file is found and no environment overrides are set.\n\t *\n\t * @returns The loaded configuration with environment overrides applied, or null if no config found\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t *\n\t * if (config) {\n\t * console.log('Max history size:', config.maxHistorySize);\n\t * console.log('Log level:', config.logLevel);\n\t * }\n\t * ```\n\t */\n\tload(): ConfigFileOptions | null {\n\t\tlet config: ConfigFileOptions | null = null;\n\n\t\tfor (const configPath of this._configPaths) {\n\t\t\tif (existsSync(configPath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconfig = this.parseConfig(configPath);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Failed to load config from ${configPath}:`,\n\t\t\t\t\t\tgetErrorMessage(error)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.applyEnvironmentOverrides(config || {});\n\t}\n\n\t/**\n\t * Applies environment variable overrides to the configuration.\n\t *\n\t * Environment variables take precedence over file-based configuration.\n\t * Supported environment variables:\n\t * - `MAX_HISTORY_SIZE`, `MAX_BRANCHES`, `MAX_BRANCH_SIZE` (numbers)\n\t * - `LOG_LEVEL` (debug/info/warn/error)\n\t * - `PRETTY_LOG` (\"false\" to disable)\n\t * - `SKILL_DIRS` (colon-separated paths)\n\t * - `DISCOVERY_CACHE_TTL` (in seconds, converted to ms)\n\t * - `DISCOVERY_CACHE_MAX_SIZE` (number)\n\t *\n\t * @param config - The configuration to apply overrides to\n\t * @returns A new configuration object with environment overrides applied\n\t * @private\n\t */\n\tprivate applyEnvironmentOverrides(config: ConfigFileOptions): ConfigFileOptions {\n\t\tconst result: Mutable<ConfigFileOptions> = { ...config };\n\n\t\tif (process.env.MAX_HISTORY_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_HISTORY_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxHistorySize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCHES) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCHES, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranches = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCH_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCH_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranchSize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (\n\t\t\tprocess.env.LOG_LEVEL &&\n\t\t\t['debug', 'info', 'warn', 'error'].includes(process.env.LOG_LEVEL)\n\t\t) {\n\t\t\tresult.logLevel = process.env.LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error';\n\t\t}\n\t\tif (process.env.PRETTY_LOG === 'false') {\n\t\t\tresult.prettyLog = false;\n\t\t}\n\t\tif (process.env.SKILL_DIRS) {\n\t\t\tresult.skillDirs = process.env.SKILL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_TTL) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_TTL, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = { ...(result.discoveryCache ?? {}), ttl: parsed * 1000 };\n\t\t\t}\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_MAX_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_MAX_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = { ...(result.discoveryCache ?? {}), maxSize: parsed };\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveTtlMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveSweepMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.SESSION_MAX_PER_OWNER) {\n\t\t\tconst parsed = parseInt(process.env.SESSION_MAX_PER_OWNER, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxSessionsPerOwner = parsed;\n\t\t\t}\n\t\t}\n\n\t\tthis.applyFeatureFlagOverrides(result);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Applies TRACELATTICE_FEATURES_* environment variable overrides for feature flags.\n\t * Booleans accept 'true'/'false'/'1'/'0' (case-insensitive).\n\t * Invalid reasoningStrategy values are warned and ignored (fall back to default).\n\t *\n\t * @param result - Configuration object to mutate with feature flag overrides\n\t * @private\n\t */\n\tprivate applyFeatureFlagOverrides(result: Mutable<ConfigFileOptions>): void {\n\t\tconst boolMap: Record<string, Exclude<keyof FeatureFlags, 'reasoningStrategy'>> = {\n\t\t\tTRACELATTICE_FEATURES_DAG_EDGES: 'dagEdges',\n\t\t\tTRACELATTICE_FEATURES_CALIBRATION: 'calibration',\n\t\t\tTRACELATTICE_FEATURES_COMPRESSION: 'compression',\n\t\t\tTRACELATTICE_FEATURES_TOOL_INTERLEAVE: 'toolInterleave',\n\t\t\tTRACELATTICE_FEATURES_NEW_THOUGHT_TYPES: 'newThoughtTypes',\n\t\t\tTRACELATTICE_FEATURES_OUTCOME_RECORDING: 'outcomeRecording',\n\t\t};\n\t\tfor (const [envVar, key] of Object.entries(boolMap)) {\n\t\t\tconst raw = process.env[envVar];\n\t\t\tif (raw === undefined) continue;\n\t\t\tconst parsed = this.parseBoolean(raw);\n\t\t\tif (parsed === undefined) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid boolean value for ${envVar}: \"${raw}\" (expected true/false/1/0). Ignoring.`\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\tresult.features ?? {};\n\t\t\tfeatures[key] = parsed;\n\t\t\tresult.features = features;\n\t\t}\n\n\t\tconst strategyRaw = process.env.TRACELATTICE_FEATURES_REASONING_STRATEGY;\n\t\tif (strategyRaw !== undefined) {\n\t\t\tconst allowed = ['sequential', 'tot'] as const;\n\t\t\tif ((allowed as readonly string[]).includes(strategyRaw)) {\n\t\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\t\tresult.features ?? {};\n\t\t\t\tfeatures.reasoningStrategy = strategyRaw as 'sequential' | 'tot';\n\t\t\t\tresult.features = features;\n\t\t\t} else {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid value for TRACELATTICE_FEATURES_REASONING_STRATEGY: \"${strategyRaw}\" ` +\n\t\t\t\t\t\t`(expected one of ${allowed.join(', ')}). Falling back to 'sequential'.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parses a boolean from an environment variable string.\n\t * Accepts 'true'/'false'/'1'/'0' case-insensitively.\n\t *\n\t * @param raw - Raw environment variable string\n\t * @returns Parsed boolean, or undefined if the value is invalid\n\t * @private\n\t */\n\tprivate parseBoolean(raw: string): boolean | undefined {\n\t\tconst v = raw.trim().toLowerCase();\n\t\tif (v === 'true' || v === '1') return true;\n\t\tif (v === 'false' || v === '0') return false;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Parses a configuration file (JSON or YAML).\n\t *\n\t * Detects the file type by extension and uses the appropriate parser.\n\t * Supports `.json`, `.yaml`, and `.yml` file extensions.\n\t *\n\t * @param filePath - Path to the configuration file to parse\n\t * @returns The parsed configuration object\n\t * @throws {Error} If the file cannot be parsed\n\t * @private\n\t */\n\tprivate parseConfig(filePath: string): ConfigFileOptions {\n\t\tconst content = readFileSync(filePath, 'utf-8');\n\t\tconst ext = filePath.split('.').pop()?.toLowerCase();\n\n\t\tif (ext === 'yaml' || ext === 'yml') {\n\t\t\treturn parseYaml(content) as ConfigFileOptions;\n\t\t}\n\n\t\treturn JSON.parse(content) as ConfigFileOptions;\n\t}\n\n\t/**\n\t * Converts file-based configuration to ServerConfig options.\n\t *\n\t * This is a convenience method for extracting the ServerConfig-relevant\n\t * options from a file-based configuration.\n\t *\n\t * @param config - The configuration to convert\n\t * @returns An object with ServerConfig-compatible options\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t * if (config) {\n\t * const serverOpts = loader.toServerConfigOptions(config);\n\t * const serverConfig = new ServerConfig(serverOpts);\n\t * }\n\t * ```\n\t */\n\ttoServerConfigOptions(config: ConfigFileOptions): {\n\t\tmaxHistorySize?: number;\n\t\tmaxBranches?: number;\n\t\tmaxBranchSize?: number;\n\t\tfeatures?: Partial<FeatureFlags>;\n\t\ttoolInterleaveTtlMs?: number;\n\t\ttoolInterleaveSweepMs?: number;\n\t\tmaxSessionsPerOwner?: number;\n\t} {\n\t\treturn {\n\t\t\tmaxHistorySize: config.maxHistorySize,\n\t\t\tmaxBranches: config.maxBranches,\n\t\t\tmaxBranchSize: config.maxBranchSize,\n\t\t\tfeatures: config.features,\n\t\t\ttoolInterleaveTtlMs: config.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: config.toolInterleaveSweepMs,\n\t\t\tmaxSessionsPerOwner: config.maxSessionsPerOwner,\n\t\t};\n\t}\n}\n"],"names":["ConfigLoader","customPath","join","homedir","config","configPath","existsSync","error","console","getErrorMessage","result","process","parsed","parseInt","Number","boolMap","envVar","key","Object","raw","undefined","features","strategyRaw","allowed","v","filePath","content","readFileSync","ext","parseYaml","JSON"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ThoughtData } from '../core/thought.js';
|
|
2
2
|
import type { Edge } from '../core/graph/Edge.js';
|
|
3
3
|
import type { Summary } from '../core/compression/Summary.js';
|
|
4
|
+
import type { BranchId } from './ids.js';
|
|
4
5
|
/**
|
|
5
6
|
* Persistence backend interface for storing thought history and branches.
|
|
6
7
|
*
|
|
@@ -27,20 +28,20 @@ export interface PersistenceBackend {
|
|
|
27
28
|
* @param branchId - The unique identifier for the branch
|
|
28
29
|
* @param thoughts - Array of thoughts in branch
|
|
29
30
|
*/
|
|
30
|
-
saveBranch(branchId:
|
|
31
|
+
saveBranch(branchId: BranchId, thoughts: ThoughtData[]): Promise<void>;
|
|
31
32
|
/**
|
|
32
33
|
* Load all thoughts for a specific branch.
|
|
33
34
|
*
|
|
34
35
|
* @param branchId - The unique identifier for the branch
|
|
35
36
|
* @returns Array of thoughts in branch, or undefined if branch doesn't exist
|
|
36
37
|
*/
|
|
37
|
-
loadBranch(branchId:
|
|
38
|
+
loadBranch(branchId: BranchId): Promise<ThoughtData[] | undefined>;
|
|
38
39
|
/**
|
|
39
40
|
* List all branch IDs that are persisted.
|
|
40
41
|
*
|
|
41
42
|
* @returns Array of branch identifiers
|
|
42
43
|
*/
|
|
43
|
-
listBranches(): Promise<
|
|
44
|
+
listBranches(): Promise<BranchId[]>;
|
|
44
45
|
/**
|
|
45
46
|
* Check if backend is healthy.
|
|
46
47
|
* @returns Promise that resolves to true if healthy, false otherwise
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersistenceBackend.d.ts","sourceRoot":"","sources":["../../src/contracts/PersistenceBackend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"PersistenceBackend.d.ts","sourceRoot":"","sources":["../../src/contracts/PersistenceBackend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;;OAKG;IACH,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEtC;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvE;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,CAAC;IAEnE;;;;OAIG;IACH,YAAY,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEpC;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE5B;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;;;;;OAOG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9C;;;;OAIG;IACH,gBAAgB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtC;;;;;OAKG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/E;;;;;;;OAOG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC,OAAO,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACF"}
|
package/dist/contracts/ids.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export type ThoughtId = Brand<string, 'ThoughtId'>;
|
|
|
26
26
|
export type EdgeId = Brand<string, 'EdgeId'>;
|
|
27
27
|
/** Branded suspension token. */
|
|
28
28
|
export type SuspensionToken = Brand<string, 'SuspensionToken'>;
|
|
29
|
+
/** Branded branch identifier. */
|
|
30
|
+
export type BranchId = Brand<string, 'BranchId'>;
|
|
29
31
|
/**
|
|
30
32
|
* Validate and brand a string as a {@link SessionId}.
|
|
31
33
|
*
|
|
@@ -41,6 +43,8 @@ export declare function asThoughtId(value: string): ThoughtId;
|
|
|
41
43
|
export declare function asEdgeId(value: string): EdgeId;
|
|
42
44
|
/** Brand a string as a {@link SuspensionToken} without validation. */
|
|
43
45
|
export declare function asSuspensionToken(value: string): SuspensionToken;
|
|
46
|
+
/** Brand a string as a {@link BranchId} without validation. */
|
|
47
|
+
export declare function asBranchId(value: string): BranchId;
|
|
44
48
|
/** Generate a fresh {@link ThoughtId}. */
|
|
45
49
|
export declare function generateThoughtId(): ThoughtId;
|
|
46
50
|
/** Generate a fresh {@link EdgeId}. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/contracts/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,CAAC,MAAM,OAAO,EAAE,OAAO,MAAM,CAAC;AAErC;;;;;GAKG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEvE,kCAAkC;AAClC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEnD,kCAAkC;AAClC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEnD,+BAA+B;AAC/B,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE7C,gCAAgC;AAChC,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAoBpD;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAEpD;AAED,8DAA8D;AAC9D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAEhE;AAED,0CAA0C;AAC1C,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C;AAED,uCAAuC;AACvC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,gDAAgD;AAChD,wBAAgB,uBAAuB,IAAI,eAAe,CAEzD;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAqC,CAAC"}
|
|
1
|
+
{"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/contracts/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,CAAC,MAAM,OAAO,EAAE,OAAO,MAAM,CAAC;AAErC;;;;;GAKG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEvE,kCAAkC;AAClC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEnD,kCAAkC;AAClC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEnD,+BAA+B;AAC/B,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE7C,gCAAgC;AAChC,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAE/D,iCAAiC;AACjC,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAoBpD;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAEpD;AAED,8DAA8D;AAC9D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAEhE;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAElD;AAED,0CAA0C;AAC1C,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C;AAED,uCAAuC;AACvC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,gDAAgD;AAChD,wBAAgB,uBAAuB,IAAI,eAAe,CAEzD;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAqC,CAAC"}
|
package/dist/contracts/ids.js
CHANGED
|
@@ -16,6 +16,9 @@ function asEdgeId(value) {
|
|
|
16
16
|
function asSuspensionToken(value) {
|
|
17
17
|
return value;
|
|
18
18
|
}
|
|
19
|
+
function asBranchId(value) {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
19
22
|
function generateThoughtId() {
|
|
20
23
|
return generateUlid();
|
|
21
24
|
}
|
|
@@ -26,6 +29,6 @@ function generateSuspensionToken() {
|
|
|
26
29
|
return generateUlid();
|
|
27
30
|
}
|
|
28
31
|
const GLOBAL_SESSION_ID = '__global__';
|
|
29
|
-
export { GLOBAL_SESSION_ID, asEdgeId, asSessionId, asSuspensionToken, asThoughtId, generateEdgeId, generateSuspensionToken, generateThoughtId };
|
|
32
|
+
export { GLOBAL_SESSION_ID, asBranchId, asEdgeId, asSessionId, asSuspensionToken, asThoughtId, generateEdgeId, generateSuspensionToken, generateThoughtId };
|
|
30
33
|
|
|
31
34
|
//# sourceMappingURL=ids.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts/ids.js","sources":["../../src/contracts/ids.ts"],"sourcesContent":["/**\n * Branded identifier types for compile-time slot safety.\n *\n * These nominal types prevent accidental mixing of different ID kinds\n * (e.g. passing a `ThoughtId` where a `SessionId` is expected). At\n * runtime they are plain strings — the brand exists only in the type\n * system.\n *\n * @module contracts/ids\n */\n\nimport {\n\tgenerateUlid,\n\tMAX_SESSION_ID_LENGTH,\n\tSESSION_ID_PATTERN,\n} from '../core/ids.js';\nimport { ValidationError } from '../errors.js';\n\ndeclare const __brand: unique symbol;\n\n/**\n * Nominal brand helper.\n *\n * The brand is a phantom property — it exists at the type level only\n * and carries zero runtime cost.\n */\nexport type Brand<T, B extends string> = T & { readonly [__brand]: B };\n\n/** Branded session identifier. */\nexport type SessionId = Brand<string, 'SessionId'>;\n\n/** Branded thought identifier. */\nexport type ThoughtId = Brand<string, 'ThoughtId'>;\n\n/** Branded edge identifier. */\nexport type EdgeId = Brand<string, 'EdgeId'>;\n\n/** Branded suspension token. */\nexport type SuspensionToken = Brand<string, 'SuspensionToken'>;\n\n/**\n * Validate and brand a string as a {@link SessionId}.\n *\n * Enforces {@link SESSION_ID_PATTERN} and {@link MAX_SESSION_ID_LENGTH}.\n * The reserved global session sentinel `__global__` is always accepted.\n *\n * @throws {ValidationError} when the input is not a valid session id.\n */\nexport function asSessionId(value: string): SessionId {\n\tif (value === '__global__') {\n\t\treturn value as SessionId;\n\t}\n\tif (typeof value !== 'string' || value.length === 0) {\n\t\tthrow new ValidationError('session_id', 'must be a non-empty string');\n\t}\n\tif (value.length > MAX_SESSION_ID_LENGTH) {\n\t\tthrow new ValidationError(\n\t\t\t'session_id',\n\t\t\t`exceeds max length of ${MAX_SESSION_ID_LENGTH}`,\n\t\t);\n\t}\n\tif (!SESSION_ID_PATTERN.test(value)) {\n\t\tthrow new ValidationError(\n\t\t\t'session_id',\n\t\t\t'must match alphanumeric, hyphens, underscores',\n\t\t);\n\t}\n\treturn value as SessionId;\n}\n\n/** Brand a string as a {@link ThoughtId} without validation. */\nexport function asThoughtId(value: string): ThoughtId {\n\treturn value as ThoughtId;\n}\n\n/** Brand a string as an {@link EdgeId} without validation. */\nexport function asEdgeId(value: string): EdgeId {\n\treturn value as EdgeId;\n}\n\n/** Brand a string as a {@link SuspensionToken} without validation. */\nexport function asSuspensionToken(value: string): SuspensionToken {\n\treturn value as SuspensionToken;\n}\n\n/** Generate a fresh {@link ThoughtId}. */\nexport function generateThoughtId(): ThoughtId {\n\treturn generateUlid() as ThoughtId;\n}\n\n/** Generate a fresh {@link EdgeId}. */\nexport function generateEdgeId(): EdgeId {\n\treturn generateUlid() as EdgeId;\n}\n\n/** Generate a fresh {@link SuspensionToken}. */\nexport function generateSuspensionToken(): SuspensionToken {\n\treturn generateUlid() as SuspensionToken;\n}\n\n/**\n * Reserved sentinel session id used when callers omit `session_id`.\n *\n * Branded once here so production and test code share one constant\n * instead of casting `'__global__'` ad-hoc.\n */\nexport const GLOBAL_SESSION_ID: SessionId = '__global__' as SessionId;\n"],"names":["asSessionId","value","ValidationError","MAX_SESSION_ID_LENGTH","SESSION_ID_PATTERN","asThoughtId","asEdgeId","asSuspensionToken","generateThoughtId","generateUlid","generateEdgeId","generateSuspensionToken","GLOBAL_SESSION_ID"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"contracts/ids.js","sources":["../../src/contracts/ids.ts"],"sourcesContent":["/**\n * Branded identifier types for compile-time slot safety.\n *\n * These nominal types prevent accidental mixing of different ID kinds\n * (e.g. passing a `ThoughtId` where a `SessionId` is expected). At\n * runtime they are plain strings — the brand exists only in the type\n * system.\n *\n * @module contracts/ids\n */\n\nimport {\n\tgenerateUlid,\n\tMAX_SESSION_ID_LENGTH,\n\tSESSION_ID_PATTERN,\n} from '../core/ids.js';\nimport { ValidationError } from '../errors.js';\n\ndeclare const __brand: unique symbol;\n\n/**\n * Nominal brand helper.\n *\n * The brand is a phantom property — it exists at the type level only\n * and carries zero runtime cost.\n */\nexport type Brand<T, B extends string> = T & { readonly [__brand]: B };\n\n/** Branded session identifier. */\nexport type SessionId = Brand<string, 'SessionId'>;\n\n/** Branded thought identifier. */\nexport type ThoughtId = Brand<string, 'ThoughtId'>;\n\n/** Branded edge identifier. */\nexport type EdgeId = Brand<string, 'EdgeId'>;\n\n/** Branded suspension token. */\nexport type SuspensionToken = Brand<string, 'SuspensionToken'>;\n\n/** Branded branch identifier. */\nexport type BranchId = Brand<string, 'BranchId'>;\n\n/**\n * Validate and brand a string as a {@link SessionId}.\n *\n * Enforces {@link SESSION_ID_PATTERN} and {@link MAX_SESSION_ID_LENGTH}.\n * The reserved global session sentinel `__global__` is always accepted.\n *\n * @throws {ValidationError} when the input is not a valid session id.\n */\nexport function asSessionId(value: string): SessionId {\n\tif (value === '__global__') {\n\t\treturn value as SessionId;\n\t}\n\tif (typeof value !== 'string' || value.length === 0) {\n\t\tthrow new ValidationError('session_id', 'must be a non-empty string');\n\t}\n\tif (value.length > MAX_SESSION_ID_LENGTH) {\n\t\tthrow new ValidationError(\n\t\t\t'session_id',\n\t\t\t`exceeds max length of ${MAX_SESSION_ID_LENGTH}`,\n\t\t);\n\t}\n\tif (!SESSION_ID_PATTERN.test(value)) {\n\t\tthrow new ValidationError(\n\t\t\t'session_id',\n\t\t\t'must match alphanumeric, hyphens, underscores',\n\t\t);\n\t}\n\treturn value as SessionId;\n}\n\n/** Brand a string as a {@link ThoughtId} without validation. */\nexport function asThoughtId(value: string): ThoughtId {\n\treturn value as ThoughtId;\n}\n\n/** Brand a string as an {@link EdgeId} without validation. */\nexport function asEdgeId(value: string): EdgeId {\n\treturn value as EdgeId;\n}\n\n/** Brand a string as a {@link SuspensionToken} without validation. */\nexport function asSuspensionToken(value: string): SuspensionToken {\n\treturn value as SuspensionToken;\n}\n\n/** Brand a string as a {@link BranchId} without validation. */\nexport function asBranchId(value: string): BranchId {\n\treturn value as BranchId;\n}\n\n/** Generate a fresh {@link ThoughtId}. */\nexport function generateThoughtId(): ThoughtId {\n\treturn generateUlid() as ThoughtId;\n}\n\n/** Generate a fresh {@link EdgeId}. */\nexport function generateEdgeId(): EdgeId {\n\treturn generateUlid() as EdgeId;\n}\n\n/** Generate a fresh {@link SuspensionToken}. */\nexport function generateSuspensionToken(): SuspensionToken {\n\treturn generateUlid() as SuspensionToken;\n}\n\n/**\n * Reserved sentinel session id used when callers omit `session_id`.\n *\n * Branded once here so production and test code share one constant\n * instead of casting `'__global__'` ad-hoc.\n */\nexport const GLOBAL_SESSION_ID: SessionId = '__global__' as SessionId;\n"],"names":["asSessionId","value","ValidationError","MAX_SESSION_ID_LENGTH","SESSION_ID_PATTERN","asThoughtId","asEdgeId","asSuspensionToken","asBranchId","generateThoughtId","generateUlid","generateEdgeId","generateSuspensionToken","GLOBAL_SESSION_ID"],"mappings":";;AAmDO,SAASA,YAAYC,KAAa;IACxC,IAAIA,AAAU,iBAAVA,OACH,OAAOA;IAER,IAAI,AAAiB,YAAjB,OAAOA,SAAsBA,AAAiB,MAAjBA,MAAM,MAAM,EAC5C,MAAM,IAAIC,gBAAgB,cAAc;IAEzC,IAAID,MAAM,MAAM,GAAGE,uBAClB,MAAM,IAAID,gBACT,cACA,CAAC,sBAAsB,EAAEC,uBAAuB;IAGlD,IAAI,CAACC,mBAAmB,IAAI,CAACH,QAC5B,MAAM,IAAIC,gBACT,cACA;IAGF,OAAOD;AACR;AAGO,SAASI,YAAYJ,KAAa;IACxC,OAAOA;AACR;AAGO,SAASK,SAASL,KAAa;IACrC,OAAOA;AACR;AAGO,SAASM,kBAAkBN,KAAa;IAC9C,OAAOA;AACR;AAGO,SAASO,WAAWP,KAAa;IACvC,OAAOA;AACR;AAGO,SAASQ;IACf,OAAOC;AACR;AAGO,SAASC;IACf,OAAOD;AACR;AAGO,SAASE;IACf,OAAOF;AACR;AAQO,MAAMG,oBAA+B"}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { Edge } from '../core/graph/Edge.js';
|
|
14
14
|
import type { ThoughtType } from '../core/reasoning.js';
|
|
15
|
-
import type {
|
|
15
|
+
import type { ThoughtId } from './ids.js';
|
|
16
16
|
/**
|
|
17
17
|
* Metrics interface for observability.
|
|
18
18
|
*
|
|
@@ -71,7 +71,7 @@ export interface VerificationOutcome {
|
|
|
71
71
|
/** The thought number of the prediction (backward compat). */
|
|
72
72
|
thoughtNumber: number;
|
|
73
73
|
/** The session this outcome belongs to. */
|
|
74
|
-
sessionId:
|
|
74
|
+
sessionId: string;
|
|
75
75
|
/** The predicted confidence (0-1). */
|
|
76
76
|
predicted: number;
|
|
77
77
|
/** The actual outcome (0 = wrong, 1 = correct). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/contracts/interfaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/contracts/interfaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module contracts/strategy
|
|
10
10
|
*/
|
|
11
|
+
import type { SessionId } from './ids.js';
|
|
11
12
|
import type { ThoughtData } from '../core/thought.js';
|
|
12
13
|
import type { ReasoningStats } from '../core/reasoning.js';
|
|
13
14
|
import type { GraphView } from '../core/graph/GraphView.js';
|
|
@@ -31,7 +32,7 @@ import type { GraphView } from '../core/graph/GraphView.js';
|
|
|
31
32
|
*/
|
|
32
33
|
export interface StrategyContext {
|
|
33
34
|
/** Session identifier this context belongs to. */
|
|
34
|
-
readonly sessionId:
|
|
35
|
+
readonly sessionId: SessionId;
|
|
35
36
|
/** Chronological list of thoughts recorded in this session. */
|
|
36
37
|
readonly history: readonly ThoughtData[];
|
|
37
38
|
/** Read-only graph view for traversal (ancestors, descendants, etc.). Undefined when DAG edges are disabled. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../../src/contracts/strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../../src/contracts/strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG5D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAe;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,gHAAgH;IAChH,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;CACrC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,gBAAgB,GACzB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,kBAAkB;IAClC,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,CAAC;IAC/C,oDAAoD;IACpD,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;IAC5C,uDAAuD;IACvD,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;CAC/C"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @module contracts/summary
|
|
9
9
|
*/
|
|
10
10
|
import type { Summary } from '../core/compression/Summary.js';
|
|
11
|
+
import type { BranchId } from './ids.js';
|
|
11
12
|
export type { Summary };
|
|
12
13
|
/**
|
|
13
14
|
* Storage and query contract for {@link Summary} records.
|
|
@@ -74,7 +75,7 @@ export interface ISummaryStore {
|
|
|
74
75
|
* const altSummaries = store.forBranch('sess_42', 'alt-1');
|
|
75
76
|
* ```
|
|
76
77
|
*/
|
|
77
|
-
forBranch(sessionId: string, branchId:
|
|
78
|
+
forBranch(sessionId: string, branchId: BranchId): readonly Summary[];
|
|
78
79
|
/**
|
|
79
80
|
* Remove all summaries for a session. Other sessions are unaffected.
|
|
80
81
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/contracts/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/contracts/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,YAAY,EAAE,OAAO,EAAE,CAAC;AAExB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;;;;;;OASG;IACH,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAE5B;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAErC;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE,CAAC;IAElD;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,SAAS,OAAO,EAAE,CAAC;IAErE;;;;;;;;;OASG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtC;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACjC"}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import type { IMetrics } from '../contracts/interfaces.js';
|
|
15
15
|
import type { IEdgeStore } from '../contracts/interfaces.js';
|
|
16
|
+
import { type BranchId } from '../contracts/ids.js';
|
|
16
17
|
import type { ISummaryStore } from '../contracts/summary.js';
|
|
17
18
|
import type { Logger } from '../logger/StructuredLogger.js';
|
|
18
19
|
import type { PersistenceBackend } from '../contracts/PersistenceBackend.js';
|
|
@@ -111,14 +112,14 @@ export declare class HistoryManager implements IHistoryManager {
|
|
|
111
112
|
*/
|
|
112
113
|
getHistoryHydrated(sessionId?: string, opts?: DehydrationOptions): HydratedEntry[];
|
|
113
114
|
getHistoryLength(sessionId?: string): number;
|
|
114
|
-
getBranches(sessionId?: string): Record<
|
|
115
|
-
getBranchIds(sessionId?: string):
|
|
115
|
+
getBranches(sessionId?: string): Record<BranchId, ThoughtData[]>;
|
|
116
|
+
getBranchIds(sessionId?: string): BranchId[];
|
|
116
117
|
/** @throws {ValidationError} If branchId is empty or already exists. */
|
|
117
|
-
registerBranch(sessionId: string | undefined, branchId:
|
|
118
|
-
branchExists(sessionId: string | undefined, branchId:
|
|
118
|
+
registerBranch(sessionId: string | undefined, branchId: BranchId): void;
|
|
119
|
+
branchExists(sessionId: string | undefined, branchId: BranchId): boolean;
|
|
119
120
|
getAvailableMcpTools(sessionId?: string): string[] | undefined;
|
|
120
121
|
getAvailableSkills(sessionId?: string): string[] | undefined;
|
|
121
|
-
getBranch(branchId:
|
|
122
|
+
getBranch(branchId: BranchId, sessionId?: string): ThoughtData[] | undefined;
|
|
122
123
|
/** Clears history and branches. If sessionId provided, clears only that session. */
|
|
123
124
|
clear(sessionId?: string): void;
|
|
124
125
|
clearSession(sessionId: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HistoryManager.d.ts","sourceRoot":"","sources":["../../src/core/HistoryManager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"HistoryManager.d.ts","sourceRoot":"","sources":["../../src/core/HistoryManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asSessionId } from "../contracts/ids.js";
|
|
1
2
|
import { SessionAccessDeniedError, ValidationError, getErrorMessage } from "../errors.js";
|
|
2
3
|
import { NullLogger } from "../logger/NullLogger.js";
|
|
3
4
|
import { DehydrationPolicy } from "./compression/DehydrationPolicy.js";
|
|
@@ -229,9 +230,10 @@ class HistoryManager {
|
|
|
229
230
|
return this._getSession(sessionId, this._getCurrentOwner()).branches[branchId];
|
|
230
231
|
}
|
|
231
232
|
clear(sessionId) {
|
|
233
|
+
if (void 0 !== sessionId) this._getSession(sessionId, this._getCurrentOwner());
|
|
232
234
|
if (this._edgeStore) if (void 0 !== sessionId) this._edgeStore.clearSession(sessionId);
|
|
233
235
|
else {
|
|
234
|
-
for (const sid of this._sessions.keys())this._edgeStore.clearSession(sid);
|
|
236
|
+
for (const sid of this._sessions.keys())this._edgeStore.clearSession(asSessionId(sid));
|
|
235
237
|
this._edgeStore.clearSession(HistoryManager.DEFAULT_SESSION);
|
|
236
238
|
}
|
|
237
239
|
if (void 0 !== sessionId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core/HistoryManager.js","sources":["../../src/core/HistoryManager.ts"],"sourcesContent":["/**\n * History and branch management for sequential thinking.\n *\n * This module provides the `HistoryManager` class which manages thought history,\n * branching, and optional persistence with per-session state isolation.\n *\n * Internally delegates to three focused collaborators:\n * - `EdgeEmitter` — DAG edge emission\n * - `PersistenceBuffer` — buffered persistence + retry/backoff\n * - `SessionManager` — session lifecycle (TTL/LRU eviction)\n *\n * @module HistoryManager\n */\n\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport type { IEdgeStore } from '../contracts/interfaces.js';\nimport type { ISummaryStore } from '../contracts/summary.js';\nimport { ValidationError, SessionAccessDeniedError, getErrorMessage } from '../errors.js';\nimport { NullLogger } from '../logger/NullLogger.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\nimport type { PersistenceBackend } from '../contracts/PersistenceBackend.js';\nimport {\n\tDehydrationPolicy,\n\ttype DehydrationOptions,\n\ttype HydratedEntry,\n} from './compression/DehydrationPolicy.js';\nimport { EdgeEmitter } from './graph/EdgeEmitter.js';\nimport type { IHistoryManager } from './IHistoryManager.js';\nimport { PersistenceBuffer, type PersistenceEventEmitter } from './PersistenceBuffer.js';\nimport { SessionManager } from './SessionManager.js';\nimport type { ThoughtData } from './thought.js';\nimport { getOwner } from '../context/RequestContext.js';\n\n\n/** Absolute maximum history size (~20MB at 2KB/thought). Cannot be overridden. */\nexport const ABSOLUTE_MAX_HISTORY_SIZE = 10_000;\n\ninterface SessionState {\n\tthought_history: ThoughtData[];\n\tbranches: Record<string, ThoughtData[]>;\n\tavailableMcpTools: string[] | undefined;\n\tavailableSkills: string[] | undefined;\n\twriteBuffer: ThoughtData[];\n\tlastAccessedAt: number;\n\tregisteredBranches: Set<string>;\n\t/** Owner identifier set on first owner-aware access. Immutable thereafter. */\n\towner?: string;\n}\n\nexport interface HistoryManagerConfig {\n\t/** Maximum number of thoughts to keep in main history. @default 1000 */\n\tmaxHistorySize?: number;\n\t/** Maximum number of branches to maintain. @default 50 */\n\tmaxBranches?: number;\n\t/** Maximum size of each branch. @default 100 */\n\tmaxBranchSize?: number;\n\tlogger?: Logger;\n\tpersistence?: PersistenceBackend | null;\n\tmetrics?: IMetrics;\n\t/** Maximum number of thoughts to buffer before flushing. @default 100 */\n\tpersistenceBufferSize?: number;\n\t/** Periodic flush interval in ms. @default 1000 */\n\tpersistenceFlushInterval?: number;\n\t/** Max retries for failed persistence flushes. @default 3 */\n\tpersistenceMaxRetries?: number;\n\teventEmitter?: PersistenceEventEmitter;\n\tedgeStore?: IEdgeStore;\n\tsummaryStore?: ISummaryStore;\n\t/** Whether to emit DAG edges (gated independently of edgeStore). @default false */\n\tdagEdges?: boolean;\n\t/** Maximum sessions per owner (per-owner LRU bucket). @default 50 */\n\tmaxSessionsPerOwner?: number;\n}\n\n/**\n * Manages thought history and branching for sequential thinking.\n *\n * Owns the per-session `Map<string, SessionState>`. Delegates DAG edge emission,\n * buffered persistence, and session TTL/LRU eviction to focused collaborators while\n * preserving test-coupled private member names (`_flushTimer`, `_startFlushTimer`,\n * `_flushBuffer`, `_sessions`).\n */\nexport class HistoryManager implements IHistoryManager {\n\tprivate static readonly DEFAULT_SESSION = '__global__';\n\tprivate static readonly SESSION_TTL_MS = 30 * 60 * 1000;\n\tprivate static readonly MAX_SESSIONS = 100;\n\tprivate _sessions: Map<string, SessionState> = new Map();\n\tprivate _maxHistorySize: number;\n\tprivate _maxBranches: number;\n\tprivate _maxBranchSize: number;\n\tprivate _logger: Logger;\n\tprivate _persistence: PersistenceBackend | null;\n\tprivate _persistenceEnabled: boolean;\n\tprivate _metrics?: IMetrics;\n\n\tprivate _edgeStore?: IEdgeStore;\n\tprivate _summaryStore?: ISummaryStore;\n\tprivate _dagEdges: boolean;\n\n\tprivate _eventEmitter: PersistenceEventEmitter | null;\n\n\tprivate readonly _edgeEmitter: EdgeEmitter;\n\tprivate _persistenceBuffer: PersistenceBuffer<SessionState> | null;\n\tprivate readonly _sessionManager: SessionManager<SessionState>;\n\n\tconstructor(config: HistoryManagerConfig = {}) {\n\t\tthis._logger = config.logger ?? new NullLogger();\n\t\tconst requestedMaxSize = config.maxHistorySize ?? 10000;\n\t\tthis._maxHistorySize = Math.min(requestedMaxSize, ABSOLUTE_MAX_HISTORY_SIZE);\n\t\tif (requestedMaxSize > ABSOLUTE_MAX_HISTORY_SIZE) {\n\t\t\tthis._logger.warn('maxHistorySize exceeds absolute maximum, capped', {\n\t\t\t\trequested: requestedMaxSize,\n\t\t\t\tapplied: ABSOLUTE_MAX_HISTORY_SIZE,\n\t\t\t});\n\t\t}\n\t\tthis._maxBranches = config.maxBranches || 50;\n\t\tthis._maxBranchSize = config.maxBranchSize || 100;\n\t\tthis._persistence = config.persistence ?? null;\n\t\tthis._persistenceEnabled = this._persistence !== null;\n\t\tthis._metrics = config.metrics;\n\t\tthis._eventEmitter = config.eventEmitter ?? null;\n\t\tthis._edgeStore = config.edgeStore;\n\t\tthis._summaryStore = config.summaryStore;\n\t\tthis._dagEdges = config.dagEdges ?? true;\n\n\t\t// Wire delegates\n\t\tthis._edgeEmitter = new EdgeEmitter({\n\t\t\tedgeStore: this._edgeStore,\n\t\t\tdagEdges: this._dagEdges,\n\t\t\tdefaultSessionId: HistoryManager.DEFAULT_SESSION,\n\t\t\tlogger: this._logger,\n\t\t});\n\n\t\tthis._sessionManager = new SessionManager<SessionState>({\n\t\t\tdefaultSessionId: HistoryManager.DEFAULT_SESSION,\n\t\t\tsessionTtlMs: HistoryManager.SESSION_TTL_MS,\n\t\t\tcleanupIntervalMs: 5 * 60 * 1000,\n\t\t\tgetMaxSessions: () => HistoryManager.MAX_SESSIONS,\n\t\t\tmaxSessionsPerOwner: config.maxSessionsPerOwner ?? 50,\n\t\t\tlogger: this._logger,\n\t\t});\n\n\t\tthis._persistenceBuffer = null;\n\t\tif (this._persistenceEnabled && this._persistence) {\n\t\t\tthis._persistenceBuffer = new PersistenceBuffer<SessionState>({\n\t\t\t\tpersistence: this._persistence,\n\t\t\t\tbufferSize: config.persistenceBufferSize ?? 100,\n\t\t\t\tflushInterval: config.persistenceFlushInterval ?? 1000,\n\t\t\t\tmaxRetries: config.persistenceMaxRetries ?? 3,\n\t\t\t\tdefaultSessionId: HistoryManager.DEFAULT_SESSION,\n\t\t\t\tgetSessions: () => this._sessions,\n\t\t\t\tgetDefaultSession: () => this._getSession(),\n\t\t\t\tedgeStore: this._edgeStore,\n\t\t\t\teventEmitter: this._eventEmitter,\n\t\t\t\tlogger: this._logger,\n\t\t\t});\n\t\t\tthis._startFlushTimer();\n\t\t}\n\n\t\tthis._sessionManager.startCleanupTimer(this._sessions);\n\t}\n\n\t// Test-coupled accessors: these private member names must remain reachable\n\t// via `manager as unknown as { _flushTimer; _startFlushTimer }`.\n\tprivate get _flushTimer(): ReturnType<typeof setInterval> | null {\n\t\treturn this._persistenceBuffer?.timer ?? null;\n\t}\n\n\tprivate _startFlushTimer(): void {\n\t\tthis._persistenceBuffer?.startFlushTimer();\n\t}\n\n\tprivate _stopFlushTimer(): void {\n\t\tif (this._flushTimer === null) return;\n\t\tthis._persistenceBuffer?.stopFlushTimer();\n\t}\n\n\t/** @internal Public for backward-compatible test coupling. */\n\tpublic async _flushBuffer(): Promise<void> {\n\t\tawait this._persistenceBuffer?.flush();\n\t}\n\n\t/** EdgeStore instance, if configured. Used by ThoughtProcessor for StrategyContext. */\n\tpublic getEdgeStore(): IEdgeStore | undefined {\n\t\treturn this._edgeStore;\n\t}\n\n\tprivate log(message: string, meta?: Record<string, unknown>): void {\n\t\tthis._logger.info(message, meta);\n\t}\n\n\t/** Reads owner from RequestContext (AsyncLocalStorage). Stdio path returns undefined. */\n\tprivate _getCurrentOwner(): string | undefined {\n\t\treturn getOwner();\n\t}\n\n\t/**\n\t * Gets or creates session state; updates lastAccessedAt.\n\t *\n\t * Ownership semantics:\n\t * - `owner === undefined` (stdio path): never rejects, never sets owner.\n\t * - `owner !== undefined`: if session has a different owner, throws\n\t * `SessionAccessDeniedError`. If session was created without an owner\n\t * (e.g. by stdio), the owner is set on first owner-aware access.\n\t */\n\tprivate _getSession(sessionId?: string, owner?: string): SessionState {\n\t\tconst key = sessionId ?? HistoryManager.DEFAULT_SESSION;\n\t\tlet session = this._sessions.get(key);\n\t\tif (!session) {\n\t\t\tsession = {\n\t\t\t\tthought_history: [],\n\t\t\t\tbranches: {},\n\t\t\t\tavailableMcpTools: undefined,\n\t\t\t\tavailableSkills: undefined,\n\t\t\t\twriteBuffer: [],\n\t\t\t\tlastAccessedAt: Date.now(),\n\t\t\t\tregisteredBranches: new Set<string>(),\n\t\t\t\towner,\n\t\t\t};\n\t\t\tthis._sessions.set(key, session);\n\t\t\tthis._sessionManager.evictExcessSessions(this._sessions);\n\t\t} else if (owner !== undefined) {\n\t\t\tif (session.owner !== undefined && session.owner !== owner) {\n\t\t\t\tthrow new SessionAccessDeniedError(key, session.owner, owner);\n\t\t\t}\n\t\t\tif (session.owner === undefined) {\n\t\t\t\t// First owner-aware access: bind owner. Acceptable promotion path\n\t\t\t\t// for sessions created by stdio that later receive an owner-bearing\n\t\t\t\t// access (single-user transition).\n\t\t\t\tsession.owner = owner;\n\t\t\t}\n\t\t}\n\t\tsession.lastAccessedAt = Date.now();\n\t\treturn session;\n\t}\n\n\t/**\n\t * Adds a thought to the history. Routes per-session, applies retraction for backtrack,\n\t * caches tools/skills, trims, branches, emits DAG edges, and buffers for persistence.\n\t */\n\tpublic addThought(thought: ThoughtData): void {\n\t\tconst session = this._getSession(thought.session_id, this._getCurrentOwner());\n\t\tthis._metrics?.counter(\n\t\t\t'thought_requests_total',\n\t\t\t1,\n\t\t\t{},\n\t\t\t'Total thought requests added to history'\n\t\t);\n\n\t\tsession.thought_history.push(thought);\n\n\t\t// Logical retraction: when a backtrack thought is added, mark its target\n\t\t// as retracted (append-only — target remains in history).\n\t\tif (thought.thought_type === 'backtrack' && thought.backtrack_target !== undefined) {\n\t\t\tthis._applyRetraction(session, thought.backtrack_target);\n\t\t}\n\n\t\t// Cache available_mcp_tools/available_skills for cross-call persistence\n\t\tif (thought.available_mcp_tools) {\n\t\t\tsession.availableMcpTools = thought.available_mcp_tools;\n\t\t}\n\t\tif (thought.available_skills) {\n\t\t\tsession.availableSkills = thought.available_skills;\n\t\t}\n\n\t\tif (session.thought_history.length > this._maxHistorySize) {\n\t\t\tsession.thought_history = session.thought_history.slice(-this._maxHistorySize);\n\t\t\tthis.log(`History trimmed to ${this._maxHistorySize} items`, {\n\t\t\t\tmaxSize: this._maxHistorySize,\n\t\t\t});\n\t\t}\n\n\t\tif (thought.branch_from_thought && thought.branch_id) {\n\t\t\tthis._addToSessionBranch(session, thought.branch_id, thought);\n\t\t}\n\n\t\t// Track merge operations for analytics\n\t\tif (thought.merge_from_thoughts?.length || thought.merge_branch_ids?.length) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'thought_merge_operations_total',\n\t\t\t\t1,\n\t\t\t\t{},\n\t\t\t\t'Total merge operations (graph topology)'\n\t\t\t);\n\t\t}\n\n\t\t// Emit DAG edges (no-op unless edgeStore + dagEdges flag both enabled)\n\t\tthis._edgeEmitter.emitEdgesForThought(session, thought);\n\n\t\t// Buffer thought for persistence (no-op when persistence disabled)\n\t\tif (this._persistenceBuffer) {\n\t\t\tthis._persistenceBuffer.bufferThought(session, thought);\n\t\t}\n\t}\n\n\t/** Marks the thought as retracted within the session (append-only). */\n\tprivate _applyRetraction(session: SessionState, targetNumber: number): void {\n\t\tfor (const t of session.thought_history) {\n\t\t\tif (t.thought_number === targetNumber) {\n\t\t\t\tt.retracted = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tfor (const branchThoughts of Object.values(session.branches)) {\n\t\t\tfor (const t of branchThoughts) {\n\t\t\t\tif (t.thought_number === targetNumber) {\n\t\t\t\t\tt.retracted = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _addToSessionBranch(session: SessionState, branchId: string, thought: ThoughtData): void {\n\t\tif (!session.branches[branchId]) {\n\t\t\tsession.branches[branchId] = [];\n\t\t}\n\t\tthis._trimSessionBranchSize(session, branchId);\n\t\tsession.branches[branchId].push(thought);\n\n\t\tif (Object.keys(session.branches).length > this._maxBranches) {\n\t\t\tthis._cleanupSessionBranches(session);\n\t\t}\n\n\t\t// Persist branch to backend if enabled\n\t\tif (this._persistenceEnabled && this._persistence) {\n\t\t\tthis._persistence.saveBranch(branchId, session.branches[branchId]).catch((err) => {\n\t\t\t\tthis.log('Failed to persist branch', {\n\t\t\t\t\tbranchId,\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate _cleanupSessionBranches(session: SessionState): void {\n\t\tconst branchCount = Object.keys(session.branches).length;\n\t\tif (branchCount > this._maxBranches) {\n\t\t\tconst branchesToRemove = Object.keys(session.branches).slice(\n\t\t\t\t0,\n\t\t\t\tbranchCount - this._maxBranches\n\t\t\t);\n\t\t\tfor (const branchId of branchesToRemove) {\n\t\t\t\tdelete session.branches[branchId];\n\t\t\t\tthis.log(`Removed old branch: ${branchId}`, { branchId });\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _trimSessionBranchSize(session: SessionState, branchId: string): void {\n\t\tif ((session.branches[branchId] ?? []).length > this._maxBranchSize) {\n\t\t\tconst removed = session.branches[branchId]!.length - this._maxBranchSize;\n\t\t\tsession.branches[branchId] = session.branches[branchId]!.slice(-this._maxBranchSize);\n\t\t\tthis.log(`Trimmed branch '${branchId}': removed ${removed} old thoughts`, {\n\t\t\t\tbranchId,\n\t\t\t\tremoved,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic getHistory(sessionId?: string): ThoughtData[] {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).thought_history;\n\t}\n\n\t/**\n\t * Returns history with optional sliding-window dehydration. Non-mutating: when\n\t * `dagEdges` is off OR no `ISummaryStore` is configured, returns same as getHistory.\n\t */\n\tpublic getHistoryHydrated(\n\t\tsessionId?: string,\n\t\topts?: DehydrationOptions\n\t): HydratedEntry[] {\n\t\tconst history = this.getHistory(sessionId);\n\t\tif (!this._dagEdges || !this._summaryStore) {\n\t\t\treturn history.slice();\n\t\t}\n\t\tconst sid = sessionId ?? HistoryManager.DEFAULT_SESSION;\n\t\tconst policy = new DehydrationPolicy(this._summaryStore);\n\t\treturn policy.apply(history, sid, opts);\n\t}\n\n\tpublic getHistoryLength(sessionId?: string): number {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).thought_history.length;\n\t}\n\n\tpublic getBranches(sessionId?: string): Record<string, ThoughtData[]> {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).branches;\n\t}\n\n\tpublic getBranchIds(sessionId?: string): string[] {\n\t\tconst session = this._getSession(sessionId, this._getCurrentOwner());\n\t\tconst ids = new Set<string>(Object.keys(session.branches));\n\t\tfor (const id of session.registeredBranches) ids.add(id);\n\t\treturn Array.from(ids);\n\t}\n\n\t/** @throws {ValidationError} If branchId is empty or already exists. */\n\tpublic registerBranch(sessionId: string | undefined, branchId: string): void {\n\t\tif (typeof branchId !== 'string' || branchId.length === 0) {\n\t\t\tthrow new ValidationError('branch_id', 'branch_id must be a non-empty string');\n\t\t}\n\t\tconst session = this._getSession(sessionId, this._getCurrentOwner());\n\t\tif (branchId in session.branches || session.registeredBranches.has(branchId)) {\n\t\t\tthrow new ValidationError('branch_id', `Branch already exists: ${branchId}`);\n\t\t}\n\t\tsession.registeredBranches.add(branchId);\n\t\tthis.log('Registered branch', { branchId, sessionId: sessionId ?? null });\n\t}\n\n\tpublic branchExists(sessionId: string | undefined, branchId: string): boolean {\n\t\tconst session = this._getSession(sessionId, this._getCurrentOwner());\n\t\treturn branchId in session.branches || session.registeredBranches.has(branchId);\n\t}\n\n\tpublic getAvailableMcpTools(sessionId?: string): string[] | undefined {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).availableMcpTools;\n\t}\n\n\tpublic getAvailableSkills(sessionId?: string): string[] | undefined {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).availableSkills;\n\t}\n\n\tpublic getBranch(branchId: string, sessionId?: string): ThoughtData[] | undefined {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).branches[branchId];\n\t}\n\n\t/** Clears history and branches. If sessionId provided, clears only that session. */\n\tpublic clear(sessionId?: string): void {\n\t\t// Clear edges from EdgeStore (before session map mutation so keys are still available)\n\t\tif (this._edgeStore) {\n\t\t\tif (sessionId !== undefined) {\n\t\t\t\tthis._edgeStore.clearSession(sessionId);\n\t\t\t} else {\n\t\t\t\tfor (const sid of this._sessions.keys()) {\n\t\t\t\t\tthis._edgeStore.clearSession(sid);\n\t\t\t\t}\n\t\t\t\t// Also clear the default session in case no session entries exist yet\n\t\t\t\tthis._edgeStore.clearSession(HistoryManager.DEFAULT_SESSION);\n\t\t\t}\n\t\t}\n\n\t\tif (sessionId !== undefined) {\n\t\t\tthis._sessions.delete(sessionId);\n\t\t\tthis.log('Session cleared', { sessionId });\n\t\t} else {\n\t\t\tthis._sessions.clear();\n\t\t\tthis.log('History cleared (all sessions)');\n\t\t}\n\n\t\t// Clear persisted data if enabled\n\t\tif (this._persistenceEnabled && this._persistence) {\n\t\t\tthis._persistence.clear().catch((err) => {\n\t\t\t\tthis.log('Failed to clear persisted data', {\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic clearSession(sessionId: string): void {\n\t\tthis.clear(sessionId);\n\t}\n\n\tpublic getSessionIds(): string[] {\n\t\treturn Array.from(this._sessions.keys());\n\t}\n\n\tpublic getSessionCount(): number {\n\t\treturn this._sessions.size;\n\t}\n\n\t/** Loads history from persistence into the global session. Call at init. */\n\tpublic async loadFromPersistence(): Promise<void> {\n\t\tif (!this._persistenceEnabled || !this._persistence) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst isHealthy = await this._persistence.healthy();\n\t\t\tif (!isHealthy) {\n\t\t\t\tthis.log('Persistence backend not healthy, skipping load');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst globalSession = this._getSession();\n\n\t\t\tconst history = await this._persistence.loadHistory();\n\t\t\tif (history.length > 0) {\n\t\t\t\tglobalSession.thought_history = history.slice(-this._maxHistorySize);\n\t\t\t\tthis.log(`Loaded ${globalSession.thought_history.length} thoughts from persistence`);\n\t\t\t}\n\n\t\t\tconst branchIds = await this._persistence.listBranches();\n\t\t\tfor (const branchId of branchIds) {\n\t\t\t\tconst branchData = await this._persistence.loadBranch(branchId);\n\t\t\t\tif (branchData) {\n\t\t\t\t\tglobalSession.branches[branchId] = branchData.slice(-this._maxBranchSize);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.log(`Loaded ${Object.keys(globalSession.branches).length} branches from persistence`);\n\n\t\t\t// Load edges if EdgeStore is configured — restore for ALL persisted sessions\n\t\t\tif (this._edgeStore) {\n\t\t\t\ttry {\n\t\t\t\t\tconst edgeSessions = await this._persistence.listEdgeSessions();\n\t\t\t\t\tlet totalEdges = 0;\n\t\t\t\t\tfor (const sessionId of edgeSessions) {\n\t\t\t\t\t\tconst edges = await this._persistence.loadEdges(sessionId);\n\t\t\t\t\t\tfor (const edge of edges) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tthis._edgeStore.addEdge(edge);\n\t\t\t\t\t\t\t\ttotalEdges++;\n\t\t\t\t\t\t\t} catch (edgeErr) {\n\t\t\t\t\t\t\t\tthis.log('Failed to restore edge', {\n\t\t\t\t\t\t\t\t\tedgeId: edge.id,\n\t\t\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\t\t\terror: getErrorMessage(edgeErr),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.log(\n\t\t\t\t\t\t`Loaded ${totalEdges} edges across ${edgeSessions.length} sessions from persistence`,\n\t\t\t\t\t);\n\t\t\t\t} catch (edgeError) {\n\t\t\t\t\tthis.log('Failed to load edges from persistence', {\n\t\t\t\t\t\terror: getErrorMessage(edgeError),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log('Failed to load from persistence', {\n\t\t\t\terror: getErrorMessage(error),\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic isPersistenceEnabled(): boolean {\n\t\treturn this._persistenceEnabled;\n\t}\n\n\tpublic getPersistenceBackend(): PersistenceBackend | null {\n\t\treturn this._persistence;\n\t}\n\n\t/** Sets the event emitter for persistence error events (post-construction wiring). */\n\tpublic setEventEmitter(emitter: PersistenceEventEmitter): void {\n\t\tthis._eventEmitter = emitter;\n\t\tthis._persistenceBuffer?.setEventEmitter(emitter);\n\t}\n\n\t/** Stops timers and flushes any remaining buffered writes. */\n\tpublic async shutdown(): Promise<void> {\n\t\tthis._stopFlushTimer();\n\t\tthis._sessionManager.stopCleanupTimer();\n\t\tawait this._flushBuffer();\n\t}\n\n\t/** Total write buffer length across all sessions. */\n\tpublic getWriteBufferLength(): number {\n\t\tlet total = 0;\n\t\tfor (const session of this._sessions.values()) {\n\t\t\ttotal += session.writeBuffer.length;\n\t\t}\n\t\treturn total;\n\t}\n}\n"],"names":["ABSOLUTE_MAX_HISTORY_SIZE","HistoryManager","Map","config","NullLogger","requestedMaxSize","Math","EdgeEmitter","SessionManager","PersistenceBuffer","message","meta","getOwner","sessionId","owner","key","session","undefined","SessionAccessDeniedError","Date","Set","thought","targetNumber","t","branchThoughts","Object","branchId","err","getErrorMessage","branchCount","branchesToRemove","removed","opts","history","sid","policy","DehydrationPolicy","ids","id","Array","ValidationError","isHealthy","globalSession","branchIds","branchData","edgeSessions","totalEdges","edges","edge","edgeErr","edgeError","error","emitter","total"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core/HistoryManager.js","sources":["../../src/core/HistoryManager.ts"],"sourcesContent":["/**\n * History and branch management for sequential thinking.\n *\n * This module provides the `HistoryManager` class which manages thought history,\n * branching, and optional persistence with per-session state isolation.\n *\n * Internally delegates to three focused collaborators:\n * - `EdgeEmitter` — DAG edge emission\n * - `PersistenceBuffer` — buffered persistence + retry/backoff\n * - `SessionManager` — session lifecycle (TTL/LRU eviction)\n *\n * @module HistoryManager\n */\n\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport type { IEdgeStore } from '../contracts/interfaces.js';\nimport { asSessionId, type BranchId } from '../contracts/ids.js';\nimport type { ISummaryStore } from '../contracts/summary.js';\nimport { ValidationError, SessionAccessDeniedError, getErrorMessage } from '../errors.js';\nimport { NullLogger } from '../logger/NullLogger.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\nimport type { PersistenceBackend } from '../contracts/PersistenceBackend.js';\nimport {\n\tDehydrationPolicy,\n\ttype DehydrationOptions,\n\ttype HydratedEntry,\n} from './compression/DehydrationPolicy.js';\nimport { EdgeEmitter } from './graph/EdgeEmitter.js';\nimport type { IHistoryManager } from './IHistoryManager.js';\nimport { PersistenceBuffer, type PersistenceEventEmitter } from './PersistenceBuffer.js';\nimport { SessionManager } from './SessionManager.js';\nimport type { ThoughtData } from './thought.js';\nimport { getOwner } from '../context/RequestContext.js';\n\n\n/** Absolute maximum history size (~20MB at 2KB/thought). Cannot be overridden. */\nexport const ABSOLUTE_MAX_HISTORY_SIZE = 10_000;\n\ninterface SessionState {\n\tthought_history: ThoughtData[];\n\tbranches: Record<string, ThoughtData[]>;\n\tavailableMcpTools: string[] | undefined;\n\tavailableSkills: string[] | undefined;\n\twriteBuffer: ThoughtData[];\n\tlastAccessedAt: number;\n\tregisteredBranches: Set<BranchId>;\n\t/** Owner identifier set on first owner-aware access. Immutable thereafter. */\n\towner?: string;\n}\n\nexport interface HistoryManagerConfig {\n\t/** Maximum number of thoughts to keep in main history. @default 1000 */\n\tmaxHistorySize?: number;\n\t/** Maximum number of branches to maintain. @default 50 */\n\tmaxBranches?: number;\n\t/** Maximum size of each branch. @default 100 */\n\tmaxBranchSize?: number;\n\tlogger?: Logger;\n\tpersistence?: PersistenceBackend | null;\n\tmetrics?: IMetrics;\n\t/** Maximum number of thoughts to buffer before flushing. @default 100 */\n\tpersistenceBufferSize?: number;\n\t/** Periodic flush interval in ms. @default 1000 */\n\tpersistenceFlushInterval?: number;\n\t/** Max retries for failed persistence flushes. @default 3 */\n\tpersistenceMaxRetries?: number;\n\teventEmitter?: PersistenceEventEmitter;\n\tedgeStore?: IEdgeStore;\n\tsummaryStore?: ISummaryStore;\n\t/** Whether to emit DAG edges (gated independently of edgeStore). @default false */\n\tdagEdges?: boolean;\n\t/** Maximum sessions per owner (per-owner LRU bucket). @default 50 */\n\tmaxSessionsPerOwner?: number;\n}\n\n/**\n * Manages thought history and branching for sequential thinking.\n *\n * Owns the per-session `Map<string, SessionState>`. Delegates DAG edge emission,\n * buffered persistence, and session TTL/LRU eviction to focused collaborators while\n * preserving test-coupled private member names (`_flushTimer`, `_startFlushTimer`,\n * `_flushBuffer`, `_sessions`).\n */\nexport class HistoryManager implements IHistoryManager {\n\tprivate static readonly DEFAULT_SESSION = '__global__';\n\tprivate static readonly SESSION_TTL_MS = 30 * 60 * 1000;\n\tprivate static readonly MAX_SESSIONS = 100;\n\tprivate _sessions: Map<string, SessionState> = new Map();\n\tprivate _maxHistorySize: number;\n\tprivate _maxBranches: number;\n\tprivate _maxBranchSize: number;\n\tprivate _logger: Logger;\n\tprivate _persistence: PersistenceBackend | null;\n\tprivate _persistenceEnabled: boolean;\n\tprivate _metrics?: IMetrics;\n\n\tprivate _edgeStore?: IEdgeStore;\n\tprivate _summaryStore?: ISummaryStore;\n\tprivate _dagEdges: boolean;\n\n\tprivate _eventEmitter: PersistenceEventEmitter | null;\n\n\tprivate readonly _edgeEmitter: EdgeEmitter;\n\tprivate _persistenceBuffer: PersistenceBuffer<SessionState> | null;\n\tprivate readonly _sessionManager: SessionManager<SessionState>;\n\n\tconstructor(config: HistoryManagerConfig = {}) {\n\t\tthis._logger = config.logger ?? new NullLogger();\n\t\tconst requestedMaxSize = config.maxHistorySize ?? 10000;\n\t\tthis._maxHistorySize = Math.min(requestedMaxSize, ABSOLUTE_MAX_HISTORY_SIZE);\n\t\tif (requestedMaxSize > ABSOLUTE_MAX_HISTORY_SIZE) {\n\t\t\tthis._logger.warn('maxHistorySize exceeds absolute maximum, capped', {\n\t\t\t\trequested: requestedMaxSize,\n\t\t\t\tapplied: ABSOLUTE_MAX_HISTORY_SIZE,\n\t\t\t});\n\t\t}\n\t\tthis._maxBranches = config.maxBranches || 50;\n\t\tthis._maxBranchSize = config.maxBranchSize || 100;\n\t\tthis._persistence = config.persistence ?? null;\n\t\tthis._persistenceEnabled = this._persistence !== null;\n\t\tthis._metrics = config.metrics;\n\t\tthis._eventEmitter = config.eventEmitter ?? null;\n\t\tthis._edgeStore = config.edgeStore;\n\t\tthis._summaryStore = config.summaryStore;\n\t\tthis._dagEdges = config.dagEdges ?? true;\n\n\t\t// Wire delegates\n\t\tthis._edgeEmitter = new EdgeEmitter({\n\t\t\tedgeStore: this._edgeStore,\n\t\t\tdagEdges: this._dagEdges,\n\t\t\tdefaultSessionId: HistoryManager.DEFAULT_SESSION,\n\t\t\tlogger: this._logger,\n\t\t});\n\n\t\tthis._sessionManager = new SessionManager<SessionState>({\n\t\t\tdefaultSessionId: HistoryManager.DEFAULT_SESSION,\n\t\t\tsessionTtlMs: HistoryManager.SESSION_TTL_MS,\n\t\t\tcleanupIntervalMs: 5 * 60 * 1000,\n\t\t\tgetMaxSessions: () => HistoryManager.MAX_SESSIONS,\n\t\t\tmaxSessionsPerOwner: config.maxSessionsPerOwner ?? 50,\n\t\t\tlogger: this._logger,\n\t\t});\n\n\t\tthis._persistenceBuffer = null;\n\t\tif (this._persistenceEnabled && this._persistence) {\n\t\t\tthis._persistenceBuffer = new PersistenceBuffer<SessionState>({\n\t\t\t\tpersistence: this._persistence,\n\t\t\t\tbufferSize: config.persistenceBufferSize ?? 100,\n\t\t\t\tflushInterval: config.persistenceFlushInterval ?? 1000,\n\t\t\t\tmaxRetries: config.persistenceMaxRetries ?? 3,\n\t\t\t\tdefaultSessionId: HistoryManager.DEFAULT_SESSION,\n\t\t\t\tgetSessions: () => this._sessions,\n\t\t\t\tgetDefaultSession: () => this._getSession(),\n\t\t\t\tedgeStore: this._edgeStore,\n\t\t\t\teventEmitter: this._eventEmitter,\n\t\t\t\tlogger: this._logger,\n\t\t\t});\n\t\t\tthis._startFlushTimer();\n\t\t}\n\n\t\tthis._sessionManager.startCleanupTimer(this._sessions);\n\t}\n\n\t// Test-coupled accessors: these private member names must remain reachable\n\t// via `manager as unknown as { _flushTimer; _startFlushTimer }`.\n\tprivate get _flushTimer(): ReturnType<typeof setInterval> | null {\n\t\treturn this._persistenceBuffer?.timer ?? null;\n\t}\n\n\tprivate _startFlushTimer(): void {\n\t\tthis._persistenceBuffer?.startFlushTimer();\n\t}\n\n\tprivate _stopFlushTimer(): void {\n\t\tif (this._flushTimer === null) return;\n\t\tthis._persistenceBuffer?.stopFlushTimer();\n\t}\n\n\t/** @internal Public for backward-compatible test coupling. */\n\tpublic async _flushBuffer(): Promise<void> {\n\t\tawait this._persistenceBuffer?.flush();\n\t}\n\n\t/** EdgeStore instance, if configured. Used by ThoughtProcessor for StrategyContext. */\n\tpublic getEdgeStore(): IEdgeStore | undefined {\n\t\treturn this._edgeStore;\n\t}\n\n\tprivate log(message: string, meta?: Record<string, unknown>): void {\n\t\tthis._logger.info(message, meta);\n\t}\n\n\t/** Reads owner from RequestContext (AsyncLocalStorage). Stdio path returns undefined. */\n\tprivate _getCurrentOwner(): string | undefined {\n\t\treturn getOwner();\n\t}\n\n\t/**\n\t * Gets or creates session state; updates lastAccessedAt.\n\t *\n\t * Ownership semantics:\n\t * - `owner === undefined` (stdio path): never rejects, never sets owner.\n\t * - `owner !== undefined`: if session has a different owner, throws\n\t * `SessionAccessDeniedError`. If session was created without an owner\n\t * (e.g. by stdio), the owner is set on first owner-aware access.\n\t */\n\tprivate _getSession(sessionId?: string, owner?: string): SessionState {\n\t\tconst key = sessionId ?? HistoryManager.DEFAULT_SESSION;\n\t\tlet session = this._sessions.get(key);\n\t\tif (!session) {\n\t\t\tsession = {\n\t\t\t\tthought_history: [],\n\t\t\t\tbranches: {},\n\t\t\t\tavailableMcpTools: undefined,\n\t\t\t\tavailableSkills: undefined,\n\t\t\t\twriteBuffer: [],\n\t\t\t\tlastAccessedAt: Date.now(),\n\t\t\t\tregisteredBranches: new Set<BranchId>(),\n\t\t\t\towner,\n\t\t\t};\n\t\t\tthis._sessions.set(key, session);\n\t\t\tthis._sessionManager.evictExcessSessions(this._sessions);\n\t\t} else if (owner !== undefined) {\n\t\t\tif (session.owner !== undefined && session.owner !== owner) {\n\t\t\t\tthrow new SessionAccessDeniedError(key, session.owner, owner);\n\t\t\t}\n\t\t\tif (session.owner === undefined) {\n\t\t\t\t// First owner-aware access: bind owner. Acceptable promotion path\n\t\t\t\t// for sessions created by stdio that later receive an owner-bearing\n\t\t\t\t// access (single-user transition).\n\t\t\t\tsession.owner = owner;\n\t\t\t}\n\t\t}\n\t\tsession.lastAccessedAt = Date.now();\n\t\treturn session;\n\t}\n\n\t/**\n\t * Adds a thought to the history. Routes per-session, applies retraction for backtrack,\n\t * caches tools/skills, trims, branches, emits DAG edges, and buffers for persistence.\n\t */\n\tpublic addThought(thought: ThoughtData): void {\n\t\tconst session = this._getSession(thought.session_id, this._getCurrentOwner());\n\t\tthis._metrics?.counter(\n\t\t\t'thought_requests_total',\n\t\t\t1,\n\t\t\t{},\n\t\t\t'Total thought requests added to history'\n\t\t);\n\n\t\tsession.thought_history.push(thought);\n\n\t\t// Logical retraction: when a backtrack thought is added, mark its target\n\t\t// as retracted (append-only — target remains in history).\n\t\tif (thought.thought_type === 'backtrack' && thought.backtrack_target !== undefined) {\n\t\t\tthis._applyRetraction(session, thought.backtrack_target);\n\t\t}\n\n\t\t// Cache available_mcp_tools/available_skills for cross-call persistence\n\t\tif (thought.available_mcp_tools) {\n\t\t\tsession.availableMcpTools = thought.available_mcp_tools;\n\t\t}\n\t\tif (thought.available_skills) {\n\t\t\tsession.availableSkills = thought.available_skills;\n\t\t}\n\n\t\tif (session.thought_history.length > this._maxHistorySize) {\n\t\t\tsession.thought_history = session.thought_history.slice(-this._maxHistorySize);\n\t\t\tthis.log(`History trimmed to ${this._maxHistorySize} items`, {\n\t\t\t\tmaxSize: this._maxHistorySize,\n\t\t\t});\n\t\t}\n\n\t\tif (thought.branch_from_thought && thought.branch_id) {\n\t\t\tthis._addToSessionBranch(session, thought.branch_id, thought);\n\t\t}\n\n\t\t// Track merge operations for analytics\n\t\tif (thought.merge_from_thoughts?.length || thought.merge_branch_ids?.length) {\n\t\t\tthis._metrics?.counter(\n\t\t\t\t'thought_merge_operations_total',\n\t\t\t\t1,\n\t\t\t\t{},\n\t\t\t\t'Total merge operations (graph topology)'\n\t\t\t);\n\t\t}\n\n\t\t// Emit DAG edges (no-op unless edgeStore + dagEdges flag both enabled)\n\t\tthis._edgeEmitter.emitEdgesForThought(session, thought);\n\n\t\t// Buffer thought for persistence (no-op when persistence disabled)\n\t\tif (this._persistenceBuffer) {\n\t\t\tthis._persistenceBuffer.bufferThought(session, thought);\n\t\t}\n\t}\n\n\t/** Marks the thought as retracted within the session (append-only). */\n\tprivate _applyRetraction(session: SessionState, targetNumber: number): void {\n\t\tfor (const t of session.thought_history) {\n\t\t\tif (t.thought_number === targetNumber) {\n\t\t\t\tt.retracted = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tfor (const branchThoughts of Object.values(session.branches)) {\n\t\t\tfor (const t of branchThoughts) {\n\t\t\t\tif (t.thought_number === targetNumber) {\n\t\t\t\t\tt.retracted = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _addToSessionBranch(session: SessionState, branchId: BranchId, thought: ThoughtData): void {\n\t\tif (!session.branches[branchId]) {\n\t\t\tsession.branches[branchId] = [];\n\t\t}\n\t\tthis._trimSessionBranchSize(session, branchId);\n\t\tsession.branches[branchId].push(thought);\n\n\t\tif (Object.keys(session.branches).length > this._maxBranches) {\n\t\t\tthis._cleanupSessionBranches(session);\n\t\t}\n\n\t\t// Persist branch to backend if enabled\n\t\tif (this._persistenceEnabled && this._persistence) {\n\t\t\tthis._persistence.saveBranch(branchId, session.branches[branchId]).catch((err) => {\n\t\t\t\tthis.log('Failed to persist branch', {\n\t\t\t\t\tbranchId,\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate _cleanupSessionBranches(session: SessionState): void {\n\t\tconst branchCount = (Object.keys(session.branches) as BranchId[]).length;\n\t\tif (branchCount > this._maxBranches) {\n\t\t\tconst branchesToRemove = (Object.keys(session.branches) as BranchId[]).slice(\n\t\t\t\t0,\n\t\t\t\tbranchCount - this._maxBranches\n\t\t\t);\n\t\t\tfor (const branchId of branchesToRemove) {\n\t\t\t\tdelete session.branches[branchId];\n\t\t\t\tthis.log(`Removed old branch: ${branchId}`, { branchId });\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _trimSessionBranchSize(session: SessionState, branchId: BranchId): void {\n\t\tif ((session.branches[branchId] ?? []).length > this._maxBranchSize) {\n\t\t\tconst removed = session.branches[branchId]!.length - this._maxBranchSize;\n\t\t\tsession.branches[branchId] = session.branches[branchId]!.slice(-this._maxBranchSize);\n\t\t\tthis.log(`Trimmed branch '${branchId}': removed ${removed} old thoughts`, {\n\t\t\t\tbranchId,\n\t\t\t\tremoved,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic getHistory(sessionId?: string): ThoughtData[] {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).thought_history;\n\t}\n\n\t/**\n\t * Returns history with optional sliding-window dehydration. Non-mutating: when\n\t * `dagEdges` is off OR no `ISummaryStore` is configured, returns same as getHistory.\n\t */\n\tpublic getHistoryHydrated(\n\t\tsessionId?: string,\n\t\topts?: DehydrationOptions\n\t): HydratedEntry[] {\n\t\tconst history = this.getHistory(sessionId);\n\t\tif (!this._dagEdges || !this._summaryStore) {\n\t\t\treturn history.slice();\n\t\t}\n\t\tconst sid = sessionId ?? HistoryManager.DEFAULT_SESSION;\n\t\tconst policy = new DehydrationPolicy(this._summaryStore);\n\t\treturn policy.apply(history, sid, opts);\n\t}\n\n\tpublic getHistoryLength(sessionId?: string): number {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).thought_history.length;\n\t}\n\n\tpublic getBranches(sessionId?: string): Record<BranchId, ThoughtData[]> {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).branches;\n\t}\n\n\tpublic getBranchIds(sessionId?: string): BranchId[] {\n\t\tconst session = this._getSession(sessionId, this._getCurrentOwner());\n\t\tconst ids = new Set<BranchId>(Object.keys(session.branches) as BranchId[]);\n\t\tfor (const id of session.registeredBranches) ids.add(id);\n\t\treturn Array.from(ids);\n\t}\n\n\t/** @throws {ValidationError} If branchId is empty or already exists. */\n\tpublic registerBranch(sessionId: string | undefined, branchId: BranchId): void {\n\t\tif (typeof branchId !== 'string' || branchId.length === 0) {\n\t\t\tthrow new ValidationError('branch_id', 'branch_id must be a non-empty string');\n\t\t}\n\t\tconst session = this._getSession(sessionId, this._getCurrentOwner());\n\t\tif (branchId in session.branches || session.registeredBranches.has(branchId)) {\n\t\t\tthrow new ValidationError('branch_id', `Branch already exists: ${branchId}`);\n\t\t}\n\t\tsession.registeredBranches.add(branchId);\n\t\tthis.log('Registered branch', { branchId, sessionId: sessionId ?? null });\n\t}\n\n\tpublic branchExists(sessionId: string | undefined, branchId: BranchId): boolean {\n\t\tconst session = this._getSession(sessionId, this._getCurrentOwner());\n\t\treturn branchId in session.branches || session.registeredBranches.has(branchId);\n\t}\n\n\tpublic getAvailableMcpTools(sessionId?: string): string[] | undefined {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).availableMcpTools;\n\t}\n\n\tpublic getAvailableSkills(sessionId?: string): string[] | undefined {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).availableSkills;\n\t}\n\n\tpublic getBranch(branchId: BranchId, sessionId?: string): ThoughtData[] | undefined {\n\t\treturn this._getSession(sessionId, this._getCurrentOwner()).branches[branchId];\n\t}\n\n\t/** Clears history and branches. If sessionId provided, clears only that session. */\n\tpublic clear(sessionId?: string): void {\n\t\t// Enforce ownership before clearing a specific session.\n\t\t// _getSession throws SessionAccessDeniedError on owner mismatch.\n\t\tif (sessionId !== undefined) {\n\t\t\tthis._getSession(sessionId, this._getCurrentOwner());\n\t\t}\n\t\t// Clear edges from EdgeStore (before session map mutation so keys are still available)\n\t\tif (this._edgeStore) {\n\t\t\tif (sessionId !== undefined) {\n\t\t\t\tthis._edgeStore.clearSession(sessionId);\n\t\t\t} else {\n\t\t\t\tfor (const sid of this._sessions.keys()) {\n\t\t\t\t\tthis._edgeStore.clearSession(asSessionId(sid));\n\t\t\t\t}\n\t\t\t\t// Also clear the default session in case no session entries exist yet\n\t\t\t\tthis._edgeStore.clearSession(HistoryManager.DEFAULT_SESSION);\n\t\t\t}\n\t\t}\n\n\t\tif (sessionId !== undefined) {\n\t\t\tthis._sessions.delete(sessionId);\n\t\t\tthis.log('Session cleared', { sessionId });\n\t\t} else {\n\t\t\tthis._sessions.clear();\n\t\t\tthis.log('History cleared (all sessions)');\n\t\t}\n\n\t\t// Clear persisted data if enabled\n\t\tif (this._persistenceEnabled && this._persistence) {\n\t\t\tthis._persistence.clear().catch((err) => {\n\t\t\t\tthis.log('Failed to clear persisted data', {\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic clearSession(sessionId: string): void {\n\t\tthis.clear(sessionId);\n\t}\n\n\tpublic getSessionIds(): string[] {\n\t\treturn Array.from(this._sessions.keys());\n\t}\n\n\tpublic getSessionCount(): number {\n\t\treturn this._sessions.size;\n\t}\n\n\t/** Loads history from persistence into the global session. Call at init. */\n\tpublic async loadFromPersistence(): Promise<void> {\n\t\tif (!this._persistenceEnabled || !this._persistence) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst isHealthy = await this._persistence.healthy();\n\t\t\tif (!isHealthy) {\n\t\t\t\tthis.log('Persistence backend not healthy, skipping load');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst globalSession = this._getSession();\n\n\t\t\tconst history = await this._persistence.loadHistory();\n\t\t\tif (history.length > 0) {\n\t\t\t\tglobalSession.thought_history = history.slice(-this._maxHistorySize);\n\t\t\t\tthis.log(`Loaded ${globalSession.thought_history.length} thoughts from persistence`);\n\t\t\t}\n\n\t\t\tconst branchIds = await this._persistence.listBranches();\n\t\t\tfor (const branchId of branchIds) {\n\t\t\t\tconst branchData = await this._persistence.loadBranch(branchId);\n\t\t\t\tif (branchData) {\n\t\t\t\t\tglobalSession.branches[branchId] = branchData.slice(-this._maxBranchSize);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.log(`Loaded ${Object.keys(globalSession.branches).length} branches from persistence`);\n\n\t\t\t// Load edges if EdgeStore is configured — restore for ALL persisted sessions\n\t\t\tif (this._edgeStore) {\n\t\t\t\ttry {\n\t\t\t\t\tconst edgeSessions = await this._persistence.listEdgeSessions();\n\t\t\t\t\tlet totalEdges = 0;\n\t\t\t\t\tfor (const sessionId of edgeSessions) {\n\t\t\t\t\t\tconst edges = await this._persistence.loadEdges(sessionId);\n\t\t\t\t\t\tfor (const edge of edges) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tthis._edgeStore.addEdge(edge);\n\t\t\t\t\t\t\t\ttotalEdges++;\n\t\t\t\t\t\t\t} catch (edgeErr) {\n\t\t\t\t\t\t\t\tthis.log('Failed to restore edge', {\n\t\t\t\t\t\t\t\t\tedgeId: edge.id,\n\t\t\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\t\t\terror: getErrorMessage(edgeErr),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.log(\n\t\t\t\t\t\t`Loaded ${totalEdges} edges across ${edgeSessions.length} sessions from persistence`,\n\t\t\t\t\t);\n\t\t\t\t} catch (edgeError) {\n\t\t\t\t\tthis.log('Failed to load edges from persistence', {\n\t\t\t\t\t\terror: getErrorMessage(edgeError),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log('Failed to load from persistence', {\n\t\t\t\terror: getErrorMessage(error),\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic isPersistenceEnabled(): boolean {\n\t\treturn this._persistenceEnabled;\n\t}\n\n\tpublic getPersistenceBackend(): PersistenceBackend | null {\n\t\treturn this._persistence;\n\t}\n\n\t/** Sets the event emitter for persistence error events (post-construction wiring). */\n\tpublic setEventEmitter(emitter: PersistenceEventEmitter): void {\n\t\tthis._eventEmitter = emitter;\n\t\tthis._persistenceBuffer?.setEventEmitter(emitter);\n\t}\n\n\t/** Stops timers and flushes any remaining buffered writes. */\n\tpublic async shutdown(): Promise<void> {\n\t\tthis._stopFlushTimer();\n\t\tthis._sessionManager.stopCleanupTimer();\n\t\tawait this._flushBuffer();\n\t}\n\n\t/** Total write buffer length across all sessions. */\n\tpublic getWriteBufferLength(): number {\n\t\tlet total = 0;\n\t\tfor (const session of this._sessions.values()) {\n\t\t\ttotal += session.writeBuffer.length;\n\t\t}\n\t\treturn total;\n\t}\n}\n"],"names":["ABSOLUTE_MAX_HISTORY_SIZE","HistoryManager","Map","config","NullLogger","requestedMaxSize","Math","EdgeEmitter","SessionManager","PersistenceBuffer","message","meta","getOwner","sessionId","owner","key","session","undefined","SessionAccessDeniedError","Date","Set","thought","targetNumber","t","branchThoughts","Object","branchId","err","getErrorMessage","branchCount","branchesToRemove","removed","opts","history","sid","policy","DehydrationPolicy","ids","id","Array","ValidationError","asSessionId","isHealthy","globalSession","branchIds","branchData","edgeSessions","totalEdges","edges","edge","edgeErr","edgeError","error","emitter","total"],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @module IHistoryManager
|
|
8
8
|
*/
|
|
9
9
|
import type { IEdgeStore } from '../contracts/interfaces.js';
|
|
10
|
+
import type { BranchId } from '../contracts/ids.js';
|
|
10
11
|
import type { ThoughtData } from './thought.js';
|
|
11
12
|
/**
|
|
12
13
|
* Interface for history and branch management.
|
|
@@ -67,14 +68,14 @@ export interface IHistoryManager {
|
|
|
67
68
|
* @param sessionId - Optional session ID for session-scoped results
|
|
68
69
|
* @returns A record mapping branch IDs to their thought arrays
|
|
69
70
|
*/
|
|
70
|
-
getBranches(sessionId?: string): Record<
|
|
71
|
+
getBranches(sessionId?: string): Record<BranchId, ThoughtData[]>;
|
|
71
72
|
/**
|
|
72
73
|
* Gets all branch IDs.
|
|
73
74
|
*
|
|
74
75
|
* @param sessionId - Optional session ID for session-scoped results
|
|
75
76
|
* @returns An array of branch identifiers
|
|
76
77
|
*/
|
|
77
|
-
getBranchIds(sessionId?: string):
|
|
78
|
+
getBranchIds(sessionId?: string): BranchId[];
|
|
78
79
|
/**
|
|
79
80
|
* Clears history and branches.
|
|
80
81
|
* If sessionId is provided, clears only that session.
|
|
@@ -105,7 +106,7 @@ export interface IHistoryManager {
|
|
|
105
106
|
* @param branchId - The branch identifier to register
|
|
106
107
|
* @throws ValidationError if branchId is empty or already exists
|
|
107
108
|
*/
|
|
108
|
-
registerBranch(sessionId: string | undefined, branchId:
|
|
109
|
+
registerBranch(sessionId: string | undefined, branchId: BranchId): void;
|
|
109
110
|
/**
|
|
110
111
|
* Checks whether a branch exists (has thoughts OR was pre-declared).
|
|
111
112
|
*
|
|
@@ -113,7 +114,7 @@ export interface IHistoryManager {
|
|
|
113
114
|
* @param branchId - The branch identifier to check
|
|
114
115
|
* @returns true if the branch exists or has been registered
|
|
115
116
|
*/
|
|
116
|
-
branchExists(sessionId: string | undefined, branchId:
|
|
117
|
+
branchExists(sessionId: string | undefined, branchId: BranchId): boolean;
|
|
117
118
|
/**
|
|
118
119
|
* Access the EdgeStore, if configured.
|
|
119
120
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IHistoryManager.d.ts","sourceRoot":"","sources":["../../src/core/IHistoryManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAEvC;;;;;OAKG;IACH,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IAE9C;;;;;OAKG;IACH,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;OAKG;IACH,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"IHistoryManager.d.ts","sourceRoot":"","sources":["../../src/core/IHistoryManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAEvC;;;;;OAKG;IACH,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IAE9C;;;;;OAKG;IACH,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;OAKG;IACH,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;IAEjE;;;;;OAKG;IACH,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAE7C;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;;;;OAKG;IACH,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IAE/D;;;;;OAKG;IACH,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IAE7D;;;;;;;OAOG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAExE;;;;;;OAMG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;IAEzE;;;;;;;OAOG;IACH,YAAY,IAAI,UAAU,GAAG,SAAS,CAAC;CACvC"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* @module processor
|
|
12
12
|
*/
|
|
13
13
|
import type { ThoughtData } from './thought.js';
|
|
14
|
+
import { type BranchId } from '../contracts/ids.js';
|
|
14
15
|
/**
|
|
15
16
|
* Recursively sanitizes all string values within an unknown structure.
|
|
16
17
|
* Walks into plain objects and arrays to reach deeply nested strings.
|
|
@@ -40,7 +41,7 @@ export declare function sanitizeRecursive(value: unknown): unknown;
|
|
|
40
41
|
* sanitizeBranchId('../etc/passwd'); // throws ValidationError
|
|
41
42
|
* ```
|
|
42
43
|
*/
|
|
43
|
-
export declare function sanitizeBranchId(branchId: string):
|
|
44
|
+
export declare function sanitizeBranchId(branchId: string): BranchId;
|
|
44
45
|
/**
|
|
45
46
|
* Sanitizes and validates a session ID.
|
|
46
47
|
*
|