@kb-labs/shared-testing 2.119.0-canary.448a88d0f → 2.119.0-canary.62ffd5965

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mock-llm.ts","../src/mock-cache.ts","../src/mock-storage.ts","../src/mock-logger.ts","../src/mock-embeddings.ts"],"names":["vi"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/shared-testing/mock-llm\n *\n * LLM mock builder with fluent API and call tracking.\n *\n * @example\n * ```typescript\n * const llm = mockLLM()\n * .onComplete('Generate commit').respondWith('feat: add login')\n * .onComplete(/explain/i).respondWith('This function does X')\n * .onAnyComplete().respondWith('default answer');\n *\n * const res = await llm.complete('Generate commit message');\n * expect(res.content).toBe('feat: add login');\n * expect(llm.complete).toHaveBeenCalledOnce();\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type {\n ILLM,\n LLMOptions,\n LLMResponse,\n LLMMessage,\n LLMToolCallOptions,\n LLMToolCallResponse,\n LLMToolCall,\n} from '@kb-labs/core-platform';\n\n// ────────────────────────────────────────────────────────────────────\n// Types\n// ────────────────────────────────────────────────────────────────────\n\n/** Recorded call to complete() */\nexport interface LLMCall {\n prompt: string;\n options?: LLMOptions;\n response: LLMResponse;\n}\n\n/** Recorded call to chatWithTools() */\nexport interface LLMToolCallRecord {\n messages: LLMMessage[];\n options: LLMToolCallOptions;\n response: LLMToolCallResponse;\n}\n\ntype PromptMatcher = string | RegExp | ((prompt: string) => boolean);\n\ninterface CompletionRule {\n matcher: PromptMatcher;\n response: string | LLMResponse | ((prompt: string) => string | LLMResponse);\n}\n\n/**\n * Mock LLM instance with call tracking and fluent API.\n * All methods are vi.fn() spies.\n */\nexport interface MockLLMInstance extends ILLM {\n /** All recorded complete() calls */\n calls: LLMCall[];\n /** Last complete() call (or undefined) */\n lastCall: LLMCall | undefined;\n /** All recorded chatWithTools() calls */\n toolCalls: LLMToolCallRecord[];\n /** Reset all recorded calls and spies */\n resetCalls: () => void;\n}\n\n/** Public type returned by mockLLM() — builder fluent API + ILLM spy instance */\nexport interface MockLLM extends MockLLMInstance {\n onComplete(matcher: PromptMatcher): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLM };\n onAnyComplete(): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLM };\n streaming(chunks: string[]): MockLLM;\n failing(error: Error): MockLLM;\n withToolCalls(calls: LLMToolCall[], content?: string): MockLLM;\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Builder\n// ────────────────────────────────────────────────────────────────────\n\nclass MockLLMBuilder {\n private rules: CompletionRule[] = [];\n private defaultResponse: string | LLMResponse | ((prompt: string) => string | LLMResponse) = 'mock response';\n private streamChunks: string[] = ['mock'];\n private errorToThrow: Error | null = null;\n private toolCallsToReturn: LLMToolCall[] = [];\n private toolCallResponseContent = '';\n\n /**\n * Match a specific prompt (exact string or regex).\n * Returns a handler to set the response.\n */\n onComplete(matcher: PromptMatcher): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLMBuilder } {\n return {\n respondWith: (response) => {\n this.rules.push({ matcher, response });\n return this;\n },\n };\n }\n\n /**\n * Set the default response for any prompt that doesn't match a rule.\n */\n onAnyComplete(): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLMBuilder } {\n return {\n respondWith: (response) => {\n this.defaultResponse = response;\n return this;\n },\n };\n }\n\n /**\n * Configure streaming to yield specific chunks.\n */\n streaming(chunks: string[]): MockLLMBuilder {\n this.streamChunks = chunks;\n return this;\n }\n\n /**\n * Make the LLM throw an error on every call.\n */\n failing(error: Error): MockLLMBuilder {\n this.errorToThrow = error;\n return this;\n }\n\n /**\n * Configure chatWithTools() to return specific tool calls.\n */\n withToolCalls(calls: LLMToolCall[], content = ''): MockLLMBuilder {\n this.toolCallsToReturn = calls;\n this.toolCallResponseContent = content;\n return this;\n }\n\n /**\n * Build the mock ILLM instance. Called automatically by mockLLM().\n */\n build(): MockLLMInstance {\n const calls: LLMCall[] = [];\n const toolCallRecords: LLMToolCallRecord[] = [];\n const rules = this.rules;\n const defaultResponse = this.defaultResponse;\n const streamChunks = this.streamChunks;\n const errorToThrow = this.errorToThrow;\n const toolCallsToReturn = this.toolCallsToReturn;\n const toolCallResponseContent = this.toolCallResponseContent;\n\n function resolveResponse(prompt: string): LLMResponse {\n // Check rules in order\n for (const rule of rules) {\n if (matchesPrompt(rule.matcher, prompt)) {\n return toResponse(rule.response, prompt);\n }\n }\n // Fallback\n return toResponse(defaultResponse, prompt);\n }\n\n const completeFn = vi.fn(async (prompt: string, options?: LLMOptions): Promise<LLMResponse> => {\n if (errorToThrow) {throw errorToThrow;}\n const response = resolveResponse(prompt);\n calls.push({ prompt, options, response });\n return response;\n });\n\n const streamFn = vi.fn(async function* (_prompt: string, _options?: LLMOptions): AsyncIterable<string> {\n if (errorToThrow) {throw errorToThrow;}\n for (const chunk of streamChunks) {\n yield chunk;\n }\n });\n\n const chatWithToolsFn = vi.fn(async (messages: LLMMessage[], options: LLMToolCallOptions): Promise<LLMToolCallResponse> => {\n if (errorToThrow) {throw errorToThrow;}\n\n const lastUserMsg = messages.filter(m => m.role === 'user').pop();\n const prompt = lastUserMsg?.content ?? '';\n const baseResponse = resolveResponse(prompt);\n\n const response: LLMToolCallResponse = {\n ...baseResponse,\n content: toolCallsToReturn.length > 0 ? toolCallResponseContent : baseResponse.content,\n toolCalls: toolCallsToReturn.length > 0 ? toolCallsToReturn : undefined,\n };\n\n toolCallRecords.push({ messages, options, response });\n return response;\n });\n\n const instance: MockLLMInstance = {\n complete: completeFn,\n stream: streamFn,\n chatWithTools: chatWithToolsFn,\n calls,\n toolCalls: toolCallRecords,\n get lastCall() {\n return calls[calls.length - 1];\n },\n resetCalls: () => {\n calls.length = 0;\n toolCallRecords.length = 0;\n completeFn.mockClear();\n streamFn.mockClear();\n chatWithToolsFn.mockClear();\n },\n };\n\n return instance;\n }\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Helpers\n// ────────────────────────────────────────────────────────────────────\n\nfunction matchesPrompt(matcher: PromptMatcher, prompt: string): boolean {\n if (typeof matcher === 'string') {return prompt.includes(matcher);}\n if (matcher instanceof RegExp) {return matcher.test(prompt);}\n return matcher(prompt);\n}\n\nfunction toResponse(\n value: string | LLMResponse | ((prompt: string) => string | LLMResponse),\n prompt: string,\n): LLMResponse {\n const resolved = typeof value === 'function' ? value(prompt) : value;\n if (typeof resolved === 'string') {\n return {\n content: resolved,\n usage: { promptTokens: 0, completionTokens: 0 },\n model: 'mock',\n };\n }\n return resolved;\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Public API\n// ────────────────────────────────────────────────────────────────────\n\n/**\n * Create a mock LLM with fluent builder API.\n *\n * @example\n * ```typescript\n * // Simple: always returns same response\n * const llm = mockLLM();\n *\n * // With specific responses\n * const llm = mockLLM()\n * .onComplete('generate commit').respondWith('feat: add feature')\n * .onComplete(/explain/i).respondWith('This code does...')\n * .onAnyComplete().respondWith('default');\n *\n * // Streaming\n * const llm = mockLLM().streaming(['chunk1', 'chunk2', 'chunk3']);\n *\n * // Error simulation\n * const llm = mockLLM().failing(new Error('rate limit exceeded'));\n *\n * // Tool calling\n * const llm = mockLLM().withToolCalls([\n * { id: 'call-1', name: 'search', input: { query: 'test' } },\n * ]);\n * ```\n */\nexport function mockLLM(): MockLLM {\n const builder = new MockLLMBuilder();\n\n // Create a Proxy that acts as both builder and built instance.\n // Builder methods are forwarded to the builder.\n // ILLM methods (complete, stream, etc.) trigger auto-build on first access.\n let built: MockLLMInstance | null = null;\n\n function ensureBuilt(): MockLLMInstance {\n if (!built) {built = builder.build();}\n return built;\n }\n\n // Use Record<string, unknown> index signatures so we can introspect builder / instance\n // properties without falling back to `any`. The Proxy target is the builder.\n type BuilderRecord = MockLLMBuilder & Record<string, unknown>;\n type InstanceRecord = MockLLMInstance & Record<string, unknown>;\n\n const proxy = new Proxy(builder as BuilderRecord, {\n get(target: BuilderRecord, prop: string | symbol, _receiver: unknown): unknown {\n // Builder methods — return from builder\n if (prop in target && typeof target[prop as string] === 'function') {\n const method = (target[prop as string] as (...args: unknown[]) => unknown).bind(target);\n // After calling a builder method, invalidate the built instance\n return (...args: unknown[]): unknown => {\n built = null;\n const result = method(...args);\n // If the result is the builder itself (chaining), return the proxy\n if (result === target || (result !== null && typeof result === 'object' && 'respondWith' in result)) {\n if (result === target) {return proxy;}\n // Wrap respondWith to return proxy\n const resultWithRespond = result as { respondWith: (...rArgs: unknown[]) => unknown };\n return {\n respondWith: (...rArgs: unknown[]): unknown => {\n built = null;\n resultWithRespond.respondWith(...rArgs);\n return proxy;\n },\n };\n }\n return result;\n };\n }\n\n // ILLM instance properties — auto-build\n const instance = ensureBuilt() as InstanceRecord;\n // Return functions directly (not bound) to preserve vi.fn() spy identity\n return instance[prop as string];\n },\n });\n\n return proxy as unknown as MockLLM;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-cache\n *\n * In-memory cache mock that actually stores data (unlike noop mocks).\n * All methods are vi.fn() spies for assertion.\n *\n * @example\n * ```typescript\n * const cache = mockCache();\n * await cache.set('key', { data: 42 }, 5000);\n * expect(await cache.get('key')).toEqual({ data: 42 });\n * expect(cache.set).toHaveBeenCalledWith('key', { data: 42 }, 5000);\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type { ICache } from '@kb-labs/core-platform';\n\ninterface CacheEntry {\n value: unknown;\n expiresAt: number | null; // null = no TTL\n}\n\ninterface SortedSetMember {\n score: number;\n member: string;\n}\n\n/**\n * Mock cache instance with working in-memory storage.\n * All methods are vi.fn() spies.\n */\nexport interface MockCacheInstance extends ICache {\n /** Direct access to the internal store (for assertions) */\n readonly store: Map<string, CacheEntry>;\n /** Direct access to sorted sets (for assertions) */\n readonly sortedSets: Map<string, SortedSetMember[]>;\n /** Reset all data and spy call history */\n reset: () => void;\n}\n\n/**\n * Create a mock cache with working in-memory storage.\n *\n * Unlike noop mocks, this cache actually stores and retrieves data,\n * respects TTL, and supports sorted set operations.\n *\n * @param initial - Optional initial data to populate the cache\n *\n * @example\n * ```typescript\n * // Empty cache\n * const cache = mockCache();\n *\n * // Pre-populated cache\n * const cache = mockCache({ 'user:1': { name: 'Alice' } });\n *\n * // TTL works\n * await cache.set('temp', 'value', 100); // expires in 100ms\n * await new Promise(r => setTimeout(r, 150));\n * expect(await cache.get('temp')).toBeNull(); // expired\n * ```\n */\nexport function mockCache(initial?: Record<string, unknown>): MockCacheInstance {\n const store = new Map<string, CacheEntry>();\n const sortedSets = new Map<string, SortedSetMember[]>();\n\n // Populate initial data\n if (initial) {\n for (const [key, value] of Object.entries(initial)) {\n store.set(key, { value, expiresAt: null });\n }\n }\n\n function isExpired(entry: CacheEntry): boolean {\n return entry.expiresAt !== null && Date.now() > entry.expiresAt;\n }\n\n // Keep raw vi.fn() references for mockClear() in reset.\n // The ICache-typed versions are cast below for the public interface.\n const spies: ReturnType<typeof vi.fn>[] = [];\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function spy<T extends (...args: any[]) => unknown>(fn: T): T {\n const s = vi.fn(fn) as unknown as T;\n spies.push(s as unknown as ReturnType<typeof vi.fn>);\n return s;\n }\n\n const getFn = spy(async (key: string): Promise<unknown> => {\n const entry = store.get(key);\n if (!entry || isExpired(entry)) {\n if (entry) {store.delete(key);} // cleanup expired\n return null;\n }\n return entry.value;\n });\n\n const setFn = spy(async (key: string, value: unknown, ttl?: number): Promise<void> => {\n store.set(key, {\n value,\n expiresAt: ttl ? Date.now() + ttl : null,\n });\n });\n\n const deleteFn = spy(async (key: string): Promise<void> => {\n store.delete(key);\n });\n\n const clearFn = spy(async (pattern?: string): Promise<void> => {\n if (!pattern) {\n store.clear();\n return;\n }\n // Simple glob matching: only support trailing *\n const prefix = pattern.replace(/\\*$/, '');\n for (const key of store.keys()) {\n if (key.startsWith(prefix)) {\n store.delete(key);\n }\n }\n });\n\n const zaddFn = spy(async (key: string, score: number, member: string): Promise<void> => {\n if (!sortedSets.has(key)) {sortedSets.set(key, []);}\n const set = sortedSets.get(key)!;\n // Remove existing member\n const idx = set.findIndex(m => m.member === member);\n if (idx >= 0) {set.splice(idx, 1);}\n // Add with new score\n set.push({ score, member });\n // Keep sorted by score\n set.sort((a, b) => a.score - b.score);\n });\n\n const zrangebyscoreFn = spy(async (key: string, min: number, max: number): Promise<string[]> => {\n const set = sortedSets.get(key);\n if (!set) {return [];}\n return set\n .filter(m => m.score >= min && m.score <= max)\n .map(m => m.member);\n });\n\n const zremFn = spy(async (key: string, member: string): Promise<void> => {\n const set = sortedSets.get(key);\n if (!set) {return;}\n const idx = set.findIndex(m => m.member === member);\n if (idx >= 0) {set.splice(idx, 1);}\n });\n\n const setIfNotExistsFn = spy(async (key: string, value: unknown, ttl?: number): Promise<boolean> => {\n const existing = store.get(key);\n if (existing && !isExpired(existing)) {return false;}\n store.set(key, {\n value,\n expiresAt: ttl ? Date.now() + ttl : null,\n });\n return true;\n });\n\n const instance: MockCacheInstance = {\n get: getFn as unknown as ICache['get'],\n set: setFn as unknown as ICache['set'],\n delete: deleteFn,\n clear: clearFn,\n zadd: zaddFn,\n zrangebyscore: zrangebyscoreFn,\n zrem: zremFn,\n setIfNotExists: setIfNotExistsFn as unknown as ICache['setIfNotExists'],\n get store() { return store; },\n get sortedSets() { return sortedSets; },\n reset: () => {\n store.clear();\n sortedSets.clear();\n for (const s of spies) {s.mockClear();}\n },\n };\n\n return instance;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-storage\n *\n * Virtual filesystem mock for IStorage interface.\n * All methods are vi.fn() spies.\n *\n * @example\n * ```typescript\n * const storage = mockStorage({\n * 'config.json': '{\"key\": \"value\"}',\n * 'data/file.txt': 'hello world',\n * });\n *\n * const content = await storage.read('config.json');\n * expect(content?.toString()).toBe('{\"key\": \"value\"}');\n * expect(storage.read).toHaveBeenCalledWith('config.json');\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type { IStorage } from '@kb-labs/core-platform';\n\n/**\n * Mock storage instance with in-memory virtual filesystem.\n */\nexport interface MockStorageInstance extends IStorage {\n /** Direct access to the virtual filesystem (for assertions) */\n readonly files: Map<string, Buffer>;\n /** Reset all files and spy call history */\n reset: () => void;\n}\n\n/**\n * Create a mock storage with in-memory virtual filesystem.\n *\n * @param initial - Optional initial files. Keys are paths, values are content (string or Buffer).\n *\n * @example\n * ```typescript\n * const storage = mockStorage({\n * 'data.json': JSON.stringify({ items: [] }),\n * 'binary.dat': Buffer.from([0x00, 0x01]),\n * });\n *\n * // Write and read\n * await storage.write('new.txt', Buffer.from('hello'));\n * expect(await storage.exists('new.txt')).toBe(true);\n *\n * // List files\n * const files = await storage.list('');\n * expect(files).toContain('new.txt');\n * ```\n */\nexport function mockStorage(initial?: Record<string, string | Buffer>): MockStorageInstance {\n const files = new Map<string, Buffer>();\n\n // Populate initial files\n if (initial) {\n for (const [path, content] of Object.entries(initial)) {\n files.set(path, typeof content === 'string' ? Buffer.from(content) : content);\n }\n }\n\n const readFn = vi.fn(async (path: string): Promise<Buffer | null> => {\n return files.get(path) ?? null;\n });\n\n const writeFn = vi.fn(async (path: string, data: Buffer): Promise<void> => {\n files.set(path, data);\n });\n\n const deleteFn = vi.fn(async (path: string): Promise<void> => {\n files.delete(path);\n });\n\n const listFn = vi.fn(async (prefix: string): Promise<string[]> => {\n const result: string[] = [];\n for (const path of files.keys()) {\n if (path.startsWith(prefix)) {\n result.push(path);\n }\n }\n return result.sort();\n });\n\n const existsFn = vi.fn(async (path: string): Promise<boolean> => {\n return files.has(path);\n });\n\n const instance: MockStorageInstance = {\n read: readFn,\n write: writeFn,\n delete: deleteFn,\n list: listFn,\n exists: existsFn,\n get files() { return files; },\n reset: () => {\n files.clear();\n readFn.mockClear();\n writeFn.mockClear();\n deleteFn.mockClear();\n listFn.mockClear();\n existsFn.mockClear();\n },\n };\n\n return instance;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-logger\n *\n * Logger mock with message recording and vi.fn() spies.\n *\n * @example\n * ```typescript\n * const logger = mockLogger();\n * logger.info('hello', { extra: 'data' });\n * logger.error('oops', new Error('fail'));\n *\n * expect(logger.messages).toEqual([\n * { level: 'info', msg: 'hello', meta: { extra: 'data' } },\n * { level: 'error', msg: 'oops', error: expect.any(Error), meta: undefined },\n * ]);\n * expect(logger.info).toHaveBeenCalledWith('hello', { extra: 'data' });\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type { ILogger } from '@kb-labs/core-platform';\n\n/** Recorded log entry */\nexport interface LogEntry {\n level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n msg: string;\n error?: Error;\n meta?: Record<string, unknown>;\n}\n\n/**\n * Mock logger instance with message recording.\n */\nexport interface MockLoggerInstance extends ILogger {\n /** All recorded log messages */\n readonly messages: LogEntry[];\n /** Reset messages and spy call history */\n reset: () => void;\n}\n\n/**\n * Create a mock logger with message recording.\n *\n * All log methods are vi.fn() spies. Messages are collected\n * into a `.messages` array for easy assertion.\n *\n * Child loggers share the same messages array.\n *\n * @example\n * ```typescript\n * const logger = mockLogger();\n * const child = logger.child({ module: 'auth' });\n *\n * child.info('user logged in');\n * expect(logger.messages).toHaveLength(1);\n * expect(logger.messages[0].msg).toBe('user logged in');\n * ```\n */\nexport function mockLogger(sharedMessages?: LogEntry[]): MockLoggerInstance {\n const messages: LogEntry[] = sharedMessages ?? [];\n\n // trace, debug, info, warn: (message, meta?)\n function createSimpleLogMethod(level: LogEntry['level']) {\n return vi.fn((msg: string, meta?: Record<string, unknown>) => {\n messages.push({ level, msg, meta });\n });\n }\n\n // error, fatal: (message, error?, meta?)\n function createErrorLogMethod(level: 'error' | 'fatal') {\n return vi.fn((msg: string, error?: Error, meta?: Record<string, unknown>) => {\n messages.push({ level, msg, error, meta });\n });\n }\n\n const instance: MockLoggerInstance = {\n trace: createSimpleLogMethod('trace'),\n debug: createSimpleLogMethod('debug'),\n info: createSimpleLogMethod('info'),\n warn: createSimpleLogMethod('warn'),\n error: createErrorLogMethod('error'),\n fatal: createErrorLogMethod('fatal'),\n child: (_bindings?: Record<string, unknown>) => mockLogger(messages),\n get messages() { return messages; },\n reset: () => {\n messages.length = 0;\n (instance.trace as ReturnType<typeof vi.fn>).mockClear();\n (instance.debug as ReturnType<typeof vi.fn>).mockClear();\n (instance.info as ReturnType<typeof vi.fn>).mockClear();\n (instance.warn as ReturnType<typeof vi.fn>).mockClear();\n (instance.error as ReturnType<typeof vi.fn>).mockClear();\n (instance.fatal as ReturnType<typeof vi.fn>).mockClear();\n },\n };\n\n return instance;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-embeddings\n *\n * Deterministic in-memory `IEmbeddings` test double.\n *\n * Generates stable, normalised vectors from a text hash so tests that\n * need real math (cosine similarity, nearest-neighbour lookups) produce\n * reproducible results across runs — without any network call or model.\n *\n * @example\n * ```typescript\n * import { MockEmbeddings } from '@kb-labs/shared-testing';\n * const embed = new MockEmbeddings();\n * const vec = await embed.embed('hello'); // length === 1536, normalised\n * ```\n */\n\nimport type { IEmbeddings } from '@kb-labs/core-platform/adapters';\n\nexport class MockEmbeddings implements IEmbeddings {\n readonly dimensions = 1536;\n\n private hash(text: string): number {\n let h = 0;\n for (let i = 0; i < text.length; i++) {\n h = ((h << 5) - h) + text.charCodeAt(i);\n h = h & h;\n }\n return h;\n }\n\n private generateVector(text: string): number[] {\n const seed = this.hash(text);\n const vec: number[] = [];\n for (let i = 0; i < this.dimensions; i++) {\n vec.push(Math.sin(seed * (i + 1)) * 0.5);\n }\n const mag = Math.sqrt(vec.reduce((s, v) => s + v * v, 0));\n return vec.map((v) => v / mag);\n }\n\n async embed(text: string): Promise<number[]> {\n return this.generateVector(text);\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n return texts.map((t) => this.generateVector(t));\n }\n\n async getDimensions(): Promise<number> {\n return this.dimensions;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../home/runner/work/kb-labs/kb-labs/shared/testing/src/mock-llm.ts","../../home/runner/work/kb-labs/kb-labs/shared/testing/src/mock-cache.ts","../../home/runner/work/kb-labs/kb-labs/shared/testing/src/mock-storage.ts","../../home/runner/work/kb-labs/kb-labs/shared/testing/src/mock-logger.ts","../../home/runner/work/kb-labs/kb-labs/shared/testing/src/mock-embeddings.ts"],"names":["vi"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/shared-testing/mock-llm\n *\n * LLM mock builder with fluent API and call tracking.\n *\n * @example\n * ```typescript\n * const llm = mockLLM()\n * .onComplete('Generate commit').respondWith('feat: add login')\n * .onComplete(/explain/i).respondWith('This function does X')\n * .onAnyComplete().respondWith('default answer');\n *\n * const res = await llm.complete('Generate commit message');\n * expect(res.content).toBe('feat: add login');\n * expect(llm.complete).toHaveBeenCalledOnce();\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type {\n ILLM,\n LLMOptions,\n LLMResponse,\n LLMMessage,\n LLMToolCallOptions,\n LLMToolCallResponse,\n LLMToolCall,\n} from '@kb-labs/core-platform';\n\n// ────────────────────────────────────────────────────────────────────\n// Types\n// ────────────────────────────────────────────────────────────────────\n\n/** Recorded call to complete() */\nexport interface LLMCall {\n prompt: string;\n options?: LLMOptions;\n response: LLMResponse;\n}\n\n/** Recorded call to chatWithTools() */\nexport interface LLMToolCallRecord {\n messages: LLMMessage[];\n options: LLMToolCallOptions;\n response: LLMToolCallResponse;\n}\n\ntype PromptMatcher = string | RegExp | ((prompt: string) => boolean);\n\ninterface CompletionRule {\n matcher: PromptMatcher;\n response: string | LLMResponse | ((prompt: string) => string | LLMResponse);\n}\n\n/**\n * Mock LLM instance with call tracking and fluent API.\n * All methods are vi.fn() spies.\n */\nexport interface MockLLMInstance extends ILLM {\n /** All recorded complete() calls */\n calls: LLMCall[];\n /** Last complete() call (or undefined) */\n lastCall: LLMCall | undefined;\n /** All recorded chatWithTools() calls */\n toolCalls: LLMToolCallRecord[];\n /** Reset all recorded calls and spies */\n resetCalls: () => void;\n}\n\n/** Public type returned by mockLLM() — builder fluent API + ILLM spy instance */\nexport interface MockLLM extends MockLLMInstance {\n onComplete(matcher: PromptMatcher): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLM };\n onAnyComplete(): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLM };\n streaming(chunks: string[]): MockLLM;\n failing(error: Error): MockLLM;\n withToolCalls(calls: LLMToolCall[], content?: string): MockLLM;\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Builder\n// ────────────────────────────────────────────────────────────────────\n\nclass MockLLMBuilder {\n private rules: CompletionRule[] = [];\n private defaultResponse: string | LLMResponse | ((prompt: string) => string | LLMResponse) = 'mock response';\n private streamChunks: string[] = ['mock'];\n private errorToThrow: Error | null = null;\n private toolCallsToReturn: LLMToolCall[] = [];\n private toolCallResponseContent = '';\n\n /**\n * Match a specific prompt (exact string or regex).\n * Returns a handler to set the response.\n */\n onComplete(matcher: PromptMatcher): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLMBuilder } {\n return {\n respondWith: (response) => {\n this.rules.push({ matcher, response });\n return this;\n },\n };\n }\n\n /**\n * Set the default response for any prompt that doesn't match a rule.\n */\n onAnyComplete(): { respondWith: (response: string | LLMResponse | ((prompt: string) => string | LLMResponse)) => MockLLMBuilder } {\n return {\n respondWith: (response) => {\n this.defaultResponse = response;\n return this;\n },\n };\n }\n\n /**\n * Configure streaming to yield specific chunks.\n */\n streaming(chunks: string[]): MockLLMBuilder {\n this.streamChunks = chunks;\n return this;\n }\n\n /**\n * Make the LLM throw an error on every call.\n */\n failing(error: Error): MockLLMBuilder {\n this.errorToThrow = error;\n return this;\n }\n\n /**\n * Configure chatWithTools() to return specific tool calls.\n */\n withToolCalls(calls: LLMToolCall[], content = ''): MockLLMBuilder {\n this.toolCallsToReturn = calls;\n this.toolCallResponseContent = content;\n return this;\n }\n\n /**\n * Build the mock ILLM instance. Called automatically by mockLLM().\n */\n build(): MockLLMInstance {\n const calls: LLMCall[] = [];\n const toolCallRecords: LLMToolCallRecord[] = [];\n const rules = this.rules;\n const defaultResponse = this.defaultResponse;\n const streamChunks = this.streamChunks;\n const errorToThrow = this.errorToThrow;\n const toolCallsToReturn = this.toolCallsToReturn;\n const toolCallResponseContent = this.toolCallResponseContent;\n\n function resolveResponse(prompt: string): LLMResponse {\n // Check rules in order\n for (const rule of rules) {\n if (matchesPrompt(rule.matcher, prompt)) {\n return toResponse(rule.response, prompt);\n }\n }\n // Fallback\n return toResponse(defaultResponse, prompt);\n }\n\n const completeFn = vi.fn(async (prompt: string, options?: LLMOptions): Promise<LLMResponse> => {\n if (errorToThrow) {throw errorToThrow;}\n const response = resolveResponse(prompt);\n calls.push({ prompt, options, response });\n return response;\n });\n\n const streamFn = vi.fn(async function* (_prompt: string, _options?: LLMOptions): AsyncIterable<string> {\n if (errorToThrow) {throw errorToThrow;}\n for (const chunk of streamChunks) {\n yield chunk;\n }\n });\n\n const chatWithToolsFn = vi.fn(async (messages: LLMMessage[], options: LLMToolCallOptions): Promise<LLMToolCallResponse> => {\n if (errorToThrow) {throw errorToThrow;}\n\n const lastUserMsg = messages.filter(m => m.role === 'user').pop();\n const prompt = lastUserMsg?.content ?? '';\n const baseResponse = resolveResponse(prompt);\n\n const response: LLMToolCallResponse = {\n ...baseResponse,\n content: toolCallsToReturn.length > 0 ? toolCallResponseContent : baseResponse.content,\n toolCalls: toolCallsToReturn.length > 0 ? toolCallsToReturn : undefined,\n };\n\n toolCallRecords.push({ messages, options, response });\n return response;\n });\n\n const instance: MockLLMInstance = {\n complete: completeFn,\n stream: streamFn,\n chatWithTools: chatWithToolsFn,\n calls,\n toolCalls: toolCallRecords,\n get lastCall() {\n return calls[calls.length - 1];\n },\n resetCalls: () => {\n calls.length = 0;\n toolCallRecords.length = 0;\n completeFn.mockClear();\n streamFn.mockClear();\n chatWithToolsFn.mockClear();\n },\n };\n\n return instance;\n }\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Helpers\n// ────────────────────────────────────────────────────────────────────\n\nfunction matchesPrompt(matcher: PromptMatcher, prompt: string): boolean {\n if (typeof matcher === 'string') {return prompt.includes(matcher);}\n if (matcher instanceof RegExp) {return matcher.test(prompt);}\n return matcher(prompt);\n}\n\nfunction toResponse(\n value: string | LLMResponse | ((prompt: string) => string | LLMResponse),\n prompt: string,\n): LLMResponse {\n const resolved = typeof value === 'function' ? value(prompt) : value;\n if (typeof resolved === 'string') {\n return {\n content: resolved,\n usage: { promptTokens: 0, completionTokens: 0 },\n model: 'mock',\n };\n }\n return resolved;\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Public API\n// ────────────────────────────────────────────────────────────────────\n\n/**\n * Create a mock LLM with fluent builder API.\n *\n * @example\n * ```typescript\n * // Simple: always returns same response\n * const llm = mockLLM();\n *\n * // With specific responses\n * const llm = mockLLM()\n * .onComplete('generate commit').respondWith('feat: add feature')\n * .onComplete(/explain/i).respondWith('This code does...')\n * .onAnyComplete().respondWith('default');\n *\n * // Streaming\n * const llm = mockLLM().streaming(['chunk1', 'chunk2', 'chunk3']);\n *\n * // Error simulation\n * const llm = mockLLM().failing(new Error('rate limit exceeded'));\n *\n * // Tool calling\n * const llm = mockLLM().withToolCalls([\n * { id: 'call-1', name: 'search', input: { query: 'test' } },\n * ]);\n * ```\n */\nexport function mockLLM(): MockLLM {\n const builder = new MockLLMBuilder();\n\n // Create a Proxy that acts as both builder and built instance.\n // Builder methods are forwarded to the builder.\n // ILLM methods (complete, stream, etc.) trigger auto-build on first access.\n let built: MockLLMInstance | null = null;\n\n function ensureBuilt(): MockLLMInstance {\n if (!built) {built = builder.build();}\n return built;\n }\n\n // Use Record<string, unknown> index signatures so we can introspect builder / instance\n // properties without falling back to `any`. The Proxy target is the builder.\n type BuilderRecord = MockLLMBuilder & Record<string, unknown>;\n type InstanceRecord = MockLLMInstance & Record<string, unknown>;\n\n const proxy = new Proxy(builder as BuilderRecord, {\n get(target: BuilderRecord, prop: string | symbol, _receiver: unknown): unknown {\n // Builder methods — return from builder\n if (prop in target && typeof target[prop as string] === 'function') {\n const method = (target[prop as string] as (...args: unknown[]) => unknown).bind(target);\n // After calling a builder method, invalidate the built instance\n return (...args: unknown[]): unknown => {\n built = null;\n const result = method(...args);\n // If the result is the builder itself (chaining), return the proxy\n if (result === target || (result !== null && typeof result === 'object' && 'respondWith' in result)) {\n if (result === target) {return proxy;}\n // Wrap respondWith to return proxy\n const resultWithRespond = result as { respondWith: (...rArgs: unknown[]) => unknown };\n return {\n respondWith: (...rArgs: unknown[]): unknown => {\n built = null;\n resultWithRespond.respondWith(...rArgs);\n return proxy;\n },\n };\n }\n return result;\n };\n }\n\n // ILLM instance properties — auto-build\n const instance = ensureBuilt() as InstanceRecord;\n // Return functions directly (not bound) to preserve vi.fn() spy identity\n return instance[prop as string];\n },\n });\n\n return proxy as unknown as MockLLM;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-cache\n *\n * In-memory cache mock that actually stores data (unlike noop mocks).\n * All methods are vi.fn() spies for assertion.\n *\n * @example\n * ```typescript\n * const cache = mockCache();\n * await cache.set('key', { data: 42 }, 5000);\n * expect(await cache.get('key')).toEqual({ data: 42 });\n * expect(cache.set).toHaveBeenCalledWith('key', { data: 42 }, 5000);\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type { ICache } from '@kb-labs/core-platform';\n\ninterface CacheEntry {\n value: unknown;\n expiresAt: number | null; // null = no TTL\n}\n\ninterface SortedSetMember {\n score: number;\n member: string;\n}\n\n/**\n * Mock cache instance with working in-memory storage.\n * All methods are vi.fn() spies.\n */\nexport interface MockCacheInstance extends ICache {\n /** Direct access to the internal store (for assertions) */\n readonly store: Map<string, CacheEntry>;\n /** Direct access to sorted sets (for assertions) */\n readonly sortedSets: Map<string, SortedSetMember[]>;\n /** Reset all data and spy call history */\n reset: () => void;\n}\n\n/**\n * Create a mock cache with working in-memory storage.\n *\n * Unlike noop mocks, this cache actually stores and retrieves data,\n * respects TTL, and supports sorted set operations.\n *\n * @param initial - Optional initial data to populate the cache\n *\n * @example\n * ```typescript\n * // Empty cache\n * const cache = mockCache();\n *\n * // Pre-populated cache\n * const cache = mockCache({ 'user:1': { name: 'Alice' } });\n *\n * // TTL works\n * await cache.set('temp', 'value', 100); // expires in 100ms\n * await new Promise(r => setTimeout(r, 150));\n * expect(await cache.get('temp')).toBeNull(); // expired\n * ```\n */\nexport function mockCache(initial?: Record<string, unknown>): MockCacheInstance {\n const store = new Map<string, CacheEntry>();\n const sortedSets = new Map<string, SortedSetMember[]>();\n\n // Populate initial data\n if (initial) {\n for (const [key, value] of Object.entries(initial)) {\n store.set(key, { value, expiresAt: null });\n }\n }\n\n function isExpired(entry: CacheEntry): boolean {\n return entry.expiresAt !== null && Date.now() > entry.expiresAt;\n }\n\n // Keep raw vi.fn() references for mockClear() in reset.\n // The ICache-typed versions are cast below for the public interface.\n const spies: ReturnType<typeof vi.fn>[] = [];\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function spy<T extends (...args: any[]) => unknown>(fn: T): T {\n const s = vi.fn(fn) as unknown as T;\n spies.push(s as unknown as ReturnType<typeof vi.fn>);\n return s;\n }\n\n const getFn = spy(async (key: string): Promise<unknown> => {\n const entry = store.get(key);\n if (!entry || isExpired(entry)) {\n if (entry) {store.delete(key);} // cleanup expired\n return null;\n }\n return entry.value;\n });\n\n const setFn = spy(async (key: string, value: unknown, ttl?: number): Promise<void> => {\n store.set(key, {\n value,\n expiresAt: ttl ? Date.now() + ttl : null,\n });\n });\n\n const deleteFn = spy(async (key: string): Promise<void> => {\n store.delete(key);\n });\n\n const clearFn = spy(async (pattern?: string): Promise<void> => {\n if (!pattern) {\n store.clear();\n return;\n }\n // Simple glob matching: only support trailing *\n const prefix = pattern.replace(/\\*$/, '');\n for (const key of store.keys()) {\n if (key.startsWith(prefix)) {\n store.delete(key);\n }\n }\n });\n\n const zaddFn = spy(async (key: string, score: number, member: string): Promise<void> => {\n if (!sortedSets.has(key)) {sortedSets.set(key, []);}\n const set = sortedSets.get(key)!;\n // Remove existing member\n const idx = set.findIndex(m => m.member === member);\n if (idx >= 0) {set.splice(idx, 1);}\n // Add with new score\n set.push({ score, member });\n // Keep sorted by score\n set.sort((a, b) => a.score - b.score);\n });\n\n const zrangebyscoreFn = spy(async (key: string, min: number, max: number): Promise<string[]> => {\n const set = sortedSets.get(key);\n if (!set) {return [];}\n return set\n .filter(m => m.score >= min && m.score <= max)\n .map(m => m.member);\n });\n\n const zremFn = spy(async (key: string, member: string): Promise<void> => {\n const set = sortedSets.get(key);\n if (!set) {return;}\n const idx = set.findIndex(m => m.member === member);\n if (idx >= 0) {set.splice(idx, 1);}\n });\n\n const setIfNotExistsFn = spy(async (key: string, value: unknown, ttl?: number): Promise<boolean> => {\n const existing = store.get(key);\n if (existing && !isExpired(existing)) {return false;}\n store.set(key, {\n value,\n expiresAt: ttl ? Date.now() + ttl : null,\n });\n return true;\n });\n\n const instance: MockCacheInstance = {\n get: getFn as unknown as ICache['get'],\n set: setFn as unknown as ICache['set'],\n delete: deleteFn,\n clear: clearFn,\n zadd: zaddFn,\n zrangebyscore: zrangebyscoreFn,\n zrem: zremFn,\n setIfNotExists: setIfNotExistsFn as unknown as ICache['setIfNotExists'],\n get store() { return store; },\n get sortedSets() { return sortedSets; },\n reset: () => {\n store.clear();\n sortedSets.clear();\n for (const s of spies) {s.mockClear();}\n },\n };\n\n return instance;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-storage\n *\n * Virtual filesystem mock for IStorage interface.\n * All methods are vi.fn() spies.\n *\n * @example\n * ```typescript\n * const storage = mockStorage({\n * 'config.json': '{\"key\": \"value\"}',\n * 'data/file.txt': 'hello world',\n * });\n *\n * const content = await storage.read('config.json');\n * expect(content?.toString()).toBe('{\"key\": \"value\"}');\n * expect(storage.read).toHaveBeenCalledWith('config.json');\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type { IStorage } from '@kb-labs/core-platform';\n\n/**\n * Mock storage instance with in-memory virtual filesystem.\n */\nexport interface MockStorageInstance extends IStorage {\n /** Direct access to the virtual filesystem (for assertions) */\n readonly files: Map<string, Buffer>;\n /** Reset all files and spy call history */\n reset: () => void;\n}\n\n/**\n * Create a mock storage with in-memory virtual filesystem.\n *\n * @param initial - Optional initial files. Keys are paths, values are content (string or Buffer).\n *\n * @example\n * ```typescript\n * const storage = mockStorage({\n * 'data.json': JSON.stringify({ items: [] }),\n * 'binary.dat': Buffer.from([0x00, 0x01]),\n * });\n *\n * // Write and read\n * await storage.write('new.txt', Buffer.from('hello'));\n * expect(await storage.exists('new.txt')).toBe(true);\n *\n * // List files\n * const files = await storage.list('');\n * expect(files).toContain('new.txt');\n * ```\n */\nexport function mockStorage(initial?: Record<string, string | Buffer>): MockStorageInstance {\n const files = new Map<string, Buffer>();\n\n // Populate initial files\n if (initial) {\n for (const [path, content] of Object.entries(initial)) {\n files.set(path, typeof content === 'string' ? Buffer.from(content) : content);\n }\n }\n\n const readFn = vi.fn(async (path: string): Promise<Buffer | null> => {\n return files.get(path) ?? null;\n });\n\n const writeFn = vi.fn(async (path: string, data: Buffer): Promise<void> => {\n files.set(path, data);\n });\n\n const deleteFn = vi.fn(async (path: string): Promise<void> => {\n files.delete(path);\n });\n\n const listFn = vi.fn(async (prefix: string): Promise<string[]> => {\n const result: string[] = [];\n for (const path of files.keys()) {\n if (path.startsWith(prefix)) {\n result.push(path);\n }\n }\n return result.sort();\n });\n\n const existsFn = vi.fn(async (path: string): Promise<boolean> => {\n return files.has(path);\n });\n\n const instance: MockStorageInstance = {\n read: readFn,\n write: writeFn,\n delete: deleteFn,\n list: listFn,\n exists: existsFn,\n get files() { return files; },\n reset: () => {\n files.clear();\n readFn.mockClear();\n writeFn.mockClear();\n deleteFn.mockClear();\n listFn.mockClear();\n existsFn.mockClear();\n },\n };\n\n return instance;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-logger\n *\n * Logger mock with message recording and vi.fn() spies.\n *\n * @example\n * ```typescript\n * const logger = mockLogger();\n * logger.info('hello', { extra: 'data' });\n * logger.error('oops', new Error('fail'));\n *\n * expect(logger.messages).toEqual([\n * { level: 'info', msg: 'hello', meta: { extra: 'data' } },\n * { level: 'error', msg: 'oops', error: expect.any(Error), meta: undefined },\n * ]);\n * expect(logger.info).toHaveBeenCalledWith('hello', { extra: 'data' });\n * ```\n */\n\nimport { vi } from 'vitest';\nimport type { ILogger } from '@kb-labs/core-platform';\n\n/** Recorded log entry */\nexport interface LogEntry {\n level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n msg: string;\n error?: Error;\n meta?: Record<string, unknown>;\n}\n\n/**\n * Mock logger instance with message recording.\n */\nexport interface MockLoggerInstance extends ILogger {\n /** All recorded log messages */\n readonly messages: LogEntry[];\n /** Reset messages and spy call history */\n reset: () => void;\n}\n\n/**\n * Create a mock logger with message recording.\n *\n * All log methods are vi.fn() spies. Messages are collected\n * into a `.messages` array for easy assertion.\n *\n * Child loggers share the same messages array.\n *\n * @example\n * ```typescript\n * const logger = mockLogger();\n * const child = logger.child({ module: 'auth' });\n *\n * child.info('user logged in');\n * expect(logger.messages).toHaveLength(1);\n * expect(logger.messages[0].msg).toBe('user logged in');\n * ```\n */\nexport function mockLogger(sharedMessages?: LogEntry[]): MockLoggerInstance {\n const messages: LogEntry[] = sharedMessages ?? [];\n\n // trace, debug, info, warn: (message, meta?)\n function createSimpleLogMethod(level: LogEntry['level']) {\n return vi.fn((msg: string, meta?: Record<string, unknown>) => {\n messages.push({ level, msg, meta });\n });\n }\n\n // error, fatal: (message, error?, meta?)\n function createErrorLogMethod(level: 'error' | 'fatal') {\n return vi.fn((msg: string, error?: Error, meta?: Record<string, unknown>) => {\n messages.push({ level, msg, error, meta });\n });\n }\n\n const instance: MockLoggerInstance = {\n trace: createSimpleLogMethod('trace'),\n debug: createSimpleLogMethod('debug'),\n info: createSimpleLogMethod('info'),\n warn: createSimpleLogMethod('warn'),\n error: createErrorLogMethod('error'),\n fatal: createErrorLogMethod('fatal'),\n child: (_bindings?: Record<string, unknown>) => mockLogger(messages),\n get messages() { return messages; },\n reset: () => {\n messages.length = 0;\n (instance.trace as ReturnType<typeof vi.fn>).mockClear();\n (instance.debug as ReturnType<typeof vi.fn>).mockClear();\n (instance.info as ReturnType<typeof vi.fn>).mockClear();\n (instance.warn as ReturnType<typeof vi.fn>).mockClear();\n (instance.error as ReturnType<typeof vi.fn>).mockClear();\n (instance.fatal as ReturnType<typeof vi.fn>).mockClear();\n },\n };\n\n return instance;\n}\n","/**\n * @module @kb-labs/shared-testing/mock-embeddings\n *\n * Deterministic in-memory `IEmbeddings` test double.\n *\n * Generates stable, normalised vectors from a text hash so tests that\n * need real math (cosine similarity, nearest-neighbour lookups) produce\n * reproducible results across runs — without any network call or model.\n *\n * @example\n * ```typescript\n * import { MockEmbeddings } from '@kb-labs/shared-testing';\n * const embed = new MockEmbeddings();\n * const vec = await embed.embed('hello'); // length === 1536, normalised\n * ```\n */\n\nimport type { IEmbeddings } from '@kb-labs/core-platform/adapters';\n\nexport class MockEmbeddings implements IEmbeddings {\n readonly dimensions = 1536;\n\n private hash(text: string): number {\n let h = 0;\n for (let i = 0; i < text.length; i++) {\n h = ((h << 5) - h) + text.charCodeAt(i);\n h = h & h;\n }\n return h;\n }\n\n private generateVector(text: string): number[] {\n const seed = this.hash(text);\n const vec: number[] = [];\n for (let i = 0; i < this.dimensions; i++) {\n vec.push(Math.sin(seed * (i + 1)) * 0.5);\n }\n const mag = Math.sqrt(vec.reduce((s, v) => s + v * v, 0));\n return vec.map((v) => v / mag);\n }\n\n async embed(text: string): Promise<number[]> {\n return this.generateVector(text);\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n return texts.map((t) => this.generateVector(t));\n }\n\n async getDimensions(): Promise<number> {\n return this.dimensions;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kb-labs/shared-testing",
3
3
  "description": "Test utilities for KB Labs plugin development — mock builders, platform setup, test context",
4
- "version": "2.119.0-canary.448a88d0f",
4
+ "version": "2.119.0-canary.62ffd5965",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -18,14 +18,14 @@
18
18
  ],
19
19
  "dependencies": {
20
20
  "vitest": "^3.2.6",
21
- "@kb-labs/core-platform": "2.119.0-canary.448a88d0f"
21
+ "@kb-labs/core-platform": "2.119.0-canary.62ffd5965"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^24.3.3",
25
25
  "rimraf": "^6.0.1",
26
26
  "tsup": "^8.5.0",
27
27
  "typescript": "^5.6.3",
28
- "@kb-labs/devkit": "2.119.0-canary.448a88d0f"
28
+ "@kb-labs/devkit": "2.119.0-canary.62ffd5965"
29
29
  },
30
30
  "engines": {
31
31
  "node": ">=22.0.0",