mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
# Conflicts: # docs/config-catalog.md # docs/development.i18n.yaml # docs/development.zh.md # docs/rfc/implemented/feature/2026-06-14-acp-agent-client-protocol.md # docs/rfc/implemented/feature/2026-07-06-sandbox.md # examples/AGENTS.md # examples/README.md # examples/acp-agent/README.md # examples/acp-agent/cordis.yml # examples/acp-agent/tests/acp.e2e.ts # examples/acp-agent/tests/escalation.e2e.ts # examples/sandbox-acp-agent/README.md # examples/sandbox-acp-agent/cordis.snapshot.yml # examples/sandbox-acp-agent/cordis.yml # examples/sandbox-acp-agent/tests/acp.snapshot.ts # packages/ui/acp-agent/src/bin.ts # packages/ui/acp/README.md # packages/ui/jsonrpc-agent/README.md # packages/ui/jsonrpc-agent/src/bin.ts # scripts/verify-translation-pairing.ts
53 lines
1.9 KiB
JavaScript
53 lines
1.9 KiB
JavaScript
#!/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-agent/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} <path/to/cordis.yml> (or set DSH_CORDIS_CONFIG=<path>, 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<void> {
|
|
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 */
|