The runtime profile default is correct for installed applications, but the supported TypeScript CLI also runs tsx workspace aliases. In that launch, profile resolution loaded both packages/core/tools/src/index.ts and packages/core/tools/lib/index.js. The ToolRuntime instance and agent-loop consumer therefore held different private TOOL_RUNTIME_SCHEDULER symbols; the first tool call failed while reading scheduler.prepare. The source bin now explicitly selects linked profile resolution using its own .ts module identity. Built and packaged launches keep runtime resolution, and explicit runProfile overrides remain unchanged. No service or symbol identity is widened to conceal duplicate module instances. Forward the existing sourceImport option through runLoaderSmoke and select tsx/esm for headless source snapshots. This exercises the actual supported source-launch vector while retaining the same recorded Session and expected outputs. The loader-smoke subprocess test covers forwarding that hook. Evidence: the official tsx/esm compaction replay failed before the fix while loading both Tools module URLs. After the fix it loads only src/index.ts and prints COMPACTION RECOVERED. The same focused replay passes under both DSH_EXAMPLE_MODE=src and lib after rebuilding Host artifacts. The 43 CLI and loader tests passed, including runtime defaults and explicit link/dual/runtime overrides. Loader-smoke coverage passed 25 tests with 100% statements, branches, functions, and lines. Host build, full lint, and all 41 doc-sync gates passed. Recorded JSONL generations and snapshot normalization are unchanged; temporary diagnostics were removed from built artifacts.
78 lines
2.6 KiB
JavaScript
78 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,
|
|
// Keep tsx workspace imports and profile plugins in the same source module graph.
|
|
...(import.meta.url.endsWith('.ts') ? { resolutionMode: 'link' as const } : {}),
|
|
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
|
|
}
|
|
default:
|
|
invocation satisfies never
|
|
throw new Error(`dsh: unhandled invocation mode ${JSON.stringify(invocation)}`)
|
|
}
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
await runCli()
|
|
}
|