mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-22 06:42:19 +03:00
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host. Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean. Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
40 lines
1.6 KiB
TypeScript
40 lines
1.6 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
// Invariantes de segurança/UX do chat com voz (componentes React: vitest-ui advisory + dashboard-typecheck).
|
|
const CHAT = "src/app/(dashboard)/dashboard/conductor/FaroChat.tsx";
|
|
|
|
function src(): string {
|
|
return fs.readFileSync(path.join(process.cwd(), CHAT), "utf8");
|
|
}
|
|
|
|
test("client fala SÓ com o OmniRoute: /api/conductor/ask + /api/v1/audio/* (nunca Faro/hub direto)", () => {
|
|
const s = src();
|
|
assert.match(s, /"use client"/);
|
|
assert.match(s, /\/api\/conductor\/ask/);
|
|
assert.match(s, /\/api\/v1\/audio\/transcriptions/);
|
|
assert.match(s, /\/api\/v1\/audio\/speech/);
|
|
assert.ok(!s.includes(":7920"), "endereço do Faro nunca no client");
|
|
assert.ok(!s.includes("CONDUCTOR_"), "nenhuma env do Conductor no client");
|
|
});
|
|
|
|
test("pending do Faro → botões Sim/Não que enviam 'sim'/'não' (trava de confirmação é do motor do Faro)", () => {
|
|
const s = src();
|
|
assert.match(s, /pending/);
|
|
assert.match(s, /"sim"/);
|
|
assert.match(s, /"não"/);
|
|
});
|
|
|
|
test("voz: push-to-talk com MediaRecorder/getUserMedia; STT multipart sem Content-Type manual; TTS via Blob com revoke", () => {
|
|
const s = src();
|
|
assert.match(s, /navigator\.mediaDevices\.getUserMedia/);
|
|
assert.match(s, /MediaRecorder/);
|
|
assert.match(s, /FormData\(\)/);
|
|
assert.ok(!/audio\/transcriptions[\s\S]{0,300}content-type/i.test(s), "multipart deixa o browser definir o boundary");
|
|
assert.match(s, /URL\.createObjectURL/);
|
|
assert.match(s, /URL\.revokeObjectURL/);
|
|
assert.match(s, /useTranslations\("conductor"\)/);
|
|
});
|