@@ -40,7 +40,7 @@ import { handleSpeech } from "./speech.js";
4040import { handleTranscription } from "./transcription.js" ;
4141import { handleVideoCreate , handleVideoStatus , VideoStateMap } from "./video.js" ;
4242import { handleElevenLabsAudio } from "./elevenlabs-audio.js" ;
43- import { handleFalQueue } from "./fal-audio.js" ;
43+ import { handleFalQueue , falJobs } from "./fal-audio.js" ;
4444import { handleOllama , handleOllamaGenerate } from "./ollama.js" ;
4545import { handleCohere } from "./cohere.js" ;
4646import { handleSearch , type SearchFixture } from "./search.js" ;
@@ -80,6 +80,11 @@ const TRANSCRIPTIONS_PATH = "/v1/audio/transcriptions";
8080const VIDEOS_PATH = "/v1/videos" ;
8181const VIDEOS_STATUS_RE = / ^ \/ v 1 \/ v i d e o s \/ ( [ ^ / ] + ) $ / ;
8282const GEMINI_PREDICT_RE = / ^ \/ v 1 b e t a \/ m o d e l s \/ ( [ ^ : ] + ) : p r e d i c t $ / ;
83+ const ELEVENLABS_SOUND_GENERATION_PATH = "/v1/sound-generation" ;
84+ const ELEVENLABS_MUSIC_RE = / ^ \/ v 1 \/ m u s i c \/ ( g e n e r a t i o n | v a r i a t i o n | r e m i x | e x t e n d ) $ / ;
85+ const FAL_QUEUE_SUBMIT_RE = / ^ \/ f a l \/ q u e u e \/ s u b m i t \/ ( .+ ) $ / ;
86+ const FAL_QUEUE_REQUESTS_RE = / ^ \/ f a l \/ q u e u e \/ r e q u e s t s \/ ( .+ ) $ / ;
87+ const FAL_RUN_RE = / ^ \/ f a l \/ r u n \/ ( .+ ) $ / ;
8388const 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