@iworkforces/tracelattice 2.2.0 → 2.2.1

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/README.md CHANGED
@@ -110,7 +110,9 @@ Set `TRACELATTICE_LOG_LEVEL` in the process environment to `debug`, `info`, `war
110
110
  TRACELATTICE_LOG_LEVEL=debug tracelattice
111
111
  ```
112
112
 
113
- Environment variables override values from configuration files.
113
+ Supported environment variables override values from configuration files. The defaults below describe
114
+ `ServerConfig` when no file or environment override is present; `.example.env` contains explicit example
115
+ overrides, not another set of defaults.
114
116
 
115
117
  | Variable | Default | Description |
116
118
  | --------------------------------------- | ------------ | ------------------------------------------- |
@@ -119,14 +121,14 @@ Environment variables override values from configuration files.
119
121
  | `TRACELATTICE_MAX_BRANCHES` | `50` | Maximum number of branches |
120
122
  | `TRACELATTICE_MAX_BRANCH_SIZE` | `100` | Maximum size of each branch |
121
123
  | `TRACELATTICE_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
122
- | `TRACELATTICE_PRETTY_LOG` | `true` | Enable pretty log output |
124
+ | `TRACELATTICE_PRETTY_LOG` | `true` | Only the literal `false` disables pretty logging; other values do not override a file setting |
123
125
  | `TRACELATTICE_SESSION_MAX_PER_OWNER` | `50` | Maximum isolated sessions per owner |
124
126
  | `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` | `60000` | Suspended tool-call token TTL in ms |
125
127
  | `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` | `60000` | Expired suspension cleanup interval in ms |
126
128
 
127
129
  ### Config files
128
130
 
129
- Configuration files are loaded from the first matching path in this order: a custom path passed to `ConfigLoader`, `.claude/config.json`, `.claude/config.yaml`, `.claude/config.yml`, then the same filenames under `~/.claude/`. Environment variables override file values.
131
+ Configuration files are loaded from the first valid path in this order: an explicit `ConfigLoader` path or `TRACELATTICE_CONFIG` replaces the search list; otherwise `.claude/config.json`, `.claude/config.yaml`, `.claude/config.yml`, then the same filenames under `~/.claude/`. An invalid file is logged and the next candidate is tried. With no valid file, the loader applies environment overrides to an empty object; `ServerConfig` supplies defaults. Only supported environment variables override file values. Logging (`logLevel` and `prettyLog`) is read from the loaded file/environment configuration separately from `ServerConfig`.
130
132
 
131
133
  ```yaml
132
134
  maxHistorySize: 10000
@@ -135,8 +137,10 @@ maxBranchSize: 100
135
137
  skillDirs:
136
138
  - .claude/skills
137
139
  - ~/.claude/skills
140
+ - .agents/skills
141
+ - ~/.agents/skills
138
142
  discoveryCache:
139
- ttl: 300000
143
+ ttl: 42000 # example override in milliseconds; default 300000, env TTL is seconds
140
144
  maxSize: 100
141
145
  persistence:
142
146
  enabled: false
@@ -144,6 +148,9 @@ persistence:
144
148
  options:
145
149
  dataDir: ./.tracelattice
146
150
  dbPath: ./.tracelattice/history.db
151
+ persistenceBufferSize: 7 # example file-only override; default 100
152
+ persistenceFlushInterval: 750 # milliseconds, file-only; default 1000
153
+ persistenceMaxRetries: 2 # example file-only override; default 3
147
154
  features:
148
155
  dagEdges: true
149
156
  reasoningStrategy: sequential # sequential or tot
@@ -152,8 +159,8 @@ features:
152
159
  toolInterleave: true
153
160
  newThoughtTypes: true
154
161
  outcomeRecording: true
155
- toolInterleaveTtlMs: 60000
156
- toolInterleaveSweepMs: 60000
162
+ toolInterleaveTtlMs: 45000 # example override in milliseconds; default 60000
163
+ toolInterleaveSweepMs: 55000 # example override in milliseconds; default 60000
157
164
  maxSessionsPerOwner: 50
158
165
  ```
159
166
 
@@ -187,12 +194,24 @@ All feature flags default to enabled in `ServerConfig`. Set a boolean flag to `f
187
194
 
188
195
  | Variable | Default | Description |
189
196
  | --------------------------------------- | -------------------------------------- | ------------------------------------------------------- |
190
- | `TRACELATTICE_SKILL_DIRS` | `.claude/skills:<home>/.claude/skills` | Colon-separated skill directories |
197
+ | `TRACELATTICE_SKILL_DIRS` | `.claude/skills:<home>/.claude/skills:.agents/skills:<home>/.agents/skills` | Colon-separated skill directories |
191
198
  | `TRACELATTICE_TOOL_DIRS` | `.claude/tools:<home>/.claude/tools` | Colon-separated tool directories |
192
199
  | `TRACELATTICE_DISCOVERY_CACHE_TTL` | `300` | Discovery cache TTL in seconds; stored internally as ms |
193
200
  | `TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE` | `100` | Discovery cache max entries |
194
201
  | `TRACELATTICE_WATCHER_VERBOSE` | unset | Log skill watcher events when set to `true` |
195
202
 
203
+ The default skill paths include project-local `.claude/skills` and `.agents/skills` plus both paths
204
+ under the user's home directory. The default tool paths include only `.claude/tools` and its home
205
+ directory counterpart. Setting either root variable replaces its entire default list; `~` in an
206
+ environment value is not expanded by `ConfigLoader`. `TRACELATTICE_DISCOVERY_CACHE_TTL=300` means
207
+ 300 seconds and becomes `discoveryCache.ttl: 300000` milliseconds. The interleave environment
208
+ variables ending in `_MS` and the corresponding YAML fields use milliseconds.
209
+
210
+ `persistenceBufferSize` (default 100 thoughts), `persistenceFlushInterval` (default 1000 ms), and
211
+ `persistenceMaxRetries` (default 3) are YAML/JSON settings, not environment variables. There are no
212
+ `TRACELATTICE_PERSISTENCE_BUFFER_SIZE`, `TRACELATTICE_PERSISTENCE_FLUSH_INTERVAL`, or
213
+ `TRACELATTICE_PERSISTENCE_MAX_RETRIES` overrides.
214
+
196
215
  ## Transports
197
216
 
198
217
  Set `TRACELATTICE_TRANSPORT_TYPE` to pick one:
@@ -28,7 +28,7 @@ import type { FeatureFlags } from './contracts/features.js';
28
28
  export interface ServerConfigOptions {
29
29
  /**
30
30
  * Maximum number of thoughts to keep in history.
31
- * @default 1000
31
+ * @default 10000
32
32
  */
33
33
  maxHistorySize?: number;
34
34
  /**
@@ -43,7 +43,7 @@ export interface ServerConfigOptions {
43
43
  maxBranchSize?: number;
44
44
  /**
45
45
  * Directory paths to search for skills.
46
- * @default ['.claude/skills', '~/.claude/skills', '.agents/skills', '~/.agents/skills']
46
+ * @default Project .claude/skills and .agents/skills, plus both paths under the home directory
47
47
  */
48
48
  skillDirs?: string[];
49
49
  /**
@@ -72,16 +72,19 @@ export interface ServerConfigOptions {
72
72
  persistence?: PersistenceConfig;
73
73
  /**
74
74
  * Maximum number of thoughts to buffer before flushing to persistence.
75
+ * YAML/JSON only; no environment override.
75
76
  * @default 100
76
77
  */
77
78
  persistenceBufferSize?: number;
78
79
  /**
79
80
  * Interval in milliseconds between periodic persistence flushes.
81
+ * YAML/JSON only; no environment override.
80
82
  * @default 1000
81
83
  */
82
84
  persistenceFlushInterval?: number;
83
85
  /**
84
86
  * Maximum number of retries for failed persistence flushes.
87
+ * YAML/JSON only; no environment override.
85
88
  * @default 3
86
89
  */
87
90
  persistenceMaxRetries?: number;
@@ -115,7 +118,8 @@ export interface ServerConfigOptions {
115
118
  *
116
119
  * @remarks
117
120
  * - Values outside recommended ranges trigger warnings but are still applied
118
- * - Environment variables override file-based configuration
121
+ * - Supported environment variables override file-based configuration through ConfigLoader
122
+ * - Logging uses file/environment input separately; ServerConfig does not hold log settings
119
123
  * - The `toJSON()` method provides a plain object representation
120
124
  *
121
125
  * @example
@@ -186,7 +190,7 @@ export declare class ServerConfig {
186
190
  /**
187
191
  * Validates the max history size value.
188
192
  * @param value - The value to validate
189
- * @returns The validated value or default (1000)
193
+ * @returns The validated value or default (10000)
190
194
  * @private
191
195
  */
192
196
  private validateMaxHistorySize;
@@ -207,7 +211,7 @@ export declare class ServerConfig {
207
211
  /**
208
212
  * Validates the skill directories value.
209
213
  * @param value - The value to validate
210
- * @returns The validated value or default ['.claude/skills', '~/.claude/skills', '.agents/skills', '~/.agents/skills']
214
+ * @returns The validated value or project-local and home-directory .claude/.agents skill paths
211
215
  * @private
212
216
  */
213
217
  private validateSkillDirs;
@@ -1 +1 @@
1
- {"version":3,"file":"ServerConfig.d.ts","sourceRoot":"","sources":["../src/ServerConfig.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ServerConfig.d.ts","sourceRoot":"","sources":["../src/ServerConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAE3E;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,MAAM,WAAW,mBAAmB;IACnC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;OAEG;IACH,cAAc,CAAC,EAAE;QAChB;;;WAGG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb;;;WAGG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEhC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAElC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,YAAY;IACxB,qDAAqD;IAC9C,cAAc,EAAE,MAAM,CAAC;IAE9B,8CAA8C;IACvC,WAAW,EAAE,MAAM,CAAC;IAE3B,mCAAmC;IAC5B,aAAa,EAAE,MAAM,CAAC;IAE7B,4CAA4C;IACrC,SAAS,EAAE,MAAM,EAAE,CAAC;IAE3B,2CAA2C;IACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAE1B,qCAAqC;IAC9B,cAAc,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAExD,iCAAiC;IAC1B,WAAW,EAAE,iBAAiB,CAAC;IAEtC,2EAA2E;IACpE,qBAAqB,EAAE,MAAM,CAAC;IAErC,qEAAqE;IAC9D,wBAAwB,EAAE,MAAM,CAAC;IAExC,gEAAgE;IACzD,qBAAqB,EAAE,MAAM,CAAC;IAErC,4BAA4B;IACrB,QAAQ,EAAE,YAAY,CAAC;IAE9B,iEAAiE;IAC1D,mBAAmB,EAAE,MAAM,CAAC;IAEnC,6EAA6E;IACtE,qBAAqB,EAAE,MAAM,CAAC;IAErC,yDAAyD;IAClD,mBAAmB,EAAE,MAAM,CAAC;IAEnC;;;;;;;;;;;;;;;OAeG;gBACS,OAAO,GAAE,mBAAwB;IA2B7C;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAe7B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,gBAAgB;IAKxB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAyB3B;;;;;OAKG;IACH,OAAO,CAAC,6BAA6B;IAerC;;;;;OAKG;IACH,OAAO,CAAC,gCAAgC;IAiBxC;;;;;OAKG;IACH,OAAO,CAAC,6BAA6B;IAerC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;;;OAKG;IACH,OAAO,CAAC,2BAA2B;IAenC;;;;;;;;;;;;;;OAcG;IACI,MAAM,IAAI,mBAAmB;CAkBpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ServerConfig.js","sources":["../src/ServerConfig.ts"],"sourcesContent":["/**\n * Server configuration management with validation.\n *\n * This module provides the `ServerConfig` class which handles all server configuration\n * with built-in validation and sensible defaults. Configuration values are validated\n * on construction and warnings are emitted for out-of-range values.\n *\n * @module ServerConfig\n */\n\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { ConfigurationError } from './errors.js';\nimport type { PersistenceConfig } from './contracts/PersistenceBackend.js';\n\n/**\n * Configuration options for creating a `ServerConfig` instance.\n *\n * All properties are optional with sensible defaults applied during validation.\n *\n * @example\n * ```typescript\n * const options: ServerConfigOptions = {\n * maxHistorySize: 500,\n * maxBranches: 25,\n * skillDirs: ['./custom-skills'],\n * toolDirs: ['./custom-tools'],\n * persistence: { enabled: true, backend: 'sqlite' }\n * };\n * ```\n */\n\nimport type { FeatureFlags } from './contracts/features.js';\nexport interface ServerConfigOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * @default 1000\n\t */\n\tmaxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * @default 50\n\t */\n\tmaxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * @default 100\n\t */\n\tmaxBranchSize?: number;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * @default ['.claude/skills', '~/.claude/skills', '.agents/skills', '~/.agents/skills']\n\t */\n\tskillDirs?: string[];\n\n\t/**\n\t * Directory paths to search for tools.\n\t * @default ['.claude/tools', '~/.claude/tools']\n\t */\n\ttoolDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t */\n\tdiscoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * @default 300000 (5 minutes)\n\t\t */\n\t\tttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t * @default 100\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 * Maximum number of thoughts to buffer before flushing to persistence.\n\t * @default 100\n\t */\n\tpersistenceBufferSize?: number;\n\n\t/**\n\t * Interval in milliseconds between periodic persistence flushes.\n\t * @default 1000\n\t */\n\tpersistenceFlushInterval?: number;\n\n\t/**\n\t * Maximum number of retries for failed persistence flushes.\n\t * @default 3\n\t */\n\tpersistenceMaxRetries?: number;\n\n\t/**\n\t * Feature flag overrides. Missing fields are filled with defaults (all ON,\n\t * reasoningStrategy='sequential').\n\t */\n\tfeatures?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries in SuspensionStore.\n\t * @default 60000\n\t */\n\ttoolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * @default 60000\n\t */\n\ttoolInterleaveSweepMs?: number;\n\n\t/**\n\t * Maximum sessions per owner. Prevents one user from consuming all session slots.\n\t * @default 50\n\t */\n\tmaxSessionsPerOwner?: number;\n}\n\n/**\n * Server configuration with validation and defaults.\n *\n * This class manages all server configuration including history limits,\n * branch limits, discovery directories, cache settings, and persistence.\n * All values are validated on construction with appropriate defaults applied.\n *\n * @remarks\n * - Values outside recommended ranges trigger warnings but are still applied\n * - Environment variables override file-based configuration\n * - The `toJSON()` method provides a plain object representation\n *\n * @example\n * ```typescript\n * // Using defaults\n * const config1 = new ServerConfig();\n * console.log(config1.maxHistorySize); // 10000\n *\n * // With custom options\n * const config2 = new ServerConfig({\n * maxHistorySize: 500,\n * persistence: { enabled: true, backend: 'file', options: { dataDir: './data' } }\n * });\n *\n * // Export as plain object\n * const json = config2.toJSON();\n * ```\n */\nexport class ServerConfig {\n\t/** Maximum number of thoughts to keep in history. */\n\tpublic maxHistorySize: number;\n\n\t/** Maximum number of branches to maintain. */\n\tpublic maxBranches: number;\n\n\t/** Maximum size of each branch. */\n\tpublic maxBranchSize: number;\n\n\t/** Directory paths to search for skills. */\n\tpublic skillDirs: string[];\n\n\t/** Directory paths to search for tools. */\n\tpublic toolDirs: string[];\n\n\t/** Discovery cache configuration. */\n\tpublic discoveryCache: { ttl: number; maxSize: number };\n\n\t/** Persistence configuration. */\n\tpublic persistence: PersistenceConfig;\n\n\t/** Maximum number of thoughts to buffer before flushing to persistence. */\n\tpublic persistenceBufferSize: number;\n\n\t/** Interval in milliseconds between periodic persistence flushes. */\n\tpublic persistenceFlushInterval: number;\n\n\t/** Maximum number of retries for failed persistence flushes. */\n\tpublic persistenceMaxRetries: number;\n\n\t/** Feature flag toggles. */\n\tpublic features: FeatureFlags;\n\n\t/** TTL in milliseconds for suspended tool-interleave entries. */\n\tpublic toolInterleaveTtlMs: number;\n\n\t/** Sweep interval in milliseconds for SuspensionStore expiration cleanup. */\n\tpublic toolInterleaveSweepMs: number;\n\n\t/** Maximum sessions per owner (LRU per-owner bucket). */\n\tpublic maxSessionsPerOwner: number;\n\n\t/**\n\t * Creates a new ServerConfig instance with validation.\n\t *\n\t * All values are validated and defaults are applied for undefined options.\n\t * Warnings are emitted to console for values outside recommended ranges.\n\t *\n\t * @param options - Optional configuration overrides\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({\n\t * maxHistorySize: 500,\n\t * skillDirs: ['./my-skills']\n\t * });\n\t * ```\n\t */\n\tconstructor(options: ServerConfigOptions = {}) {\n\t\tthis.maxHistorySize = this.validateMaxHistorySize(options.maxHistorySize);\n\t\tthis.maxBranches = this.validateMaxBranches(options.maxBranches);\n\t\tthis.maxBranchSize = this.validateMaxBranchSize(options.maxBranchSize);\n\t\tthis.skillDirs = this.validateSkillDirs(options.skillDirs);\n\t\tthis.toolDirs = this.validateToolDirs(options.toolDirs);\n\t\tthis.discoveryCache = this.validateDiscoveryCache(options.discoveryCache);\n\t\tthis.persistence = this.validatePersistence(options.persistence);\n\t\tthis.persistenceBufferSize = this.validatePersistenceBufferSize(options.persistenceBufferSize);\n\t\tthis.persistenceFlushInterval = this.validatePersistenceFlushInterval(\n\t\t\toptions.persistenceFlushInterval\n\t\t);\n\t\tthis.persistenceMaxRetries = this.validatePersistenceMaxRetries(options.persistenceMaxRetries);\n\t\tthis.features = this.validateFeatures(options.features);\n\t\tthis.toolInterleaveTtlMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveTtlMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveTtlMs'\n\t\t);\n\t\tthis.toolInterleaveSweepMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveSweepMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveSweepMs'\n\t\t);\n\t\tthis.maxSessionsPerOwner = this.validateMaxSessionsPerOwner(options.maxSessionsPerOwner);\n\t}\n\n\t/**\n\t * Validates the max history size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (1000)\n\t * @private\n\t */\n\tprivate validateMaxHistorySize(value?: number): number {\n\t\tconst defaultValue = 10000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branches value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (50)\n\t * @private\n\t */\n\tprivate validateMaxBranches(value?: number): number {\n\t\tconst defaultValue = 50;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranches must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branch size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validateMaxBranchSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the skill directories value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default ['.claude/skills', '~/.claude/skills', '.agents/skills', '~/.agents/skills']\n\t * @private\n\t */\n\tprivate validateSkillDirs(value?: string[]): string[] {\n\t\tconst defaultValue = [\n\t\t\t'.claude/skills',\n\t\t\tjoin(homedir(), '.claude/skills'),\n\t\t\t'.agents/skills',\n\t\t\tjoin(homedir(), '.agents/skills'),\n\t\t];\n\t\treturn value === undefined ? defaultValue : [...value];\n\t}\n\n\tprivate validateToolDirs(value?: string[]): string[] {\n\t\tconst defaultValue = ['.claude/tools', join(homedir(), '.claude/tools')];\n\t\treturn value === undefined ? defaultValue : [...value];\n\t}\n\n\t/**\n\t * Validates the discovery cache configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validateDiscoveryCache(value?: { ttl?: number; maxSize?: number }): {\n\t\tttl: number;\n\t\tmaxSize: number;\n\t} {\n\t\treturn {\n\t\t\tttl: value?.ttl ?? 300000,\n\t\t\tmaxSize: value?.maxSize ?? 100,\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validatePersistence(value?: PersistenceConfig): PersistenceConfig {\n\t\tif (!value) {\n\t\t\t// Default to in-memory (no actual persistence, just consistency)\n\t\t\treturn {\n\t\t\t\tenabled: false,\n\t\t\t\tbackend: 'memory',\n\t\t\t};\n\t\t}\n\n\t\t// Validate backend type\n\t\tconst validBackends = ['file', 'sqlite', 'memory'];\n\t\tconst backend = value.backend ?? 'memory';\n\t\tif (!validBackends.includes(backend)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistence.backend must be one of ${validBackends.join(', ')}, got ${backend}`\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tenabled: value.enabled ?? false,\n\t\t\tbackend,\n\t\t\toptions: value.options ?? {},\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence buffer size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validatePersistenceBufferSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence flush interval value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (1000)\n\t * @private\n\t */\n\tprivate validatePersistenceFlushInterval(value?: number): number {\n\t\tconst defaultValue = 1000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistenceFlushInterval must be a finite number, got ${value}`\n\t\t\t);\n\t\t}\n\t\tif (value < 100) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must be at least 100, got ${value}`);\n\t\t}\n\t\tif (value > 60000) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must not exceed 60000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence max retries value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (3)\n\t * @private\n\t */\n\tprivate validatePersistenceMaxRetries(value?: number): number {\n\t\tconst defaultValue = 3;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 10) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must not exceed 10, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates feature flags and fills defaults for missing fields.\n\t * @param value - Partial feature flag overrides\n\t * @returns Fully populated FeatureFlags with defaults applied\n\t * @private\n\t */\n\tprivate validateFeatures(value?: Partial<FeatureFlags>): FeatureFlags {\n\t\tconst reasoningStrategy = value?.reasoningStrategy ?? 'sequential';\n\t\tif (reasoningStrategy !== 'sequential' && reasoningStrategy !== 'tot') {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`features.reasoningStrategy must be one of sequential, tot, got ${reasoningStrategy}`\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tdagEdges: value?.dagEdges ?? true,\n\t\t\treasoningStrategy,\n\t\t\tcalibration: value?.calibration ?? true,\n\t\t\tcompression: value?.compression ?? true,\n\t\t\ttoolInterleave: value?.toolInterleave ?? true,\n\t\t\tnewThoughtTypes: value?.newThoughtTypes ?? true,\n\t\t\toutcomeRecording: value?.outcomeRecording ?? true,\n\t\t};\n\t}\n\n\t/**\n\t * Validates a positive millisecond value with a default fallback.\n\t * @param value - The value to validate\n\t * @param defaultValue - Default applied if value is undefined/null\n\t * @param fieldName - Field name for error messages\n\t * @returns The validated millisecond value\n\t * @private\n\t */\n\tprivate validatePositiveMs(\n\t\tvalue: number | undefined,\n\t\tdefaultValue: number,\n\t\tfieldName: string\n\t): number {\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be at least 1, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max sessions per owner value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (50)\n\t * @private\n\t */\n\tprivate validateMaxSessionsPerOwner(value?: number): number {\n\t\tconst defaultValue = 50;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxSessionsPerOwner must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxSessionsPerOwner must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`maxSessionsPerOwner must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Converts the configuration to a plain object.\n\t *\n\t * Useful for serialization, logging, or when a plain object representation\n\t * is preferred over the ServerConfig instance.\n\t *\n\t * @returns A plain object representation of the configuration\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({ maxHistorySize: 500 });\n\t * const json = config.toJSON();\n\t * console.log(JSON.stringify(json, null, 2));\n\t * ```\n\t */\n\tpublic toJSON(): ServerConfigOptions {\n\t\treturn {\n\t\t\tmaxHistorySize: this.maxHistorySize,\n\t\t\tmaxBranches: this.maxBranches,\n\t\t\tmaxBranchSize: this.maxBranchSize,\n\t\t\tskillDirs: this.skillDirs,\n\t\t\ttoolDirs: this.toolDirs,\n\t\t\tdiscoveryCache: this.discoveryCache,\n\t\t\tpersistence: this.persistence,\n\t\t\tpersistenceBufferSize: this.persistenceBufferSize,\n\t\t\tpersistenceFlushInterval: this.persistenceFlushInterval,\n\t\t\tpersistenceMaxRetries: this.persistenceMaxRetries,\n\t\t\tfeatures: this.features,\n\t\t\ttoolInterleaveTtlMs: this.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: this.toolInterleaveSweepMs,\n\t\t\tmaxSessionsPerOwner: this.maxSessionsPerOwner,\n\t\t};\n\t}\n}\n"],"names":["ServerConfig","options","value","defaultValue","Number","ConfigurationError","join","homedir","undefined","validBackends","backend","reasoningStrategy","fieldName"],"mappings":"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"}
1
+ {"version":3,"file":"ServerConfig.js","sources":["../src/ServerConfig.ts"],"sourcesContent":["/**\n * Server configuration management with validation.\n *\n * This module provides the `ServerConfig` class which handles all server configuration\n * with built-in validation and sensible defaults. Configuration values are validated\n * on construction and warnings are emitted for out-of-range values.\n *\n * @module ServerConfig\n */\n\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { ConfigurationError } from './errors.js';\nimport type { PersistenceConfig } from './contracts/PersistenceBackend.js';\n\n/**\n * Configuration options for creating a `ServerConfig` instance.\n *\n * All properties are optional with sensible defaults applied during validation.\n *\n * @example\n * ```typescript\n * const options: ServerConfigOptions = {\n * maxHistorySize: 500,\n * maxBranches: 25,\n * skillDirs: ['./custom-skills'],\n * toolDirs: ['./custom-tools'],\n * persistence: { enabled: true, backend: 'sqlite' }\n * };\n * ```\n */\n\nimport type { FeatureFlags } from './contracts/features.js';\nexport interface ServerConfigOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * @default 10000\n\t */\n\tmaxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * @default 50\n\t */\n\tmaxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * @default 100\n\t */\n\tmaxBranchSize?: number;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * @default Project .claude/skills and .agents/skills, plus both paths under the home directory\n\t */\n\tskillDirs?: string[];\n\n\t/**\n\t * Directory paths to search for tools.\n\t * @default ['.claude/tools', '~/.claude/tools']\n\t */\n\ttoolDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t */\n\tdiscoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * @default 300000 (5 minutes)\n\t\t */\n\t\tttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t * @default 100\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 * Maximum number of thoughts to buffer before flushing to persistence.\n\t * YAML/JSON only; no environment override.\n\t * @default 100\n\t */\n\tpersistenceBufferSize?: number;\n\n\t/**\n\t * Interval in milliseconds between periodic persistence flushes.\n\t * YAML/JSON only; no environment override.\n\t * @default 1000\n\t */\n\tpersistenceFlushInterval?: number;\n\n\t/**\n\t * Maximum number of retries for failed persistence flushes.\n\t * YAML/JSON only; no environment override.\n\t * @default 3\n\t */\n\tpersistenceMaxRetries?: number;\n\n\t/**\n\t * Feature flag overrides. Missing fields are filled with defaults (all ON,\n\t * reasoningStrategy='sequential').\n\t */\n\tfeatures?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries in SuspensionStore.\n\t * @default 60000\n\t */\n\ttoolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * @default 60000\n\t */\n\ttoolInterleaveSweepMs?: number;\n\n\t/**\n\t * Maximum sessions per owner. Prevents one user from consuming all session slots.\n\t * @default 50\n\t */\n\tmaxSessionsPerOwner?: number;\n}\n\n/**\n * Server configuration with validation and defaults.\n *\n * This class manages all server configuration including history limits,\n * branch limits, discovery directories, cache settings, and persistence.\n * All values are validated on construction with appropriate defaults applied.\n *\n * @remarks\n * - Values outside recommended ranges trigger warnings but are still applied\n * - Supported environment variables override file-based configuration through ConfigLoader\n * - Logging uses file/environment input separately; ServerConfig does not hold log settings\n * - The `toJSON()` method provides a plain object representation\n *\n * @example\n * ```typescript\n * // Using defaults\n * const config1 = new ServerConfig();\n * console.log(config1.maxHistorySize); // 10000\n *\n * // With custom options\n * const config2 = new ServerConfig({\n * maxHistorySize: 500,\n * persistence: { enabled: true, backend: 'file', options: { dataDir: './data' } }\n * });\n *\n * // Export as plain object\n * const json = config2.toJSON();\n * ```\n */\nexport class ServerConfig {\n\t/** Maximum number of thoughts to keep in history. */\n\tpublic maxHistorySize: number;\n\n\t/** Maximum number of branches to maintain. */\n\tpublic maxBranches: number;\n\n\t/** Maximum size of each branch. */\n\tpublic maxBranchSize: number;\n\n\t/** Directory paths to search for skills. */\n\tpublic skillDirs: string[];\n\n\t/** Directory paths to search for tools. */\n\tpublic toolDirs: string[];\n\n\t/** Discovery cache configuration. */\n\tpublic discoveryCache: { ttl: number; maxSize: number };\n\n\t/** Persistence configuration. */\n\tpublic persistence: PersistenceConfig;\n\n\t/** Maximum number of thoughts to buffer before flushing to persistence. */\n\tpublic persistenceBufferSize: number;\n\n\t/** Interval in milliseconds between periodic persistence flushes. */\n\tpublic persistenceFlushInterval: number;\n\n\t/** Maximum number of retries for failed persistence flushes. */\n\tpublic persistenceMaxRetries: number;\n\n\t/** Feature flag toggles. */\n\tpublic features: FeatureFlags;\n\n\t/** TTL in milliseconds for suspended tool-interleave entries. */\n\tpublic toolInterleaveTtlMs: number;\n\n\t/** Sweep interval in milliseconds for SuspensionStore expiration cleanup. */\n\tpublic toolInterleaveSweepMs: number;\n\n\t/** Maximum sessions per owner (LRU per-owner bucket). */\n\tpublic maxSessionsPerOwner: number;\n\n\t/**\n\t * Creates a new ServerConfig instance with validation.\n\t *\n\t * All values are validated and defaults are applied for undefined options.\n\t * Warnings are emitted to console for values outside recommended ranges.\n\t *\n\t * @param options - Optional configuration overrides\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({\n\t * maxHistorySize: 500,\n\t * skillDirs: ['./my-skills']\n\t * });\n\t * ```\n\t */\n\tconstructor(options: ServerConfigOptions = {}) {\n\t\tthis.maxHistorySize = this.validateMaxHistorySize(options.maxHistorySize);\n\t\tthis.maxBranches = this.validateMaxBranches(options.maxBranches);\n\t\tthis.maxBranchSize = this.validateMaxBranchSize(options.maxBranchSize);\n\t\tthis.skillDirs = this.validateSkillDirs(options.skillDirs);\n\t\tthis.toolDirs = this.validateToolDirs(options.toolDirs);\n\t\tthis.discoveryCache = this.validateDiscoveryCache(options.discoveryCache);\n\t\tthis.persistence = this.validatePersistence(options.persistence);\n\t\tthis.persistenceBufferSize = this.validatePersistenceBufferSize(options.persistenceBufferSize);\n\t\tthis.persistenceFlushInterval = this.validatePersistenceFlushInterval(\n\t\t\toptions.persistenceFlushInterval\n\t\t);\n\t\tthis.persistenceMaxRetries = this.validatePersistenceMaxRetries(options.persistenceMaxRetries);\n\t\tthis.features = this.validateFeatures(options.features);\n\t\tthis.toolInterleaveTtlMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveTtlMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveTtlMs'\n\t\t);\n\t\tthis.toolInterleaveSweepMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveSweepMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveSweepMs'\n\t\t);\n\t\tthis.maxSessionsPerOwner = this.validateMaxSessionsPerOwner(options.maxSessionsPerOwner);\n\t}\n\n\t/**\n\t * Validates the max history size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (10000)\n\t * @private\n\t */\n\tprivate validateMaxHistorySize(value?: number): number {\n\t\tconst defaultValue = 10000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branches value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (50)\n\t * @private\n\t */\n\tprivate validateMaxBranches(value?: number): number {\n\t\tconst defaultValue = 50;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranches must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branch size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validateMaxBranchSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the skill directories value.\n\t * @param value - The value to validate\n\t * @returns The validated value or project-local and home-directory .claude/.agents skill paths\n\t * @private\n\t */\n\tprivate validateSkillDirs(value?: string[]): string[] {\n\t\tconst defaultValue = [\n\t\t\t'.claude/skills',\n\t\t\tjoin(homedir(), '.claude/skills'),\n\t\t\t'.agents/skills',\n\t\t\tjoin(homedir(), '.agents/skills'),\n\t\t];\n\t\treturn value === undefined ? defaultValue : [...value];\n\t}\n\n\tprivate validateToolDirs(value?: string[]): string[] {\n\t\tconst defaultValue = ['.claude/tools', join(homedir(), '.claude/tools')];\n\t\treturn value === undefined ? defaultValue : [...value];\n\t}\n\n\t/**\n\t * Validates the discovery cache configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validateDiscoveryCache(value?: { ttl?: number; maxSize?: number }): {\n\t\tttl: number;\n\t\tmaxSize: number;\n\t} {\n\t\treturn {\n\t\t\tttl: value?.ttl ?? 300000,\n\t\t\tmaxSize: value?.maxSize ?? 100,\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validatePersistence(value?: PersistenceConfig): PersistenceConfig {\n\t\tif (!value) {\n\t\t\t// Default to in-memory (no actual persistence, just consistency)\n\t\t\treturn {\n\t\t\t\tenabled: false,\n\t\t\t\tbackend: 'memory',\n\t\t\t};\n\t\t}\n\n\t\t// Validate backend type\n\t\tconst validBackends = ['file', 'sqlite', 'memory'];\n\t\tconst backend = value.backend ?? 'memory';\n\t\tif (!validBackends.includes(backend)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistence.backend must be one of ${validBackends.join(', ')}, got ${backend}`\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tenabled: value.enabled ?? false,\n\t\t\tbackend,\n\t\t\toptions: value.options ?? {},\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence buffer size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validatePersistenceBufferSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence flush interval value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (1000)\n\t * @private\n\t */\n\tprivate validatePersistenceFlushInterval(value?: number): number {\n\t\tconst defaultValue = 1000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistenceFlushInterval must be a finite number, got ${value}`\n\t\t\t);\n\t\t}\n\t\tif (value < 100) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must be at least 100, got ${value}`);\n\t\t}\n\t\tif (value > 60000) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must not exceed 60000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence max retries value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (3)\n\t * @private\n\t */\n\tprivate validatePersistenceMaxRetries(value?: number): number {\n\t\tconst defaultValue = 3;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 10) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must not exceed 10, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates feature flags and fills defaults for missing fields.\n\t * @param value - Partial feature flag overrides\n\t * @returns Fully populated FeatureFlags with defaults applied\n\t * @private\n\t */\n\tprivate validateFeatures(value?: Partial<FeatureFlags>): FeatureFlags {\n\t\tconst reasoningStrategy = value?.reasoningStrategy ?? 'sequential';\n\t\tif (reasoningStrategy !== 'sequential' && reasoningStrategy !== 'tot') {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`features.reasoningStrategy must be one of sequential, tot, got ${reasoningStrategy}`\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tdagEdges: value?.dagEdges ?? true,\n\t\t\treasoningStrategy,\n\t\t\tcalibration: value?.calibration ?? true,\n\t\t\tcompression: value?.compression ?? true,\n\t\t\ttoolInterleave: value?.toolInterleave ?? true,\n\t\t\tnewThoughtTypes: value?.newThoughtTypes ?? true,\n\t\t\toutcomeRecording: value?.outcomeRecording ?? true,\n\t\t};\n\t}\n\n\t/**\n\t * Validates a positive millisecond value with a default fallback.\n\t * @param value - The value to validate\n\t * @param defaultValue - Default applied if value is undefined/null\n\t * @param fieldName - Field name for error messages\n\t * @returns The validated millisecond value\n\t * @private\n\t */\n\tprivate validatePositiveMs(\n\t\tvalue: number | undefined,\n\t\tdefaultValue: number,\n\t\tfieldName: string\n\t): number {\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be at least 1, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max sessions per owner value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (50)\n\t * @private\n\t */\n\tprivate validateMaxSessionsPerOwner(value?: number): number {\n\t\tconst defaultValue = 50;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxSessionsPerOwner must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxSessionsPerOwner must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`maxSessionsPerOwner must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Converts the configuration to a plain object.\n\t *\n\t * Useful for serialization, logging, or when a plain object representation\n\t * is preferred over the ServerConfig instance.\n\t *\n\t * @returns A plain object representation of the configuration\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({ maxHistorySize: 500 });\n\t * const json = config.toJSON();\n\t * console.log(JSON.stringify(json, null, 2));\n\t * ```\n\t */\n\tpublic toJSON(): ServerConfigOptions {\n\t\treturn {\n\t\t\tmaxHistorySize: this.maxHistorySize,\n\t\t\tmaxBranches: this.maxBranches,\n\t\t\tmaxBranchSize: this.maxBranchSize,\n\t\t\tskillDirs: this.skillDirs,\n\t\t\ttoolDirs: this.toolDirs,\n\t\t\tdiscoveryCache: this.discoveryCache,\n\t\t\tpersistence: this.persistence,\n\t\t\tpersistenceBufferSize: this.persistenceBufferSize,\n\t\t\tpersistenceFlushInterval: this.persistenceFlushInterval,\n\t\t\tpersistenceMaxRetries: this.persistenceMaxRetries,\n\t\t\tfeatures: this.features,\n\t\t\ttoolInterleaveTtlMs: this.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: this.toolInterleaveSweepMs,\n\t\t\tmaxSessionsPerOwner: this.maxSessionsPerOwner,\n\t\t};\n\t}\n}\n"],"names":["ServerConfig","options","value","defaultValue","Number","ConfigurationError","join","homedir","undefined","validBackends","backend","reasoningStrategy","fieldName"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * This module provides the `ConfigLoader` class which handles loading configuration
5
5
  * from YAML and JSON files in standard locations, with automatic environment variable
6
- * overrides for all settings.
6
+ * overrides for supported settings. Persistence buffer, flush, and retry settings are file-only.
7
7
  *
8
8
  * @module config
9
9
  */
@@ -14,8 +14,8 @@ import type { ServerConfigOptions } from '../ServerConfig.js';
14
14
  * Configuration options loaded from config files.
15
15
  *
16
16
  * These options represent the structure of configuration files (JSON or YAML)
17
- * that can be loaded from standard locations. All values can be overridden
18
- * by environment variables.
17
+ * that can be loaded from standard locations. Only supported fields have
18
+ * environment overrides; persistence buffer, flush, and retry settings are file-only.
19
19
  *
20
20
  * @example
21
21
  * ```yaml
@@ -94,8 +94,11 @@ export interface ConfigFileOptions {
94
94
  * Persistence configuration for storing history and state.
95
95
  */
96
96
  readonly persistence?: PersistenceConfig;
97
+ /** Maximum buffered thoughts before flushing; file-only (default 100 in ServerConfig). */
97
98
  readonly persistenceBufferSize?: number;
99
+ /** Periodic flush interval in milliseconds; file-only (default 1000 in ServerConfig). */
98
100
  readonly persistenceFlushInterval?: number;
101
+ /** Maximum flush retries; file-only (default 3 in ServerConfig). */
99
102
  readonly persistenceMaxRetries?: number;
100
103
  /**
101
104
  * Feature flag overrides. Each field can be set independently.
@@ -124,11 +127,11 @@ export interface ConfigFileOptions {
124
127
  *
125
128
  * This class searches for configuration files in standard locations and applies
126
129
  * environment variable overrides. Files are searched in priority order, with the
127
- * first match being used. Environment variables always take precedence over file values.
130
+ * first valid match being used. Supported environment variables take precedence over file values.
128
131
  *
129
132
  * @remarks
130
133
  * **Config File Search Order (priority):**
131
- * 1. Custom path (if provided to constructor)
134
+ * 1. Custom path or `TRACELATTICE_CONFIG` (if present, replaces the default search list)
132
135
  * 2. `.claude/config.json` (project-local)
133
136
  * 3. `.claude/config.yaml` (project-local)
134
137
  * 4. `.claude/config.yml` (project-local)
@@ -148,6 +151,11 @@ export interface ConfigFileOptions {
148
151
  * | `TRACELATTICE_TOOL_DIRS` | string | Colon-separated directory paths |
149
152
  * | `TRACELATTICE_DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |
150
153
  * | `TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE` | number | Max cache entries |
154
+ * | `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` / `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` | number | Milliseconds |
155
+ * | `TRACELATTICE_SESSION_MAX_PER_OWNER` | number | Max sessions per owner |
156
+ * | `TRACELATTICE_FEATURES_*` | boolean or strategy | Feature toggles or `sequential`/`tot` |
157
+ *
158
+ * Persistence buffer size, flush interval (milliseconds), and retries are file-only.
151
159
  *
152
160
  * @example
153
161
  * ```typescript
@@ -186,9 +194,10 @@ export declare class ConfigLoader {
186
194
  *
187
195
  * Searches for config files in the configured paths (in priority order),
188
196
  * parses the first match, and applies environment variable overrides.
189
- * Returns null if no config file is found and no environment overrides are set.
197
+ * A malformed file is logged and skipped. With no valid file, applies environment
198
+ * overrides to an empty object (the declared nullable return type does not return null).
190
199
  *
191
- * @returns The loaded configuration with environment overrides applied, or null if no config found
200
+ * @returns The loaded configuration with environment overrides applied, or an empty/overlaid object
192
201
  *
193
202
  * @example
194
203
  * ```typescript
@@ -215,6 +224,10 @@ export declare class ConfigLoader {
215
224
  * - `TRACELATTICE_TOOL_DIRS` (colon-separated paths)
216
225
  * - `TRACELATTICE_DISCOVERY_CACHE_TTL` (in seconds, converted to ms)
217
226
  * - `TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE` (number)
227
+ * - `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS`, `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` (milliseconds)
228
+ * - `TRACELATTICE_SESSION_MAX_PER_OWNER` (number)
229
+ * - `TRACELATTICE_FEATURES_*` (booleans true/false/1/0 or sequential/tot strategy)
230
+ * Persistence buffer, flush interval, and retry settings have no environment aliases.
218
231
  *
219
232
  * @param config - The configuration to apply overrides to
220
233
  * @returns A new configuration object with environment overrides applied
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAiC9D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAExD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE;QACzB;;;WAGG;QACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QACtB;;WAEG;QACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEzC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAExC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAE3C,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAEtC;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAExC;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBAAa,YAAY;IACxB,+DAA+D;IAC/D,OAAO,CAAC,YAAY,CAAW;IAE/B;;;;;;;;;;;;;OAaG;gBACS,UAAU,CAAC,EAAE,MAAM;IAc/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,IAAI,IAAI,iBAAiB,GAAG,IAAI;IAiBhC;;;;;;;;;;;;;;;;OAgBG;IACI,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB;IAsF9E,OAAO,CAAC,WAAW;IAsBnB;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAuCjC,OAAO,CAAC,uBAAuB;IAW/B;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAOpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,WAAW;IASnB;;;;;;;;;;;;;;;;;;OAkBG;IACH,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,mBAAmB;CAkBrE"}
1
+ {"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAiC9D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAExD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE;QACzB;;;WAGG;QACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QACtB;;WAEG;QACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEzC,0FAA0F;IAC1F,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAExC,yFAAyF;IACzF,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAE3C,oEAAoE;IACpE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAEtC;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAExC;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,qBAAa,YAAY;IACxB,+DAA+D;IAC/D,OAAO,CAAC,YAAY,CAAW;IAE/B;;;;;;;;;;;;;OAaG;gBACS,UAAU,CAAC,EAAE,MAAM;IAc/B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,IAAI,IAAI,iBAAiB,GAAG,IAAI;IAiBhC;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB;IAsF9E,OAAO,CAAC,WAAW;IAsBnB;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAuCjC,OAAO,CAAC,uBAAuB;IAW/B;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAOpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,WAAW;IASnB;;;;;;;;;;;;;;;;;;OAkBG;IACH,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,mBAAmB;CAkBrE"}
@@ -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 * as v from 'valibot';\nimport type { PersistenceConfig } from '../contracts/PersistenceBackend.js';\nimport { ConfigurationError, getErrorMessage } from '../errors.js';\nimport type { FeatureFlags } from '../contracts/features.js';\nimport type { ServerConfigOptions } from '../ServerConfig.js';\n\n/**\n * Lenient runtime schema for config files. Only validates top-level shape;\n * unknown extra fields are preserved by Valibot's default object behavior\n * being strict is avoided by using `v.looseObject`. All fields are optional.\n */\nconst ConfigFileOptionsSchema = v.looseObject({\n\tmaxHistorySize: v.optional(v.number()),\n\tmaxBranches: v.optional(v.number()),\n\tmaxBranchSize: v.optional(v.number()),\n\tlogLevel: v.optional(v.picklist(['debug', 'info', 'warn', 'error'])),\n\tprettyLog: v.optional(v.boolean()),\n\tskillDirs: v.optional(v.array(v.string())),\n\ttoolDirs: v.optional(v.array(v.string())),\n\tdiscoveryCache: v.optional(\n\t\tv.looseObject({\n\t\t\tttl: v.optional(v.number()),\n\t\t\tmaxSize: v.optional(v.number()),\n\t\t})\n\t),\n\tpersistence: v.optional(v.looseObject({})),\n\tpersistenceBufferSize: v.optional(v.number()),\n\tpersistenceFlushInterval: v.optional(v.number()),\n\tpersistenceMaxRetries: v.optional(v.number()),\n\tfeatures: v.optional(v.looseObject({})),\n\ttoolInterleaveTtlMs: v.optional(v.number()),\n\ttoolInterleaveSweepMs: v.optional(v.number()),\n\tmaxSessionsPerOwner: v.optional(v.number()),\n});\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 * toolDirs:\n * - ./custom-tools\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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_SKILL_DIRS` environment variable (colon-separated).\n\t */\n\treadonly skillDirs?: string[];\n\n\t/**\n\t * Directory paths to search for tools.\n\t * Can be overridden by `TRACELATTICE_TOOL_DIRS` environment variable (colon-separated).\n\t */\n\treadonly toolDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t * Can be overridden by `TRACELATTICE_DISCOVERY_CACHE_TTL` and\n\t * `TRACELATTICE_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 `TRACELATTICE_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\treadonly persistenceBufferSize?: number;\n\n\treadonly persistenceFlushInterval?: number;\n\n\treadonly persistenceMaxRetries?: number;\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 `TRACELATTICE_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 * | `TRACELATTICE_MAX_HISTORY_SIZE` | number | Max thoughts in history |\n * | `TRACELATTICE_MAX_BRANCHES` | number | Max number of branches |\n * | `TRACELATTICE_MAX_BRANCH_SIZE` | number | Max size of each branch |\n * | `TRACELATTICE_LOG_LEVEL` | string | Logging level (debug/info/warn/error) |\n * | `TRACELATTICE_PRETTY_LOG` | string | \"false\" to disable pretty logging |\n * | `TRACELATTICE_SKILL_DIRS` | string | Colon-separated directory paths |\n * | `TRACELATTICE_TOOL_DIRS` | string | Colon-separated directory paths |\n * | `TRACELATTICE_DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |\n * | `TRACELATTICE_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\tconst configuredPath = customPath ?? process.env.TRACELATTICE_CONFIG;\n\t\tthis._configPaths = configuredPath\n\t\t\t? [configuredPath]\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(`Failed to load config from ${configPath}:`, getErrorMessage(error));\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 * - `TRACELATTICE_MAX_HISTORY_SIZE`, `TRACELATTICE_MAX_BRANCHES`,\n\t * `TRACELATTICE_MAX_BRANCH_SIZE` (numbers)\n\t * - `TRACELATTICE_LOG_LEVEL` (debug/info/warn/error)\n\t * - `TRACELATTICE_PRETTY_LOG` (\"false\" to disable)\n\t * - `TRACELATTICE_SKILL_DIRS` (colon-separated paths)\n\t * - `TRACELATTICE_TOOL_DIRS` (colon-separated paths)\n\t * - `TRACELATTICE_DISCOVERY_CACHE_TTL` (in seconds, converted to ms)\n\t * - `TRACELATTICE_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 */\n\tpublic applyEnvironmentOverrides(config: ConfigFileOptions): ConfigFileOptions {\n\t\tconst result = this.cloneConfig(config);\n\n\t\tif (process.env.TRACELATTICE_MAX_HISTORY_SIZE !== undefined) {\n\t\t\tresult.maxHistorySize = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_MAX_HISTORY_SIZE',\n\t\t\t\tprocess.env.TRACELATTICE_MAX_HISTORY_SIZE\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_MAX_BRANCHES !== undefined) {\n\t\t\tresult.maxBranches = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_MAX_BRANCHES',\n\t\t\t\tprocess.env.TRACELATTICE_MAX_BRANCHES\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_MAX_BRANCH_SIZE !== undefined) {\n\t\t\tresult.maxBranchSize = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_MAX_BRANCH_SIZE',\n\t\t\t\tprocess.env.TRACELATTICE_MAX_BRANCH_SIZE\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tprocess.env.TRACELATTICE_LOG_LEVEL &&\n\t\t\t['debug', 'info', 'warn', 'error'].includes(process.env.TRACELATTICE_LOG_LEVEL)\n\t\t) {\n\t\t\tresult.logLevel = process.env.TRACELATTICE_LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error';\n\t\t}\n\t\tif (process.env.TRACELATTICE_PRETTY_LOG === 'false') {\n\t\t\tresult.prettyLog = false;\n\t\t}\n\t\tif (process.env.TRACELATTICE_SKILL_DIRS !== undefined) {\n\t\t\tresult.skillDirs =\n\t\t\t\tprocess.env.TRACELATTICE_SKILL_DIRS === ''\n\t\t\t\t\t? []\n\t\t\t\t\t: process.env.TRACELATTICE_SKILL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_DIRS !== undefined) {\n\t\t\tresult.toolDirs =\n\t\t\t\tprocess.env.TRACELATTICE_TOOL_DIRS === ''\n\t\t\t\t\t? []\n\t\t\t\t\t: process.env.TRACELATTICE_TOOL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.TRACELATTICE_DISCOVERY_CACHE_TTL !== undefined) {\n\t\t\tconst seconds = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_DISCOVERY_CACHE_TTL',\n\t\t\t\tprocess.env.TRACELATTICE_DISCOVERY_CACHE_TTL\n\t\t\t);\n\t\t\tconst ttl = seconds * 1000;\n\t\t\tif (!Number.isSafeInteger(ttl)) {\n\t\t\t\tthrow new ConfigurationError(\n\t\t\t\t\t'TRACELATTICE_DISCOVERY_CACHE_TTL exceeds the safe integer range'\n\t\t\t\t);\n\t\t\t}\n\t\t\tresult.discoveryCache = { ...result.discoveryCache, ttl };\n\t\t}\n\t\tif (process.env.TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE !== undefined) {\n\t\t\tconst maxSize = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE',\n\t\t\t\tprocess.env.TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE\n\t\t\t);\n\t\t\tresult.discoveryCache = { ...result.discoveryCache, maxSize };\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS !== undefined) {\n\t\t\tresult.toolInterleaveTtlMs = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_TOOL_INTERLEAVE_TTL_MS',\n\t\t\t\tprocess.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS !== undefined) {\n\t\t\tresult.toolInterleaveSweepMs = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS',\n\t\t\t\tprocess.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_SESSION_MAX_PER_OWNER !== undefined) {\n\t\t\tresult.maxSessionsPerOwner = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_SESSION_MAX_PER_OWNER',\n\t\t\t\tprocess.env.TRACELATTICE_SESSION_MAX_PER_OWNER\n\t\t\t);\n\t\t}\n\n\t\tthis.applyFeatureFlagOverrides(result);\n\n\t\treturn result;\n\t}\n\n\tprivate cloneConfig(config: ConfigFileOptions): Mutable<ConfigFileOptions> {\n\t\treturn {\n\t\t\t...config,\n\t\t\t...(config.skillDirs === undefined ? {} : { skillDirs: [...config.skillDirs] }),\n\t\t\t...(config.toolDirs === undefined ? {} : { toolDirs: [...config.toolDirs] }),\n\t\t\t...(config.discoveryCache === undefined\n\t\t\t\t? {}\n\t\t\t\t: { discoveryCache: { ...config.discoveryCache } }),\n\t\t\t...(config.persistence === undefined\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tpersistence: {\n\t\t\t\t\t\t\t...config.persistence,\n\t\t\t\t\t\t\t...(config.persistence.options === undefined\n\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t: { options: { ...config.persistence.options } }),\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t...(config.features === undefined ? {} : { features: { ...config.features } }),\n\t\t};\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 rejected.\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\tif (strategyRaw !== 'sequential' && strategyRaw !== 'tot') {\n\t\t\t\tthrow new ConfigurationError(\n\t\t\t\t\t`TRACELATTICE_FEATURES_REASONING_STRATEGY must be one of sequential, tot, got ${strategyRaw}`\n\t\t\t\t);\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.reasoningStrategy = strategyRaw;\n\t\t\tresult.features = features;\n\t\t}\n\t}\n\n\tprivate parseEnvironmentInteger(environmentName: string, raw: string): number {\n\t\tif (!/^(0|[1-9]\\d*)$/.test(raw)) {\n\t\t\tthrow new ConfigurationError(`${environmentName} must be an integer, got ${raw}`);\n\t\t}\n\t\tconst parsed = Number(raw);\n\t\tif (!Number.isSafeInteger(parsed)) {\n\t\t\tthrow new ConfigurationError(`${environmentName} must be a safe integer, got ${raw}`);\n\t\t}\n\t\treturn parsed;\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\tconst raw: unknown = ext === 'yaml' || ext === 'yml' ? parseYaml(content) : JSON.parse(content);\n\n\t\treturn v.parse(ConfigFileOptionsSchema, raw) 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): ServerConfigOptions {\n\t\treturn {\n\t\t\tmaxHistorySize: config.maxHistorySize,\n\t\t\tmaxBranches: config.maxBranches,\n\t\t\tmaxBranchSize: config.maxBranchSize,\n\t\t\tskillDirs: config.skillDirs,\n\t\t\ttoolDirs: config.toolDirs,\n\t\t\tdiscoveryCache: config.discoveryCache,\n\t\t\tpersistence: config.persistence,\n\t\t\tpersistenceBufferSize: config.persistenceBufferSize,\n\t\t\tpersistenceFlushInterval: config.persistenceFlushInterval,\n\t\t\tpersistenceMaxRetries: config.persistenceMaxRetries,\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":["ConfigFileOptionsSchema","v","ConfigLoader","customPath","configuredPath","process","join","homedir","config","configPath","existsSync","error","console","getErrorMessage","result","undefined","seconds","ttl","Number","ConfigurationError","maxSize","boolMap","envVar","key","Object","raw","parsed","features","strategyRaw","environmentName","filePath","content","readFileSync","ext","parseYaml","JSON"],"mappings":";;;;;;AAyBA,MAAMA,0BAA0BC,0BAAAA,WAAa,CAAC;IAC7C,gBAAgBA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IACnC,aAAaA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IAChC,eAAeA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IAClC,UAAUA,0BAAAA,QAAU,CAACA,0BAAAA,QAAU,CAAC;QAAC;QAAS;QAAQ;QAAQ;KAAQ;IAClE,WAAWA,0BAAAA,QAAU,CAACA,0BAAAA,OAAS;IAC/B,WAAWA,0BAAAA,QAAU,CAACA,0BAAAA,KAAO,CAACA,0BAAAA,MAAQ;IACtC,UAAUA,0BAAAA,QAAU,CAACA,0BAAAA,KAAO,CAACA,0BAAAA,MAAQ;IACrC,gBAAgBA,0BAAAA,QAAU,CACzBA,0BAAAA,WAAa,CAAC;QACb,KAAKA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;QACxB,SAASA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IAC7B;IAED,aAAaA,0BAAAA,QAAU,CAACA,0BAAAA,WAAa,CAAC,CAAC;IACvC,uBAAuBA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IAC1C,0BAA0BA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IAC7C,uBAAuBA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IAC1C,UAAUA,0BAAAA,QAAU,CAACA,0BAAAA,WAAa,CAAC,CAAC;IACpC,qBAAqBA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IACxC,uBAAuBA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;IAC1C,qBAAqBA,0BAAAA,QAAU,CAACA,0BAAAA,MAAQ;AACzC;AA6KO,MAAMC;IAEJ,aAAuB;IAgB/B,YAAYC,UAAmB,CAAE;QAChC,MAAMC,iBAAiBD,cAAcE,QAAQ,GAAG,CAAC,mBAAmB;QACpE,IAAI,CAAC,YAAY,GAAGD,iBACjB;YAACA;SAAe,GAChB;YACA;YACA;YACA;YACAE,KAAKC,WAAW;YAChBD,KAAKC,WAAW;YAChBD,KAAKC,WAAW;SAChB;IACJ;IAsBA,OAAiC;QAChC,IAAIC,SAAmC;QAEvC,KAAK,MAAMC,cAAc,IAAI,CAAC,YAAY,CACzC,IAAIC,WAAWD,aACd,IAAI;YACHD,SAAS,IAAI,CAAC,WAAW,CAACC;YAC1B;QACD,EAAE,OAAOE,OAAO;YACfC,QAAQ,KAAK,CAAC,CAAC,2BAA2B,EAAEH,WAAW,CAAC,CAAC,EAAEI,gBAAgBF;QAC5E;QAIF,OAAO,IAAI,CAAC,yBAAyB,CAACH,UAAU,CAAC;IAClD;IAmBO,0BAA0BA,MAAyB,EAAqB;QAC9E,MAAMM,SAAS,IAAI,CAAC,WAAW,CAACN;QAEhC,IAAIH,AAA8CU,WAA9CV,QAAQ,GAAG,CAAC,6BAA6B,EAC5CS,OAAO,cAAc,GAAG,IAAI,CAAC,uBAAuB,CACnD,iCACAT,QAAQ,GAAG,CAAC,6BAA6B;QAG3C,IAAIA,AAA0CU,WAA1CV,QAAQ,GAAG,CAAC,yBAAyB,EACxCS,OAAO,WAAW,GAAG,IAAI,CAAC,uBAAuB,CAChD,6BACAT,QAAQ,GAAG,CAAC,yBAAyB;QAGvC,IAAIA,AAA6CU,WAA7CV,QAAQ,GAAG,CAAC,4BAA4B,EAC3CS,OAAO,aAAa,GAAG,IAAI,CAAC,uBAAuB,CAClD,gCACAT,QAAQ,GAAG,CAAC,4BAA4B;QAG1C,IACCA,QAAQ,GAAG,CAAC,sBAAsB,IAClC;YAAC;YAAS;YAAQ;YAAQ;SAAQ,CAAC,QAAQ,CAACA,QAAQ,GAAG,CAAC,sBAAsB,GAE9ES,OAAO,QAAQ,GAAGT,QAAQ,GAAG,CAAC,sBAAsB;QAErD,IAAIA,AAAwC,YAAxCA,QAAQ,GAAG,CAAC,uBAAuB,EACtCS,OAAO,SAAS,GAAG;QAEpB,IAAIT,AAAwCU,WAAxCV,QAAQ,GAAG,CAAC,uBAAuB,EACtCS,OAAO,SAAS,GACfT,AAAwC,OAAxCA,QAAQ,GAAG,CAAC,uBAAuB,GAChC,EAAE,GACFA,QAAQ,GAAG,CAAC,uBAAuB,CAAC,KAAK,CAAC;QAE/C,IAAIA,AAAuCU,WAAvCV,QAAQ,GAAG,CAAC,sBAAsB,EACrCS,OAAO,QAAQ,GACdT,AAAuC,OAAvCA,QAAQ,GAAG,CAAC,sBAAsB,GAC/B,EAAE,GACFA,QAAQ,GAAG,CAAC,sBAAsB,CAAC,KAAK,CAAC;QAE9C,IAAIA,AAAiDU,WAAjDV,QAAQ,GAAG,CAAC,gCAAgC,EAAgB;YAC/D,MAAMW,UAAU,IAAI,CAAC,uBAAuB,CAC3C,oCACAX,QAAQ,GAAG,CAAC,gCAAgC;YAE7C,MAAMY,MAAMD,AAAU,OAAVA;YACZ,IAAI,CAACE,OAAO,aAAa,CAACD,MACzB,MAAM,IAAIE,mBACT;YAGFL,OAAO,cAAc,GAAG;gBAAE,GAAGA,OAAO,cAAc;gBAAEG;YAAI;QACzD;QACA,IAAIZ,AAAsDU,WAAtDV,QAAQ,GAAG,CAAC,qCAAqC,EAAgB;YACpE,MAAMe,UAAU,IAAI,CAAC,uBAAuB,CAC3C,yCACAf,QAAQ,GAAG,CAAC,qCAAqC;YAElDS,OAAO,cAAc,GAAG;gBAAE,GAAGA,OAAO,cAAc;gBAAEM;YAAQ;QAC7D;QACA,IAAIf,AAAoDU,WAApDV,QAAQ,GAAG,CAAC,mCAAmC,EAClDS,OAAO,mBAAmB,GAAG,IAAI,CAAC,uBAAuB,CACxD,uCACAT,QAAQ,GAAG,CAAC,mCAAmC;QAGjD,IAAIA,AAAsDU,WAAtDV,QAAQ,GAAG,CAAC,qCAAqC,EACpDS,OAAO,qBAAqB,GAAG,IAAI,CAAC,uBAAuB,CAC1D,yCACAT,QAAQ,GAAG,CAAC,qCAAqC;QAGnD,IAAIA,AAAmDU,WAAnDV,QAAQ,GAAG,CAAC,kCAAkC,EACjDS,OAAO,mBAAmB,GAAG,IAAI,CAAC,uBAAuB,CACxD,sCACAT,QAAQ,GAAG,CAAC,kCAAkC;QAIhD,IAAI,CAAC,yBAAyB,CAACS;QAE/B,OAAOA;IACR;IAEQ,YAAYN,MAAyB,EAA8B;QAC1E,OAAO;YACN,GAAGA,MAAM;YACT,GAAIA,AAAqBO,WAArBP,OAAO,SAAS,GAAiB,CAAC,IAAI;gBAAE,WAAW;uBAAIA,OAAO,SAAS;iBAAC;YAAC,CAAC;YAC9E,GAAIA,AAAoBO,WAApBP,OAAO,QAAQ,GAAiB,CAAC,IAAI;gBAAE,UAAU;uBAAIA,OAAO,QAAQ;iBAAC;YAAC,CAAC;YAC3E,GAAIA,AAA0BO,WAA1BP,OAAO,cAAc,GACtB,CAAC,IACD;gBAAE,gBAAgB;oBAAE,GAAGA,OAAO,cAAc;gBAAC;YAAE,CAAC;YACnD,GAAIA,AAAuBO,WAAvBP,OAAO,WAAW,GACnB,CAAC,IACD;gBACA,aAAa;oBACZ,GAAGA,OAAO,WAAW;oBACrB,GAAIA,AAA+BO,WAA/BP,OAAO,WAAW,CAAC,OAAO,GAC3B,CAAC,IACD;wBAAE,SAAS;4BAAE,GAAGA,OAAO,WAAW,CAAC,OAAO;wBAAC;oBAAE,CAAC;gBAClD;YACD,CAAC;YACH,GAAIA,AAAoBO,WAApBP,OAAO,QAAQ,GAAiB,CAAC,IAAI;gBAAE,UAAU;oBAAE,GAAGA,OAAO,QAAQ;gBAAC;YAAE,CAAC;QAC9E;IACD;IAUQ,0BAA0BM,MAAkC,EAAQ;QAC3E,MAAMO,UAA4E;YACjF,iCAAiC;YACjC,mCAAmC;YACnC,mCAAmC;YACnC,uCAAuC;YACvC,yCAAyC;YACzC,yCAAyC;QAC1C;QACA,KAAK,MAAM,CAACC,QAAQC,IAAI,IAAIC,OAAO,OAAO,CAACH,SAAU;YACpD,MAAMI,MAAMpB,QAAQ,GAAG,CAACiB,OAAO;YAC/B,IAAIG,AAAQV,WAARU,KAAmB;YACvB,MAAMC,SAAS,IAAI,CAAC,YAAY,CAACD;YACjC,IAAIC,AAAWX,WAAXW,QAAsB;gBACzBd,QAAQ,IAAI,CACX,CAAC,0BAA0B,EAAEU,OAAO,GAAG,EAAEG,IAAI,sCAAsC,CAAC;gBAErF;YACD;YACA,MAAME,WACLb,OAAO,QAAQ,IAAI,CAAC;YACrBa,QAAQ,CAACJ,IAAI,GAAGG;YAChBZ,OAAO,QAAQ,GAAGa;QACnB;QAEA,MAAMC,cAAcvB,QAAQ,GAAG,CAAC,wCAAwC;QACxE,IAAIuB,AAAgBb,WAAhBa,aAA2B;YAC9B,IAAIA,AAAgB,iBAAhBA,eAAgCA,AAAgB,UAAhBA,aACnC,MAAM,IAAIT,mBACT,CAAC,6EAA6E,EAAES,aAAa;YAG/F,MAAMD,WACLb,OAAO,QAAQ,IAAI,CAAC;YACrBa,SAAS,iBAAiB,GAAGC;YAC7Bd,OAAO,QAAQ,GAAGa;QACnB;IACD;IAEQ,wBAAwBE,eAAuB,EAAEJ,GAAW,EAAU;QAC7E,IAAI,CAAC,iBAAiB,IAAI,CAACA,MAC1B,MAAM,IAAIN,mBAAmB,GAAGU,gBAAgB,yBAAyB,EAAEJ,KAAK;QAEjF,MAAMC,SAASR,OAAOO;QACtB,IAAI,CAACP,OAAO,aAAa,CAACQ,SACzB,MAAM,IAAIP,mBAAmB,GAAGU,gBAAgB,6BAA6B,EAAEJ,KAAK;QAErF,OAAOC;IACR;IAUQ,aAAaD,GAAW,EAAuB;QACtD,MAAMxB,IAAIwB,IAAI,IAAI,GAAG,WAAW;QAChC,IAAIxB,AAAM,WAANA,KAAgBA,AAAM,QAANA,GAAW,OAAO;QACtC,IAAIA,AAAM,YAANA,KAAiBA,AAAM,QAANA,GAAW,OAAO;IAExC;IAaQ,YAAY6B,QAAgB,EAAqB;QACxD,MAAMC,UAAUC,aAAaF,UAAU;QACvC,MAAMG,MAAMH,SAAS,KAAK,CAAC,KAAK,GAAG,IAAI;QAEvC,MAAML,MAAeQ,AAAQ,WAARA,OAAkBA,AAAQ,UAARA,MAAgBC,MAAUH,WAAWI,KAAK,KAAK,CAACJ;QAEvF,OAAO9B,0BAAAA,KAAO,CAACD,yBAAyByB;IACzC;IAqBA,sBAAsBjB,MAAyB,EAAuB;QACrE,OAAO;YACN,gBAAgBA,OAAO,cAAc;YACrC,aAAaA,OAAO,WAAW;YAC/B,eAAeA,OAAO,aAAa;YACnC,WAAWA,OAAO,SAAS;YAC3B,UAAUA,OAAO,QAAQ;YACzB,gBAAgBA,OAAO,cAAc;YACrC,aAAaA,OAAO,WAAW;YAC/B,uBAAuBA,OAAO,qBAAqB;YACnD,0BAA0BA,OAAO,wBAAwB;YACzD,uBAAuBA,OAAO,qBAAqB;YACnD,UAAUA,OAAO,QAAQ;YACzB,qBAAqBA,OAAO,mBAAmB;YAC/C,uBAAuBA,OAAO,qBAAqB;YACnD,qBAAqBA,OAAO,mBAAmB;QAChD;IACD;AACD"}
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 supported settings. Persistence buffer, flush, and retry settings are file-only.\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 * as v from 'valibot';\nimport type { PersistenceConfig } from '../contracts/PersistenceBackend.js';\nimport { ConfigurationError, getErrorMessage } from '../errors.js';\nimport type { FeatureFlags } from '../contracts/features.js';\nimport type { ServerConfigOptions } from '../ServerConfig.js';\n\n/**\n * Lenient runtime schema for config files. Only validates top-level shape;\n * unknown extra fields are preserved by Valibot's default object behavior\n * being strict is avoided by using `v.looseObject`. All fields are optional.\n */\nconst ConfigFileOptionsSchema = v.looseObject({\n\tmaxHistorySize: v.optional(v.number()),\n\tmaxBranches: v.optional(v.number()),\n\tmaxBranchSize: v.optional(v.number()),\n\tlogLevel: v.optional(v.picklist(['debug', 'info', 'warn', 'error'])),\n\tprettyLog: v.optional(v.boolean()),\n\tskillDirs: v.optional(v.array(v.string())),\n\ttoolDirs: v.optional(v.array(v.string())),\n\tdiscoveryCache: v.optional(\n\t\tv.looseObject({\n\t\t\tttl: v.optional(v.number()),\n\t\t\tmaxSize: v.optional(v.number()),\n\t\t})\n\t),\n\tpersistence: v.optional(v.looseObject({})),\n\tpersistenceBufferSize: v.optional(v.number()),\n\tpersistenceFlushInterval: v.optional(v.number()),\n\tpersistenceMaxRetries: v.optional(v.number()),\n\tfeatures: v.optional(v.looseObject({})),\n\ttoolInterleaveTtlMs: v.optional(v.number()),\n\ttoolInterleaveSweepMs: v.optional(v.number()),\n\tmaxSessionsPerOwner: v.optional(v.number()),\n});\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. Only supported fields have\n * environment overrides; persistence buffer, flush, and retry settings are file-only.\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 * toolDirs:\n * - ./custom-tools\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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_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 `TRACELATTICE_SKILL_DIRS` environment variable (colon-separated).\n\t */\n\treadonly skillDirs?: string[];\n\n\t/**\n\t * Directory paths to search for tools.\n\t * Can be overridden by `TRACELATTICE_TOOL_DIRS` environment variable (colon-separated).\n\t */\n\treadonly toolDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t * Can be overridden by `TRACELATTICE_DISCOVERY_CACHE_TTL` and\n\t * `TRACELATTICE_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 `TRACELATTICE_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/** Maximum buffered thoughts before flushing; file-only (default 100 in ServerConfig). */\n\treadonly persistenceBufferSize?: number;\n\n\t/** Periodic flush interval in milliseconds; file-only (default 1000 in ServerConfig). */\n\treadonly persistenceFlushInterval?: number;\n\n\t/** Maximum flush retries; file-only (default 3 in ServerConfig). */\n\treadonly persistenceMaxRetries?: number;\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 `TRACELATTICE_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 valid match being used. Supported environment variables take precedence over file values.\n *\n * @remarks\n * **Config File Search Order (priority):**\n * 1. Custom path or `TRACELATTICE_CONFIG` (if present, replaces the default search list)\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 * | `TRACELATTICE_MAX_HISTORY_SIZE` | number | Max thoughts in history |\n * | `TRACELATTICE_MAX_BRANCHES` | number | Max number of branches |\n * | `TRACELATTICE_MAX_BRANCH_SIZE` | number | Max size of each branch |\n * | `TRACELATTICE_LOG_LEVEL` | string | Logging level (debug/info/warn/error) |\n * | `TRACELATTICE_PRETTY_LOG` | string | \"false\" to disable pretty logging |\n * | `TRACELATTICE_SKILL_DIRS` | string | Colon-separated directory paths |\n * | `TRACELATTICE_TOOL_DIRS` | string | Colon-separated directory paths |\n * | `TRACELATTICE_DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |\n * | `TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE` | number | Max cache entries |\n * | `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` / `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` | number | Milliseconds |\n * | `TRACELATTICE_SESSION_MAX_PER_OWNER` | number | Max sessions per owner |\n * | `TRACELATTICE_FEATURES_*` | boolean or strategy | Feature toggles or `sequential`/`tot` |\n *\n * Persistence buffer size, flush interval (milliseconds), and retries are file-only.\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\tconst configuredPath = customPath ?? process.env.TRACELATTICE_CONFIG;\n\t\tthis._configPaths = configuredPath\n\t\t\t? [configuredPath]\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 * A malformed file is logged and skipped. With no valid file, applies environment\n\t * overrides to an empty object (the declared nullable return type does not return null).\n\t *\n\t * @returns The loaded configuration with environment overrides applied, or an empty/overlaid object\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(`Failed to load config from ${configPath}:`, getErrorMessage(error));\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 * - `TRACELATTICE_MAX_HISTORY_SIZE`, `TRACELATTICE_MAX_BRANCHES`,\n\t * `TRACELATTICE_MAX_BRANCH_SIZE` (numbers)\n\t * - `TRACELATTICE_LOG_LEVEL` (debug/info/warn/error)\n\t * - `TRACELATTICE_PRETTY_LOG` (\"false\" to disable)\n\t * - `TRACELATTICE_SKILL_DIRS` (colon-separated paths)\n\t * - `TRACELATTICE_TOOL_DIRS` (colon-separated paths)\n\t * - `TRACELATTICE_DISCOVERY_CACHE_TTL` (in seconds, converted to ms)\n\t * - `TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE` (number)\n\t * - `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS`, `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` (milliseconds)\n\t * - `TRACELATTICE_SESSION_MAX_PER_OWNER` (number)\n\t * - `TRACELATTICE_FEATURES_*` (booleans true/false/1/0 or sequential/tot strategy)\n\t * Persistence buffer, flush interval, and retry settings have no environment aliases.\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 */\n\tpublic applyEnvironmentOverrides(config: ConfigFileOptions): ConfigFileOptions {\n\t\tconst result = this.cloneConfig(config);\n\n\t\tif (process.env.TRACELATTICE_MAX_HISTORY_SIZE !== undefined) {\n\t\t\tresult.maxHistorySize = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_MAX_HISTORY_SIZE',\n\t\t\t\tprocess.env.TRACELATTICE_MAX_HISTORY_SIZE\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_MAX_BRANCHES !== undefined) {\n\t\t\tresult.maxBranches = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_MAX_BRANCHES',\n\t\t\t\tprocess.env.TRACELATTICE_MAX_BRANCHES\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_MAX_BRANCH_SIZE !== undefined) {\n\t\t\tresult.maxBranchSize = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_MAX_BRANCH_SIZE',\n\t\t\t\tprocess.env.TRACELATTICE_MAX_BRANCH_SIZE\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tprocess.env.TRACELATTICE_LOG_LEVEL &&\n\t\t\t['debug', 'info', 'warn', 'error'].includes(process.env.TRACELATTICE_LOG_LEVEL)\n\t\t) {\n\t\t\tresult.logLevel = process.env.TRACELATTICE_LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error';\n\t\t}\n\t\tif (process.env.TRACELATTICE_PRETTY_LOG === 'false') {\n\t\t\tresult.prettyLog = false;\n\t\t}\n\t\tif (process.env.TRACELATTICE_SKILL_DIRS !== undefined) {\n\t\t\tresult.skillDirs =\n\t\t\t\tprocess.env.TRACELATTICE_SKILL_DIRS === ''\n\t\t\t\t\t? []\n\t\t\t\t\t: process.env.TRACELATTICE_SKILL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_DIRS !== undefined) {\n\t\t\tresult.toolDirs =\n\t\t\t\tprocess.env.TRACELATTICE_TOOL_DIRS === ''\n\t\t\t\t\t? []\n\t\t\t\t\t: process.env.TRACELATTICE_TOOL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.TRACELATTICE_DISCOVERY_CACHE_TTL !== undefined) {\n\t\t\tconst seconds = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_DISCOVERY_CACHE_TTL',\n\t\t\t\tprocess.env.TRACELATTICE_DISCOVERY_CACHE_TTL\n\t\t\t);\n\t\t\tconst ttl = seconds * 1000;\n\t\t\tif (!Number.isSafeInteger(ttl)) {\n\t\t\t\tthrow new ConfigurationError(\n\t\t\t\t\t'TRACELATTICE_DISCOVERY_CACHE_TTL exceeds the safe integer range'\n\t\t\t\t);\n\t\t\t}\n\t\t\tresult.discoveryCache = { ...result.discoveryCache, ttl };\n\t\t}\n\t\tif (process.env.TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE !== undefined) {\n\t\t\tconst maxSize = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE',\n\t\t\t\tprocess.env.TRACELATTICE_DISCOVERY_CACHE_MAX_SIZE\n\t\t\t);\n\t\t\tresult.discoveryCache = { ...result.discoveryCache, maxSize };\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS !== undefined) {\n\t\t\tresult.toolInterleaveTtlMs = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_TOOL_INTERLEAVE_TTL_MS',\n\t\t\t\tprocess.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS !== undefined) {\n\t\t\tresult.toolInterleaveSweepMs = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS',\n\t\t\t\tprocess.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS\n\t\t\t);\n\t\t}\n\t\tif (process.env.TRACELATTICE_SESSION_MAX_PER_OWNER !== undefined) {\n\t\t\tresult.maxSessionsPerOwner = this.parseEnvironmentInteger(\n\t\t\t\t'TRACELATTICE_SESSION_MAX_PER_OWNER',\n\t\t\t\tprocess.env.TRACELATTICE_SESSION_MAX_PER_OWNER\n\t\t\t);\n\t\t}\n\n\t\tthis.applyFeatureFlagOverrides(result);\n\n\t\treturn result;\n\t}\n\n\tprivate cloneConfig(config: ConfigFileOptions): Mutable<ConfigFileOptions> {\n\t\treturn {\n\t\t\t...config,\n\t\t\t...(config.skillDirs === undefined ? {} : { skillDirs: [...config.skillDirs] }),\n\t\t\t...(config.toolDirs === undefined ? {} : { toolDirs: [...config.toolDirs] }),\n\t\t\t...(config.discoveryCache === undefined\n\t\t\t\t? {}\n\t\t\t\t: { discoveryCache: { ...config.discoveryCache } }),\n\t\t\t...(config.persistence === undefined\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tpersistence: {\n\t\t\t\t\t\t\t...config.persistence,\n\t\t\t\t\t\t\t...(config.persistence.options === undefined\n\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t: { options: { ...config.persistence.options } }),\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t...(config.features === undefined ? {} : { features: { ...config.features } }),\n\t\t};\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 rejected.\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\tif (strategyRaw !== 'sequential' && strategyRaw !== 'tot') {\n\t\t\t\tthrow new ConfigurationError(\n\t\t\t\t\t`TRACELATTICE_FEATURES_REASONING_STRATEGY must be one of sequential, tot, got ${strategyRaw}`\n\t\t\t\t);\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.reasoningStrategy = strategyRaw;\n\t\t\tresult.features = features;\n\t\t}\n\t}\n\n\tprivate parseEnvironmentInteger(environmentName: string, raw: string): number {\n\t\tif (!/^(0|[1-9]\\d*)$/.test(raw)) {\n\t\t\tthrow new ConfigurationError(`${environmentName} must be an integer, got ${raw}`);\n\t\t}\n\t\tconst parsed = Number(raw);\n\t\tif (!Number.isSafeInteger(parsed)) {\n\t\t\tthrow new ConfigurationError(`${environmentName} must be a safe integer, got ${raw}`);\n\t\t}\n\t\treturn parsed;\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\tconst raw: unknown = ext === 'yaml' || ext === 'yml' ? parseYaml(content) : JSON.parse(content);\n\n\t\treturn v.parse(ConfigFileOptionsSchema, raw) 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): ServerConfigOptions {\n\t\treturn {\n\t\t\tmaxHistorySize: config.maxHistorySize,\n\t\t\tmaxBranches: config.maxBranches,\n\t\t\tmaxBranchSize: config.maxBranchSize,\n\t\t\tskillDirs: config.skillDirs,\n\t\t\ttoolDirs: config.toolDirs,\n\t\t\tdiscoveryCache: config.discoveryCache,\n\t\t\tpersistence: config.persistence,\n\t\t\tpersistenceBufferSize: config.persistenceBufferSize,\n\t\t\tpersistenceFlushInterval: config.persistenceFlushInterval,\n\t\t\tpersistenceMaxRetries: config.persistenceMaxRetries,\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":["ConfigFileOptionsSchema","v","ConfigLoader","customPath","configuredPath","process","join","homedir","config","configPath","existsSync","error","console","getErrorMessage","result","undefined","seconds","ttl","Number","ConfigurationError","maxSize","boolMap","envVar","key","Object","raw","parsed","features","strategyRaw","environmentName","filePath","content","readFileSync","ext","parseYaml","JSON"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.impl.d.ts","sourceRoot":"","sources":["../../src/metrics/metrics.impl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,oBAAY,UAAU;IACrB,wDAAwD;IACxD,OAAO,YAAY;IAEnB,+CAA+C;IAC/C,KAAK,UAAU;IAEf,qDAAqD;IACrD,SAAS,cAAc;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACtB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb,iDAAiD;IACjD,IAAI,EAAE,UAAU,CAAC;IAEjB,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IAEd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE/B,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qBAAa,OAAO;IACnB,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAsB;IAEtC,wBAAwB;IACxB,OAAO,CAAC,WAAW,CAA+B;IAElD,kCAAkC;IAClC,OAAO,CAAC,OAAO,CAAS;IAExB,6CAA6C;IAC7C,OAAO,CAAC,cAAc,CAAyB;IAE/C,+CAA+C;IAC/C,OAAO,CAAC,kBAAkB,CAAa;IAEvC;;;;;;;;;OASG;gBACS,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAO;IAOrF;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAuB1F;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAe5F;;;;;;;;;;;;;;OAcG;IACH,SAAS,CACR,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACnC,OAAO,WAAkB,GACvB,IAAI;IAkCP;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,GAAG,SAAS;IAO1E;;;;;;;;;;OAUG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAIxD;;;;;;;;;;OAUG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAKxD;;;;;;;;OAQG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;;;;;;OAUG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;;;;;;;;;;;;;OAcG;IACH,MAAM,IAAI,MAAM;IA8DhB;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IASjB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,iBAAiB;CAGzB"}
1
+ {"version":3,"file":"metrics.impl.d.ts","sourceRoot":"","sources":["../../src/metrics/metrics.impl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,oBAAY,UAAU;IACrB,wDAAwD;IACxD,OAAO,YAAY;IAEnB,+CAA+C;IAC/C,KAAK,UAAU;IAEf,qDAAqD;IACrD,SAAS,cAAc;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACtB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb,iDAAiD;IACjD,IAAI,EAAE,UAAU,CAAC;IAEjB,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IAEd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE/B,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAgBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qBAAa,OAAO;IACnB,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAsB;IAEtC,wBAAwB;IACxB,OAAO,CAAC,WAAW,CAA+B;IAElD,kCAAkC;IAClC,OAAO,CAAC,OAAO,CAAS;IAExB,6CAA6C;IAC7C,OAAO,CAAC,cAAc,CAAyB;IAE/C,+CAA+C;IAC/C,OAAO,CAAC,kBAAkB,CAAa;IAEvC;;;;;;;;;OASG;gBACS,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAO;IAOrF;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAuB1F;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAe5F;;;;;;;;;;;;;;OAcG;IACH,SAAS,CACR,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACnC,OAAO,WAAkB,GACvB,IAAI;IA6CP;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,GAAG,SAAS;IAO1E;;;;;;;;;;OAUG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAIxD;;;;;;;;;;OAUG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAKxD;;;;;;;;OAQG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;;;;;;OAUG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;;;;;;;;;;;;;OAcG;IACH,MAAM,IAAI,MAAM;IA+DhB;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IASjB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,iBAAiB;CAGzB"}
@@ -80,12 +80,16 @@ class Metrics {
80
80
  };
81
81
  const key = this._metricKey(fullName, allLabels);
82
82
  const histogram = this._histograms.get(key);
83
+ let previousBoundary = -1 / 0;
84
+ for (const boundary of buckets){
85
+ if (!Number.isFinite(boundary) || boundary <= previousBoundary) throw new RangeError('Histogram boundaries must be finite and strictly increasing');
86
+ previousBoundary = boundary;
87
+ }
88
+ if (histogram && (histogram.boundaries.length !== buckets.length || histogram.boundaries.some((boundary, index)=>boundary !== buckets[index]))) throw new RangeError('Histogram bucket layout differs from the existing series');
83
89
  if (histogram) {
84
90
  histogram.sum += value;
85
91
  histogram.count += 1;
86
- for (const boundary of buckets)if (value <= boundary) histogram.buckets.set(boundary, (histogram.buckets.get(boundary) ?? 0) + 1);
87
- else histogram.buckets.set(boundary, histogram.buckets.get(boundary) ?? 0);
88
- histogram.buckets.set(1 / 0, (histogram.buckets.get(1 / 0) ?? 0) + 1);
92
+ for (const boundary of histogram.boundaries)if (value <= boundary) histogram.buckets.set(boundary, (histogram.buckets.get(boundary) ?? 0) + 1);
89
93
  } else {
90
94
  const histogramData = {
91
95
  name: fullName,
@@ -94,10 +98,12 @@ class Metrics {
94
98
  },
95
99
  sum: value,
96
100
  count: 1,
101
+ boundaries: [
102
+ ...buckets
103
+ ],
97
104
  buckets: new Map()
98
105
  };
99
106
  for (const boundary of buckets)histogramData.buckets.set(boundary, value <= boundary ? 1 : 0);
100
- histogramData.buckets.set(1 / 0, 1);
101
107
  this._histograms.set(key, histogramData);
102
108
  }
103
109
  this._operationsCounter++;
@@ -135,7 +141,7 @@ class Metrics {
135
141
  for (const metric of metrics){
136
142
  if (!helpEntries.has(metric.name)) {
137
143
  const helpText = metric.help ?? `${metric.name} metric`;
138
- lines.push(`# HELP ${metric.name} ${helpText}`);
144
+ lines.push(`# HELP ${metric.name} ${helpText.replaceAll('\\', '\\\\').replaceAll('\n', '\\n')}`);
139
145
  helpEntries.set(metric.name, helpText);
140
146
  }
141
147
  if (!typeEntries.has(metric.name)) {
@@ -159,14 +165,20 @@ class Metrics {
159
165
  };
160
166
  lines.push(formatMetricLine('_sum', histogram.sum));
161
167
  lines.push(formatMetricLine('_count', histogram.count));
162
- for (const [boundary, count] of histogram.buckets.entries()){
163
- const boundaryLabel = 1 / 0 === boundary ? '+Inf' : Number.isFinite(boundary) ? String(boundary) : String(boundary);
168
+ for (const boundary of histogram.boundaries){
169
+ const count = histogram.buckets.get(boundary);
170
+ const boundaryLabel = String(boundary);
164
171
  const boundaryLabelStr = this._formatLabels({
165
172
  le: boundaryLabel
166
173
  });
167
174
  const bucketLabels = 0 === labelStr.length ? boundaryLabelStr : `${labelStr},${boundaryLabelStr}`;
168
175
  lines.push(`${fullName}_bucket{${bucketLabels}} ${count}`);
169
176
  }
177
+ const infLabelStr = this._formatLabels({
178
+ le: '+Inf'
179
+ });
180
+ const infLabels = 0 === labelStr.length ? infLabelStr : `${labelStr},${infLabelStr}`;
181
+ lines.push(`${fullName}_bucket{${infLabels}} ${histogram.count}`);
170
182
  }
171
183
  }
172
184
  return lines.join('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"metrics/metrics.impl.js","sources":["../../src/metrics/metrics.impl.ts"],"sourcesContent":["/**\n * Prometheus-compatible metrics collection.\n *\n * This module provides metrics collection and export in Prometheus text format.\n * Supports counters, gauges, and histograms for observability.\n *\n * @module metrics\n */\n\n/**\n * Metric types supported by the metrics collector.\n */\nexport enum MetricType {\n\t/** Counter - a cumulative metric that only increases */\n\tCounter = 'counter',\n\n\t/** Gauge - a metric that can go up and down */\n\tGauge = 'gauge',\n\n\t/** Histogram - a metric for sampling observations */\n\tHistogram = 'histogram',\n}\n\n/**\n * A collected metric with its value and labels.\n */\nexport interface Metric {\n\t/** Name of the metric */\n\tname: string;\n\n\t/** Type of metric (counter, gauge, histogram) */\n\ttype: MetricType;\n\n\t/** Current value */\n\tvalue: number;\n\n\t/** Labels for the metric */\n\tlabels: Record<string, string>;\n\n\t/** Help text describing the metric */\n\thelp?: string;\n\n\t/** Timestamp when metric was recorded (Unix epoch) */\n\ttimestamp?: number;\n}\n\ninterface HistogramMetric {\n\tname: string;\n\tlabels: Record<string, string>;\n\tsum: number;\n\tcount: number;\n\tbuckets: Map<number, number>;\n}\n\n/**\n * Histogram bucket boundaries for latency tracking.\n */\nconst DEFAULT_BUCKETS = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\n\n/**\n * Prometheus-compatible metrics collector.\n *\n * Collects and exports metrics in Prometheus text format for scraping.\n * Thread-safe and supports counters, gauges, and histograms.\n *\n * @remarks\n * **Metric Types:**\n * - **Counter**: Cumulative value that only increases (e.g., request counts)\n * - **Gauge**: Value that can go up or down (e.g., active connections)\n * - **Histogram**: Sampling observations (e.g., request latency)\n *\n * **Labels:**\n * Metrics can have labels for dimensional data:\n * ```typescript\n * counter('http_requests_total', { method: 'GET', status: '200' });\n * ```\n *\n * **Export Format:**\n * Metrics are exported in Prometheus text format:\n * ```\n * # HELP http_requests_total Total HTTP requests\n * # TYPE http_requests_total counter\n * http_requests_total{method=\"GET\",status=\"200\"} 1234\n * ```\n *\n * @example\n * ```typescript\n * const metrics = new Metrics({ prefix: 'mcp_server' });\n *\n * // Count requests\n * metrics.counter('requests_total', { method: 'GET' }).inc();\n *\n * // Track active connections\n * const activeConnections = metrics.gauge('active_connections');\n * activeConnections.set(5);\n * activeConnections.dec();\n *\n * // Record latency\n * metrics.histogram('request_duration_seconds').observe(0.023);\n *\n * // Export for Prometheus\n * const prometheusText = metrics.export();\n * ```\n */\nexport class Metrics {\n\t/** Metrics storage indexed by name and label hash */\n\tprivate _metrics: Map<string, Metric>;\n\n\t/** Histogram samples */\n\tprivate _histograms: Map<string, HistogramMetric>;\n\n\t/** Prefix for all metric names */\n\tprivate _prefix: string;\n\n\t/** Default labels to apply to all metrics */\n\tprivate _defaultLabels: Record<string, string>;\n\n\t/** Counter for metric collection operations */\n\tprivate _operationsCounter: number = 0;\n\n\t/**\n\t * Creates a new Metrics instance.\n\t *\n\t * @param options - Configuration options\n\t *\n\t * @example\n\t * ```typescript\n\t * const metrics = new Metrics({ prefix: 'mcp_server' });\n\t * ```\n\t */\n\tconstructor(options: { prefix?: string; defaultLabels?: Record<string, string> } = {}) {\n\t\tthis._metrics = new Map();\n\t\tthis._histograms = new Map();\n\t\tthis._prefix = options.prefix ?? '';\n\t\tthis._defaultLabels = { ...options.defaultLabels };\n\t}\n\n\t/**\n\t * Creates a counter metric.\n\t *\n\t * @param name - Metric name\n\t * @param value - Increment value (default: 1)\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.counter('requests_total', 1, { method: 'GET' });\n\t * metrics.counter('errors_total', 1, { type: 'timeout' });\n\t * ```\n\t */\n\tcounter(name: string, value = 1, labels: Record<string, string> = {}, help?: string): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst existing = this._metrics.get(key);\n\n\t\tif (existing) {\n\t\t\texisting.value += value;\n\t\t\tif (help && !existing.help) {\n\t\t\t\texisting.help = help;\n\t\t\t}\n\t\t} else {\n\t\t\tthis._metrics.set(key, {\n\t\t\t\tname: fullName,\n\t\t\t\ttype: MetricType.Counter,\n\t\t\t\tvalue,\n\t\t\t\tlabels: { ...allLabels },\n\t\t\t\thelp,\n\t\t\t});\n\t\t}\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Creates a gauge metric.\n\t *\n\t * @param name - Metric name\n\t * @param value - Current value\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t *\n\t * @example\n\t * ```typescript\n\t * const activeConnections = metrics.gauge('active_connections');\n\t * activeConnections.set(5);\n\t * activeConnections.dec();\n\t * ```\n\t */\n\tgauge(name: string, value: number, labels: Record<string, string> = {}, help?: string): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst existing = this._metrics.get(key);\n\t\tthis._metrics.set(key, {\n\t\t\tname: fullName,\n\t\t\ttype: MetricType.Gauge,\n\t\t\tvalue,\n\t\t\tlabels: { ...allLabels },\n\t\t\thelp: help ?? existing?.help,\n\t\t});\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Records a histogram observation.\n\t *\n\t * @param name - Histogram name\n\t * @param value - Observed value\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t * @param buckets - Custom bucket boundaries\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.histogram('request_duration_seconds').observe(0.023);\n\t * metrics.histogram('thought_processing_ms').observe(45);\n\t * ```\n\t */\n\thistogram(\n\t\tname: string,\n\t\tvalue: number,\n\t\tlabels: Record<string, string> = {},\n\t\tbuckets = DEFAULT_BUCKETS\n\t): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst histogram = this._histograms.get(key);\n\n\t\tif (histogram) {\n\t\t\thistogram.sum += value;\n\t\t\thistogram.count += 1;\n\t\t\tfor (const boundary of buckets) {\n\t\t\t\tif (value <= boundary) {\n\t\t\t\t\thistogram.buckets.set(boundary, (histogram.buckets.get(boundary) ?? 0) + 1);\n\t\t\t\t} else {\n\t\t\t\t\thistogram.buckets.set(boundary, histogram.buckets.get(boundary) ?? 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\thistogram.buckets.set(Infinity, (histogram.buckets.get(Infinity) ?? 0) + 1);\n\t\t} else {\n\t\t\tconst histogramData = {\n\t\t\t\tname: fullName,\n\t\t\t\tlabels: { ...allLabels },\n\t\t\t\tsum: value,\n\t\t\t\tcount: 1,\n\t\t\t\tbuckets: new Map<number, number>(),\n\t\t\t};\n\t\t\tfor (const boundary of buckets) {\n\t\t\t\thistogramData.buckets.set(boundary, value <= boundary ? 1 : 0);\n\t\t\t}\n\t\t\thistogramData.buckets.set(Infinity, 1);\n\t\t\tthis._histograms.set(key, histogramData);\n\t\t}\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Gets the current value of a metric.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Labels\n\t * @returns Current value or undefined if not found\n\t *\n\t * @example\n\t * ```typescript\n\t * const count = metrics.get('requests_total', { method: 'GET' });\n\t * ```\n\t */\n\tget(name: string, labels: Record<string, string> = {}): number | undefined {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\treturn this._metrics.get(key)?.value;\n\t}\n\n\t/**\n\t * Increments a counter by 1.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Optional labels\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.inc('requests_total', { method: 'GET' });\n\t * ```\n\t */\n\tinc(name: string, labels?: Record<string, string>): void {\n\t\tthis.counter(name, 1, labels);\n\t}\n\n\t/**\n\t * Decrements a gauge by 1.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Optional labels\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.dec('active_connections');\n\t * ```\n\t */\n\tdec(name: string, labels?: Record<string, string>): void {\n\t\tconst value = this.get(name, labels) ?? 0;\n\t\tthis.gauge(name, value - 1, labels);\n\t}\n\n\t/**\n\t * Resets all metrics to zero.\n\t * Useful for testing or on server restart.\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.reset();\n\t * ```\n\t */\n\treset(): void {\n\t\tthis._metrics.clear();\n\t\tthis._histograms.clear();\n\t\tthis._operationsCounter = 0;\n\t}\n\n\t/**\n\t * Gets the number of metric operations performed.\n\t * Useful for testing.\n\t *\n\t * @returns Operation count\n\t *\n\t * @example\n\t * ```typescript\n\t * const ops = metrics.getOperationCount();\n\t * ```\n\t */\n\tgetOperationCount(): number {\n\t\treturn this._operationsCounter;\n\t}\n\n\t/**\n\t * Exports metrics in Prometheus text format.\n\t *\n\t * @returns Prometheus text format string\n\t *\n\t * @example\n\t * ```typescript\n\t * const prometheusText = metrics.export();\n\t * console.log(prometheusText);\n\t * // Output:\n\t * // # HELP http_requests_total Total HTTP requests\n\t * // # TYPE http_requests_total counter\n\t * // http_requests_total{method=\"GET\",status=\"200\"} 1234\n\t * ```\n\t */\n\texport(): string {\n\t\tconst lines: string[] = [];\n\n\t\tconst metrics = Array.from(this._metrics.values());\n\t\tconst histograms = Array.from(this._histograms.values());\n\n\t\tconst helpEntries = new Map<string, string>();\n\t\tconst typeEntries = new Map<string, MetricType>();\n\n\t\tfor (const metric of metrics) {\n\t\t\tif (!helpEntries.has(metric.name)) {\n\t\t\t\tconst helpText = metric.help ?? `${metric.name} metric`;\n\t\t\t\tlines.push(`# HELP ${metric.name} ${helpText}`);\n\t\t\t\thelpEntries.set(metric.name, helpText);\n\t\t\t}\n\t\t\tif (!typeEntries.has(metric.name)) {\n\t\t\t\tlines.push(`# TYPE ${metric.name} ${metric.type}`);\n\t\t\t\ttypeEntries.set(metric.name, metric.type);\n\t\t\t}\n\n\t\t\tconst labelStr = this._formatLabels(metric.labels);\n\t\t\tlines.push(`${metric.name}{${labelStr}} ${metric.value}`);\n\t\t}\n\n\t\tfor (const histogram of histograms) {\n\t\t\tconst { name: fullName, labels } = histogram;\n\t\t\tif (histogram.count > 0) {\n\t\t\t\tif (!typeEntries.has(fullName)) {\n\t\t\t\t\tlines.push(`# TYPE ${fullName} histogram`);\n\t\t\t\t\ttypeEntries.set(fullName, MetricType.Histogram);\n\t\t\t\t}\n\n\t\t\t\tconst labelStr = this._formatLabels(labels);\n\t\t\t\tconst formatMetricLine = (suffix: string, value: number): string => {\n\t\t\t\t\tif (labelStr.length === 0) {\n\t\t\t\t\t\treturn `${fullName}${suffix} ${value}`;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn `${fullName}${suffix}{${labelStr}} ${value}`;\n\t\t\t\t};\n\n\t\t\t\tlines.push(formatMetricLine('_sum', histogram.sum));\n\t\t\t\tlines.push(formatMetricLine('_count', histogram.count));\n\n\t\t\t\tfor (const [boundary, count] of histogram.buckets.entries()) {\n\t\t\t\t\tconst boundaryLabel =\n\t\t\t\t\t\tboundary === Infinity\n\t\t\t\t\t\t\t? '+Inf'\n\t\t\t\t\t\t\t: Number.isFinite(boundary)\n\t\t\t\t\t\t\t\t? String(boundary)\n\t\t\t\t\t\t\t\t: String(boundary);\n\t\t\t\t\tconst boundaryLabelStr = this._formatLabels({ le: boundaryLabel });\n\t\t\t\t\tconst bucketLabels =\n\t\t\t\t\t\tlabelStr.length === 0 ? boundaryLabelStr : `${labelStr},${boundaryLabelStr}`;\n\t\t\t\t\tlines.push(`${fullName}_bucket{${bucketLabels}} ${count}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join('\\n');\n\t}\n\n\t/**\n\t * Gets metric name with prefix.\n\t * @param name - Metric name\n\t * @returns Full metric name\n\t * @private\n\t */\n\tprivate _fullName(name: string): string {\n\t\tif (!this._prefix) {\n\t\t\treturn name;\n\t\t}\n\n\t\tconst prefix = `${this._prefix}_`;\n\t\treturn name.startsWith(prefix) ? name : `${prefix}${name}`;\n\t}\n\n\t/**\n\t * Creates a unique key for a metric with labels.\n\t * @param name - Metric name\n\t * @param labels - Labels\n\t * @returns Unique key\n\t * @private\n\t */\n\tprivate _metricKey(name: string, labels: Record<string, string>): string {\n\t\tconst sortedLabels = Object.entries(labels).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n\t\treturn JSON.stringify([name, sortedLabels]);\n\t}\n\n\tprivate _formatLabels(labels: Record<string, string>): string {\n\t\treturn Object.entries(labels)\n\t\t\t.map(([key, value]) => `${key}=\"${this._escapeLabelValue(value)}\"`)\n\t\t\t.join(',');\n\t}\n\n\tprivate _escapeLabelValue(value: string): string {\n\t\treturn value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"').replaceAll('\\n', '\\\\n');\n\t}\n}\n"],"names":["MetricType","DEFAULT_BUCKETS","Metrics","options","Map","name","value","labels","help","fullName","allLabels","key","existing","buckets","histogram","boundary","Infinity","histogramData","lines","metrics","Array","histograms","helpEntries","typeEntries","metric","helpText","labelStr","formatMetricLine","suffix","count","boundaryLabel","Number","String","boundaryLabelStr","bucketLabels","prefix","sortedLabels","Object","a","b","JSON"],"mappings":"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"}
1
+ {"version":3,"file":"metrics/metrics.impl.js","sources":["../../src/metrics/metrics.impl.ts"],"sourcesContent":["/**\n * Prometheus-compatible metrics collection.\n *\n * This module provides metrics collection and export in Prometheus text format.\n * Supports counters, gauges, and histograms for observability.\n *\n * @module metrics\n */\n\n/**\n * Metric types supported by the metrics collector.\n */\nexport enum MetricType {\n\t/** Counter - a cumulative metric that only increases */\n\tCounter = 'counter',\n\n\t/** Gauge - a metric that can go up and down */\n\tGauge = 'gauge',\n\n\t/** Histogram - a metric for sampling observations */\n\tHistogram = 'histogram',\n}\n\n/**\n * A collected metric with its value and labels.\n */\nexport interface Metric {\n\t/** Name of the metric */\n\tname: string;\n\n\t/** Type of metric (counter, gauge, histogram) */\n\ttype: MetricType;\n\n\t/** Current value */\n\tvalue: number;\n\n\t/** Labels for the metric */\n\tlabels: Record<string, string>;\n\n\t/** Help text describing the metric */\n\thelp?: string;\n\n\t/** Timestamp when metric was recorded (Unix epoch) */\n\ttimestamp?: number;\n}\n\ninterface HistogramMetric {\n\tname: string;\n\tlabels: Record<string, string>;\n\tsum: number;\n\tcount: number;\n\tboundaries: readonly number[];\n\tbuckets: Map<number, number>;\n}\n\n/**\n * Histogram bucket boundaries for latency tracking.\n */\nconst DEFAULT_BUCKETS = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\n\n/**\n * Prometheus-compatible metrics collector.\n *\n * Collects and exports metrics in Prometheus text format for scraping.\n * Thread-safe and supports counters, gauges, and histograms.\n *\n * @remarks\n * **Metric Types:**\n * - **Counter**: Cumulative value that only increases (e.g., request counts)\n * - **Gauge**: Value that can go up or down (e.g., active connections)\n * - **Histogram**: Sampling observations (e.g., request latency)\n *\n * **Labels:**\n * Metrics can have labels for dimensional data:\n * ```typescript\n * counter('http_requests_total', { method: 'GET', status: '200' });\n * ```\n *\n * **Export Format:**\n * Metrics are exported in Prometheus text format:\n * ```\n * # HELP http_requests_total Total HTTP requests\n * # TYPE http_requests_total counter\n * http_requests_total{method=\"GET\",status=\"200\"} 1234\n * ```\n *\n * @example\n * ```typescript\n * const metrics = new Metrics({ prefix: 'mcp_server' });\n *\n * // Count requests\n * metrics.counter('requests_total', { method: 'GET' }).inc();\n *\n * // Track active connections\n * const activeConnections = metrics.gauge('active_connections');\n * activeConnections.set(5);\n * activeConnections.dec();\n *\n * // Record latency\n * metrics.histogram('request_duration_seconds').observe(0.023);\n *\n * // Export for Prometheus\n * const prometheusText = metrics.export();\n * ```\n */\nexport class Metrics {\n\t/** Metrics storage indexed by name and label hash */\n\tprivate _metrics: Map<string, Metric>;\n\n\t/** Histogram samples */\n\tprivate _histograms: Map<string, HistogramMetric>;\n\n\t/** Prefix for all metric names */\n\tprivate _prefix: string;\n\n\t/** Default labels to apply to all metrics */\n\tprivate _defaultLabels: Record<string, string>;\n\n\t/** Counter for metric collection operations */\n\tprivate _operationsCounter: number = 0;\n\n\t/**\n\t * Creates a new Metrics instance.\n\t *\n\t * @param options - Configuration options\n\t *\n\t * @example\n\t * ```typescript\n\t * const metrics = new Metrics({ prefix: 'mcp_server' });\n\t * ```\n\t */\n\tconstructor(options: { prefix?: string; defaultLabels?: Record<string, string> } = {}) {\n\t\tthis._metrics = new Map();\n\t\tthis._histograms = new Map();\n\t\tthis._prefix = options.prefix ?? '';\n\t\tthis._defaultLabels = { ...options.defaultLabels };\n\t}\n\n\t/**\n\t * Creates a counter metric.\n\t *\n\t * @param name - Metric name\n\t * @param value - Increment value (default: 1)\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.counter('requests_total', 1, { method: 'GET' });\n\t * metrics.counter('errors_total', 1, { type: 'timeout' });\n\t * ```\n\t */\n\tcounter(name: string, value = 1, labels: Record<string, string> = {}, help?: string): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst existing = this._metrics.get(key);\n\n\t\tif (existing) {\n\t\t\texisting.value += value;\n\t\t\tif (help && !existing.help) {\n\t\t\t\texisting.help = help;\n\t\t\t}\n\t\t} else {\n\t\t\tthis._metrics.set(key, {\n\t\t\t\tname: fullName,\n\t\t\t\ttype: MetricType.Counter,\n\t\t\t\tvalue,\n\t\t\t\tlabels: { ...allLabels },\n\t\t\t\thelp,\n\t\t\t});\n\t\t}\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Creates a gauge metric.\n\t *\n\t * @param name - Metric name\n\t * @param value - Current value\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t *\n\t * @example\n\t * ```typescript\n\t * const activeConnections = metrics.gauge('active_connections');\n\t * activeConnections.set(5);\n\t * activeConnections.dec();\n\t * ```\n\t */\n\tgauge(name: string, value: number, labels: Record<string, string> = {}, help?: string): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst existing = this._metrics.get(key);\n\t\tthis._metrics.set(key, {\n\t\t\tname: fullName,\n\t\t\ttype: MetricType.Gauge,\n\t\t\tvalue,\n\t\t\tlabels: { ...allLabels },\n\t\t\thelp: help ?? existing?.help,\n\t\t});\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Records a histogram observation.\n\t *\n\t * @param name - Histogram name\n\t * @param value - Observed value\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t * @param buckets - Custom bucket boundaries\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.histogram('request_duration_seconds').observe(0.023);\n\t * metrics.histogram('thought_processing_ms').observe(45);\n\t * ```\n\t */\n\thistogram(\n\t\tname: string,\n\t\tvalue: number,\n\t\tlabels: Record<string, string> = {},\n\t\tbuckets = DEFAULT_BUCKETS\n\t): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst histogram = this._histograms.get(key);\n\t\tlet previousBoundary = -Infinity;\n\t\tfor (const boundary of buckets) {\n\t\t\tif (!Number.isFinite(boundary) || boundary <= previousBoundary) {\n\t\t\t\tthrow new RangeError('Histogram boundaries must be finite and strictly increasing');\n\t\t\t}\n\t\t\tpreviousBoundary = boundary;\n\t\t}\n\t\tif (\n\t\t\thistogram &&\n\t\t\t(histogram.boundaries.length !== buckets.length ||\n\t\t\t\thistogram.boundaries.some((boundary, index) => boundary !== buckets[index]))\n\t\t) {\n\t\t\tthrow new RangeError('Histogram bucket layout differs from the existing series');\n\t\t}\n\n\t\tif (histogram) {\n\t\t\thistogram.sum += value;\n\t\t\thistogram.count += 1;\n\t\t\tfor (const boundary of histogram.boundaries) {\n\t\t\t\tif (value <= boundary) {\n\t\t\t\t\thistogram.buckets.set(boundary, (histogram.buckets.get(boundary) ?? 0) + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst histogramData = {\n\t\t\t\tname: fullName,\n\t\t\t\tlabels: { ...allLabels },\n\t\t\t\tsum: value,\n\t\t\t\tcount: 1,\n\t\t\t\tboundaries: [...buckets],\n\t\t\t\tbuckets: new Map<number, number>(),\n\t\t\t};\n\t\t\tfor (const boundary of buckets) {\n\t\t\t\thistogramData.buckets.set(boundary, value <= boundary ? 1 : 0);\n\t\t\t}\n\t\t\tthis._histograms.set(key, histogramData);\n\t\t}\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Gets the current value of a metric.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Labels\n\t * @returns Current value or undefined if not found\n\t *\n\t * @example\n\t * ```typescript\n\t * const count = metrics.get('requests_total', { method: 'GET' });\n\t * ```\n\t */\n\tget(name: string, labels: Record<string, string> = {}): number | undefined {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\treturn this._metrics.get(key)?.value;\n\t}\n\n\t/**\n\t * Increments a counter by 1.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Optional labels\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.inc('requests_total', { method: 'GET' });\n\t * ```\n\t */\n\tinc(name: string, labels?: Record<string, string>): void {\n\t\tthis.counter(name, 1, labels);\n\t}\n\n\t/**\n\t * Decrements a gauge by 1.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Optional labels\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.dec('active_connections');\n\t * ```\n\t */\n\tdec(name: string, labels?: Record<string, string>): void {\n\t\tconst value = this.get(name, labels) ?? 0;\n\t\tthis.gauge(name, value - 1, labels);\n\t}\n\n\t/**\n\t * Resets all metrics to zero.\n\t * Useful for testing or on server restart.\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.reset();\n\t * ```\n\t */\n\treset(): void {\n\t\tthis._metrics.clear();\n\t\tthis._histograms.clear();\n\t\tthis._operationsCounter = 0;\n\t}\n\n\t/**\n\t * Gets the number of metric operations performed.\n\t * Useful for testing.\n\t *\n\t * @returns Operation count\n\t *\n\t * @example\n\t * ```typescript\n\t * const ops = metrics.getOperationCount();\n\t * ```\n\t */\n\tgetOperationCount(): number {\n\t\treturn this._operationsCounter;\n\t}\n\n\t/**\n\t * Exports metrics in Prometheus text format.\n\t *\n\t * @returns Prometheus text format string\n\t *\n\t * @example\n\t * ```typescript\n\t * const prometheusText = metrics.export();\n\t * console.log(prometheusText);\n\t * // Output:\n\t * // # HELP http_requests_total Total HTTP requests\n\t * // # TYPE http_requests_total counter\n\t * // http_requests_total{method=\"GET\",status=\"200\"} 1234\n\t * ```\n\t */\n\texport(): string {\n\t\tconst lines: string[] = [];\n\n\t\tconst metrics = Array.from(this._metrics.values());\n\t\tconst histograms = Array.from(this._histograms.values());\n\n\t\tconst helpEntries = new Map<string, string>();\n\t\tconst typeEntries = new Map<string, MetricType>();\n\n\t\tfor (const metric of metrics) {\n\t\t\tif (!helpEntries.has(metric.name)) {\n\t\t\t\tconst helpText = metric.help ?? `${metric.name} metric`;\n\t\t\t\tlines.push(\n\t\t\t\t\t`# HELP ${metric.name} ${helpText.replaceAll('\\\\', '\\\\\\\\').replaceAll('\\n', '\\\\n')}`\n\t\t\t\t);\n\t\t\t\thelpEntries.set(metric.name, helpText);\n\t\t\t}\n\t\t\tif (!typeEntries.has(metric.name)) {\n\t\t\t\tlines.push(`# TYPE ${metric.name} ${metric.type}`);\n\t\t\t\ttypeEntries.set(metric.name, metric.type);\n\t\t\t}\n\n\t\t\tconst labelStr = this._formatLabels(metric.labels);\n\t\t\tlines.push(`${metric.name}{${labelStr}} ${metric.value}`);\n\t\t}\n\n\t\tfor (const histogram of histograms) {\n\t\t\tconst { name: fullName, labels } = histogram;\n\t\t\tif (histogram.count > 0) {\n\t\t\t\tif (!typeEntries.has(fullName)) {\n\t\t\t\t\tlines.push(`# TYPE ${fullName} histogram`);\n\t\t\t\t\ttypeEntries.set(fullName, MetricType.Histogram);\n\t\t\t\t}\n\n\t\t\t\tconst labelStr = this._formatLabels(labels);\n\t\t\t\tconst formatMetricLine = (suffix: string, value: number): string => {\n\t\t\t\t\tif (labelStr.length === 0) {\n\t\t\t\t\t\treturn `${fullName}${suffix} ${value}`;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn `${fullName}${suffix}{${labelStr}} ${value}`;\n\t\t\t\t};\n\n\t\t\t\tlines.push(formatMetricLine('_sum', histogram.sum));\n\t\t\t\tlines.push(formatMetricLine('_count', histogram.count));\n\n\t\t\t\tfor (const boundary of histogram.boundaries) {\n\t\t\t\t\tconst count = histogram.buckets.get(boundary);\n\t\t\t\t\tconst boundaryLabel = String(boundary);\n\t\t\t\t\tconst boundaryLabelStr = this._formatLabels({ le: boundaryLabel });\n\t\t\t\t\tconst bucketLabels =\n\t\t\t\t\t\tlabelStr.length === 0 ? boundaryLabelStr : `${labelStr},${boundaryLabelStr}`;\n\t\t\t\t\tlines.push(`${fullName}_bucket{${bucketLabels}} ${count}`);\n\t\t\t\t}\n\t\t\t\tconst infLabelStr = this._formatLabels({ le: '+Inf' });\n\t\t\t\tconst infLabels = labelStr.length === 0 ? infLabelStr : `${labelStr},${infLabelStr}`;\n\t\t\t\tlines.push(`${fullName}_bucket{${infLabels}} ${histogram.count}`);\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join('\\n');\n\t}\n\n\t/**\n\t * Gets metric name with prefix.\n\t * @param name - Metric name\n\t * @returns Full metric name\n\t * @private\n\t */\n\tprivate _fullName(name: string): string {\n\t\tif (!this._prefix) {\n\t\t\treturn name;\n\t\t}\n\n\t\tconst prefix = `${this._prefix}_`;\n\t\treturn name.startsWith(prefix) ? name : `${prefix}${name}`;\n\t}\n\n\t/**\n\t * Creates a unique key for a metric with labels.\n\t * @param name - Metric name\n\t * @param labels - Labels\n\t * @returns Unique key\n\t * @private\n\t */\n\tprivate _metricKey(name: string, labels: Record<string, string>): string {\n\t\tconst sortedLabels = Object.entries(labels).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n\t\treturn JSON.stringify([name, sortedLabels]);\n\t}\n\n\tprivate _formatLabels(labels: Record<string, string>): string {\n\t\treturn Object.entries(labels)\n\t\t\t.map(([key, value]) => `${key}=\"${this._escapeLabelValue(value)}\"`)\n\t\t\t.join(',');\n\t}\n\n\tprivate _escapeLabelValue(value: string): string {\n\t\treturn value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"').replaceAll('\\n', '\\\\n');\n\t}\n}\n"],"names":["MetricType","DEFAULT_BUCKETS","Metrics","options","Map","name","value","labels","help","fullName","allLabels","key","existing","buckets","histogram","previousBoundary","boundary","Number","RangeError","index","histogramData","lines","metrics","Array","histograms","helpEntries","typeEntries","metric","helpText","labelStr","formatMetricLine","suffix","count","boundaryLabel","String","boundaryLabelStr","bucketLabels","infLabelStr","infLabels","prefix","sortedLabels","Object","a","b","JSON"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iworkforces/tracelattice",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "Semantic Sequential Thinking Layer For AI Agents.",
5
5
  "type": "module",
6
6
  "main": "dist/lib.js",
@@ -76,7 +76,7 @@
76
76
  "@tmcp/transport-stdio": "^0.5.0",
77
77
  "@tsconfig/node26": "^26.0.1",
78
78
  "@valibot/to-json-schema": "^1.8.0",
79
- "chalk": "^6.0.0",
79
+ "chalk": "^6.0.1",
80
80
  "chokidar": "^5.0.0",
81
81
  "or": "^0.2.0",
82
82
  "tmcp": "^1.20.0",
@@ -86,19 +86,19 @@
86
86
  "devDependencies": {
87
87
  "@changesets/cli": "^3.0.3",
88
88
  "@eslint/js": "^10.0.1",
89
- "@rsbuild/core": "^2.2.8",
90
- "@rslib/core": "^1.0.1",
91
- "@types/node": "^26.6.2",
89
+ "@rsbuild/core": "^2.2.10",
90
+ "@rslib/core": "^1.0.2",
91
+ "@types/node": "^26.6.3",
92
92
  "@typescript-eslint/eslint-plugin": "^8.70.1",
93
93
  "@typescript-eslint/parser": "^8.70.1",
94
- "@vitest/coverage-v8": "^5.0.1",
94
+ "@vitest/coverage-v8": "^5.0.2",
95
95
  "better-sqlite3": "13.0.3",
96
96
  "eslint": "^10.11.0",
97
97
  "globals": "^17.12.0",
98
- "prettier": "^3.9.8",
98
+ "prettier": "^3.9.9",
99
99
  "typescript": "^6.0.3",
100
- "typescript-eslint": "^8.70.0",
101
- "vitest": "^5.0.1"
100
+ "typescript-eslint": "^8.70.1",
101
+ "vitest": "^5.0.2"
102
102
  },
103
103
  "allowScripts": {
104
104
  "fsevents@2.3.3": true,