@iworkforces/tracelattice 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -3
- package/dist/contracts/PersistenceBackend.d.ts +10 -1
- package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
- package/dist/contracts/calibrator.d.ts +9 -6
- package/dist/contracts/calibrator.d.ts.map +1 -1
- package/dist/contracts/interfaces.d.ts +6 -0
- package/dist/contracts/interfaces.d.ts.map +1 -1
- package/dist/contracts/persistence-work.d.ts +13 -1
- package/dist/contracts/persistence-work.d.ts.map +1 -1
- package/dist/contracts/strategy.d.ts +14 -9
- package/dist/contracts/strategy.d.ts.map +1 -1
- package/dist/core/DurableThoughtIdentityIndex.d.ts +35 -0
- package/dist/core/DurableThoughtIdentityIndex.d.ts.map +1 -0
- package/dist/core/DurableThoughtIdentityIndex.js +94 -0
- package/dist/core/DurableThoughtIdentityIndex.js.map +1 -0
- package/dist/core/HistoryManager.d.ts +5 -0
- package/dist/core/HistoryManager.d.ts.map +1 -1
- package/dist/core/HistoryManager.js +37 -4
- package/dist/core/HistoryManager.js.map +1 -1
- package/dist/core/IHistoryManager.d.ts +2 -0
- package/dist/core/IHistoryManager.d.ts.map +1 -1
- package/dist/core/PersistenceBuffer.d.ts +7 -1
- package/dist/core/PersistenceBuffer.d.ts.map +1 -1
- package/dist/core/PersistenceBuffer.js +13 -1
- package/dist/core/PersistenceBuffer.js.map +1 -1
- package/dist/core/PersistenceRestore.d.ts.map +1 -1
- package/dist/core/PersistenceRestore.js +11 -3
- package/dist/core/PersistenceRestore.js.map +1 -1
- package/dist/core/PersistenceWorkQueue.d.ts +13 -1
- package/dist/core/PersistenceWorkQueue.d.ts.map +1 -1
- package/dist/core/PersistenceWorkQueue.js +86 -11
- package/dist/core/PersistenceWorkQueue.js.map +1 -1
- package/dist/core/PersistenceWriter.d.ts.map +1 -1
- package/dist/core/PersistenceWriter.js +3 -0
- package/dist/core/PersistenceWriter.js.map +1 -1
- package/dist/core/ThoughtEvaluator.d.ts +7 -4
- package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
- package/dist/core/ThoughtEvaluator.js +15 -7
- package/dist/core/ThoughtEvaluator.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js +19 -7
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/core/ThoughtReferenceIndex.d.ts +4 -0
- package/dist/core/ThoughtReferenceIndex.d.ts.map +1 -1
- package/dist/core/ThoughtReferenceIndex.js +28 -1
- package/dist/core/ThoughtReferenceIndex.js.map +1 -1
- package/dist/core/VerificationOutcomeAdmission.d.ts +8 -1
- package/dist/core/VerificationOutcomeAdmission.d.ts.map +1 -1
- package/dist/core/VerificationOutcomeAdmission.js.map +1 -1
- package/dist/core/VerificationTargetRestore.d.ts +5 -0
- package/dist/core/VerificationTargetRestore.d.ts.map +1 -0
- package/dist/core/VerificationTargetRestore.js +61 -0
- package/dist/core/VerificationTargetRestore.js.map +1 -0
- package/dist/core/evaluator/Aggregator.d.ts +2 -1
- package/dist/core/evaluator/Aggregator.d.ts.map +1 -1
- package/dist/core/evaluator/Aggregator.js +4 -12
- package/dist/core/evaluator/Aggregator.js.map +1 -1
- package/dist/core/evaluator/Calibrator.d.ts +13 -9
- package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
- package/dist/core/evaluator/Calibrator.js +25 -11
- package/dist/core/evaluator/Calibrator.js.map +1 -1
- package/dist/core/evaluator/PatternDetector.d.ts +2 -1
- package/dist/core/evaluator/PatternDetector.d.ts.map +1 -1
- package/dist/core/evaluator/PatternDetector.js +13 -12
- package/dist/core/evaluator/PatternDetector.js.map +1 -1
- package/dist/core/evaluator/SignalComputer.d.ts +3 -2
- package/dist/core/evaluator/SignalComputer.d.ts.map +1 -1
- package/dist/core/evaluator/SignalComputer.js +4 -9
- package/dist/core/evaluator/SignalComputer.js.map +1 -1
- package/dist/core/evaluator/VerificationLinks.d.ts +19 -0
- package/dist/core/evaluator/VerificationLinks.d.ts.map +1 -0
- package/dist/core/evaluator/VerificationLinks.js +113 -0
- package/dist/core/evaluator/VerificationLinks.js.map +1 -0
- package/dist/core/evaluator/calibration-math.d.ts +12 -2
- package/dist/core/evaluator/calibration-math.d.ts.map +1 -1
- package/dist/core/evaluator/calibration-math.js +11 -2
- package/dist/core/evaluator/calibration-math.js.map +1 -1
- package/dist/core/graph/EdgeEmitter.d.ts.map +1 -1
- package/dist/core/graph/EdgeEmitter.js +2 -1
- package/dist/core/graph/EdgeEmitter.js.map +1 -1
- package/dist/core/graph/GraphView.d.ts +5 -5
- package/dist/core/graph/GraphView.d.ts.map +1 -1
- package/dist/core/graph/GraphView.js +11 -11
- package/dist/core/graph/GraphView.js.map +1 -1
- package/dist/core/reasoning/ActiveEvidenceProjection.d.ts +20 -0
- package/dist/core/reasoning/ActiveEvidenceProjection.d.ts.map +1 -0
- package/dist/core/reasoning/ActiveEvidenceProjection.js +100 -0
- package/dist/core/reasoning/ActiveEvidenceProjection.js.map +1 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts +5 -4
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts.map +1 -1
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js +24 -14
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js.map +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +3 -1
- package/dist/lib.js.map +1 -1
- package/dist/persistence/BacktrackPersistence.d.ts +13 -0
- package/dist/persistence/BacktrackPersistence.d.ts.map +1 -0
- package/dist/persistence/BacktrackPersistence.js +90 -0
- package/dist/persistence/BacktrackPersistence.js.map +1 -0
- package/dist/persistence/FilePersistence.d.ts +2 -1
- package/dist/persistence/FilePersistence.d.ts.map +1 -1
- package/dist/persistence/FilePersistence.js +28 -0
- package/dist/persistence/FilePersistence.js.map +1 -1
- package/dist/persistence/FileSnapshotV2.d.ts +2 -0
- package/dist/persistence/FileSnapshotV2.d.ts.map +1 -1
- package/dist/persistence/FileSnapshotV2.js +6 -2
- package/dist/persistence/FileSnapshotV2.js.map +1 -1
- package/dist/persistence/MemoryPersistence.d.ts +2 -1
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
- package/dist/persistence/MemoryPersistence.js +21 -1
- package/dist/persistence/MemoryPersistence.js.map +1 -1
- package/dist/persistence/PersistenceCodec.d.ts.map +1 -1
- package/dist/persistence/PersistenceCodec.js +5 -0
- package/dist/persistence/PersistenceCodec.js.map +1 -1
- package/dist/persistence/PersistenceErrors.d.ts +1 -1
- package/dist/persistence/PersistenceErrors.d.ts.map +1 -1
- package/dist/persistence/PersistenceErrors.js.map +1 -1
- package/dist/persistence/PersistenceScope.d.ts +1 -1
- package/dist/persistence/PersistenceScope.d.ts.map +1 -1
- package/dist/persistence/PersistenceScope.js.map +1 -1
- package/dist/persistence/SqlitePersistence.d.ts +2 -1
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.js +18 -0
- package/dist/persistence/SqlitePersistence.js.map +1 -1
- package/dist/registry/BaseRegistry.d.ts +10 -2
- package/dist/registry/BaseRegistry.d.ts.map +1 -1
- package/dist/registry/BaseRegistry.js +128 -81
- package/dist/registry/BaseRegistry.js.map +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry/BaseRegistry.js","sources":["../../src/registry/BaseRegistry.ts"],"sourcesContent":["/**\n * Base registry providing shared CRUD, caching, and discovery logic.\n *\n * This abstract generic class extracts the common patterns from `ToolRegistry`\n * and `SkillRegistry` into a single reusable base. Subclasses only need to\n * implement item-specific parsing, file filtering, and error construction.\n *\n * @template T - The registry item type (must have a `name` property)\n * @module registry\n */\n\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { DiscoveryCache } from '../cache/DiscoveryCache.js';\nimport { NullLogger } from '../logger/NullLogger.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\nimport { getErrorMessage } from '../errors.js';\n\n/**\n * Configuration options for creating a `BaseRegistry` instance.\n */\nexport interface BaseRegistryOptions {\n\t/** Optional logger for diagnostics. */\n\tlogger?: Logger;\n\n\t/** Optional cache for lookups. */\n\tcache?: DiscoveryCache<{ name: string }>;\n\n\t/**\n\t * Directory paths to search for items.\n\t */\n\tsearchDirs?: string[];\n\n\t/**\n\t * Enable lazy discovery (discover on first access instead of startup).\n\t * @default false\n\t */\n\tlazyDiscovery?: boolean;\n}\n\n/**\n * Abstract base registry for managing named items with discovery and caching.\n *\n * Provides shared CRUD operations, filesystem discovery with deduplication,\n * and optional LRU caching. Subclasses implement item-specific parsing logic\n * and error construction.\n *\n * @template T - The registry item type (must have a `name` property)\n */\nexport abstract class BaseRegistry<T extends { name: string }> {\n\t/** Internal storage for items indexed by name. */\n\tprotected _items: Map<string, T>;\n\tprivate _manualItems: Map<string, T>;\n\tprivate _discoveredItemsByPath: Map<string, T>;\n\n\t/** Logger for diagnostics. */\n\tprotected _logger: Logger;\n\n\t/** Optional cache for lookups. */\n\tprotected _cache: DiscoveryCache<T>;\n\n\t/** Directory paths to search for items. */\n\tprotected _searchDirs: string[];\n\n\t/** Whether discovery has been performed. */\n\tprotected _discovered: boolean = false;\n\n\t/** Promise for in-progress discovery (null if not in progress). */\n\tprotected _discoveryPromise: Promise<number> | null = null;\n\tprivate _refreshRequested = false;\n\n\t/** File extensions to match during discovery. */\n\tprotected abstract readonly _fileExtensions: string[];\n\n\t/**\n\t * Creates an error for invalid item data.\n\t * @param reason - The reason for the validation failure\n\t */\n\tprotected abstract _createInvalidError(reason: string): Error;\n\n\t/**\n\t * Creates an error for duplicate items.\n\t * @param name - The name of the duplicate item\n\t */\n\tprotected abstract _createDuplicateError(name: string): Error;\n\n\t/**\n\t * Creates an error for items not found.\n\t * @param name - The name of the missing item\n\t * @param action - The action that was attempted\n\t */\n\tprotected abstract _createNotFoundError(name: string, action: string): Error;\n\n\t/**\n\t * Parses frontmatter content into a partial item.\n\t * @param content - The file content to parse\n\t * @returns A partial item, with an `_error` property if parsing failed\n\t */\n\tprotected abstract _parseFrontmatter(content: string): Partial<T> & { _error?: string };\n\n\t/**\n\t * Determines whether a file should be skipped during discovery.\n\t * @param fileName - The name of the file to check\n\t * @returns true if the file should be skipped\n\t */\n\tprotected abstract _shouldSkipFile(fileName: string): boolean;\n\n\t/**\n\t * Constructs a complete item from parsed frontmatter data.\n\t * Returns null if the parsed data is insufficient.\n\t * @param parsed - The parsed frontmatter data\n\t * @returns A complete item, or null if data is insufficient\n\t */\n\tprotected abstract _buildItem(parsed: Partial<T>): T | null;\n\n\t/**\n\t * The entity name used in log messages (e.g., 'tool', 'skill').\n\t */\n\tprotected abstract readonly _entityName: string;\n\n\tconstructor(options: BaseRegistryOptions) {\n\t\tthis._items = new Map();\n\t\tthis._manualItems = new Map();\n\t\tthis._discoveredItemsByPath = new Map();\n\t\tthis._logger = (options.logger ?? new NullLogger()) as Logger;\n\t\tthis._cache = (options.cache ||\n\t\t\tnew DiscoveryCache<T>({ maxSize: 50, ttl: 300000 })) as DiscoveryCache<T>;\n\t\tthis._searchDirs = (options.searchDirs ?? []) as string[];\n\t}\n\n\t/**\n\t * Internal logging method.\n\t * @param message - The message to log\n\t * @param meta - Optional metadata\n\t */\n\tprotected log(message: string, meta?: Record<string, unknown>): void {\n\t\tthis._logger.info(message, meta);\n\t}\n\n\t/**\n\t * Adds an item to the registry.\n\t *\n\t * @param item - The item to add\n\t * @throws If item already exists or name is invalid\n\t */\n\tpublic add(item: T): void {\n\t\tif (!item.name) {\n\t\t\tthrow this._createInvalidError(`${this._entityName} must have a valid name`);\n\t\t}\n\t\tif (this._items.has(item.name)) {\n\t\t\tthrow this._createDuplicateError(item.name);\n\t\t}\n\t\tthis._items.set(item.name, item);\n\t\tthis._manualItems.set(item.name, item);\n\t\tthis.log(`Added ${this._entityName}: ${item.name}`, { [`${this._entityName}Name`]: item.name });\n\t\t// Invalidate cache when adding a new item\n\t\tthis._cache?.invalidate('all');\n\t}\n\n\t/**\n\t * Removes an item from the registry.\n\t *\n\t * @param name - The name of the item to remove\n\t * @throws If item not found\n\t */\n\tpublic remove(name: string): void {\n\t\tif (!this._items.has(name)) {\n\t\t\tthrow this._createNotFoundError(name, 'remove');\n\t\t}\n\t\tthis._items.delete(name);\n\t\tthis._manualItems.delete(name);\n\t\tfor (const [filePath, item] of this._discoveredItemsByPath) {\n\t\t\tif (item.name === name) this._discoveredItemsByPath.delete(filePath);\n\t\t}\n\t\tthis.log(`Removed ${this._entityName}: ${name}`, { [`${this._entityName}Name`]: name });\n\t\t// Invalidate cache when removing an item\n\t\tthis._cache?.invalidate('all');\n\t\tthis._cache?.invalidate(name);\n\t}\n\n\t/**\n\t * Updates an existing item with partial data.\n\t *\n\t * @param name - The name of the item to update\n\t * @param updates - Partial item data with fields to update\n\t * @throws If item not found\n\t */\n\tpublic update(name: string, updates: Partial<T>): void {\n\t\tif (!this._items.has(name)) {\n\t\t\tthrow this._createNotFoundError(name, 'update');\n\t\t}\n\t\tconst existing = this._items.get(name)!;\n\t\tconst updated = { ...existing, ...updates };\n\t\tthis._items.set(name, updated);\n\t\tif (this._manualItems.has(name)) this._manualItems.set(name, updated);\n\t\tfor (const [filePath, item] of this._discoveredItemsByPath) {\n\t\t\tif (item.name === name) this._discoveredItemsByPath.set(filePath, updated);\n\t\t}\n\t\tthis.log(`Updated ${this._entityName}: ${name}`, { [`${this._entityName}Name`]: name });\n\t\t// Invalidate cache when updating an item\n\t\tthis._cache?.invalidate('all');\n\t\tthis._cache?.invalidate(name);\n\t}\n\n\t/**\n\t * Gets an item by name.\n\t *\n\t * @param name - The name of the item to get\n\t * @returns The item if found, undefined otherwise\n\t */\n\tpublic get(name: string): T | undefined {\n\t\treturn this._items.get(name);\n\t}\n\n\t/**\n\t * Gets all items as an array.\n\t *\n\t * Uses cache if available for performance.\n\t *\n\t * @returns An array of all registered items\n\t */\n\tpublic getAll(): T[] {\n\t\t// Check cache first\n\t\tif (this._cache) {\n\t\t\tconst cached = this._cache.get('all');\n\t\t\tif (cached) {\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t}\n\t\t// Get from storage\n\t\tconst items = Array.from(this._items.values());\n\t\t// Cache the result\n\t\tthis._cache?.set('all', items);\n\t\treturn items;\n\t}\n\n\t/**\n\t * Checks if an item exists in the registry.\n\t *\n\t * @param name - The name of the item to check\n\t * @returns true if the item exists, false otherwise\n\t */\n\tpublic has(name: string): boolean {\n\t\treturn this._items.has(name);\n\t}\n\n\t/**\n\t * Gets all item names as an array.\n\t *\n\t * @returns An array of item names\n\t */\n\tpublic getNames(): string[] {\n\t\treturn Array.from(this._items.keys());\n\t}\n\n\t/**\n\t * Clears all items from the registry.\n\t */\n\tpublic clear(): void {\n\t\tthis._items.clear();\n\t\tthis._manualItems.clear();\n\t\tthis._discoveredItemsByPath.clear();\n\t\tthis.log(`Cleared all ${this._entityName}s`);\n\t\t// Invalidate cache when clearing all items\n\t\tthis._cache?.clear();\n\t}\n\n\t/**\n\t * Gets the number of items in the registry.\n\t *\n\t * @returns The count of registered items\n\t */\n\tpublic size(): number {\n\t\treturn this._items.size;\n\t}\n\n\t/**\n\t * Asynchronously discovers items from the configured directories.\n\t *\n\t * Multiple concurrent calls share the same discovery promise.\n\t * Subsequent calls return cached results if discovery has already completed.\n\t *\n\t * @returns A Promise resolving to the number of items discovered\n\t */\n\tpublic async discoverAsync(): Promise<number> {\n\t\tif (this._discoveryPromise) {\n\t\t\treturn this._discoveryPromise;\n\t\t}\n\n\t\tif (this._discovered) {\n\t\t\tconst cached = this._cache.get('all');\n\t\t\treturn cached?.length ?? 0;\n\t\t}\n\n\t\treturn this._beginDiscovery();\n\t}\n\n\t/**\n\t * Re-scans configured directories and atomically reconciles discovered items.\n\t *\n\t * Calls made during an active scan share its promise and request at most one\n\t * follow-up pass, ensuring an event that arrives mid-scan is not lost.\n\t *\n\t * @returns A Promise resolving to the number of discovered filesystem items\n\t */\n\tpublic async refreshAsync(): Promise<number> {\n\t\tthis._refreshRequested = true;\n\t\treturn this._discoveryPromise ?? this._beginDiscovery();\n\t}\n\n\tprivate _beginDiscovery(): Promise<number> {\n\t\tconst operation = this._runDiscoveryLoop();\n\t\tthis._discoveryPromise = operation;\n\t\tconst clearOperation = (): void => {\n\t\t\tif (this._discoveryPromise === operation) this._discoveryPromise = null;\n\t\t};\n\t\toperation.then(clearOperation, clearOperation);\n\t\treturn operation;\n\t}\n\n\tprivate async _runDiscoveryLoop(): Promise<number> {\n\t\tthis._refreshRequested = false;\n\t\tlet count = await this._performDiscovery();\n\t\twhile (this._refreshRequested) {\n\t\t\tthis._refreshRequested = false;\n\t\t\tcount = await this._performDiscovery();\n\t\t}\n\t\treturn count;\n\t}\n\n\t/**\n\t * Performs the actual discovery operation.\n\t *\n\t * Scans configured directories for item files, parses their frontmatter,\n\t * and adds valid items to the registry.\n\t *\n\t * @returns A Promise resolving to the number of items discovered\n\t */\n\tprotected async _performDiscovery(): Promise<number> {\n\t\tconst discoveredItems = new Map<string, T>();\n\t\tconst claimedNames = new Set(this._manualItems.keys());\n\n\t\tfor (const dir of this._searchDirs) {\n\t\t\ttry {\n\t\t\t\tif (!existsSync(dir)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst entries = await readdir(dir, { withFileTypes: true });\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tif (this._shouldSkipFile(entry.name)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (entry.isFile() && this._fileExtensions.some((ext) => entry.name.endsWith(ext))) {\n\t\t\t\t\t\tconst filePath = join(dir, entry.name);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst content = await readFile(filePath, 'utf-8');\n\t\t\t\t\t\t\tconst parsed = this._parseFrontmatter(content);\n\t\t\t\t\t\t\tif (parsed._error) {\n\t\t\t\t\t\t\t\tthis._retainLastKnownGood(filePath, parsed._error, discoveredItems, claimedNames);\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (parsed.name) {\n\t\t\t\t\t\t\t\tconst item = this._buildItem(parsed);\n\t\t\t\t\t\t\t\tif (item && !claimedNames.has(item.name)) {\n\t\t\t\t\t\t\t\t\tdiscoveredItems.set(filePath, item);\n\t\t\t\t\t\t\t\t\tclaimedNames.add(item.name);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (readError) {\n\t\t\t\t\t\t\tthis._retainLastKnownGood(\n\t\t\t\t\t\t\t\tfilePath,\n\t\t\t\t\t\t\t\tgetErrorMessage(readError),\n\t\t\t\t\t\t\t\tdiscoveredItems,\n\t\t\t\t\t\t\t\tclaimedNames\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis._logger.warn(`Failed to scan ${this._entityName} directory`, {\n\t\t\t\t\tdirectory: dir,\n\t\t\t\t\terror: getErrorMessage(error),\n\t\t\t\t});\n\t\t\t\tthis._retainDirectory(dir, discoveredItems, claimedNames);\n\t\t\t}\n\t\t}\n\n\t\tthis._discoveredItemsByPath = discoveredItems;\n\t\tthis._items = new Map(this._manualItems);\n\t\tfor (const item of discoveredItems.values()) {\n\t\t\tif (!this._items.has(item.name)) this._items.set(item.name, item);\n\t\t}\n\t\tthis._discovered = true;\n\t\tthis._cache.clear();\n\t\tthis._cache.set('all', Array.from(this._items.values()));\n\t\tthis.log(`Discovery complete: found ${discoveredItems.size} ${this._entityName}s`, {\n\t\t\tdiscoveredCount: discoveredItems.size,\n\t\t});\n\t\treturn discoveredItems.size;\n\t}\n\n\tprivate _retainLastKnownGood(\n\t\tfilePath: string,\n\t\treason: string,\n\t\tdiscoveredItems: Map<string, T>,\n\t\tclaimedNames: Set<string>\n\t): void {\n\t\tconst previous = this._discoveredItemsByPath.get(filePath);\n\t\tif (previous && !claimedNames.has(previous.name)) {\n\t\t\tdiscoveredItems.set(filePath, previous);\n\t\t\tclaimedNames.add(previous.name);\n\t\t}\n\t\tthis._logger.warn(`Invalid ${this._entityName} discovery file`, {\n\t\t\tfilePath,\n\t\t\treason,\n\t\t\tretainedLastKnownGood: previous !== undefined,\n\t\t});\n\t}\n\n\tprivate _retainDirectory(\n\t\tdirectory: string,\n\t\tdiscoveredItems: Map<string, T>,\n\t\tclaimedNames: Set<string>\n\t): void {\n\t\tfor (const [filePath, item] of this._discoveredItemsByPath) {\n\t\t\tif (dirname(filePath) === directory && !claimedNames.has(item.name)) {\n\t\t\t\tdiscoveredItems.set(filePath, item);\n\t\t\t\tclaimedNames.add(item.name);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parses YAML frontmatter from file content.\n\t *\n\t * This is a shared utility for subclasses that parse YAML frontmatter.\n\t *\n\t * @param content - The file content to parse\n\t * @returns The parsed YAML object, or null if no frontmatter found\n\t */\n\tprotected _extractFrontmatter(content: string): Record<string, unknown> | null {\n\t\tconst match = content.match(/^---\\n([\\s\\S]+?)\\n---/);\n\t\tif (!match) {\n\t\t\treturn null;\n\t\t}\n\t\treturn parseYaml(match[1]!) as Record<string, unknown>;\n\t}\n\n\t/**\n\t * Sets items from an external source.\n\t *\n\t * Clears existing items and adds new ones from the provided array.\n\t *\n\t * @param items - Array of items from an external source\n\t */\n\tpublic setAll(items: T[]): void {\n\t\tthis.clear();\n\t\tfor (const item of items) {\n\t\t\ttry {\n\t\t\t\tthis.add(item);\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Error adding ${this._entityName} '${item.name}':`, {\n\t\t\t\t\t[`${this._entityName}Name`]: item.name,\n\t\t\t\t\terror: getErrorMessage(error),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.log(`Set ${items.length} ${this._entityName}s from external source`, {\n\t\t\t[`${this._entityName}Count`]: items.length,\n\t\t});\n\t}\n}\n"],"names":["BaseRegistry","options","Map","NullLogger","DiscoveryCache","message","meta","item","name","filePath","updates","existing","updated","cached","items","Array","operation","clearOperation","count","discoveredItems","claimedNames","Set","dir","existsSync","entries","readdir","entry","ext","join","content","readFile","parsed","readError","getErrorMessage","error","reason","previous","undefined","directory","dirname","match","parseYaml"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry/BaseRegistry.js","sources":["../../src/registry/BaseRegistry.ts"],"sourcesContent":["/**\n * Base registry providing shared CRUD, caching, and discovery logic.\n *\n * This abstract generic class extracts the common patterns from `ToolRegistry`\n * and `SkillRegistry` into a single reusable base. Subclasses only need to\n * implement item-specific parsing, file filtering, and error construction.\n *\n * @template T - The registry item type (must have a `name` property)\n * @module registry\n */\n\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { DiscoveryCache } from '../cache/DiscoveryCache.js';\nimport { NullLogger } from '../logger/NullLogger.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\nimport { getErrorMessage } from '../errors.js';\n\n/**\n * Configuration options for creating a `BaseRegistry` instance.\n */\nexport interface BaseRegistryOptions {\n\t/** Optional logger for diagnostics. */\n\tlogger?: Logger;\n\n\t/** Optional cache for lookups. */\n\tcache?: DiscoveryCache<{ name: string }>;\n\n\t/**\n\t * Directory paths to search for items.\n\t */\n\tsearchDirs?: string[];\n\n\t/**\n\t * Enable lazy discovery (discover on first access instead of startup).\n\t * @default false\n\t */\n\tlazyDiscovery?: boolean;\n}\n\ninterface DiscoveryWarning {\n\treadonly message: string;\n\treadonly meta: Record<string, unknown>;\n}\n\ninterface DiscoveryScan<T> {\n\treadonly itemsByPath: Map<string, T>;\n\treadonly claimedNames: Set<string>;\n\treadonly previousItemsByPath: ReadonlyMap<string, T>;\n\treadonly warnings: DiscoveryWarning[];\n}\n\n/**\n * Abstract base registry for managing named items with discovery and caching.\n *\n * Provides shared CRUD operations, filesystem discovery with deduplication,\n * and optional LRU caching. Subclasses implement item-specific parsing logic\n * and error construction.\n *\n * @template T - The registry item type (must have a `name` property)\n */\nexport abstract class BaseRegistry<T extends { name: string }> {\n\t/** Internal storage for items indexed by name. */\n\tprotected _items: Map<string, T>;\n\tprivate _manualItems: Map<string, T>;\n\tprivate _discoveredItemsByPath: Map<string, T>;\n\n\t/** Logger for diagnostics. */\n\tprotected _logger: Logger;\n\n\t/** Optional cache for lookups. */\n\tprotected _cache: DiscoveryCache<T>;\n\n\t/** Directory paths to search for items. */\n\tprotected _searchDirs: string[];\n\n\t/** Whether discovery has been performed. */\n\tprotected _discovered: boolean = false;\n\n\t/** Promise for in-progress discovery (null if not in progress). */\n\tprotected _discoveryPromise: Promise<number> | null = null;\n\tprivate _activeDiscoveryEpoch: number | null = null;\n\tprivate _queuedRefreshEpoch: number | null = null;\n\tprivate _replacementEpoch = 0;\n\tprivate _discoveredCount = 0;\n\n\t/** File extensions to match during discovery. */\n\tprotected abstract readonly _fileExtensions: string[];\n\n\t/**\n\t * Creates an error for invalid item data.\n\t * @param reason - The reason for the validation failure\n\t */\n\tprotected abstract _createInvalidError(reason: string): Error;\n\n\t/**\n\t * Creates an error for duplicate items.\n\t * @param name - The name of the duplicate item\n\t */\n\tprotected abstract _createDuplicateError(name: string): Error;\n\n\t/**\n\t * Creates an error for items not found.\n\t * @param name - The name of the missing item\n\t * @param action - The action that was attempted\n\t */\n\tprotected abstract _createNotFoundError(name: string, action: string): Error;\n\n\t/**\n\t * Parses frontmatter content into a partial item.\n\t * @param content - The file content to parse\n\t * @returns A partial item, with an `_error` property if parsing failed\n\t */\n\tprotected abstract _parseFrontmatter(content: string): Partial<T> & { _error?: string };\n\n\t/**\n\t * Determines whether a file should be skipped during discovery.\n\t * @param fileName - The name of the file to check\n\t * @returns true if the file should be skipped\n\t */\n\tprotected abstract _shouldSkipFile(fileName: string): boolean;\n\n\t/**\n\t * Constructs a complete item from parsed frontmatter data.\n\t * Returns null if the parsed data is insufficient.\n\t * @param parsed - The parsed frontmatter data\n\t * @returns A complete item, or null if data is insufficient\n\t */\n\tprotected abstract _buildItem(parsed: Partial<T>): T | null;\n\n\t/**\n\t * The entity name used in log messages (e.g., 'tool', 'skill').\n\t */\n\tprotected abstract readonly _entityName: string;\n\n\tconstructor(options: BaseRegistryOptions) {\n\t\tthis._items = new Map();\n\t\tthis._manualItems = new Map();\n\t\tthis._discoveredItemsByPath = new Map();\n\t\tthis._logger = (options.logger ?? new NullLogger()) as Logger;\n\t\tthis._cache = (options.cache ||\n\t\t\tnew DiscoveryCache<T>({ maxSize: 50, ttl: 300000 })) as DiscoveryCache<T>;\n\t\tthis._searchDirs = (options.searchDirs ?? []) as string[];\n\t}\n\n\t/**\n\t * Internal logging method.\n\t * @param message - The message to log\n\t * @param meta - Optional metadata\n\t */\n\tprotected log(message: string, meta?: Record<string, unknown>): void {\n\t\tthis._logger.info(message, meta);\n\t}\n\n\t/**\n\t * Adds an item to the registry.\n\t *\n\t * @param item - The item to add\n\t * @throws If item already exists or name is invalid\n\t */\n\tpublic add(item: T): void {\n\t\tif (!item.name) {\n\t\t\tthrow this._createInvalidError(`${this._entityName} must have a valid name`);\n\t\t}\n\t\tif (this._items.has(item.name)) {\n\t\t\tthrow this._createDuplicateError(item.name);\n\t\t}\n\t\tthis._items.set(item.name, item);\n\t\tthis._manualItems.set(item.name, item);\n\t\tthis.log(`Added ${this._entityName}: ${item.name}`, { [`${this._entityName}Name`]: item.name });\n\t\t// Invalidate cache when adding a new item\n\t\tthis._cache?.invalidate('all');\n\t}\n\n\t/**\n\t * Removes an item from the registry.\n\t *\n\t * @param name - The name of the item to remove\n\t * @throws If item not found\n\t */\n\tpublic remove(name: string): void {\n\t\tif (!this._items.has(name)) {\n\t\t\tthrow this._createNotFoundError(name, 'remove');\n\t\t}\n\t\tconst removedManualItem = this._manualItems.delete(name);\n\t\tif (!removedManualItem) {\n\t\t\tfor (const [filePath, item] of this._discoveredItemsByPath) {\n\t\t\t\tif (item.name === name) this._discoveredItemsByPath.delete(filePath);\n\t\t\t}\n\t\t}\n\t\tthis._rebuildVisibleItems();\n\t\tthis.log(`Removed ${this._entityName}: ${name}`, { [`${this._entityName}Name`]: name });\n\t\t// Invalidate cache when removing an item\n\t\tthis._cache?.invalidate('all');\n\t\tthis._cache?.invalidate(name);\n\t}\n\n\t/**\n\t * Updates an existing item with partial data.\n\t *\n\t * @param name - The name of the item to update\n\t * @param updates - Partial item data with fields to update\n\t * @throws If item not found\n\t */\n\tpublic update(name: string, updates: Partial<T>): void {\n\t\tif (!this._items.has(name)) {\n\t\t\tthrow this._createNotFoundError(name, 'update');\n\t\t}\n\t\tconst isManualItem = this._manualItems.has(name);\n\t\tconst existing = this._items.get(name)!;\n\t\tconst updated = { ...existing, ...updates, name };\n\t\tthis._items.set(name, updated);\n\t\tif (isManualItem) {\n\t\t\tthis._manualItems.set(name, updated);\n\t\t} else {\n\t\t\tfor (const [filePath, item] of this._discoveredItemsByPath) {\n\t\t\t\tif (item.name === name) this._discoveredItemsByPath.set(filePath, updated);\n\t\t\t}\n\t\t}\n\t\tthis.log(`Updated ${this._entityName}: ${name}`, { [`${this._entityName}Name`]: name });\n\t\t// Invalidate cache when updating an item\n\t\tthis._cache?.invalidate('all');\n\t\tthis._cache?.invalidate(name);\n\t}\n\n\t/**\n\t * Gets an item by name.\n\t *\n\t * @param name - The name of the item to get\n\t * @returns The item if found, undefined otherwise\n\t */\n\tpublic get(name: string): T | undefined {\n\t\treturn this._items.get(name);\n\t}\n\n\t/**\n\t * Gets all items as an array.\n\t *\n\t * Uses cache if available for performance.\n\t *\n\t * @returns An array of all registered items\n\t */\n\tpublic getAll(): T[] {\n\t\t// Check cache first\n\t\tif (this._cache) {\n\t\t\tconst cached = this._cache.get('all');\n\t\t\tif (cached) {\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t}\n\t\t// Get from storage\n\t\tconst items = Array.from(this._items.values());\n\t\t// Cache the result\n\t\tthis._cache?.set('all', items);\n\t\treturn items;\n\t}\n\n\t/**\n\t * Checks if an item exists in the registry.\n\t *\n\t * @param name - The name of the item to check\n\t * @returns true if the item exists, false otherwise\n\t */\n\tpublic has(name: string): boolean {\n\t\treturn this._items.has(name);\n\t}\n\n\t/**\n\t * Gets all item names as an array.\n\t *\n\t * @returns An array of item names\n\t */\n\tpublic getNames(): string[] {\n\t\treturn Array.from(this._items.keys());\n\t}\n\n\t/**\n\t * Clears all items from the registry.\n\t */\n\tpublic clear(): void {\n\t\tthis._beginReplacement();\n\t\tthis.log(`Cleared all ${this._entityName}s`);\n\t}\n\n\t/**\n\t * Gets the number of items in the registry.\n\t *\n\t * @returns The count of registered items\n\t */\n\tpublic size(): number {\n\t\treturn this._items.size;\n\t}\n\n\t/**\n\t * Asynchronously discovers items from the configured directories.\n\t *\n\t * Multiple concurrent calls share the same discovery promise.\n\t * Subsequent calls return cached results if discovery has already completed.\n\t *\n\t * @returns A Promise resolving to the number of items discovered\n\t */\n\tpublic async discoverAsync(): Promise<number> {\n\t\tif (this._discoveryPromise) {\n\t\t\tif (\n\t\t\t\t!this._discovered &&\n\t\t\t\tthis._activeDiscoveryEpoch !== this._replacementEpoch\n\t\t\t) {\n\t\t\t\tthis._queuedRefreshEpoch = this._replacementEpoch;\n\t\t\t}\n\t\t\treturn this._discoveryPromise;\n\t\t}\n\n\t\tif (this._discovered) {\n\t\t\treturn this._discoveredCount;\n\t\t}\n\n\t\treturn this._beginDiscovery();\n\t}\n\n\t/**\n\t * Re-scans configured directories and atomically reconciles discovered items.\n\t *\n\t * Calls made during an active scan share its promise and request at most one\n\t * follow-up pass, ensuring an event that arrives mid-scan is not lost.\n\t *\n\t * @returns A Promise resolving to the number of discovered filesystem items\n\t */\n\tpublic async refreshAsync(): Promise<number> {\n\t\tif (this._discoveryPromise) {\n\t\t\tthis._queuedRefreshEpoch = this._replacementEpoch;\n\t\t\treturn this._discoveryPromise;\n\t\t}\n\t\treturn this._beginDiscovery();\n\t}\n\n\tprivate _beginDiscovery(): Promise<number> {\n\t\tconst operation = this._runDiscoveryLoop();\n\t\tthis._discoveryPromise = operation;\n\t\treturn operation;\n\t}\n\n\tprivate async _runDiscoveryLoop(): Promise<number> {\n\t\tlet passEpoch = this._replacementEpoch;\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tthis._activeDiscoveryEpoch = passEpoch;\n\t\t\t\tlet count: number;\n\t\t\t\ttry {\n\t\t\t\t\tcount = await this._performDiscovery(passEpoch);\n\t\t\t\t} finally {\n\t\t\t\t\tthis._activeDiscoveryEpoch = null;\n\t\t\t\t}\n\n\t\t\t\tconst queuedEpoch = this._queuedRefreshEpoch;\n\t\t\t\tthis._queuedRefreshEpoch = null;\n\t\t\t\tif (queuedEpoch === null) return count;\n\t\t\t\tpassEpoch = queuedEpoch;\n\t\t\t}\n\t\t} finally {\n\t\t\tthis._discoveryPromise = null;\n\t\t}\n\t}\n\n\t/**\n\t * Performs the actual discovery operation.\n\t *\n\t * Scans configured directories for item files, parses their frontmatter,\n\t * and adds valid items to the registry.\n\t *\n\t * @returns A Promise resolving to the number of items discovered\n\t */\n\tprotected async _performDiscovery(epoch = this._replacementEpoch): Promise<number> {\n\t\tconst scan: DiscoveryScan<T> = {\n\t\t\titemsByPath: new Map(),\n\t\t\tclaimedNames: new Set(),\n\t\t\tpreviousItemsByPath: new Map(this._discoveredItemsByPath),\n\t\t\twarnings: [],\n\t\t};\n\t\tfor (const dir of this._searchDirs) {\n\t\t\tawait this._scanDirectory(dir, scan);\n\t\t}\n\t\treturn this._publishDiscovery(epoch, scan);\n\t}\n\n\tprivate async _scanDirectory(directory: string, scan: DiscoveryScan<T>): Promise<void> {\n\t\ttry {\n\t\t\tif (!existsSync(directory)) return;\n\t\t\tconst entries = await readdir(directory, { withFileTypes: true });\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (this._shouldSkipFile(entry.name) || !entry.isFile()) continue;\n\t\t\t\tif (!this._fileExtensions.some((extension) => entry.name.endsWith(extension))) continue;\n\t\t\t\tawait this._scanFile(join(directory, entry.name), scan);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tscan.warnings.push({\n\t\t\t\tmessage: `Failed to scan ${this._entityName} directory`,\n\t\t\t\tmeta: { directory, error: getErrorMessage(error) },\n\t\t\t});\n\t\t\tthis._retainDirectory(directory, scan);\n\t\t}\n\t}\n\n\tprivate async _scanFile(filePath: string, scan: DiscoveryScan<T>): Promise<void> {\n\t\ttry {\n\t\t\tconst content = await readFile(filePath, 'utf-8');\n\t\t\tconst parsed = this._parseFrontmatter(content);\n\t\t\tif (parsed._error) {\n\t\t\t\tthis._retainLastKnownGood(filePath, parsed._error, scan);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!parsed.name) return;\n\t\t\tconst item = this._buildItem(parsed);\n\t\t\tif (item && !scan.claimedNames.has(item.name)) {\n\t\t\t\tscan.itemsByPath.set(filePath, item);\n\t\t\t\tscan.claimedNames.add(item.name);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis._retainLastKnownGood(filePath, getErrorMessage(error), scan);\n\t\t}\n\t}\n\n\tprivate _retainLastKnownGood(filePath: string, reason: string, scan: DiscoveryScan<T>): void {\n\t\tconst previous = scan.previousItemsByPath.get(filePath);\n\t\tif (previous && !scan.claimedNames.has(previous.name)) {\n\t\t\tscan.itemsByPath.set(filePath, previous);\n\t\t\tscan.claimedNames.add(previous.name);\n\t\t}\n\t\tscan.warnings.push({\n\t\t\tmessage: `Invalid ${this._entityName} discovery file`,\n\t\t\tmeta: { filePath, reason, retainedLastKnownGood: previous !== undefined },\n\t\t});\n\t}\n\n\tprivate _retainDirectory(directory: string, scan: DiscoveryScan<T>): void {\n\t\tfor (const [filePath, item] of scan.previousItemsByPath) {\n\t\t\tif (dirname(filePath) === directory && !scan.claimedNames.has(item.name)) {\n\t\t\t\tscan.itemsByPath.set(filePath, item);\n\t\t\t\tscan.claimedNames.add(item.name);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _publishDiscovery(epoch: number, scan: DiscoveryScan<T>): number {\n\t\tif (epoch !== this._replacementEpoch) return this._discoveredCount;\n\n\t\tthis._discoveredItemsByPath = scan.itemsByPath;\n\t\tthis._rebuildVisibleItems();\n\t\tthis._discovered = true;\n\t\tthis._cache.clear();\n\t\tthis._cache.set('all', Array.from(this._items.values()));\n\t\tfor (const warning of scan.warnings) this._logger.warn(warning.message, warning.meta);\n\t\tthis.log(`Discovery complete: found ${this._discoveredCount} ${this._entityName}s`, {\n\t\t\tdiscoveredCount: this._discoveredCount,\n\t\t});\n\t\treturn this._discoveredCount;\n\t}\n\n\tprivate _rebuildVisibleItems(): void {\n\t\tconst visibleItems = new Map(this._manualItems);\n\t\tlet visibleDiscoveredCount = 0;\n\t\tfor (const item of this._discoveredItemsByPath.values()) {\n\t\t\tif (visibleItems.has(item.name)) continue;\n\t\t\tvisibleItems.set(item.name, item);\n\t\t\tvisibleDiscoveredCount++;\n\t\t}\n\t\tthis._items = visibleItems;\n\t\tthis._discoveredCount = visibleDiscoveredCount;\n\t}\n\n\tprivate _beginReplacement(): void {\n\t\tthis._replacementEpoch++;\n\t\tthis._queuedRefreshEpoch = null;\n\t\tthis._items.clear();\n\t\tthis._manualItems.clear();\n\t\tthis._discoveredItemsByPath.clear();\n\t\tthis._discovered = false;\n\t\tthis._discoveredCount = 0;\n\t\tthis._cache.clear();\n\t}\n\n\t/**\n\t * Parses YAML frontmatter from file content.\n\t *\n\t * This is a shared utility for subclasses that parse YAML frontmatter.\n\t *\n\t * @param content - The file content to parse\n\t * @returns The parsed YAML object, or null if no frontmatter found\n\t */\n\tprotected _extractFrontmatter(content: string): Record<string, unknown> | null {\n\t\tconst match = content.match(/^---\\n([\\s\\S]+?)\\n---/);\n\t\tif (!match) {\n\t\t\treturn null;\n\t\t}\n\t\treturn parseYaml(match[1]!) as Record<string, unknown>;\n\t}\n\n\t/**\n\t * Sets items from an external source.\n\t *\n\t * Clears existing items and adds new ones from the provided array.\n\t *\n\t * @param items - Array of items from an external source\n\t */\n\tpublic setAll(items: T[]): void {\n\t\tthis._beginReplacement();\n\t\tfor (const item of items) {\n\t\t\ttry {\n\t\t\t\tthis.add(item);\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Error adding ${this._entityName} '${item.name}':`, {\n\t\t\t\t\t[`${this._entityName}Name`]: item.name,\n\t\t\t\t\terror: getErrorMessage(error),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.log(`Set ${items.length} ${this._entityName}s from external source`, {\n\t\t\t[`${this._entityName}Count`]: items.length,\n\t\t});\n\t}\n}\n"],"names":["BaseRegistry","options","Map","NullLogger","DiscoveryCache","message","meta","item","name","removedManualItem","filePath","updates","isManualItem","existing","updated","cached","items","Array","operation","passEpoch","count","queuedEpoch","epoch","scan","Set","dir","directory","existsSync","entries","readdir","entry","extension","join","error","getErrorMessage","content","readFile","parsed","reason","previous","undefined","dirname","warning","visibleItems","visibleDiscoveredCount","match","parseYaml"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iworkforces/tracelattice",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Semantic Sequential Thinking Layer For AI Agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/lib.js",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"@valibot/to-json-schema": "^1.8.0",
|
|
79
79
|
"chalk": "^6.0.0",
|
|
80
80
|
"chokidar": "^5.0.0",
|
|
81
|
+
"or": "^0.2.0",
|
|
81
82
|
"tmcp": "^1.20.0",
|
|
82
83
|
"valibot": "^1.5.0",
|
|
83
84
|
"yaml": "^2.9.1"
|
|
@@ -88,8 +89,8 @@
|
|
|
88
89
|
"@rsbuild/core": "^2.2.8",
|
|
89
90
|
"@rslib/core": "^1.0.1",
|
|
90
91
|
"@types/node": "^26.6.2",
|
|
91
|
-
"@typescript-eslint/eslint-plugin": "^8.70.
|
|
92
|
-
"@typescript-eslint/parser": "^8.70.
|
|
92
|
+
"@typescript-eslint/eslint-plugin": "^8.70.1",
|
|
93
|
+
"@typescript-eslint/parser": "^8.70.1",
|
|
93
94
|
"@vitest/coverage-v8": "^5.0.1",
|
|
94
95
|
"better-sqlite3": "13.0.3",
|
|
95
96
|
"eslint": "^10.11.0",
|