import test from 'node:test'; import assert from 'node:assert/strict'; import { createHermesAgentService, resolveHermesAgentConfig } from '../src/hermes-agent-service.js'; import { analyzePhoto } from '../src/vision-service.js'; import { OverloadError, createInferenceQueue } from '../src/inference-queue.js'; const origin = 'http://127.0.0.1:4173'; const accessCode = 'test-agent-access-code-2026'; const configured = () => resolveHermesAgentConfig({ TIMMY_AGENT_ENABLED: 'true', TIMMY_AGENT_ACCESS_TOKEN: accessCode, TIMMY_PUBLIC_ORIGIN: origin, TIMMY_AGENT_WORKDIR: '/tmp/timmy-agent-workspace', }); function deferred() { let resolve; let reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve, reject }; } test('urgent messages intercept before Hermes even when the queue is saturated', async () => { let clock = 0; let hermesCalls = 0; const gate = deferred(); const service = createHermesAgentService({ config: { ...configured(), maxQueueDepth: 0 }, randomToken: () => 'urgent-cookie', now: () => clock, runTurn: async () => { hermesCalls += 1; return gate.promise; }, }); await service.unlock({ origin, accessCode }); // Saturate the single slot so any queued path would be rejected as overloaded. const active = service.chat({ origin, cookieToken: 'urgent-cookie', payload: { message: 'normal question', ledger: [] } }); await new Promise(resolve => setImmediate(resolve)); assert.equal(hermesCalls, 1); const urgent = await service.chat({ origin, cookieToken: 'urgent-cookie', payload: { message: 'I have rectal bleeding', ledger: [] } }); assert.equal(hermesCalls, 1, 'Hermes was called exactly once — only for the non-urgent request'); assert.equal(urgent.safetyOverride, true); assert.match(urgent.reply, /medical help/i); gate.resolve({ reply: 'late', sessionId: 'urgent_session_01' }); assert.match((await active).reply, /late/); }); test('vision analysis is bounded by the shared queue and overload returns the manual-fallback copy', async () => { let clock = 0; let providerCalls = 0; const gates = []; const queue = createInferenceQueue({ concurrency: 1, maxQueueDepth: 1, requestTimeoutMs: 60_000, now: () => clock }); const visionFetch = async (url, options) => { providerCalls += 1; const gate = deferred(); gates.push(gate); options.signal?.addEventListener('abort', () => gate.reject(new Error('aborted'))); return new Promise((resolve, reject) => { gate.promise.then(() => resolve({ ok: true, json: async () => ({ choices: [{ message: { content: JSON.stringify({ isStool: true, bristolType: 4, color: 'brown', confidence: 0.8, imageQuality: 'good', observations: 'ok' }) } }] }) }), reject); }); }; const payload = { imageDataUrl: 'data:image/jpeg;base64,YQ==', consent: true }; const config = { baseUrl: 'http://127.0.0.1:8645/v1', apiKey: 'test-key-not-real', model: 'm' }; const first = queue.run(signal => analyzePhoto({ payload, fetchImpl: visionFetch, config, signal })); while (providerCalls < 1) await Promise.resolve(); const second = queue.run(signal => analyzePhoto({ payload, fetchImpl: visionFetch, config, signal })); await Promise.resolve(); await assert.rejects(() => queue.run((signal) => analyzePhoto({ payload, fetchImpl: visionFetch, config, signal })), error => { assert.ok(error instanceof OverloadError); assert.match(error.message, /continue manually/i); assert.doesNotMatch(error.message, /api|key|token|127\.0\.0\.1|fetch/i); return true; }, 'third request beyond depth is overloaded with sanitized copy'); assert.equal(providerCalls, 1, 'overloaded request never reached the provider'); gates[0].resolve('go'); const result = await Promise.race([first, new Promise(resolve => setTimeout(() => resolve('pending'), 100))]); assert.notEqual(result, 'pending'); }); test('vision requests carry cancellation so disconnected clients release provider work', async () => { let capturedSignal; const controller = new AbortController(); const gate = deferred(); const fetchImpl = async (url, options) => { capturedSignal = options.signal; options.signal?.addEventListener('abort', () => gate.reject(new Error('aborted'))); return gate.promise; }; const payload = { imageDataUrl: 'data:image/jpeg;base64,YQ==', consent: true }; const config = { baseUrl: 'http://127.0.0.1:8645/v1', apiKey: 'test-key-not-real', model: 'm' }; const attempt = analyzePhoto({ payload, fetchImpl, config, signal: controller.signal }); while (!capturedSignal) await Promise.resolve(); controller.abort(new Error('client disconnected')); await assert.rejects(() => attempt, /continue manually|unavailable/i); assert.equal(capturedSignal.aborted, true, 'the provider fetch observed the cancellation'); });