#!/usr/bin/env node /** * Boots an external `cordis.yml`; its `@deepseek-ai/dsh-jsonrpc` entry serves * newline-delimited JSON-RPC on stdio. `$DSH_CORDIS_CONFIG` wins over `argv[2]`; * empty or missing paths exit 1, with no default config or `DSH_SNAPSHOT` mode. * App-boot owns env loading, Loader guards, and settled-tree startup. * stdin EOF and SIGTERM dispose the root context and exit 0; SIGINT exits 130. * Protocol `shutdown` belongs to the server plugin. Stdout is reserved for frames. * * @module @deepseek-ai/dsh-jsonrpc-demo/bin */ import { existsSync } from 'node:fs' import { boot, installFailLoud, loadEnv, resolveConfigPath } from '@deepseek-ai/dsh-app-boot' const NAME = 'dsh-jsonrpc-agent' /* v8 ignore start -- composition over tested app-boot/jsonrpc and executable acceptance paths */ installFailLoud(NAME) loadEnv(NAME) // Env wins over argv; empty values are absent. External config defines the deployment. const fromEnv = process.env['DSH_CORDIS_CONFIG'] const fromArgv = process.argv[2] const requested = fromEnv !== undefined && fromEnv !== '' ? fromEnv : fromArgv !== undefined && fromArgv !== '' ? fromArgv : undefined const configPath = requested === undefined ? undefined : resolveConfigPath(requested, undefined) if (configPath === undefined || !existsSync(configPath)) { process.stderr.write( `usage: ${NAME} (or set DSH_CORDIS_CONFIG=, which wins); the config is required — there is no built-in fallback\n`, ) process.exit(1) } const ctx = await boot(NAME, configPath) let exiting = false async function disposeAndExit(code: number): Promise { if (exiting) return exiting = true try { await ctx.fiber.dispose() } finally { process.exit(code) } } process.stdin.on('end', () => { void disposeAndExit(0) }) process.on('SIGTERM', () => { void disposeAndExit(0) }) process.on('SIGINT', () => { void disposeAndExit(130) }) /* v8 ignore stop */