* feat(cli): dump native Cordis config schemas * test(cli): include schema dump in launcher help snapshot * feat(cli): export JSON Schema for Cordis configuration * fix(cli): preserve config schema discovery and annotations * fix(cli): conservatively project effectful config validation * refactor(boot): encapsulate profile config schema generation * fix(cli): follow Loader disabling and native writeback in config schema - Dormant group/include rows (disabled without group: true) may omit config and are recorded as childless trees; the entry schema skips their child declarations, matching the Loader, which never creates them. - Lazy builders run once per document, and a wrapped null-only projection keeps a deduplicated type list so the document stays compilable. - Union widening applies only when an earlier branch can write adapted values back through a container; +Infinity max and -Infinity min without a step are treated as the native no-ops they are. - Projection limitations repeat at every entry sharing a Config, and the entry schema documents the boolean/expression domain of disabled. - Record the schema-dump validation policy as an Agent Note.
81 lines
2.6 KiB
JavaScript
81 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Command-line entry for dsh.
|
|
* @module @deepseek-ai/dsh/bin
|
|
*/
|
|
|
|
/* v8 ignore file -- built-bin acceptance exercises this self-executing dispatch. */
|
|
|
|
import { readFileSync } from 'node:fs'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { loadLayeredEnv, StartupError } from '@deepseek-ai/dsh-app-boot'
|
|
import { resolveDshHome } from '@deepseek-ai/dsh-home-paths'
|
|
import { parseDshArgs } from './args.ts'
|
|
import { reportStartupFailure } from './startup-diagnostics.ts'
|
|
|
|
// Both the source tree (apps/cli/src) and the bundled bin (apps/cli/lib) sit
|
|
// one directory under apps/cli, so the checked-in manifest resolves with the
|
|
// same relative hop from either artifact.
|
|
function readVersion(): string {
|
|
const manifest = JSON.parse(
|
|
readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'),
|
|
) as { version?: unknown }
|
|
return typeof manifest.version === 'string' ? manifest.version : '0.0.0'
|
|
}
|
|
|
|
/**
|
|
* Run the public dsh command-line interface.
|
|
* @returns a promise that settles when the selected command mode finishes.
|
|
*/
|
|
export async function runCli(): Promise<void> {
|
|
const version = readVersion()
|
|
const invocation = parseDshArgs(process.argv.slice(2), version)
|
|
|
|
switch (invocation.mode) {
|
|
case 'profile': {
|
|
const { runProfile } = await import('./profile-boot.ts')
|
|
try {
|
|
await runProfile({
|
|
environment: loadLayeredEnv('dsh'),
|
|
profile: invocation.profile,
|
|
fromDefaultProfile: invocation.fromDefaultProfile,
|
|
patchFiles: invocation.patches,
|
|
args: invocation.args,
|
|
})
|
|
} catch (error) {
|
|
if (!(error instanceof StartupError)) throw error
|
|
await reportStartupFailure(error, { home: resolveDshHome(), version, profile: invocation.profile })
|
|
process.exit(1)
|
|
}
|
|
break
|
|
}
|
|
case 'plugin': {
|
|
const { runPlugin } = await import('./plugin.ts')
|
|
process.exit(await runPlugin(invocation.profile, invocation.args))
|
|
break
|
|
}
|
|
case 'dump-config': {
|
|
const { runDumpConfig } = await import('./dump-config.ts')
|
|
runDumpConfig(
|
|
invocation.profile,
|
|
invocation.defaultOnly,
|
|
invocation.patches,
|
|
invocation.fromDefaultProfile,
|
|
)
|
|
break
|
|
}
|
|
case 'dump-config-schema': {
|
|
const { runDumpConfigSchema } = await import('./dump-config-schema.ts')
|
|
await runDumpConfigSchema(invocation.profile, invocation.patches, invocation.fromDefaultProfile)
|
|
break
|
|
}
|
|
default:
|
|
invocation satisfies never
|
|
throw new Error(`dsh: unhandled invocation mode ${JSON.stringify(invocation)}`)
|
|
}
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
await runCli()
|
|
}
|