refactor(cli): extract Query CLI Adapter Module seam (#3074)
* refactor(cli): extract query adapter seam from cli entrypoint * test: update ws forwarding guard for query-cli-adapter seam * fix(query): close remaining CodeRabbit findings on cli adapter * test: address remaining CodeRabbit nitpicks on ws forwarding coverage
This commit is contained in:
@@ -18,6 +18,7 @@ import { InitRunner } from './init-runner.js';
|
||||
import { validateWorkstreamName } from './workstream-utils.js';
|
||||
import { loadConfig } from './config.js';
|
||||
import { assertRuntimeSupportsAutoMode } from './runtime-gate.js';
|
||||
import { runQueryCliCommand } from './query/query-cli-adapter.js';
|
||||
|
||||
// ─── Parsed CLI args ─────────────────────────────────────────────────────────
|
||||
|
||||
@@ -276,13 +277,6 @@ async function readStdin(): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
/** When false, unknown `gsd-sdk query` commands error instead of shelling out to gsd-tools.cjs. */
|
||||
function queryFallbackToCjsEnabled(): boolean {
|
||||
const v = process.env.GSD_QUERY_FALLBACK?.toLowerCase();
|
||||
if (v === 'off' || v === 'never' || v === 'false' || v === '0') return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ─── Main ────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -316,72 +310,35 @@ export async function main(argv: string[] = process.argv.slice(2)): Promise<void
|
||||
return;
|
||||
}
|
||||
|
||||
// ─── Query command ──────────────────────────────────────────────────────
|
||||
if (args.command === 'query') {
|
||||
const result = await runQueryCliCommand({
|
||||
projectDir: args.projectDir,
|
||||
ws: args.ws,
|
||||
queryArgv: args.queryArgv,
|
||||
});
|
||||
for (const line of result.stderrLines) console.error(line);
|
||||
for (const chunk of result.stdoutChunks) process.stdout.write(chunk);
|
||||
process.exitCode = result.exitCode;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fall back to GSD_WORKSTREAM env var when --ws is not supplied (#2791).
|
||||
// gsd-tools.cjs resolves the active workstream via this env var; parity
|
||||
// means gsd-sdk query commands see the same .planning/ path as gsd-tools.
|
||||
// means gsd-sdk command paths see the same .planning/ path as gsd-tools.
|
||||
if (args.ws === undefined && process.env.GSD_WORKSTREAM) {
|
||||
const envWs = process.env.GSD_WORKSTREAM;
|
||||
if (validateWorkstreamName(envWs)) {
|
||||
args = { ...args, ws: envWs };
|
||||
}
|
||||
// If the env var contains an invalid name, silently ignore it (same as CJS).
|
||||
}
|
||||
|
||||
// Multi-repo project-root resolution (issue #2623).
|
||||
//
|
||||
// When the user launches `gsd-sdk` from inside a `sub_repos`-listed child repo,
|
||||
// `projectDir` defaults to `process.cwd()` which points at the child, not the
|
||||
// parent workspace that owns `.planning/`. Mirror the legacy `gsd-tools.cjs`
|
||||
// walk-up semantics so handlers see the correct project root.
|
||||
//
|
||||
// Idempotent: if `projectDir` already has its own `.planning/` (including an
|
||||
// explicit `--project-dir` pointing at the workspace root), findProjectRoot
|
||||
// returns it unchanged.
|
||||
{
|
||||
const { findProjectRoot } = await import('./query/helpers.js');
|
||||
args = { ...args, projectDir: findProjectRoot(args.projectDir) };
|
||||
}
|
||||
|
||||
// ─── Query command ──────────────────────────────────────────────────────
|
||||
if (args.command === 'query') {
|
||||
const { createRegistry } = await import('./query/index.js');
|
||||
const { runQueryDispatch } = await import('./query/query-dispatch.js');
|
||||
const { resolveGsdToolsPath, GSDToolsError } = await import('./gsd-tools.js');
|
||||
const { GSDError, exitCodeFor } = await import('./errors.js');
|
||||
|
||||
try {
|
||||
const registry = createRegistry();
|
||||
const out = await runQueryDispatch({
|
||||
registry,
|
||||
projectDir: args.projectDir,
|
||||
ws: args.ws,
|
||||
cjsFallbackEnabled: queryFallbackToCjsEnabled(),
|
||||
resolveGsdToolsPath,
|
||||
dispatchNative: (cmd, argv) => registry.dispatch(cmd, argv, args.projectDir, args.ws),
|
||||
}, args.queryArgv ?? []);
|
||||
|
||||
for (const line of out.stderr) console.error(line);
|
||||
if (!out.ok) {
|
||||
console.error(out.error.message);
|
||||
process.exitCode = out.exit_code;
|
||||
return;
|
||||
}
|
||||
if (out.stdout) process.stdout.write(out.stdout);
|
||||
} catch (err) {
|
||||
if (err instanceof GSDError) {
|
||||
console.error(`Error: ${err.message}`);
|
||||
process.exitCode = exitCodeFor(err.classification);
|
||||
} else if (err instanceof GSDToolsError) {
|
||||
console.error(`Error: ${err.message}`);
|
||||
process.exitCode = err.exitCode ?? 1;
|
||||
} else {
|
||||
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.command !== 'run' && args.command !== 'init' && args.command !== 'auto') {
|
||||
console.error('Error: Expected "gsd-sdk run <prompt>", "gsd-sdk auto", "gsd-sdk init [input]", or "gsd-sdk query <command>"');
|
||||
console.error(USAGE);
|
||||
|
||||
Reference in New Issue
Block a user