Skip to content

Commit 47e8a28

Browse files
committed
fix: wire journal, CORS, chaos, FalJobMap reset, and router compatibility
1 parent 8293e9b commit 47e8a28

2 files changed

Lines changed: 105 additions & 49 deletions

File tree

src/router.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ export function matchFixture(
6262
const compatible =
6363
(reqEndpoint === "image" && isImageResponse(r)) ||
6464
(reqEndpoint === "speech" && isAudioResponse(r)) ||
65+
(reqEndpoint === "audio-gen" && isAudioResponse(r)) ||
66+
(reqEndpoint === "fal-audio" && isAudioResponse(r)) ||
6567
(reqEndpoint === "transcription" && isTranscriptionResponse(r)) ||
6668
(reqEndpoint === "video" && isVideoResponse(r));
6769
if (!compatible) continue;

src/server.ts

Lines changed: 103 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { handleSpeech } from "./speech.js";
4040
import { handleTranscription } from "./transcription.js";
4141
import { handleVideoCreate, handleVideoStatus, VideoStateMap } from "./video.js";
4242
import { handleElevenLabsAudio } from "./elevenlabs-audio.js";
43-
import { handleFalQueue } from "./fal-audio.js";
43+
import { handleFalQueue, falJobs } from "./fal-audio.js";
4444
import { handleOllama, handleOllamaGenerate } from "./ollama.js";
4545
import { handleCohere } from "./cohere.js";
4646
import { handleSearch, type SearchFixture } from "./search.js";
@@ -80,6 +80,11 @@ const TRANSCRIPTIONS_PATH = "/v1/audio/transcriptions";
8080
const VIDEOS_PATH = "/v1/videos";
8181
const VIDEOS_STATUS_RE = /^\/v1\/videos\/([^/]+)$/;
8282
const GEMINI_PREDICT_RE = /^\/v1beta\/models\/([^:]+):predict$/;
83+
const ELEVENLABS_SOUND_GENERATION_PATH = "/v1/sound-generation";
84+
const ELEVENLABS_MUSIC_RE = /^\/v1\/music\/(generation|variation|remix|extend)$/;
85+
const FAL_QUEUE_SUBMIT_RE = /^\/fal\/queue\/submit\/(.+)$/;
86+
const FAL_QUEUE_REQUESTS_RE = /^\/fal\/queue\/requests\/(.+)$/;
87+
const FAL_RUN_RE = /^\/fal\/run\/(.+)$/;
8388
const DEFAULT_CHUNK_SIZE = 20;
8489

8590
// OpenAI-compatible endpoint suffixes for path prefix normalization.
@@ -295,6 +300,7 @@ async function handleControlAPI(
295300
fixtures.length = 0;
296301
journal.clear();
297302
videoStates.clear();
303+
falJobs.clear();
298304
if (defaults.registry) {
299305
defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
300306
}
@@ -1598,19 +1604,28 @@ export async function createServer(
15981604
return;
15991605
}
16001606

1601-
// POST /v1/sound-generation — ElevenLabs Sound Effects API
1602-
if (pathname === "/v1/sound-generation" && req.method === "POST") {
1607+
// POST /v1/sound-generation — ElevenLabs Sound Generation API
1608+
if (pathname === ELEVENLABS_SOUND_GENERATION_PATH && req.method === "POST") {
1609+
setCorsHeaders(res);
16031610
try {
16041611
const raw = await readBody(req);
1605-
await handleElevenLabsAudio(
1606-
req,
1612+
const chaosResult = applyChaos(
16071613
res,
1608-
raw,
1609-
fixtures,
1610-
defaults,
1611-
journal.getFixtureMatchCountsForTest(getTestId(req)),
1612-
"sound-generation",
1614+
null,
1615+
defaults.chaos,
1616+
req.headers,
1617+
journal,
1618+
{
1619+
method: req.method ?? "POST",
1620+
path: pathname,
1621+
headers: flattenHeaders(req.headers),
1622+
body: { model: "", messages: [] },
1623+
},
1624+
defaults.registry,
1625+
defaults.logger,
16131626
);
1627+
if (chaosResult) return;
1628+
await handleElevenLabsAudio(req, res, raw, fixtures, defaults, journal, "sound-generation");
16141629
} catch (err: unknown) {
16151630
const msg = err instanceof Error ? err.message : "Internal error";
16161631
if (!res.headersSent) {
@@ -1626,21 +1641,30 @@ export async function createServer(
16261641
return;
16271642
}
16281643

1629-
// POST /v1/music or /v1/music/* — ElevenLabs Music API
1630-
if ((pathname === "/v1/music" || pathname.startsWith("/v1/music/")) && req.method === "POST") {
1631-
const musicSubType =
1632-
pathname === "/v1/music" ? "music" : pathname.slice("/v1/music/".length) || "music";
1644+
// POST /v1/music/(generation|variation|remix|extend) — ElevenLabs Music API
1645+
const musicMatch = pathname.match(ELEVENLABS_MUSIC_RE);
1646+
if (musicMatch && req.method === "POST") {
1647+
setCorsHeaders(res);
1648+
const musicSubType = musicMatch[1];
16331649
try {
16341650
const raw = await readBody(req);
1635-
await handleElevenLabsAudio(
1636-
req,
1651+
const chaosResult = applyChaos(
16371652
res,
1638-
raw,
1639-
fixtures,
1640-
defaults,
1641-
journal.getFixtureMatchCountsForTest(getTestId(req)),
1642-
musicSubType,
1653+
null,
1654+
defaults.chaos,
1655+
req.headers,
1656+
journal,
1657+
{
1658+
method: req.method ?? "POST",
1659+
path: pathname,
1660+
headers: flattenHeaders(req.headers),
1661+
body: { model: "", messages: [] },
1662+
},
1663+
defaults.registry,
1664+
defaults.logger,
16431665
);
1666+
if (chaosResult) return;
1667+
await handleElevenLabsAudio(req, res, raw, fixtures, defaults, journal, musicSubType);
16441668
} catch (err: unknown) {
16451669
const msg = err instanceof Error ? err.message : "Internal error";
16461670
if (!res.headersSent) {
@@ -1656,19 +1680,29 @@ export async function createServer(
16561680
return;
16571681
}
16581682

1659-
// POST /fal/queue/submit/* — fal.ai queue submission
1660-
if (pathname.startsWith("/fal/queue/submit/") && req.method === "POST") {
1683+
// POST /fal/queue/submit/{model} — fal.ai Queue Submit
1684+
const falQueueSubmitMatch = pathname.match(FAL_QUEUE_SUBMIT_RE);
1685+
if (falQueueSubmitMatch && req.method === "POST") {
1686+
setCorsHeaders(res);
16611687
try {
16621688
const raw = await readBody(req);
1663-
await handleFalQueue(
1664-
req,
1689+
const chaosResult = applyChaos(
16651690
res,
1666-
raw,
1667-
pathname,
1668-
fixtures,
1669-
defaults,
1670-
journal.getFixtureMatchCountsForTest(getTestId(req)),
1691+
null,
1692+
defaults.chaos,
1693+
req.headers,
1694+
journal,
1695+
{
1696+
method: req.method ?? "POST",
1697+
path: pathname,
1698+
headers: flattenHeaders(req.headers),
1699+
body: { model: "", messages: [] },
1700+
},
1701+
defaults.registry,
1702+
defaults.logger,
16711703
);
1704+
if (chaosResult) return;
1705+
await handleFalQueue(req, res, raw, pathname, fixtures, defaults, journal);
16721706
} catch (err: unknown) {
16731707
const msg = err instanceof Error ? err.message : "Internal error";
16741708
if (!res.headersSent) {
@@ -1684,19 +1718,29 @@ export async function createServer(
16841718
return;
16851719
}
16861720

1687-
// POST/GET /fal/queue/requests/* — fal.ai queue status
1688-
if (pathname.startsWith("/fal/queue/requests/")) {
1721+
// GET /fal/queue/requests/{requestId} — fal.ai Queue Status/Result
1722+
const falQueueRequestsMatch = pathname.match(FAL_QUEUE_REQUESTS_RE);
1723+
if (falQueueRequestsMatch && (req.method === "GET" || req.method === "POST")) {
1724+
setCorsHeaders(res);
16891725
try {
1690-
const raw = req.method === "POST" ? await readBody(req) : "";
1691-
await handleFalQueue(
1692-
req,
1726+
const raw = req.method === "POST" ? await readBody(req) : "{}";
1727+
const chaosResult = applyChaos(
16931728
res,
1694-
raw,
1695-
pathname,
1696-
fixtures,
1697-
defaults,
1698-
journal.getFixtureMatchCountsForTest(getTestId(req)),
1729+
null,
1730+
defaults.chaos,
1731+
req.headers,
1732+
journal,
1733+
{
1734+
method: req.method ?? "GET",
1735+
path: pathname,
1736+
headers: flattenHeaders(req.headers),
1737+
body: { model: "", messages: [] },
1738+
},
1739+
defaults.registry,
1740+
defaults.logger,
16991741
);
1742+
if (chaosResult) return;
1743+
await handleFalQueue(req, res, raw, pathname, fixtures, defaults, journal);
17001744
} catch (err: unknown) {
17011745
const msg = err instanceof Error ? err.message : "Internal error";
17021746
if (!res.headersSent) {
@@ -1712,19 +1756,29 @@ export async function createServer(
17121756
return;
17131757
}
17141758

1715-
// POST /fal/run/* — fal.ai synchronous run
1716-
if (pathname.startsWith("/fal/run/") && req.method === "POST") {
1759+
// POST /fal/run/{model} — fal.ai Synchronous Run
1760+
const falRunMatch = pathname.match(FAL_RUN_RE);
1761+
if (falRunMatch && req.method === "POST") {
1762+
setCorsHeaders(res);
17171763
try {
17181764
const raw = await readBody(req);
1719-
await handleFalQueue(
1720-
req,
1765+
const chaosResult = applyChaos(
17211766
res,
1722-
raw,
1723-
pathname,
1724-
fixtures,
1725-
defaults,
1726-
journal.getFixtureMatchCountsForTest(getTestId(req)),
1767+
null,
1768+
defaults.chaos,
1769+
req.headers,
1770+
journal,
1771+
{
1772+
method: req.method ?? "POST",
1773+
path: pathname,
1774+
headers: flattenHeaders(req.headers),
1775+
body: { model: "", messages: [] },
1776+
},
1777+
defaults.registry,
1778+
defaults.logger,
17271779
);
1780+
if (chaosResult) return;
1781+
await handleFalQueue(req, res, raw, pathname, fixtures, defaults, journal);
17281782
} catch (err: unknown) {
17291783
const msg = err instanceof Error ? err.message : "Internal error";
17301784
if (!res.headersSent) {

0 commit comments

Comments
 (0)