create-syrinx-agent 4.4.1 → 4.5.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/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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/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 = \"4.4.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 { 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 ];\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) {\n // Silently skipping here emits an agent module missing an import, which fails\n // only in the GENERATED project \u2014 far from the cause. It happened: a two-line\n // entry never matched this single-line-anchored regex and vanished.\n throw new Error(`agent-module: import line not in the expected shape: ${line}`);\n }\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 { config as loadEnv } from \"dotenv\";`,\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\n// This project ships a .env.example. Without this call nothing ever reads the\n// .env you make from it, and every provider fails on a missing api_key.\nloadEnv();\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 { GENERATOR_VERSION } from \"../version.js\";\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\n// The generator's own version. Hardcoding a literal here means every future\n// release scaffolds projects pinned to an ever-staler floor.\nconst CORE_VERSION = `^${GENERATOR_VERSION}`;\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 // The generated agent loads .env itself. Without it the project ships a\n // .env.example that nothing reads, and every provider fails on a missing key.\n dotenv: \"^16.6.1\",\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 // `syrinx` is a plain-node bin; a .ts --agent target that imports a Syrinx\n // package resolves to raw TS under node_modules, which node will not strip.\n // tsx handles both, so the shipped check runs as written.\n // The default check: a typed turn needs no audio and no recording, so it\n // passes out of the box once keys are set. It proves the agent constructs and\n // the reasoner replies \u2014 the two things most likely to be broken first.\n \"check:text\": `tsx node_modules/@kuralle-syrinx/cli/dist/index.js text \"hello\" --agent ${agentSpec} --json`,\n // Replays a recorded turn and FAILS ON TRANSCRIPT DRIFT. Needs a fixture you\n // record in the Studio (\"Save as fixture\") \u2014 the generator ships none, because\n // a synthesized-silence fixture can never produce a transcript and would make\n // this check permanently red.\n \"check:turn\": `tsx node_modules/@kuralle-syrinx/cli/dist/index.js turn --in test/fixtures/your-recording.json --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// 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"],
|
|
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 = \"4.5.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 { 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 ];\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) {\n // Silently skipping here emits an agent module missing an import, which fails\n // only in the GENERATED project \u2014 far from the cause. It happened: a two-line\n // entry never matched this single-line-anchored regex and vanished.\n throw new Error(`agent-module: import line not in the expected shape: ${line}`);\n }\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 { config as loadEnv } from \"dotenv\";`,\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\n// This project ships a .env.example. Without this call nothing ever reads the\n// .env you make from it, and every provider fails on a missing api_key.\nloadEnv();\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 { GENERATOR_VERSION } from \"../version.js\";\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\n// The generator's own version. Hardcoding a literal here means every future\n// release scaffolds projects pinned to an ever-staler floor.\nconst CORE_VERSION = `^${GENERATOR_VERSION}`;\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 // The generated agent loads .env itself. Without it the project ships a\n // .env.example that nothing reads, and every provider fails on a missing key.\n dotenv: \"^16.6.1\",\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 // `syrinx` is a plain-node bin; a .ts --agent target that imports a Syrinx\n // package resolves to raw TS under node_modules, which node will not strip.\n // tsx handles both, so the shipped check runs as written.\n // The default check: a typed turn needs no audio and no recording, so it\n // passes out of the box once keys are set. It proves the agent constructs and\n // the reasoner replies \u2014 the two things most likely to be broken first.\n \"check:text\": `tsx node_modules/@kuralle-syrinx/cli/dist/index.js text \"hello\" --agent ${agentSpec} --json`,\n // Replays a recorded turn and FAILS ON TRANSCRIPT DRIFT. Needs a fixture you\n // record in the Studio (\"Save as fixture\") \u2014 the generator ships none, because\n // a synthesized-silence fixture can never produce a transcript and would make\n // this check permanently red.\n \"check:turn\": `tsx node_modules/@kuralle-syrinx/cli/dist/index.js turn --in test/fixtures/your-recording.json --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// 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
5
|
"mappings": "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",
|
|
6
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
7
|
}
|
package/package.json
CHANGED
package/src/version.ts
CHANGED