create-syrinx-agent 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +91 -0
- package/dist/index.js +1100 -0
- package/dist/index.js.map +7 -0
- package/package.json +45 -0
- package/src/cli.ts +76 -0
- package/src/exit-codes.ts +20 -0
- package/src/generate.ts +35 -0
- package/src/help.ts +45 -0
- package/src/index.ts +16 -0
- package/src/options.test.ts +130 -0
- package/src/options.ts +176 -0
- package/src/providers/realtime.ts +31 -0
- package/src/providers/reasoner.ts +69 -0
- package/src/providers/stt.ts +68 -0
- package/src/providers/tts.ts +69 -0
- package/src/providers/types.ts +58 -0
- package/src/providers/vad-endpointing.ts +36 -0
- package/src/templates/agent-module.ts +188 -0
- package/src/templates/agents-md.ts +65 -0
- package/src/templates/cloudflare-worker.ts +172 -0
- package/src/templates/dev-server.ts +104 -0
- package/src/templates/env-example.ts +58 -0
- package/src/templates/fixture.ts +34 -0
- package/src/templates/package-json.ts +119 -0
- package/src/templates/tsconfig.ts +25 -0
- package/src/version.ts +5 -0
- package/src/write-project.test.ts +163 -0
- package/src/write-project.ts +59 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli.ts", "../src/exit-codes.ts", "../src/help.ts", "../src/version.ts", "../src/options.ts", "../src/write-project.ts", "../src/providers/stt.ts", "../src/providers/tts.ts", "../src/providers/reasoner.ts", "../src/providers/realtime.ts", "../src/providers/vad-endpointing.ts", "../src/templates/agent-module.ts", "../src/templates/dev-server.ts", "../src/templates/package-json.ts", "../src/templates/env-example.ts", "../src/templates/agents-md.ts", "../src/templates/tsconfig.ts", "../src/templates/fixture.ts", "../src/templates/cloudflare-worker.ts", "../src/generate.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["// SPDX-License-Identifier: MIT\n//\n// Argument parsing and dispatch. Never interactive beyond what --yes/TTY\n// rules allow: no spinners, no colour. Results go to stdout, diagnostics to\n// stderr.\n\nimport { parseArgs } from \"node:util\";\n\nimport { CliError, EXIT_CODES, type ExitCode } from \"./exit-codes.js\";\nimport { HELP_TEXT } from \"./help.js\";\nimport { GENERATOR_VERSION } from \"./version.js\";\nimport { runGenerate } from \"./generate.js\";\n\nexport interface CliIO {\n readonly stdout: (line: string) => void;\n readonly stderr: (line: string) => void;\n}\n\nexport const defaultIO: CliIO = {\n stdout: (line) => {\n process.stdout.write(`${line}\\n`);\n },\n stderr: (line) => {\n process.stderr.write(`${line}\\n`);\n },\n};\n\nconst PARSE_OPTIONS = {\n \"help\": { type: \"boolean\", short: \"h\" },\n \"version\": { type: \"boolean\", short: \"v\" },\n \"stt\": { type: \"string\" },\n \"tts\": { type: \"string\" },\n \"realtime\": { type: \"string\" },\n \"reasoner\": { type: \"string\" },\n \"vad\": { type: \"string\" },\n \"endpointing\": { type: \"string\" },\n \"transport\": { type: \"string\" },\n \"runtime\": { type: \"string\" },\n \"preset\": { type: \"string\" },\n \"name\": { type: \"string\" },\n \"yes\": { type: \"boolean\" },\n \"no-install\": { type: \"boolean\" },\n \"skip-install\": { type: \"boolean\" },\n \"dry-run\": { type: \"boolean\" },\n} as const;\n\nexport async function main(argv: readonly string[], io: CliIO = defaultIO): Promise<ExitCode> {\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) {\n io.stdout(HELP_TEXT);\n return EXIT_CODES.SUCCESS;\n }\n if (argv.includes(\"--version\") || argv.includes(\"-v\")) {\n io.stdout(GENERATOR_VERSION);\n return EXIT_CODES.SUCCESS;\n }\n\n let parsed: ReturnType<typeof parseArgs<{ options: typeof PARSE_OPTIONS; allowPositionals: true }>>;\n try {\n parsed = parseArgs({ args: [...argv], options: PARSE_OPTIONS, allowPositionals: true });\n } catch (err) {\n io.stderr(err instanceof Error ? err.message : String(err));\n return EXIT_CODES.USAGE;\n }\n\n try {\n await runGenerate(parsed.values, parsed.positionals, io);\n return EXIT_CODES.SUCCESS;\n } catch (err) {\n if (err instanceof CliError) {\n io.stderr(err.message);\n return err.exitCode;\n }\n io.stderr(err instanceof Error ? (err.stack ?? err.message) : String(err));\n return EXIT_CODES.INTERNAL;\n }\n}\n", "// SPDX-License-Identifier: MIT\n\nexport const EXIT_CODES = {\n SUCCESS: 0,\n INTERNAL: 1,\n USAGE: 2,\n} as const;\n\nexport type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];\n\n/** A typed error carrying the exit code the process should terminate with. */\nexport class CliError extends Error {\n readonly exitCode: ExitCode;\n\n constructor(exitCode: ExitCode, message: string) {\n super(message);\n this.name = \"CliError\";\n this.exitCode = exitCode;\n }\n}\n", "// SPDX-License-Identifier: MIT\n\nexport const HELP_TEXT = `create-syrinx-agent \u2014 scaffold a Syrinx voice agent project.\n\nOne generator with conditional emission, not enumerated template directories:\npick a provider per pipeline stage with flags and get back a project that\ndepends on exactly those providers and typechecks out of the box.\n\nUSAGE\n npm create syrinx-agent <target-dir> [options]\n create-syrinx-agent <target-dir> [options]\n\nPIPELINE (cascade mode \u2014 pick one provider per stage)\n --stt <deepgram|google|elevenlabs|grok>\n --tts <cartesia|elevenlabs|gemini|openai-tts|grok>\n --reasoner <aisdk|kuralle|mastra>\n --vad <silero-vad> optional, provider STT/endpointing owns it by default\n --endpointing <pipecat-smart-turn|vap> optional, provider STT owns it by default\n\nPIPELINE (speech-to-speech \u2014 exclusive with --stt/--tts)\n --realtime <realtime|grok>\n A speech-to-speech pipeline has no separate STT/reasoner/TTS stages.\n Passing --stt or --tts alongside --realtime is refused.\n\nTRANSPORT\n --transport <browser|twilio|telnyx|smartpbx> default: browser\n --runtime <node|cloudflare> default: node\n --runtime cloudflare --transport telnyx is generated but warned as\n deploy-unverified on the Workers edge.\n\nPRESETS (flag bundles \u2014 an explicit flag always overrides the preset)\n --preset <phone>\n\nOPTIONS\n --name <project-name> default: the target directory's basename\n --yes accept defaults for anything not passed, never prompt\n --no-install, --skip-install\n write the project but skip \\`npm install\\`\n --dry-run print the file list and exit; write nothing\n --help, -h show this help\n --version, -v print the generator's version\n\nNever prompts when --yes is passed or stdin is not a TTY: missing required\nflags fail with a USAGE error naming what is missing.\n`;\n", "// SPDX-License-Identifier: MIT\n\n// Kept in sync with package.json \"version\" by hand (mirrors packages/cli's\n// version.ts convention) \u2014 no build-time codegen step for one constant.\nexport const GENERATOR_VERSION = \"0.1.0\";\n", "// SPDX-License-Identifier: MIT\n//\n// The flag matrix, verified against packages/* \u2014 do not invent provider\n// names here. What's implemented per stage lives in the provider registries\n// in providers/*.ts, not here: this module only parses and validates shape.\n\nimport { resolve } from \"node:path\";\n\nimport { CliError, EXIT_CODES } from \"./exit-codes.js\";\n\nexport const STT_PROVIDERS = [\"deepgram\", \"google\", \"elevenlabs\", \"grok\"] as const;\nexport const TTS_PROVIDERS = [\"cartesia\", \"elevenlabs\", \"gemini\", \"openai-tts\", \"grok\"] as const;\nexport const REALTIME_PROVIDERS = [\"realtime\", \"grok\"] as const;\nexport const REASONER_PROVIDERS = [\"aisdk\", \"kuralle\", \"mastra\"] as const;\nexport const VAD_PROVIDERS = [\"silero-vad\"] as const;\nexport const ENDPOINTING_PROVIDERS = [\"pipecat-smart-turn\", \"vap\"] as const;\nexport const TRANSPORTS = [\"browser\", \"twilio\", \"telnyx\", \"smartpbx\"] as const;\nexport const RUNTIMES = [\"node\", \"cloudflare\"] as const;\n\nexport type SttProvider = (typeof STT_PROVIDERS)[number];\nexport type TtsProvider = (typeof TTS_PROVIDERS)[number];\nexport type RealtimeProvider = (typeof REALTIME_PROVIDERS)[number];\nexport type ReasonerProvider = (typeof REASONER_PROVIDERS)[number];\nexport type VadProvider = (typeof VAD_PROVIDERS)[number];\nexport type EndpointingProvider = (typeof ENDPOINTING_PROVIDERS)[number];\nexport type Transport = (typeof TRANSPORTS)[number];\nexport type Runtime = (typeof RUNTIMES)[number];\n\n/** Flags as parsed off the command line \u2014 everything optional, everything a string. */\nexport interface RawFlags {\n readonly stt?: string | undefined;\n readonly tts?: string | undefined;\n readonly realtime?: string | undefined;\n readonly reasoner?: string | undefined;\n readonly vad?: string | undefined;\n readonly endpointing?: string | undefined;\n readonly transport?: string | undefined;\n readonly runtime?: string | undefined;\n readonly preset?: string | undefined;\n readonly name?: string | undefined;\n readonly yes?: boolean | undefined;\n readonly \"no-install\"?: boolean | undefined;\n readonly \"skip-install\"?: boolean | undefined;\n readonly \"dry-run\"?: boolean | undefined;\n}\n\n/** A resolved, valid selection \u2014 either cascade (stt+tts+reasoner) or speech-to-speech (realtime). */\nexport type ResolvedOptions =\n | {\n readonly mode: \"cascade\";\n readonly stt: SttProvider;\n readonly tts: TtsProvider;\n readonly reasoner: ReasonerProvider;\n readonly vad: VadProvider | undefined;\n readonly endpointing: EndpointingProvider | undefined;\n readonly transport: Transport;\n readonly runtime: Runtime;\n readonly name: string;\n /** Absolute path the project is written to. NOT `name` \u2014 see resolveOptions. */\n readonly targetDir: string;\n readonly skipInstall: boolean;\n readonly dryRun: boolean;\n }\n | {\n readonly mode: \"realtime\";\n readonly realtime: RealtimeProvider;\n readonly transport: Transport;\n readonly runtime: Runtime;\n readonly name: string;\n /** Absolute path the project is written to. NOT `name` \u2014 see resolveOptions. */\n readonly targetDir: string;\n readonly skipInstall: boolean;\n readonly dryRun: boolean;\n };\n\ninterface Preset {\n readonly stt?: SttProvider;\n readonly tts?: TtsProvider;\n readonly reasoner?: ReasonerProvider;\n readonly transport?: Transport;\n readonly runtime?: Runtime;\n}\n\n// Presets are flag bundles, not a separate code path \u2014 every field here is\n// exactly a field an explicit flag can also set, and an explicit flag wins.\nconst PRESETS: Readonly<Record<string, Preset>> = {\n phone: { stt: \"deepgram\", tts: \"cartesia\", reasoner: \"aisdk\", transport: \"twilio\", runtime: \"node\" },\n};\n\nfunction memberOf<T extends readonly string[]>(list: T, value: string, flagName: string): T[number] {\n if (!(list as readonly string[]).includes(value)) {\n throw new CliError(EXIT_CODES.USAGE, `--${flagName} must be one of: ${list.join(\", \")} (got \"${value}\")`);\n }\n return value as T[number];\n}\n\n/**\n * Merge a preset under explicit flags (explicit always wins), validate shape,\n * and refuse the one hard conflict: --realtime combined with --stt/--tts.\n * Missing required fields in cascade mode are a USAGE error \u2014 this generator\n * never prompts, see help.ts's documented contract.\n */\nexport function resolveOptions(raw: RawFlags, positionals: readonly string[]): ResolvedOptions {\n if (raw.preset !== undefined && !(raw.preset in PRESETS)) {\n throw new CliError(EXIT_CODES.USAGE, `--preset must be one of: ${Object.keys(PRESETS).join(\", \")} (got \"${raw.preset}\")`);\n }\n const preset = raw.preset !== undefined ? PRESETS[raw.preset] : undefined;\n\n const sttRaw = raw.stt ?? preset?.stt;\n const ttsRaw = raw.tts ?? preset?.tts;\n const reasonerRaw = raw.reasoner ?? preset?.reasoner;\n const realtimeRaw = raw.realtime;\n\n if (realtimeRaw !== undefined && (sttRaw !== undefined || ttsRaw !== undefined)) {\n throw new CliError(\n EXIT_CODES.USAGE,\n `--realtime is a speech-to-speech pipeline with no separate STT/TTS stages \u2014 it cannot be combined with ${[\n sttRaw !== undefined ? \"--stt\" : undefined,\n ttsRaw !== undefined ? \"--tts\" : undefined,\n ]\n .filter((v): v is string => v !== undefined)\n .join(\" and \")}.`,\n );\n }\n\n const transport = memberOf(TRANSPORTS, raw.transport ?? preset?.transport ?? \"browser\", \"transport\");\n const runtime = memberOf(RUNTIMES, raw.runtime ?? preset?.runtime ?? \"node\", \"runtime\");\n const skipInstall = raw[\"no-install\"] === true || raw[\"skip-install\"] === true;\n const dryRun = raw[\"dry-run\"] === true;\n const targetDir = positionals[0];\n const name = raw.name ?? (targetDir !== undefined ? targetDir.split(\"/\").filter(Boolean).at(-1) : undefined);\n if (name === undefined || name.length === 0) {\n throw new CliError(EXIT_CODES.USAGE, \"a target directory or --name is required, e.g. `create-syrinx-agent my-agent`\");\n }\n // Where the files actually go. Distinct from `name`, which is only what the\n // project calls itself: writing to `./<name>` would silently ignore an absolute\n // or nested target and scatter a project into whatever directory you ran from.\n const resolvedTarget = resolve(process.cwd(), targetDir ?? name);\n\n if (realtimeRaw !== undefined) {\n const realtime = memberOf(REALTIME_PROVIDERS, realtimeRaw, \"realtime\");\n return { mode: \"realtime\", realtime, transport, runtime, name, targetDir: resolvedTarget, skipInstall, dryRun };\n }\n\n const missing = [\n sttRaw === undefined ? \"--stt\" : undefined,\n ttsRaw === undefined ? \"--tts\" : undefined,\n reasonerRaw === undefined ? \"--reasoner\" : undefined,\n ].filter((v): v is string => v !== undefined);\n if (missing.length > 0) {\n throw new CliError(\n EXIT_CODES.USAGE,\n `missing required flag(s): ${missing.join(\", \")} (or pass --realtime for a speech-to-speech pipeline, or --preset <name>)`,\n );\n }\n\n const stt = memberOf(STT_PROVIDERS, sttRaw as string, \"stt\");\n const tts = memberOf(TTS_PROVIDERS, ttsRaw as string, \"tts\");\n const reasoner = memberOf(REASONER_PROVIDERS, reasonerRaw as string, \"reasoner\");\n const vad = raw.vad !== undefined ? memberOf(VAD_PROVIDERS, raw.vad, \"vad\") : undefined;\n const endpointing = raw.endpointing !== undefined ? memberOf(ENDPOINTING_PROVIDERS, raw.endpointing, \"endpointing\") : undefined;\n\n return { mode: \"cascade\", stt, tts, reasoner, vad, endpointing, transport, runtime, name, targetDir: resolvedTarget, skipInstall, dryRun };\n}\n\n/** Non-fatal warnings for combinations that generate but aren't fully verified. */\nexport function warningsFor(opts: ResolvedOptions): readonly string[] {\n const warnings: string[] = [];\n if (opts.runtime === \"cloudflare\" && opts.transport === \"telnyx\") {\n warnings.push(\n \"runtime=cloudflare + transport=telnyx is generated but not yet bound on the Workers edge \u2014 deploy-unverified. \" +\n \"See @kuralle-syrinx/server-workers for current Cloudflare transport coverage before deploying.\",\n );\n }\n return warnings;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Orchestrates file emission: builds the file map from a resolved combination,\n// then either lists it (--dry-run) or writes it and (unless skipped) installs.\n\nimport { spawnSync } from \"node:child_process\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport type { ResolvedOptions } from \"./options.js\";\nimport { buildAgentModule } from \"./templates/agent-module.js\";\nimport { buildDevServer } from \"./templates/dev-server.js\";\nimport { buildPackageJson } from \"./templates/package-json.js\";\nimport { buildEnvExample } from \"./templates/env-example.js\";\nimport { buildAgentsMd } from \"./templates/agents-md.js\";\nimport { buildTsconfig } from \"./templates/tsconfig.js\";\nimport { buildSmokeWav } from \"./templates/fixture.js\";\nimport { buildCloudflareWorkerSource, buildWranglerJsonc } from \"./templates/cloudflare-worker.js\";\n\nexport interface ProjectFile {\n readonly relPath: string;\n readonly content: string | Buffer;\n}\n\nexport function buildFileMap(opts: ResolvedOptions): readonly ProjectFile[] {\n const files: ProjectFile[] = [\n { relPath: \"package.json\", content: buildPackageJson(opts) },\n { relPath: \"tsconfig.json\", content: buildTsconfig(opts.runtime) },\n { relPath: \".env.example\", content: buildEnvExample(opts) },\n { relPath: \"AGENTS.md\", content: buildAgentsMd(opts) },\n { relPath: \"src/agent.ts\", content: buildAgentModule(opts) },\n { relPath: \"scripts/dev-server.ts\", content: buildDevServer(opts.transport) },\n { relPath: \"test/fixtures/smoke.wav\", content: buildSmokeWav() },\n ];\n\n if (opts.runtime === \"cloudflare\") {\n files.push(\n { relPath: \"src/index.ts\", content: buildCloudflareWorkerSource(opts) },\n { relPath: \"wrangler.jsonc\", content: buildWranglerJsonc(opts) },\n );\n }\n\n return files;\n}\n\nexport async function writeProject(targetDir: string, files: readonly ProjectFile[]): Promise<void> {\n for (const file of files) {\n const abs = join(targetDir, file.relPath);\n await mkdir(dirname(abs), { recursive: true });\n await writeFile(abs, file.content);\n }\n}\n\n/** Runs `npm install` in targetDir. Errors surface to the caller (never swallowed). */\nexport function runNpmInstall(targetDir: string): void {\n const result = spawnSync(\"npm\", [\"install\"], { cwd: targetDir, stdio: \"inherit\" });\n if (result.error) throw result.error;\n if (result.status !== 0) throw new Error(`npm install exited with code ${String(result.status)}`);\n}\n", "// SPDX-License-Identifier: MIT\n//\n// STT stage registry, verified against packages/{deepgram,google,elevenlabs,grok}/src.\n// `undefined` for a provider not yet wired into the generator.\n\nimport type { SttProvider } from \"../options.js\";\nimport type { StageProvider } from \"./types.js\";\n\nconst PKG_VERSION = \"^4.3.0\";\n\nexport const STT_STAGE_PROVIDERS: Readonly<Record<SttProvider, StageProvider | undefined>> = {\n // packages/deepgram/src/stt.ts: DeepgramSTTPlugin, endpointingCapability.owner === \"provider_stt\".\n // Config fields mirror examples/02-hello-voice-headless/src/hello-voice-agent.ts.\n deepgram: {\n packageName: \"@kuralle-syrinx/deepgram\",\n packageVersion: PKG_VERSION,\n className: \"DeepgramSTTPlugin\",\n envKeys: [{ key: \"DEEPGRAM_API_KEY\", required: true }],\n usesSocketFactory: true,\n ownsEndpointing: true,\n configFields: (envRef) => [\n `api_key: ${envRef(\"DEEPGRAM_API_KEY\")}`,\n `model: \"nova-3\"`,\n `sample_rate: 16000`,\n `emit_eos_on_final: true`,\n ],\n },\n // packages/google/src/index.ts: GoogleSTTPlugin (Cloud Speech-to-Text v2).\n // api_key + project_id are required config; endpointingCapability.owner === \"provider_stt\".\n google: {\n packageName: \"@kuralle-syrinx/google\",\n packageVersion: PKG_VERSION,\n className: \"GoogleSTTPlugin\",\n envKeys: [\n { key: \"GOOGLE_CLOUD_SPEECH_API_KEY\", required: true },\n { key: \"GOOGLE_CLOUD_PROJECT_ID\", required: true },\n ],\n usesSocketFactory: true,\n ownsEndpointing: true,\n configFields: (envRef) => [\n `api_key: ${envRef(\"GOOGLE_CLOUD_SPEECH_API_KEY\")}`,\n `project_id: ${envRef(\"GOOGLE_CLOUD_PROJECT_ID\")}`,\n `sample_rate: 16000`,\n ],\n },\n // packages/elevenlabs/src/stt.ts: ElevenLabsSTTPlugin (Scribe v2 Realtime).\n elevenlabs: {\n packageName: \"@kuralle-syrinx/elevenlabs\",\n packageVersion: PKG_VERSION,\n importFrom: \"@kuralle-syrinx/elevenlabs/stt\",\n className: \"ElevenLabsSTTPlugin\",\n envKeys: [{ key: \"ELEVENLABS_API_KEY\", required: true }],\n usesSocketFactory: true,\n ownsEndpointing: true,\n configFields: (envRef) => [`api_key: ${envRef(\"ELEVENLABS_API_KEY\")}`],\n },\n // packages/grok/src/stt.ts: GrokSTTPlugin. endpointingCapability.owner === \"provider_stt\".\n grok: {\n packageName: \"@kuralle-syrinx/grok\",\n packageVersion: PKG_VERSION,\n importFrom: \"@kuralle-syrinx/grok/stt\",\n className: \"GrokSTTPlugin\",\n envKeys: [{ key: \"XAI_API_KEY\", required: true }],\n usesSocketFactory: true,\n ownsEndpointing: true,\n configFields: (envRef) => [`api_key: ${envRef(\"XAI_API_KEY\")}`, `language: \"en\"`],\n },\n};\n", "// SPDX-License-Identifier: MIT\n//\n// TTS stage registry, verified against packages/{cartesia,elevenlabs,gemini,openai-tts,grok}/src.\n\nimport type { TtsProvider } from \"../options.js\";\nimport type { StageProvider } from \"./types.js\";\n\nconst PKG_VERSION = \"^4.3.0\";\n\nexport const TTS_STAGE_PROVIDERS: Readonly<Record<TtsProvider, StageProvider | undefined>> = {\n // packages/cartesia/src/index.ts: CartesiaTTSPlugin. Config mirrors hello-voice-agent.ts.\n cartesia: {\n packageName: \"@kuralle-syrinx/cartesia\",\n packageVersion: PKG_VERSION,\n className: \"CartesiaTTSPlugin\",\n envKeys: [\n { key: \"CARTESIA_API_KEY\", required: true },\n { key: \"CARTESIA_VOICE_ID\", required: true },\n ],\n usesSocketFactory: true,\n ownsEndpointing: false,\n configFields: (envRef) => [`api_key: ${envRef(\"CARTESIA_API_KEY\")}`, `voice_id: ${envRef(\"CARTESIA_VOICE_ID\")}`],\n },\n // packages/elevenlabs/src/tts.ts: ElevenLabsTTSPlugin.\n elevenlabs: {\n packageName: \"@kuralle-syrinx/elevenlabs\",\n packageVersion: PKG_VERSION,\n importFrom: \"@kuralle-syrinx/elevenlabs/tts\",\n className: \"ElevenLabsTTSPlugin\",\n envKeys: [\n { key: \"ELEVENLABS_API_KEY\", required: true },\n { key: \"ELEVENLABS_VOICE_ID\", required: true },\n ],\n usesSocketFactory: true,\n ownsEndpointing: false,\n configFields: (envRef) => [`api_key: ${envRef(\"ELEVENLABS_API_KEY\")}`, `voice_id: ${envRef(\"ELEVENLABS_VOICE_ID\")}`],\n },\n // packages/gemini/src/index.ts: GeminiTTSPlugin. HTTP-based (@google/genai) \u2014 no SocketFactory.\n gemini: {\n packageName: \"@kuralle-syrinx/gemini\",\n packageVersion: PKG_VERSION,\n className: \"GeminiTTSPlugin\",\n envKeys: [{ key: \"GOOGLE_GENERATIVE_AI_API_KEY\", required: true }],\n usesSocketFactory: false,\n ownsEndpointing: false,\n configFields: (envRef) => [`api_key: ${envRef(\"GOOGLE_GENERATIVE_AI_API_KEY\")}`],\n },\n // packages/openai-tts/src/index.ts: OpenAICompatibleTTSPlugin. HTTP-based \u2014 no SocketFactory.\n \"openai-tts\": {\n packageName: \"@kuralle-syrinx/openai-tts\",\n packageVersion: PKG_VERSION,\n className: \"OpenAICompatibleTTSPlugin\",\n envKeys: [{ key: \"OPENAI_API_KEY\", required: true }],\n usesSocketFactory: false,\n ownsEndpointing: false,\n configFields: (envRef) => [`api_key: ${envRef(\"OPENAI_API_KEY\")}`],\n },\n // packages/grok/src/tts.ts: GrokTTSPlugin.\n grok: {\n packageName: \"@kuralle-syrinx/grok\",\n packageVersion: PKG_VERSION,\n importFrom: \"@kuralle-syrinx/grok/tts\",\n className: \"GrokTTSPlugin\",\n envKeys: [{ key: \"XAI_API_KEY\", required: true }],\n usesSocketFactory: true,\n ownsEndpointing: false,\n configFields: (envRef) => [`api_key: ${envRef(\"XAI_API_KEY\")}`, `voice_id: \"eve\"`],\n },\n};\n", "// SPDX-License-Identifier: MIT\n//\n// Reasoner registry. `undefined` for a provider not yet wired into the\n// generator \u2014 kuralle needs a real @kuralle-agents/core Runtime instance\n// (fromKuralleRuntime(runtime, opts)), which this generator does not yet\n// scaffold; see the report for why.\n//\n// Every entry's `reasonerExpr` produces a bare `Reasoner` (packages/core's\n// stream seam). The cascade template wraps it in `new ReasoningBridge(...)`\n// for the node runtime; the Cloudflare template passes it straight to\n// `withVoice`'s `reasoner: (env) => ...` \u2014 both consume the same expression.\n// `ReasoningBridge` itself is NOT imported here: the cascade agent-module\n// template always imports it from @kuralle-syrinx/aisdk (it is the generic\n// VoicePlugin wrapper around any Reasoner, independent of which provider\n// produced it \u2014 mirrors examples/.../university-support-mastra.ts, which\n// depends on @kuralle-syrinx/aisdk purely for this wrapper).\n\nimport type { ReasonerProvider } from \"../options.js\";\nimport type { ReasonerProviderEmission } from \"./types.js\";\n\nconst PKG_VERSION = \"^4.3.0\";\nconst OPENAI_SDK_VERSION = \"^3.0.67\";\nconst AI_SDK_VERSION = \"^6.0.0\";\nconst MASTRA_CORE_VERSION = \"^1.41.0\";\n\nexport const SYSTEM_PROMPT_CONST = \"SYSTEM_PROMPT\";\n\nexport const REASONER_PROVIDERS: Readonly<Record<ReasonerProvider, ReasonerProviderEmission | undefined>> = {\n // packages/aisdk/src/from-ai-sdk.ts: fromStreamText(config) -> Reasoner.\n // Mirrors examples/02-hello-voice-headless/src/hello-voice-agent.ts.\n aisdk: {\n packageName: \"@kuralle-syrinx/aisdk\",\n packageVersion: PKG_VERSION,\n extraPackages: { \"@ai-sdk/openai\": OPENAI_SDK_VERSION, ai: AI_SDK_VERSION },\n envKeys: [{ key: \"OPENAI_API_KEY\", required: true }],\n importLines: () => [\n `import { fromStreamText } from \"@kuralle-syrinx/aisdk\";`,\n `import { createOpenAI } from \"@ai-sdk/openai\";`,\n ],\n preludeLines: (envRef) => [`const openai = createOpenAI({ apiKey: ${envRef(\"OPENAI_API_KEY\")} });`],\n reasonerExpr: `fromStreamText({ model: openai(\"gpt-4.1-mini\"), system: ${SYSTEM_PROMPT_CONST} })`,\n },\n // packages/mastra/src/from-mastra.ts: fromMastraAgent(agent) -> Reasoner.\n // Mirrors examples/02-hello-voice-headless/src/university-support-mastra.ts.\n mastra: {\n packageName: \"@kuralle-syrinx/mastra\",\n packageVersion: PKG_VERSION,\n extraPackages: { \"@ai-sdk/openai\": OPENAI_SDK_VERSION, \"@mastra/core\": MASTRA_CORE_VERSION },\n envKeys: [{ key: \"OPENAI_API_KEY\", required: true }],\n importLines: () => [\n `import { fromMastraAgent, type MastraAgentLike } from \"@kuralle-syrinx/mastra\";`,\n `import { createOpenAI } from \"@ai-sdk/openai\";`,\n `import { Agent as MastraAgent } from \"@mastra/core/agent\";`,\n ],\n preludeLines: (envRef) => [\n `const openai = createOpenAI({ apiKey: ${envRef(\"OPENAI_API_KEY\")} });`,\n `const mastraAgent = new MastraAgent({`,\n ` id: \"syrinx-agent\",`,\n ` name: \"syrinx-agent\",`,\n ` instructions: ${SYSTEM_PROMPT_CONST},`,\n ` model: openai(\"gpt-4.1-mini\"),`,\n `});`,\n ],\n // Structural cast to MastraAgentLike, same pattern the reference agent uses \u2014\n // fromMastraAgent types against a structural interface, not @mastra/core's own type.\n reasonerExpr: `fromMastraAgent(mastraAgent as unknown as MastraAgentLike)`,\n },\n kuralle: undefined,\n};\n", "// SPDX-License-Identifier: MIT\n//\n// Speech-to-speech (realtime) registry, verified against\n// packages/realtime/src/from-openai-realtime.ts and\n// packages/grok/src/from-grok-realtime.ts. Mirrors\n// examples/02-hello-voice-headless/scripts/run-realtime-oneturn-smoke.ts:\n// `fromXRealtime({ apiKey, socketFactory })` -> `RealtimeAdapter`, wrapped in\n// `new RealtimeBridge(adapter)` and registered on the \"realtime\" slot with\n// `endpointingOwner: \"timer\"`.\n\nimport type { RealtimeProvider } from \"../options.js\";\nimport type { RealtimeProviderEmission } from \"./types.js\";\n\nconst PKG_VERSION = \"^4.3.0\";\n\nexport const REALTIME_PROVIDERS: Readonly<Record<RealtimeProvider, RealtimeProviderEmission | undefined>> = {\n realtime: {\n packageName: \"@kuralle-syrinx/realtime\",\n packageVersion: PKG_VERSION,\n envKeys: [{ key: \"OPENAI_API_KEY\", required: true }],\n importLines: [`import { fromOpenAIRealtime } from \"@kuralle-syrinx/realtime\";`],\n adapterExpr: (envRef, socketFactoryIdent) => `fromOpenAIRealtime({ apiKey: ${envRef(\"OPENAI_API_KEY\")}, socketFactory: ${socketFactoryIdent} })`,\n },\n grok: {\n packageName: \"@kuralle-syrinx/grok\",\n packageVersion: PKG_VERSION,\n envKeys: [{ key: \"XAI_API_KEY\", required: true }],\n importLines: [`import { fromGrokRealtime } from \"@kuralle-syrinx/grok/realtime\";`],\n adapterExpr: (envRef, socketFactoryIdent) => `fromGrokRealtime({ apiKey: ${envRef(\"XAI_API_KEY\")}, socketFactory: ${socketFactoryIdent} })`,\n },\n};\n", "// SPDX-License-Identifier: MIT\n//\n// Optional VAD / endpointing sidecar plugins. `vap` is not yet wired into the\n// generator \u2014 packages/vap exports an InteractionPolicy (VapInteractionPolicy)\n// rather than a drop-in VoicePlugin like PipecatEOSPlugin, which needs\n// InteractionCoordinator wiring this generator doesn't yet scaffold.\n\nimport type { EndpointingProvider, VadProvider } from \"../options.js\";\nimport type { SidecarPluginEmission } from \"./types.js\";\n\nconst PKG_VERSION = \"^4.3.0\";\n\nexport const VAD_SIDECAR_PROVIDERS: Readonly<Record<VadProvider, SidecarPluginEmission | undefined>> = {\n // packages/silero-vad/src/index.ts: SileroVADPlugin. No API key \u2014 a bundled ONNX model.\n \"silero-vad\": {\n packageName: \"@kuralle-syrinx/silero-vad\",\n packageVersion: PKG_VERSION,\n className: \"SileroVADPlugin\",\n slot: \"vad\",\n envKeys: [],\n configFields: () => [],\n },\n};\n\nexport const ENDPOINTING_SIDECAR_PROVIDERS: Readonly<Record<EndpointingProvider, SidecarPluginEmission | undefined>> = {\n // packages/pipecat-smart-turn/src/index.ts: PipecatEOSPlugin. No API key \u2014 a bundled ONNX model.\n \"pipecat-smart-turn\": {\n packageName: \"@kuralle-syrinx/pipecat-smart-turn\",\n packageVersion: PKG_VERSION,\n className: \"PipecatEOSPlugin\",\n slot: \"eos\",\n envKeys: [],\n configFields: () => [],\n },\n vap: undefined,\n};\n", "// SPDX-License-Identifier: MIT\n//\n// Emits src/agent.ts for the node runtime \u2014 the module the CLI's --agent\n// seam points at (`tsx scripts/dev-server.ts --agent ./src/agent.ts#createAgent`,\n// `syrinx turn --agent ./src/agent.ts#createAgent`). Mirrors\n// examples/02-hello-voice-headless/src/hello-voice-agent.ts (cascade) and\n// scripts/run-realtime-oneturn-smoke.ts (realtime).\n\nimport type { ResolvedOptions } from \"../options.js\";\nimport { STT_STAGE_PROVIDERS } from \"../providers/stt.js\";\nimport { TTS_STAGE_PROVIDERS } from \"../providers/tts.js\";\nimport { REASONER_PROVIDERS, SYSTEM_PROMPT_CONST } from \"../providers/reasoner.js\";\nimport { REALTIME_PROVIDERS } from \"../providers/realtime.js\";\nimport { VAD_SIDECAR_PROVIDERS, ENDPOINTING_SIDECAR_PROVIDERS } from \"../providers/vad-endpointing.js\";\nimport { CliError, EXIT_CODES } from \"../exit-codes.js\";\nimport type { StageProvider } from \"../providers/types.js\";\n\nconst SYSTEM_PROMPT = \"You are a helpful voice assistant. Keep your replies short.\";\n\nfunction nodeEnvRef(key: string): string {\n return `process.env[\"${key}\"] ?? \"\"`;\n}\n\nfunction requireStage(provider: StageProvider | undefined, flag: string, value: string): StageProvider {\n if (provider === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--${flag} ${value} is not yet implemented by this generator`);\n }\n return provider;\n}\n\nfunction importLine(className: string, from: string): string {\n return `import { ${className} } from \"${from}\";`;\n}\n\n/** Merge `import { A } from \"x\"; import { B } from \"x\";` pairs sharing one module into one line. */\nfunction mergeImports(lines: readonly string[]): string[] {\n const IMPORT_RE = /^import \\{ (.+) \\} from \"(.+)\";$/;\n const sourceOrder: string[] = [];\n const namesBySource = new Map<string, string[]>();\n\n for (const line of lines) {\n const match = IMPORT_RE.exec(line);\n const names = match?.[1];\n const from = match?.[2];\n if (names === undefined || from === undefined) continue; // every entry here is an import line\n let bucket = namesBySource.get(from);\n if (bucket === undefined) {\n bucket = [];\n namesBySource.set(from, bucket);\n sourceOrder.push(from);\n }\n for (const name of names.split(\",\").map((n) => n.trim())) {\n if (!bucket.includes(name)) bucket.push(name);\n }\n }\n\n return sourceOrder.map((from) => `import { ${(namesBySource.get(from) ?? []).join(\", \")} } from \"${from}\";`);\n}\n\nexport function buildAgentModule(opts: ResolvedOptions): string {\n if (opts.mode === \"realtime\") return buildRealtimeAgentModule(opts);\n return buildCascadeAgentModule(opts);\n}\n\nfunction buildCascadeAgentModule(opts: Extract<ResolvedOptions, { mode: \"cascade\" }>): string {\n const stt = requireStage(STT_STAGE_PROVIDERS[opts.stt], \"stt\", opts.stt);\n const tts = requireStage(TTS_STAGE_PROVIDERS[opts.tts], \"tts\", opts.tts);\n const reasoner = REASONER_PROVIDERS[opts.reasoner];\n if (reasoner === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--reasoner ${opts.reasoner} is not yet implemented by this generator`);\n }\n const vad = opts.vad !== undefined ? VAD_SIDECAR_PROVIDERS[opts.vad] : undefined;\n if (opts.vad !== undefined && vad === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--vad ${opts.vad} is not yet implemented by this generator`);\n }\n const eos = opts.endpointing !== undefined ? ENDPOINTING_SIDECAR_PROVIDERS[opts.endpointing] : undefined;\n if (opts.endpointing !== undefined && eos === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--endpointing ${opts.endpointing} is not yet implemented by this generator`);\n }\n const endpointingOwner = eos !== undefined ? \"smart_turn\" : stt.ownsEndpointing ? \"provider_stt\" : undefined;\n if (endpointingOwner === undefined) {\n throw new CliError(\n EXIT_CODES.USAGE,\n `--stt ${opts.stt} cannot own endpointing on its own \u2014 pass --endpointing pipecat-smart-turn`,\n );\n }\n\n const imports = [\n `import { VoiceAgentSession, type VoicePlugin } from \"@kuralle-syrinx/core\";`,\n `import { ReasoningBridge } from \"@kuralle-syrinx/aisdk\";`,\n importLine(stt.className, stt.importFrom ?? stt.packageName),\n importLine(tts.className, tts.importFrom ?? tts.packageName),\n ...(vad !== undefined ? [importLine(vad.className, vad.packageName)] : []),\n ...(eos !== undefined ? [importLine(eos.className, eos.packageName)] : []),\n ...reasoner.importLines(nodeEnvRef),\n ];\n\n const pluginConfigLines: string[] = [\n ` stt: {`,\n ...stt.configFields(nodeEnvRef).map((f) => ` ${f},`),\n ` },`,\n ];\n if (vad !== undefined) pluginConfigLines.push(` vad: {},`);\n if (eos !== undefined) pluginConfigLines.push(` eos: {},`);\n pluginConfigLines.push(\n ` bridge: {},`,\n ` tts: {`,\n ...tts.configFields(nodeEnvRef).map((f) => ` ${f},`),\n ` },`,\n );\n\n const pluginInstanceLines: string[] = [` stt: new ${stt.className}(),`];\n if (vad !== undefined) pluginInstanceLines.push(` vad: new ${vad.className}(),`);\n if (eos !== undefined) pluginInstanceLines.push(` eos: new ${eos.className}(),`);\n pluginInstanceLines.push(\n ` bridge: new ReasoningBridge(${reasoner.reasonerExpr}),`,\n ` tts: new ${tts.className}(),`,\n );\n\n return `// SPDX-License-Identifier: MIT\n//\n// Cascade voice agent: ${opts.stt} STT -> ${opts.reasoner} reasoner -> ${opts.tts} TTS.\n// Generated by create-syrinx-agent. Wired to the local dev server and to\n// \\`syrinx turn\\`/\\`syrinx text\\` through the --agent <module>#<export> seam\n// (examples/02-hello-voice-headless/scripts/dev-server.ts).\n\n${mergeImports(imports).join(\"\\n\")}\n\nconst ${SYSTEM_PROMPT_CONST} = ${JSON.stringify(SYSTEM_PROMPT)};\n\nexport function createAgent(): VoiceAgentSession {\n${reasoner.preludeLines(nodeEnvRef).map((l) => ` ${l}`).join(\"\\n\")}\n\n const session = new VoiceAgentSession({\n plugins: {\n${pluginConfigLines.join(\"\\n\")}\n },\n endpointingOwner: \"${endpointingOwner}\",\n });\n\n const plugins: Record<string, VoicePlugin> = {\n${pluginInstanceLines.join(\"\\n\")}\n };\n for (const [name, plugin] of Object.entries(plugins)) {\n session.registerPlugin(name, plugin);\n }\n\n return session;\n}\n`;\n}\n\nfunction buildRealtimeAgentModule(opts: Extract<ResolvedOptions, { mode: \"realtime\" }>): string {\n const realtime = REALTIME_PROVIDERS[opts.realtime];\n if (realtime === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--realtime ${opts.realtime} is not yet implemented by this generator`);\n }\n\n const imports = [\n `import { VoiceAgentSession } from \"@kuralle-syrinx/core\";`,\n `import { RealtimeBridge } from \"@kuralle-syrinx/realtime\";`,\n `import { createNodeWsSocket } from \"@kuralle-syrinx/ws/node\";`,\n ...realtime.importLines,\n ];\n\n return `// SPDX-License-Identifier: MIT\n//\n// Speech-to-speech voice agent: ${opts.realtime} realtime. Generated by\n// create-syrinx-agent. Wired to the local dev server and to\n// \\`syrinx turn\\`/\\`syrinx text\\` through the --agent <module>#<export> seam\n// (examples/02-hello-voice-headless/scripts/dev-server.ts).\n\n${mergeImports(imports).join(\"\\n\")}\n\nexport function createAgent(): VoiceAgentSession {\n const adapter = ${realtime.adapterExpr(nodeEnvRef, \"createNodeWsSocket\")};\n const bridge = new RealtimeBridge(adapter);\n\n const session = new VoiceAgentSession({\n plugins: { realtime: {} },\n endpointingOwner: \"timer\",\n });\n session.registerPlugin(\"realtime\", bridge);\n\n return session;\n}\n`;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Emits scripts/dev-server.ts for the node runtime \u2014 a transport host that\n// resolves --agent <module>[#export] exactly like\n// examples/02-hello-voice-headless/scripts/dev-server.ts, minus that example's\n// Studio-asset serving (this is a standalone project, not inside the monorepo;\n// bring your own browser client, e.g. @kuralle-syrinx/browser-client).\n\nimport type { Transport } from \"../options.js\";\n\ninterface TransportServerBinding {\n readonly factoryName: string;\n readonly extraOptions: readonly string[];\n readonly urlPath: string;\n}\n\nconst TRANSPORT_SERVERS: Readonly<Record<Transport, TransportServerBinding>> = {\n browser: { factoryName: \"createVoiceWebSocketServer\", extraOptions: [`path: \"/ws\"`], urlPath: \"/ws\" },\n twilio: { factoryName: \"createTwilioMediaStreamServer\", extraOptions: [], urlPath: \"/\" },\n telnyx: { factoryName: \"createTelnyxMediaStreamServer\", extraOptions: [], urlPath: \"/\" },\n smartpbx: { factoryName: \"createSmartPbxMediaStreamServer\", extraOptions: [], urlPath: \"/\" },\n};\n\nexport function buildDevServer(transport: Transport): string {\n const binding = TRANSPORT_SERVERS[transport];\n const optionsLines = [` port,`, ` host,`, ...binding.extraOptions.map((l) => ` ${l},`), ` createSession: () => factory(),`];\n\n return `// SPDX-License-Identifier: MIT\n//\n// Local dev server \u2014 wires YOUR agent module to a ${transport} transport host.\n//\n// pnpm dev -- --agent ./src/agent.ts#createAgent\n//\n// --agent is <module>[#namedExport]; the export is a zero-arg factory\n// returning a VoiceAgentSession. Same seam as\n// examples/02-hello-voice-headless/scripts/dev-server.ts.\n\nimport { isAbsolute, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { ${binding.factoryName}, installGracefulShutdown } from \"@kuralle-syrinx/server-websocket\";\nimport type { VoiceAgentSession } from \"@kuralle-syrinx/core\";\n\nexport type SessionFactory = () => VoiceAgentSession | Promise<VoiceAgentSession>;\n\n/**\n * Resolve \\`--agent <module>[#export]\\` to a factory. Fails loudly and\n * specifically \u2014 a dev server that silently falls back to a different agent\n * than the one you asked for is worse than one that refuses to start.\n */\nasync function resolveAgentFactory(spec: string | undefined): Promise<{ factory: SessionFactory; label: string }> {\n if (!spec) throw new Error(\"--agent <module>[#export] is required, e.g. --agent ./src/agent.ts#createAgent\");\n const [modulePath, exportName] = spec.split(\"#\");\n if (!modulePath) throw new Error(\\`--agent needs a module path, got: \\${spec}\\`);\n const abs = isAbsolute(modulePath) ? modulePath : resolve(process.cwd(), modulePath);\n const mod = (await import(pathToFileURL(abs).href)) as Record<string, unknown>;\n\n const picked = exportName ? mod[exportName] : (mod[\"default\"] ?? mod[\"createAgent\"] ?? mod[\"createSession\"]);\n if (typeof picked !== \"function\") {\n const available = Object.keys(mod).filter((k) => typeof mod[k] === \"function\");\n throw new Error(\n \\`\\${abs} has no callable export \\${exportName ? \\`\"\\${exportName}\"\\` : \"(default, createAgent, or createSession)\"}. \\` +\n \\`Callable exports: \\${available.length > 0 ? available.join(\", \") : \"(none)\"}\\`,\n );\n }\n return { factory: picked as SessionFactory, label: \\`\\${modulePath}\\${exportName ? \\`#\\${exportName}\\` : \"\"}\\` };\n}\n\nfunction flag(argv: readonly string[], name: string): string | undefined {\n const i = argv.indexOf(name);\n return i >= 0 ? argv[i + 1] : undefined;\n}\n\nfunction readPort(): number {\n const raw = process.env[\"SYRINX_DEV_PORT\"]?.trim();\n if (!raw) return 4173;\n const port = Number.parseInt(raw, 10);\n if (!Number.isFinite(port) || port <= 0 || port > 65535) throw new Error(\\`invalid SYRINX_DEV_PORT: \\${raw}\\`);\n return port;\n}\n\nasync function main(): Promise<void> {\n const { factory, label } = await resolveAgentFactory(flag(process.argv.slice(2), \"--agent\"));\n const port = readPort();\n const host = process.env[\"SYRINX_DEV_HOST\"]?.trim() || \"127.0.0.1\";\n\n const server = await ${binding.factoryName}({\n${optionsLines.join(\"\\n\")}\n });\n\n const address = server.address();\n if (!address || typeof address === \"string\") throw new Error(\"expected TCP server address\");\n console.log(\\`Syrinx dev server (${transport}): ws://\\${host}:\\${String(address.port)}${binding.urlPath}\\`);\n console.log(\\`Agent: \\${label}\\`);\n\n installGracefulShutdown(server, { drainDeadlineMs: 10_000, onClosed: () => process.exit(0) });\n}\n\nvoid main().catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n`;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Builds the generated project's package.json \u2014 dependencies limited to\n// exactly the chosen providers (LDT-21 requirement), plus the fixed\n// infrastructure every combination needs: core, the CLI (for `syrinx turn`/\n// `syrinx text` in the check:* scripts), and tsx (the --agent seam needs it\n// for a .ts module \u2014 see AGENTS.md).\n\nimport type { ResolvedOptions } from \"../options.js\";\nimport { STT_STAGE_PROVIDERS } from \"../providers/stt.js\";\nimport { TTS_STAGE_PROVIDERS } from \"../providers/tts.js\";\nimport { REASONER_PROVIDERS } from \"../providers/reasoner.js\";\nimport { REALTIME_PROVIDERS } from \"../providers/realtime.js\";\nimport { VAD_SIDECAR_PROVIDERS, ENDPOINTING_SIDECAR_PROVIDERS } from \"../providers/vad-endpointing.js\";\n\nconst CORE_VERSION = \"^4.3.0\";\n\n// @kuralle-syrinx/server-websocket (and any ws-based STT/TTS/realtime provider,\n// transitively through @kuralle-syrinx/ws) ships raw TS as \"main\" and declares\n// `ws` as a runtime dep but `@types/ws` only as a devDependency \u2014 devDeps of a\n// dependency are never installed for the consumer, so a project that typechecks\n// server-websocket's source needs its own `@types/ws` (mirrors\n// examples/02-hello-voice-headless/package.json, which declares both directly).\nfunction transportPackage(): Readonly<Record<string, string>> {\n return { \"@kuralle-syrinx/server-websocket\": CORE_VERSION, ws: \"^8.21.0\" };\n}\n\nexport function collectDependencies(opts: ResolvedOptions): Record<string, string> {\n const deps: Record<string, string> = {\n \"@kuralle-syrinx/core\": CORE_VERSION,\n ...transportPackage(),\n };\n\n if (opts.mode === \"cascade\") {\n const stt = STT_STAGE_PROVIDERS[opts.stt];\n const tts = TTS_STAGE_PROVIDERS[opts.tts];\n const reasoner = REASONER_PROVIDERS[opts.reasoner];\n if (stt) deps[stt.packageName] = stt.packageVersion;\n if (tts) deps[tts.packageName] = tts.packageVersion;\n // ReasoningBridge (the VoicePlugin wrapper any Reasoner needs in cascade mode) lives here.\n deps[\"@kuralle-syrinx/aisdk\"] = CORE_VERSION;\n if (reasoner) {\n deps[reasoner.packageName] = reasoner.packageVersion;\n Object.assign(deps, reasoner.extraPackages);\n }\n const vad = opts.vad !== undefined ? VAD_SIDECAR_PROVIDERS[opts.vad] : undefined;\n if (vad) deps[vad.packageName] = vad.packageVersion;\n const eos = opts.endpointing !== undefined ? ENDPOINTING_SIDECAR_PROVIDERS[opts.endpointing] : undefined;\n if (eos) deps[eos.packageName] = eos.packageVersion;\n } else {\n const realtime = REALTIME_PROVIDERS[opts.realtime];\n // RealtimeBridge (the generic VoicePlugin wrapper around any RealtimeAdapter) lives here.\n deps[\"@kuralle-syrinx/realtime\"] = CORE_VERSION;\n deps[\"@kuralle-syrinx/ws\"] = CORE_VERSION;\n if (realtime) deps[realtime.packageName] = realtime.packageVersion;\n }\n\n return deps;\n}\n\nexport function buildPackageJson(opts: ResolvedOptions): string {\n const dependencies = collectDependencies(opts);\n const agentSpec = \"./src/agent.ts#createAgent\";\n\n const scripts: Record<string, string> = {\n dev: `tsx scripts/dev-server.ts --agent ${agentSpec}`,\n \"check:typecheck\": \"tsc --noEmit\",\n \"check:turn\": `syrinx turn --in test/fixtures/smoke.wav --agent ${agentSpec} --json`,\n };\n const devDependencies: Record<string, string> = {\n \"@types/node\": \"^22.0.0\",\n \"@types/ws\": \"^8.18.1\",\n tsx: \"^4.20.0\",\n typescript: \"^5.7.0\",\n };\n\n // --runtime cloudflare additionally ships src/index.ts (the deploy artifact, a\n // withVoice(Agent) Durable Object) + wrangler.jsonc alongside the SAME src/agent.ts\n // + scripts/dev-server.ts used for local iteration and check:turn \u2014 the deploy\n // artifact's own typecheck is covered by check:typecheck (tsconfig includes all of\n // src/), but it is not live-verified (see AGENTS.md / the --transport telnyx warning).\n if (opts.runtime === \"cloudflare\") {\n dependencies[\"@kuralle-syrinx/cf-agents\"] = CORE_VERSION;\n dependencies[\"agents\"] = \"0.14.0\";\n // `agents` peer-depends on ai@^6.0.0, but its own optional @cloudflare/ai-chat\n // dependency pulls a newer `ai` major transitively \u2014 without a direct pin here\n // npm's resolver lands on the newer major and ERESOLVEs against agents' peer.\n // examples/03-cf-agent-voice/package.json pins the same \"ai\": \"^6.0.0\" for the\n // same reason, in both its cascaded AND realtime example classes.\n dependencies[\"ai\"] = \"^6.0.0\";\n // Pinned exact, not a caret range: `wrangler`'s peer on @cloudflare/workers-types\n // moved to v5 in newer releases while `agents`/`partyserver` still peer on v4,\n // so a loose `^4.19.0` resolves npm to the newest 4.x wrangler and hits an\n // ERESOLVE conflict. This exact pair is the one this monorepo's own\n // pnpm-lock.yaml already resolves.\n devDependencies[\"@cloudflare/workers-types\"] = \"^4.20260601.1\";\n devDependencies[\"wrangler\"] = \"4.97.0\";\n scripts[\"check:wrangler-dry-run\"] = \"wrangler deploy --dry-run\";\n }\n\n const pkg = {\n name: opts.name,\n version: \"0.0.1\",\n private: true,\n type: \"module\",\n license: \"MIT\",\n scripts,\n dependencies: sortKeys({ ...dependencies, \"@kuralle-syrinx/cli\": CORE_VERSION }),\n devDependencies: sortKeys(devDependencies),\n };\n\n return `${JSON.stringify(pkg, null, 2)}\\n`;\n}\n\nfunction sortKeys(obj: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const key of Object.keys(obj).sort()) out[key] = obj[key] as string;\n return out;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Builds .env.example naming exactly the keys the chosen combination needs\n// (LDT-21 requirement) \u2014 not a union of every provider's keys.\n\nimport type { ResolvedOptions } from \"../options.js\";\nimport { STT_STAGE_PROVIDERS } from \"../providers/stt.js\";\nimport { TTS_STAGE_PROVIDERS } from \"../providers/tts.js\";\nimport { REASONER_PROVIDERS } from \"../providers/reasoner.js\";\nimport { REALTIME_PROVIDERS } from \"../providers/realtime.js\";\nimport { VAD_SIDECAR_PROVIDERS, ENDPOINTING_SIDECAR_PROVIDERS } from \"../providers/vad-endpointing.js\";\nimport type { EnvKeySpec } from \"../providers/types.js\";\n\nexport function collectEnvKeys(opts: ResolvedOptions): readonly EnvKeySpec[] {\n const keys: EnvKeySpec[] = [];\n const seen = new Set<string>();\n const add = (specs: readonly EnvKeySpec[]) => {\n for (const spec of specs) {\n if (seen.has(spec.key)) continue;\n seen.add(spec.key);\n keys.push(spec);\n }\n };\n\n if (opts.mode === \"cascade\") {\n const stt = STT_STAGE_PROVIDERS[opts.stt];\n const tts = TTS_STAGE_PROVIDERS[opts.tts];\n const reasoner = REASONER_PROVIDERS[opts.reasoner];\n if (stt) add(stt.envKeys);\n if (tts) add(tts.envKeys);\n if (reasoner) add(reasoner.envKeys);\n const vad = opts.vad !== undefined ? VAD_SIDECAR_PROVIDERS[opts.vad] : undefined;\n if (vad) add(vad.envKeys);\n const eos = opts.endpointing !== undefined ? ENDPOINTING_SIDECAR_PROVIDERS[opts.endpointing] : undefined;\n if (eos) add(eos.envKeys);\n } else {\n const realtime = REALTIME_PROVIDERS[opts.realtime];\n if (realtime) add(realtime.envKeys);\n }\n\n return keys;\n}\n\nexport function buildEnvExample(opts: ResolvedOptions): string {\n const keys = collectEnvKeys(opts);\n const lines = [\n \"# Generated by create-syrinx-agent \u2014 exactly the keys this combination needs.\",\n \"# Copy to .env and fill in.\",\n \"\",\n ...keys.map((k) => `${k.key}=`),\n \"\",\n \"# Optional \u2014 local dev server bind (defaults: 127.0.0.1:4173)\",\n \"SYRINX_DEV_PORT=\",\n \"SYRINX_DEV_HOST=\",\n \"\",\n ];\n return `${lines.join(\"\\n\")}\\n`;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Builds AGENTS.md \u2014 must state plainly what a coding agent CANNOT verify\n// headlessly (LDT-21 requirement). An AGENTS.md implying headless\n// verification is complete is worse than shipping none.\n\nimport type { ResolvedOptions } from \"../options.js\";\n\nexport function buildAgentsMd(opts: ResolvedOptions): string {\n const pipelineLine =\n opts.mode === \"cascade\"\n ? `${opts.stt} STT -> ${opts.reasoner} reasoner -> ${opts.tts} TTS (cascade)`\n : `${opts.realtime} realtime (speech-to-speech, no separate STT/TTS stages)`;\n\n return `# AGENTS.md\n\nThis project was generated by \\`create-syrinx-agent\\`.\n\nPipeline: ${pipelineLine}\nTransport: ${opts.transport} \u00B7 Runtime: ${opts.runtime}\n\n## What a coding agent CAN verify here\n\n- \\`pnpm check:typecheck\\` (\\`tsc --noEmit\\`) \u2014 the agent module and dev server compile.\n- \\`pnpm check:turn\\` \u2014 runs \\`syrinx turn --in test/fixtures/smoke.wav --agent ./src/agent.ts#createAgent --json\\`.\n Given a fixture **with** a recorded expected transcript (a \\`.json\\` sidecar produced by the\n Studio's \"Save as fixture\"), this asserts the replayed transcript matches and **exits non-zero\n on drift** \u2014 a real regression check, not just a smoke test. The bundled \\`test/fixtures/smoke.wav\\`\n ships with no sidecar, so as generated this only proves the pipeline runs end-to-end and produces\n *some* transcript/reply/audio; record your own fixture with the Studio for an assertion that\n actually catches regressions.\n- Exit codes and JSON output from \\`syrinx turn\\` / \\`syrinx text\\` \u2014 parseable, deterministic,\n scriptable.\n\nBoth checks need real provider credentials in \\`.env\\` (see \\`.env.example\\`) \u2014 without them\n\\`check:turn\\` fails at the provider call, not at a code defect.\n\n## What a coding agent CANNOT verify here\n\nA coding agent can assert transcripts, exit codes, and latency numbers. It **cannot** judge:\n\n- Whether barge-in feels natural (the timing a human perceives as responsive vs. jarring).\n- Whether a pause reads as \"thinking\" or as a hang \u2014 same latency number, different human read.\n- Whether a synthesized voice sounds warm, robotic, or off \u2014 TTS quality is a perceptual judgment.\n\nThose need a human in the Syrinx Studio, listening. Do not treat a green \\`check:turn\\` as proof the\nagent is pleasant to talk to \u2014 it only proves the transcript matched (or that the pipeline ran, for\nthe unsigned bundled fixture).\n\n## \\`tsx\\` vs plain \\`node\\`\n\n\\`--agent\\` pointed at a \\`.ts\\` module (as in the scripts above) needs \\`tsx\\` \u2014 Node's built-in type\nstripping does not do TypeScript's \\`.js\\`-import-resolves-to-\\`.ts\\` remapping that this project's\nimports rely on. Built JS (after a bundler step) runs fine under plain \\`node\\`. Every script this\ngenerator wrote already invokes \\`tsx\\`; if you write your own, do the same for a \\`.ts\\` --agent target.\n\n## Layout\n\n- \\`src/agent.ts\\` \u2014 \\`createAgent()\\`, the \\`--agent\\` seam's factory export.\n- \\`scripts/dev-server.ts\\` \u2014 local dev server (\\`pnpm dev\\`), wraps \\`createAgent()\\` in a\n ${opts.transport} transport host.\n- \\`test/fixtures/smoke.wav\\` \u2014 bundled silence fixture for \\`check:turn\\`.\n- \\`.env.example\\` \u2014 exactly the provider keys this combination needs.\n`;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Generated project's tsconfig.json \u2014 mirrors examples/02-hello-voice-headless/tsconfig.json.\n// --runtime cloudflare additionally needs @cloudflare/workers-types: src/index.ts's\n// `Request`/`Response`/`fetch` globals come from there, not from a DOM lib (this\n// tsconfig has no \"DOM\" in `lib`, matching the node-runtime file it sits beside).\n\nimport type { Runtime } from \"../options.js\";\n\nexport function buildTsconfig(runtime: Runtime): string {\n const types = runtime === \"cloudflare\" ? [\"node\", \"@cloudflare/workers-types\"] : [\"node\"];\n const tsconfig = {\n compilerOptions: {\n target: \"ES2022\",\n module: \"NodeNext\",\n moduleResolution: \"NodeNext\",\n strict: true,\n skipLibCheck: true,\n noEmit: true,\n types,\n },\n include: [\"src/**/*.ts\", \"scripts/**/*.ts\"],\n };\n return `${JSON.stringify(tsconfig, null, 2)}\\n`;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// A minimal, self-contained mono 16 kHz PCM16 WAV fixture (0.5s of silence)\n// so `check:turn` (syrinx turn --in test/fixtures/smoke.wav) has something to\n// replay without depending on any file outside the generated project. It\n// carries no expected-transcript sidecar \u2014 see AGENTS.md for what that means.\n\nconst SAMPLE_RATE = 16_000;\nconst DURATION_SECONDS = 0.5;\nconst CHANNELS = 1;\nconst BITS_PER_SAMPLE = 16;\n\nexport function buildSmokeWav(): Buffer {\n const numSamples = Math.floor(SAMPLE_RATE * DURATION_SECONDS);\n const dataBytes = numSamples * CHANNELS * (BITS_PER_SAMPLE / 8);\n const buffer = Buffer.alloc(44 + dataBytes);\n\n buffer.write(\"RIFF\", 0, \"ascii\");\n buffer.writeUInt32LE(36 + dataBytes, 4);\n buffer.write(\"WAVE\", 8, \"ascii\");\n buffer.write(\"fmt \", 12, \"ascii\");\n buffer.writeUInt32LE(16, 16); // fmt chunk size\n buffer.writeUInt16LE(1, 20); // PCM\n buffer.writeUInt16LE(CHANNELS, 22);\n buffer.writeUInt32LE(SAMPLE_RATE, 24);\n buffer.writeUInt32LE(SAMPLE_RATE * CHANNELS * (BITS_PER_SAMPLE / 8), 28); // byte rate\n buffer.writeUInt16LE(CHANNELS * (BITS_PER_SAMPLE / 8), 32); // block align\n buffer.writeUInt16LE(BITS_PER_SAMPLE, 34);\n buffer.write(\"data\", 36, \"ascii\");\n buffer.writeUInt32LE(dataBytes, 40);\n // PCM16 silence: the buffer is already zero-filled by Buffer.alloc.\n\n return buffer;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Emits src/index.ts + wrangler.jsonc for --runtime cloudflare, mirroring\n// examples/03-cf-agent-voice/src/index.ts and packages/cf-agents/README.md's\n// `withVoice(Agent, { pipeline, reasoner, transport })` shape. VAD/endpointing\n// sidecars are not wired here yet (see the generator's report) \u2014 passing\n// --vad/--endpointing with --runtime cloudflare is refused upstream.\n\nimport type { ResolvedOptions, Transport } from \"../options.js\";\nimport { STT_STAGE_PROVIDERS } from \"../providers/stt.js\";\nimport { TTS_STAGE_PROVIDERS } from \"../providers/tts.js\";\nimport { REASONER_PROVIDERS, SYSTEM_PROMPT_CONST } from \"../providers/reasoner.js\";\nimport { REALTIME_PROVIDERS } from \"../providers/realtime.js\";\nimport { CliError, EXIT_CODES } from \"../exit-codes.js\";\nimport type { EnvKeySpec, StageProvider } from \"../providers/types.js\";\nimport { collectEnvKeys } from \"./env-example.js\";\n\nconst SYSTEM_PROMPT = \"You are a helpful voice assistant. Keep your replies short.\";\n\nfunction envRef(key: string): string {\n return `env.${key}`;\n}\n\nfunction importLine(className: string, from: string): string {\n return `import { ${className} } from \"${from}\";`;\n}\n\nfunction requireStage(provider: StageProvider | undefined, flag: string, value: string): StageProvider {\n if (provider === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--${flag} ${value} is not yet implemented by this generator`);\n }\n return provider;\n}\n\n/** `withVoice`'s documented `transport` option: \"edge\" | \"twilio\" | \"telnyx\" \u2014 no \"smartpbx\". */\nfunction cfTransport(transport: Transport): \"edge\" | \"twilio\" | \"telnyx\" {\n if (transport === \"browser\") return \"edge\";\n if (transport === \"twilio\" || transport === \"telnyx\") return transport;\n throw new CliError(\n EXIT_CODES.USAGE,\n `--runtime cloudflare has no ${transport} transport binding in @kuralle-syrinx/cf-agents (only edge/twilio/telnyx) \u2014 use --transport browser, twilio, or telnyx`,\n );\n}\n\nfunction envInterface(keys: readonly EnvKeySpec[]): string {\n const lines = keys.map((k) => ` readonly ${k.key}: string;`);\n return `interface Env extends Record<string, unknown> {\\n${lines.join(\"\\n\")}\\n}`;\n}\n\nexport function buildCloudflareWorkerSource(opts: ResolvedOptions): string {\n const transport = cfTransport(opts.transport);\n const envKeys = collectEnvKeys(opts);\n\n if (opts.mode === \"cascade\") {\n if (opts.vad !== undefined || opts.endpointing !== undefined) {\n throw new CliError(\n EXIT_CODES.USAGE,\n \"--vad/--endpointing are not yet implemented for --runtime cloudflare by this generator\",\n );\n }\n const stt = requireStage(STT_STAGE_PROVIDERS[opts.stt], \"stt\", opts.stt);\n const tts = requireStage(TTS_STAGE_PROVIDERS[opts.tts], \"tts\", opts.tts);\n const reasoner = REASONER_PROVIDERS[opts.reasoner];\n if (reasoner === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--reasoner ${opts.reasoner} is not yet implemented by this generator`);\n }\n\n const sttNew = stt.usesSocketFactory ? `new ${stt.className}(createWorkersSocket)` : `new ${stt.className}()`;\n const ttsNew = tts.usesSocketFactory ? `new ${tts.className}(createWorkersSocket)` : `new ${tts.className}()`;\n const needsWorkersSocket = stt.usesSocketFactory || tts.usesSocketFactory;\n\n const imports = [\n `import { Agent, routeAgentRequest } from \"agents\";`,\n `import { withVoice } from \"@kuralle-syrinx/cf-agents\";`,\n importLine(stt.className, stt.importFrom ?? stt.packageName),\n importLine(tts.className, tts.importFrom ?? tts.packageName),\n ...(needsWorkersSocket ? [`import { createWorkersSocket } from \"@kuralle-syrinx/ws/workers\";`] : []),\n ...reasoner.importLines(envRef),\n ];\n\n return `// SPDX-License-Identifier: MIT\n//\n// Cascade voice agent on Cloudflare Workers: ${opts.stt} STT -> ${opts.reasoner} reasoner -> ${opts.tts} TTS.\n// Generated by create-syrinx-agent. Mirrors examples/03-cf-agent-voice and\n// packages/cf-agents/README.md.\n\n${imports.join(\"\\n\")}\n\n${envInterface(envKeys)}\n\nconst ${SYSTEM_PROMPT_CONST} = ${JSON.stringify(SYSTEM_PROMPT)};\n\nexport class VoiceAgent extends withVoice<Env, typeof Agent<Env>>(Agent<Env>, {\n transport: \"${transport}\",\n pipeline: {\n kind: \"cascaded\",\n stt: (env) => ({\n plugin: ${sttNew},\n config: {\n${stt.configFields(envRef).map((f) => ` ${f},`).join(\"\\n\")}\n },\n }),\n tts: (env) => ({\n plugin: ${ttsNew},\n config: {\n${tts.configFields(envRef).map((f) => ` ${f},`).join(\"\\n\")}\n },\n }),\n },\n reasoner: (env) => {\n${reasoner.preludeLines(envRef).map((l) => ` ${l}`).join(\"\\n\")}\n return ${reasoner.reasonerExpr};\n },\n}) {}\n\nexport default {\n async fetch(request: Request, env: Env): Promise<Response> {\n return (await routeAgentRequest(request, env)) ?? new Response(\"Not found\", { status: 404 });\n },\n};\n`;\n }\n\n const realtime = REALTIME_PROVIDERS[opts.realtime];\n if (realtime === undefined) {\n throw new CliError(EXIT_CODES.USAGE, `--realtime ${opts.realtime} is not yet implemented by this generator`);\n }\n const imports = [\n `import { Agent, routeAgentRequest } from \"agents\";`,\n `import { withVoice } from \"@kuralle-syrinx/cf-agents\";`,\n `import { createWorkersSocket } from \"@kuralle-syrinx/ws/workers\";`,\n ...realtime.importLines,\n ];\n\n return `// SPDX-License-Identifier: MIT\n//\n// Speech-to-speech voice agent on Cloudflare Workers: ${opts.realtime} realtime.\n// Generated by create-syrinx-agent. Mirrors examples/03-cf-agent-voice and\n// packages/cf-agents/README.md.\n\n${imports.join(\"\\n\")}\n\n${envInterface(envKeys)}\n\nexport class VoiceAgent extends withVoice<Env, typeof Agent<Env>>(Agent<Env>, {\n transport: \"${transport}\",\n pipeline: {\n kind: \"realtime\",\n front: (env) => ${realtime.adapterExpr(envRef, \"createWorkersSocket\")},\n },\n}) {}\n\nexport default {\n async fetch(request: Request, env: Env): Promise<Response> {\n return (await routeAgentRequest(request, env)) ?? new Response(\"Not found\", { status: 404 });\n },\n};\n`;\n}\n\nexport function buildWranglerJsonc(opts: ResolvedOptions): string {\n const wrangler = {\n $schema: \"node_modules/wrangler/config-schema.json\",\n name: opts.name,\n main: \"src/index.ts\",\n compatibility_date: \"2026-06-01\",\n compatibility_flags: [\"nodejs_compat\"],\n durable_objects: { bindings: [{ name: \"VoiceAgent\", class_name: \"VoiceAgent\" }] },\n migrations: [{ tag: \"v1\", new_sqlite_classes: [\"VoiceAgent\"] }],\n };\n return `${JSON.stringify(wrangler, null, 2)}\\n`;\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Wires flag parsing -> validation -> file generation -> (optional) install.\n\nimport { resolveOptions, warningsFor, type RawFlags } from \"./options.js\";\nimport { buildFileMap, runNpmInstall, writeProject } from \"./write-project.js\";\nimport type { CliIO } from \"./cli.js\";\n\nexport async function runGenerate(values: RawFlags, positionals: readonly string[], io: CliIO): Promise<void> {\n const opts = resolveOptions(values, positionals);\n\n for (const warning of warningsFor(opts)) {\n io.stderr(`warning: ${warning}`);\n }\n\n const files = buildFileMap(opts);\n\n if (opts.dryRun) {\n io.stdout(`Would write ${String(files.length)} file(s) to ${opts.targetDir}:`);\n for (const file of files) io.stdout(` ${file.relPath}`);\n return;\n }\n\n await writeProject(opts.targetDir, files);\n io.stdout(`Wrote ${String(files.length)} file(s) to ${opts.targetDir}`);\n\n if (opts.skipInstall) {\n io.stdout(\"Skipped install (--no-install). Run `npm install` inside the project next.\");\n return;\n }\n\n io.stdout(`Installing dependencies in ${opts.name}/ ...`);\n runNpmInstall(opts.targetDir);\n io.stdout(\"Done.\");\n}\n", "// SPDX-License-Identifier: MIT\n//\n// Bin entry point. The shebang is injected by the esbuild banner at build\n// time (see scripts/build.mjs) so the raw TypeScript source stays a plain\n// module (mirrors packages/cli/src/index.ts).\n\nimport { main } from \"./cli.js\";\n\nmain(process.argv.slice(2))\n .then((code) => {\n process.exitCode = code;\n })\n .catch((err: unknown) => {\n console.error(err instanceof Error ? (err.stack ?? err.message) : String(err));\n process.exitCode = 1;\n });\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["envRef", "PKG_VERSION", "envRef", "PKG_VERSION", "REASONER_PROVIDERS", "envRef", "PKG_VERSION", "REALTIME_PROVIDERS", "envRef", "PKG_VERSION", "REASONER_PROVIDERS", "REALTIME_PROVIDERS", "REASONER_PROVIDERS", "REALTIME_PROVIDERS", "REASONER_PROVIDERS", "REALTIME_PROVIDERS", "SYSTEM_PROMPT", "importLine", "requireStage", "REASONER_PROVIDERS", "imports", "REALTIME_PROVIDERS"]
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-syrinx-agent",
|
|
3
|
+
"version": "4.4.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Scaffold a Syrinx voice agent project — STT/TTS/reasoner/transport picked by flag, one generator instead of enumerated templates",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"voice",
|
|
8
|
+
"voice-agent",
|
|
9
|
+
"speech",
|
|
10
|
+
"syrinx",
|
|
11
|
+
"scaffold",
|
|
12
|
+
"create"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "https://github.com/kuralle/syrinx#readme",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/kuralle/syrinx.git",
|
|
19
|
+
"directory": "packages/create-syrinx-agent"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/kuralle/syrinx/issues"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"bin": {
|
|
26
|
+
"create-syrinx-agent": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"src",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"esbuild": "^0.28.1",
|
|
37
|
+
"typescript": "^5.7.0",
|
|
38
|
+
"vitest": "^3.2.6"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "node scripts/build.mjs",
|
|
42
|
+
"typecheck": "tsc --noEmit",
|
|
43
|
+
"test": "vitest run"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// Argument parsing and dispatch. Never interactive beyond what --yes/TTY
|
|
4
|
+
// rules allow: no spinners, no colour. Results go to stdout, diagnostics to
|
|
5
|
+
// stderr.
|
|
6
|
+
|
|
7
|
+
import { parseArgs } from "node:util";
|
|
8
|
+
|
|
9
|
+
import { CliError, EXIT_CODES, type ExitCode } from "./exit-codes.js";
|
|
10
|
+
import { HELP_TEXT } from "./help.js";
|
|
11
|
+
import { GENERATOR_VERSION } from "./version.js";
|
|
12
|
+
import { runGenerate } from "./generate.js";
|
|
13
|
+
|
|
14
|
+
export interface CliIO {
|
|
15
|
+
readonly stdout: (line: string) => void;
|
|
16
|
+
readonly stderr: (line: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const defaultIO: CliIO = {
|
|
20
|
+
stdout: (line) => {
|
|
21
|
+
process.stdout.write(`${line}\n`);
|
|
22
|
+
},
|
|
23
|
+
stderr: (line) => {
|
|
24
|
+
process.stderr.write(`${line}\n`);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const PARSE_OPTIONS = {
|
|
29
|
+
"help": { type: "boolean", short: "h" },
|
|
30
|
+
"version": { type: "boolean", short: "v" },
|
|
31
|
+
"stt": { type: "string" },
|
|
32
|
+
"tts": { type: "string" },
|
|
33
|
+
"realtime": { type: "string" },
|
|
34
|
+
"reasoner": { type: "string" },
|
|
35
|
+
"vad": { type: "string" },
|
|
36
|
+
"endpointing": { type: "string" },
|
|
37
|
+
"transport": { type: "string" },
|
|
38
|
+
"runtime": { type: "string" },
|
|
39
|
+
"preset": { type: "string" },
|
|
40
|
+
"name": { type: "string" },
|
|
41
|
+
"yes": { type: "boolean" },
|
|
42
|
+
"no-install": { type: "boolean" },
|
|
43
|
+
"skip-install": { type: "boolean" },
|
|
44
|
+
"dry-run": { type: "boolean" },
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
export async function main(argv: readonly string[], io: CliIO = defaultIO): Promise<ExitCode> {
|
|
48
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
49
|
+
io.stdout(HELP_TEXT);
|
|
50
|
+
return EXIT_CODES.SUCCESS;
|
|
51
|
+
}
|
|
52
|
+
if (argv.includes("--version") || argv.includes("-v")) {
|
|
53
|
+
io.stdout(GENERATOR_VERSION);
|
|
54
|
+
return EXIT_CODES.SUCCESS;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let parsed: ReturnType<typeof parseArgs<{ options: typeof PARSE_OPTIONS; allowPositionals: true }>>;
|
|
58
|
+
try {
|
|
59
|
+
parsed = parseArgs({ args: [...argv], options: PARSE_OPTIONS, allowPositionals: true });
|
|
60
|
+
} catch (err) {
|
|
61
|
+
io.stderr(err instanceof Error ? err.message : String(err));
|
|
62
|
+
return EXIT_CODES.USAGE;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
await runGenerate(parsed.values, parsed.positionals, io);
|
|
67
|
+
return EXIT_CODES.SUCCESS;
|
|
68
|
+
} catch (err) {
|
|
69
|
+
if (err instanceof CliError) {
|
|
70
|
+
io.stderr(err.message);
|
|
71
|
+
return err.exitCode;
|
|
72
|
+
}
|
|
73
|
+
io.stderr(err instanceof Error ? (err.stack ?? err.message) : String(err));
|
|
74
|
+
return EXIT_CODES.INTERNAL;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
export const EXIT_CODES = {
|
|
4
|
+
SUCCESS: 0,
|
|
5
|
+
INTERNAL: 1,
|
|
6
|
+
USAGE: 2,
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
export type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];
|
|
10
|
+
|
|
11
|
+
/** A typed error carrying the exit code the process should terminate with. */
|
|
12
|
+
export class CliError extends Error {
|
|
13
|
+
readonly exitCode: ExitCode;
|
|
14
|
+
|
|
15
|
+
constructor(exitCode: ExitCode, message: string) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "CliError";
|
|
18
|
+
this.exitCode = exitCode;
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/generate.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// Wires flag parsing -> validation -> file generation -> (optional) install.
|
|
4
|
+
|
|
5
|
+
import { resolveOptions, warningsFor, type RawFlags } from "./options.js";
|
|
6
|
+
import { buildFileMap, runNpmInstall, writeProject } from "./write-project.js";
|
|
7
|
+
import type { CliIO } from "./cli.js";
|
|
8
|
+
|
|
9
|
+
export async function runGenerate(values: RawFlags, positionals: readonly string[], io: CliIO): Promise<void> {
|
|
10
|
+
const opts = resolveOptions(values, positionals);
|
|
11
|
+
|
|
12
|
+
for (const warning of warningsFor(opts)) {
|
|
13
|
+
io.stderr(`warning: ${warning}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const files = buildFileMap(opts);
|
|
17
|
+
|
|
18
|
+
if (opts.dryRun) {
|
|
19
|
+
io.stdout(`Would write ${String(files.length)} file(s) to ${opts.targetDir}:`);
|
|
20
|
+
for (const file of files) io.stdout(` ${file.relPath}`);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
await writeProject(opts.targetDir, files);
|
|
25
|
+
io.stdout(`Wrote ${String(files.length)} file(s) to ${opts.targetDir}`);
|
|
26
|
+
|
|
27
|
+
if (opts.skipInstall) {
|
|
28
|
+
io.stdout("Skipped install (--no-install). Run `npm install` inside the project next.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
io.stdout(`Installing dependencies in ${opts.name}/ ...`);
|
|
33
|
+
runNpmInstall(opts.targetDir);
|
|
34
|
+
io.stdout("Done.");
|
|
35
|
+
}
|
package/src/help.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
export const HELP_TEXT = `create-syrinx-agent — scaffold a Syrinx voice agent project.
|
|
4
|
+
|
|
5
|
+
One generator with conditional emission, not enumerated template directories:
|
|
6
|
+
pick a provider per pipeline stage with flags and get back a project that
|
|
7
|
+
depends on exactly those providers and typechecks out of the box.
|
|
8
|
+
|
|
9
|
+
USAGE
|
|
10
|
+
npm create syrinx-agent <target-dir> [options]
|
|
11
|
+
create-syrinx-agent <target-dir> [options]
|
|
12
|
+
|
|
13
|
+
PIPELINE (cascade mode — pick one provider per stage)
|
|
14
|
+
--stt <deepgram|google|elevenlabs|grok>
|
|
15
|
+
--tts <cartesia|elevenlabs|gemini|openai-tts|grok>
|
|
16
|
+
--reasoner <aisdk|kuralle|mastra>
|
|
17
|
+
--vad <silero-vad> optional, provider STT/endpointing owns it by default
|
|
18
|
+
--endpointing <pipecat-smart-turn|vap> optional, provider STT owns it by default
|
|
19
|
+
|
|
20
|
+
PIPELINE (speech-to-speech — exclusive with --stt/--tts)
|
|
21
|
+
--realtime <realtime|grok>
|
|
22
|
+
A speech-to-speech pipeline has no separate STT/reasoner/TTS stages.
|
|
23
|
+
Passing --stt or --tts alongside --realtime is refused.
|
|
24
|
+
|
|
25
|
+
TRANSPORT
|
|
26
|
+
--transport <browser|twilio|telnyx|smartpbx> default: browser
|
|
27
|
+
--runtime <node|cloudflare> default: node
|
|
28
|
+
--runtime cloudflare --transport telnyx is generated but warned as
|
|
29
|
+
deploy-unverified on the Workers edge.
|
|
30
|
+
|
|
31
|
+
PRESETS (flag bundles — an explicit flag always overrides the preset)
|
|
32
|
+
--preset <phone>
|
|
33
|
+
|
|
34
|
+
OPTIONS
|
|
35
|
+
--name <project-name> default: the target directory's basename
|
|
36
|
+
--yes accept defaults for anything not passed, never prompt
|
|
37
|
+
--no-install, --skip-install
|
|
38
|
+
write the project but skip \`npm install\`
|
|
39
|
+
--dry-run print the file list and exit; write nothing
|
|
40
|
+
--help, -h show this help
|
|
41
|
+
--version, -v print the generator's version
|
|
42
|
+
|
|
43
|
+
Never prompts when --yes is passed or stdin is not a TTY: missing required
|
|
44
|
+
flags fail with a USAGE error naming what is missing.
|
|
45
|
+
`;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// Bin entry point. The shebang is injected by the esbuild banner at build
|
|
4
|
+
// time (see scripts/build.mjs) so the raw TypeScript source stays a plain
|
|
5
|
+
// module (mirrors packages/cli/src/index.ts).
|
|
6
|
+
|
|
7
|
+
import { main } from "./cli.js";
|
|
8
|
+
|
|
9
|
+
main(process.argv.slice(2))
|
|
10
|
+
.then((code) => {
|
|
11
|
+
process.exitCode = code;
|
|
12
|
+
})
|
|
13
|
+
.catch((err: unknown) => {
|
|
14
|
+
console.error(err instanceof Error ? (err.stack ?? err.message) : String(err));
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
import { resolveOptions, warningsFor, type RawFlags } from "./options.js";
|
|
7
|
+
import { CliError, EXIT_CODES } from "./exit-codes.js";
|
|
8
|
+
|
|
9
|
+
const SLICE: RawFlags = { stt: "deepgram", reasoner: "aisdk", tts: "cartesia", transport: "browser" };
|
|
10
|
+
|
|
11
|
+
describe("resolveOptions", () => {
|
|
12
|
+
it("resolves the cascade slice with defaults (transport=browser, runtime=node)", () => {
|
|
13
|
+
const opts = resolveOptions(SLICE, ["my-agent"]);
|
|
14
|
+
expect(opts).toMatchObject({
|
|
15
|
+
mode: "cascade",
|
|
16
|
+
stt: "deepgram",
|
|
17
|
+
tts: "cartesia",
|
|
18
|
+
reasoner: "aisdk",
|
|
19
|
+
transport: "browser",
|
|
20
|
+
runtime: "node",
|
|
21
|
+
name: "my-agent",
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("derives the project name from the target directory positional", () => {
|
|
26
|
+
const opts = resolveOptions(SLICE, ["path/to/my-agent"]);
|
|
27
|
+
expect(opts.name).toBe("my-agent");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("--name overrides the positional", () => {
|
|
31
|
+
const opts = resolveOptions({ ...SLICE, name: "explicit-name" }, ["ignored-dir"]);
|
|
32
|
+
expect(opts.name).toBe("explicit-name");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("refuses --realtime combined with --stt/--tts, naming both flags", () => {
|
|
36
|
+
expect(() => resolveOptions({ realtime: "realtime", stt: "deepgram", tts: "cartesia" }, ["x"])).toThrow(
|
|
37
|
+
/--stt and --tts/,
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("refuses --realtime combined with --stt alone, naming only --stt", () => {
|
|
42
|
+
try {
|
|
43
|
+
resolveOptions({ realtime: "realtime", stt: "deepgram" }, ["x"]);
|
|
44
|
+
expect.unreachable();
|
|
45
|
+
} catch (err) {
|
|
46
|
+
expect(err).toBeInstanceOf(CliError);
|
|
47
|
+
expect((err as CliError).exitCode).toBe(EXIT_CODES.USAGE);
|
|
48
|
+
expect((err as CliError).message).toMatch(/--stt/);
|
|
49
|
+
expect((err as CliError).message).not.toMatch(/--tts/);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("resolves a realtime (speech-to-speech) selection", () => {
|
|
54
|
+
const opts = resolveOptions({ realtime: "grok" }, ["x"]);
|
|
55
|
+
expect(opts).toMatchObject({ mode: "realtime", realtime: "grok" });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("lists every missing required cascade flag", () => {
|
|
59
|
+
expect(() => resolveOptions({}, ["x"])).toThrow(/--stt, --tts, --reasoner/);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("requires a target directory or --name", () => {
|
|
63
|
+
expect(() => resolveOptions(SLICE, [])).toThrow(/target directory or --name/);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("rejects an unknown --stt value, listing the valid ones", () => {
|
|
67
|
+
expect(() => resolveOptions({ ...SLICE, stt: "not-a-provider" }, ["x"])).toThrow(
|
|
68
|
+
/--stt must be one of: deepgram, google, elevenlabs, grok/,
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("applies a preset, letting an explicit flag override one preset field", () => {
|
|
73
|
+
const opts = resolveOptions({ preset: "phone", tts: "elevenlabs" }, ["x"]);
|
|
74
|
+
expect(opts).toMatchObject({ mode: "cascade", stt: "deepgram", tts: "elevenlabs", transport: "twilio" });
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("rejects an unknown --preset", () => {
|
|
78
|
+
expect(() => resolveOptions({ preset: "not-a-preset" }, ["x"])).toThrow(/--preset must be one of/);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("--no-install / --skip-install / --dry-run map to the resolved flags", () => {
|
|
82
|
+
const opts = resolveOptions({ ...SLICE, "no-install": true, "dry-run": true }, ["x"]);
|
|
83
|
+
expect(opts.skipInstall).toBe(true);
|
|
84
|
+
expect(opts.dryRun).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("warningsFor", () => {
|
|
89
|
+
it("warns on runtime=cloudflare + transport=telnyx, naming both", () => {
|
|
90
|
+
const opts = resolveOptions({ ...SLICE, transport: "telnyx", runtime: "cloudflare" }, ["x"]);
|
|
91
|
+
const warnings = warningsFor(opts);
|
|
92
|
+
expect(warnings).toHaveLength(1);
|
|
93
|
+
expect(warnings[0]).toMatch(/cloudflare/);
|
|
94
|
+
expect(warnings[0]).toMatch(/telnyx/);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("emits no warning for the node+browser slice", () => {
|
|
98
|
+
const opts = resolveOptions(SLICE, ["x"]);
|
|
99
|
+
expect(warningsFor(opts)).toEqual([]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("emits no warning for runtime=cloudflare + transport=browser", () => {
|
|
103
|
+
const opts = resolveOptions({ ...SLICE, runtime: "cloudflare" }, ["x"]);
|
|
104
|
+
expect(warningsFor(opts)).toEqual([]);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe("target directory resolution", () => {
|
|
109
|
+
const base = { stt: "deepgram", tts: "cartesia", reasoner: "aisdk" } as const;
|
|
110
|
+
|
|
111
|
+
it("writes to the path given, not to ./<name>", () => {
|
|
112
|
+
// Regression: the generator used to pass `name` as the destination, so an
|
|
113
|
+
// absolute target silently scattered a project into the caller's cwd.
|
|
114
|
+
const opts = resolveOptions({ ...base }, ["/tmp/somewhere/my-agent"]);
|
|
115
|
+
expect(opts.targetDir).toBe("/tmp/somewhere/my-agent");
|
|
116
|
+
expect(opts.name).toBe("my-agent");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("resolves a relative target against cwd", () => {
|
|
120
|
+
const opts = resolveOptions({ ...base }, ["nested/dir/agent"]);
|
|
121
|
+
expect(opts.targetDir).toBe(resolve(process.cwd(), "nested/dir/agent"));
|
|
122
|
+
expect(opts.name).toBe("agent");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("falls back to --name when no positional is given", () => {
|
|
126
|
+
const opts = resolveOptions({ ...base, name: "solo" }, []);
|
|
127
|
+
expect(opts.targetDir).toBe(resolve(process.cwd(), "solo"));
|
|
128
|
+
expect(opts.name).toBe("solo");
|
|
129
|
+
});
|
|
130
|
+
});
|