| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- /**
- * The worker host's log sink: the seam that makes a failing plugin visible.
- *
- * Cordis's `LoggerService` accepts every message and, with no exporter mounted,
- * only fills a ring buffer. No profile in this repository mounts one, so a
- * provider that fails and is skipped — the skill registry logs exactly that —
- * is indistinguishable from one that found nothing. The sink is exercised here
- * rather than trusted: a diagnostic that runs nothing is a diagnostic that
- * silently stops working.
- */
- import { afterEach, describe, expect, it, vi } from 'vitest'
- import { installLogSink, type LogExporter, type LogMessage } from '../src/worker-host.ts'
- /** Capture the exporter the sink registers, and the cordis renderer it asks for. */
- function harness(): { register: () => LogExporter; requested: string[] } {
- const requested: string[] = []
- let registered: LogExporter | undefined
- const ctx = {
- loader: { internal: undefined },
- logger: { exporter: (exporter: LogExporter) => { registered = exporter; return undefined } },
- get: () => undefined,
- provide: () => {},
- fiber: { dispose: async () => {} },
- }
- const require = (specifier: string): unknown => {
- requested.push(specifier)
- // Stand in for cordis's printf renderer: the sink's contract is that it
- // formats THROUGH it, not that it reimplements the format.
- return { Logger: { format: (_exporter: LogExporter, message: LogMessage) => `rendered(${message.args.join('|')})` } }
- }
- installLogSink(ctx, require)
- if (registered === undefined) throw new Error('the sink registered no exporter')
- const exporter = registered
- return { register: () => exporter, requested }
- }
- const message = (type: LogMessage['type'], name: string, ...args: unknown[]): LogMessage => ({ name, type, args })
- // Console spies are installed on one shared object, so a surviving spy would
- // carry the previous case's calls into the counting case below.
- afterEach(() => { vi.restoreAllMocks() })
- describe('worker host log sink', () => {
- it('registers one exporter and renders through cordis', () => {
- const { register, requested } = harness()
- expect(requested).toEqual(['@deepseek-ai/cordis'])
- // Colors off: the page console has no terminal escapes to interpret.
- expect(register().colors).toBe(false)
- })
- it('declares a verbosity gate that admits warnings', () => {
- // cordis's scale counts UP with verbosity (ERROR 0, INFO 1, WARN 2, DEBUG 3)
- // and it drops a message whose level EXCEEDS the exporter's, so an exporter
- // that declares nothing inherits INFO and never sees a warning. This case is
- // the one that matters: the sink exists for warnings, and getting the
- // comparison backwards makes it silently deliver nothing.
- const admits = (exporterLevel: number, messageLevel: number): boolean => exporterLevel >= messageLevel
- const gate = harness().register().levels.default
- expect(admits(gate, 2), 'warnings must pass the gate').toBe(true)
- expect(admits(gate, 0), 'errors must pass the gate').toBe(true)
- expect(admits(gate, 3), 'debug must not pass the gate').toBe(false)
- })
- it('reports a warning with its logger name, the way a skipped provider arrives', () => {
- const warned = vi.spyOn(console, 'warn').mockImplementation(() => {})
- harness().register().export(message('warn', 'skill', 'provider "local" skipped: FS_IO_ERROR'))
- expect(warned).toHaveBeenCalledWith('skill: rendered(provider "local" skipped: FS_IO_ERROR)')
- })
- it('reports an error on the error channel', () => {
- const failed = vi.spyOn(console, 'error').mockImplementation(() => {})
- harness().register().export(message('error', 'loader', 'boom'))
- expect(failed).toHaveBeenCalledWith('loader: rendered(boom)')
- })
- it('drops info and debug, which 131 plugin rows would bury the console with', () => {
- const logged = vi.spyOn(console, 'log').mockImplementation(() => {})
- const warned = vi.spyOn(console, 'warn').mockImplementation(() => {})
- const failed = vi.spyOn(console, 'error').mockImplementation(() => {})
- const exporter = harness().register()
- exporter.export(message('info', 'timer', 'tick'))
- exporter.export(message('debug', 'loader', 'resolved'))
- expect([logged.mock.calls.length, warned.mock.calls.length, failed.mock.calls.length]).toEqual([0, 0, 0])
- })
- })
|