Skip to content

Commit 62b77b5

Browse files
committed
chore: tighten command surface cleanup
1 parent 6c4f2dc commit 62b77b5

6 files changed

Lines changed: 24 additions & 17 deletions

File tree

src/cli/batch-steps.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import type { BatchStep } from '../client-types.ts';
22
import { readInputFromCli } from '../commands/cli-grammar.ts';
3+
import { isCommandName, type CommandName } from '../commands/command-surface.ts';
34
import type { CliFlags } from '../utils/command-schema.ts';
45
import { AppError } from '../utils/errors.ts';
56

67
type LegacyCliBatchStep = {
7-
command: string;
8+
command: CommandName;
89
positionals?: string[];
910
flags?: Record<string, unknown>;
1011
runtime?: unknown;
@@ -69,8 +70,7 @@ function readLegacyCliBatchStep(step: unknown, stepNumber: number): LegacyCliBat
6970
}
7071
const record = step as Record<string, unknown>;
7172
assertLegacyBatchStepKeys(record, stepNumber);
72-
const command = typeof record.command === 'string' ? record.command.trim().toLowerCase() : '';
73-
if (!command) throw new AppError('INVALID_ARGS', `Batch step ${stepNumber} requires command.`);
73+
const command = readLegacyCommand(record.command, stepNumber);
7474
const positionals = readLegacyPositionals(record.positionals, stepNumber);
7575
const flags = readLegacyFlags(record.flags, stepNumber);
7676
return {
@@ -81,6 +81,16 @@ function readLegacyCliBatchStep(step: unknown, stepNumber: number): LegacyCliBat
8181
};
8282
}
8383

84+
function readLegacyCommand(value: unknown, stepNumber: number): CommandName {
85+
const command = typeof value === 'string' ? value.trim().toLowerCase() : '';
86+
if (!command) throw new AppError('INVALID_ARGS', `Batch step ${stepNumber} requires command.`);
87+
if (isCommandName(command)) return command;
88+
throw new AppError(
89+
'INVALID_ARGS',
90+
`Batch step ${stepNumber} command is not available through command batch: ${String(value)}`,
91+
);
92+
}
93+
8494
function assertLegacyBatchStepKeys(record: Record<string, unknown>, stepNumber: number): void {
8595
const unknownKeys = Object.keys(record).filter(
8696
(key) => !['command', 'positionals', 'flags', 'runtime'].includes(key),

src/cli/commands/generic.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { AgentDeviceClient, CommandRequestResult } from '../../client.ts';
22
import { announceReplayTestRun, renderReplayTestResponse } from '../../cli-test.ts';
33
import { listCliOutputCommandNames } from '../../commands/cli-output.ts';
44
import { runCliCommand, runCliCommandWithOutput } from '../../commands/cli-runner.ts';
5-
import { listCommandNames, type CliCommand } from '../../commands/command-surface.ts';
5+
import { listCommandNames, type CommandName } from '../../commands/command-surface.ts';
66
import type { CliOutput } from '../../commands/command-contract.ts';
77
import type { ReplaySuiteResult } from '../../daemon/types.ts';
88
import type { CliFlags } from '../../utils/command-schema.ts';
@@ -19,7 +19,7 @@ type GenericClientCommandRunner = (params: {
1919

2020
const formattedCommandHandlers = Object.fromEntries(
2121
listCliOutputCommandNames().map((command) => [command, createFormattedHandler(command)]),
22-
) as Partial<Record<CliCommand, ClientCommandHandler>>;
22+
) as Partial<Record<CommandName, ClientCommandHandler>>;
2323

2424
export const dedicatedCommandHandlers = formattedCommandHandlers;
2525

@@ -80,7 +80,7 @@ function writeGenericCliOutput(
8080
return 0;
8181
}
8282

83-
function createFormattedHandler(command: CliCommand): ClientCommandHandler {
83+
function createFormattedHandler(command: CommandName): ClientCommandHandler {
8484
return async ({ positionals, flags, client }) => {
8585
const { cliOutput } = await runCliCommandWithOutput({
8686
client,
@@ -107,6 +107,6 @@ function writeCliOutput(flags: CliFlags, output: CliOutput): void {
107107
);
108108
}
109109

110-
function isGenericCliCommand(command: CliCommand): boolean {
110+
function isGenericCliCommand(command: CommandName): boolean {
111111
return !(command in formattedCommandHandlers) && command !== 'screenshot' && command !== 'diff';
112112
}

src/commands/cli-grammar/registry.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { CliFlags } from '../../utils/command-schema.ts';
2-
import { AppError } from '../../utils/errors.ts';
32
import { appCliReaders } from './apps.ts';
43
import { captureCliReaders } from './capture.ts';
54
import { commonInputFromFlags } from './common.ts';
@@ -11,6 +10,7 @@ import { replayCliReaders } from './replay.ts';
1110
import { selectorCliReaders } from './selectors.ts';
1211
import { systemCliReaders } from './system.ts';
1312
import type { CliReader } from './types.ts';
13+
import type { CommandName } from '../command-surface.ts';
1414

1515
const cliReaders = {
1616
...appCliReaders,
@@ -29,14 +29,12 @@ const cliReaders = {
2929
maxSteps: flags.batchMaxSteps,
3030
out: flags.out,
3131
}),
32-
} satisfies Record<string, CliReader>;
32+
} satisfies Record<CommandName, CliReader>;
3333

3434
export function readInputFromCli(
35-
command: string,
35+
command: CommandName,
3636
positionals: string[],
3737
flags: CliFlags,
3838
): Record<string, unknown> {
39-
const reader = (cliReaders as Record<string, CliReader>)[command];
40-
if (!reader) throw new AppError('INVALID_ARGS', `Unknown CLI command: ${command}`);
41-
return reader(positionals, flags);
39+
return cliReaders[command](positionals, flags);
4240
}

src/commands/cli-runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import type { AgentDeviceClient, CommandRequestResult } from '../client.ts';
22
import { formatCliOutput } from './cli-output.ts';
33
import { readInputFromCli } from './cli-grammar.ts';
4-
import { runCommand, type CliCommand } from './command-surface.ts';
4+
import { runCommand, type CommandName } from './command-surface.ts';
55
import type { CliOutput } from './command-contract.ts';
66
import type { CliFlags } from '../utils/command-schema.ts';
77

88
type CliRunOptions = {
99
client: AgentDeviceClient;
10-
command: CliCommand;
10+
command: CommandName;
1111
positionals: string[];
1212
flags: CliFlags;
1313
};

src/commands/command-surface.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const commandSurface = [
2222
] as const;
2323

2424
export type CommandName = (typeof commandSurface)[number]['name'];
25-
export type CliCommand = CommandName;
2625
export type { BatchCommandName };
2726

2827
const commandMap: ReadonlyMap<CommandName, AnyExecutableCommand> = new Map(

src/utils/cli-command-overrides.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ const CLI_COMMAND_OVERRIDES = {
324324
usageOverride: 'session list',
325325
positionalArgs: ['list?'],
326326
},
327-
} as const satisfies Record<string, CommandSchemaOverride>;
327+
} as const satisfies Partial<Record<CommandName, CommandSchemaOverride>>;
328328

329329
export function getSchemaOnlyCliCommandSchema(command: string): CommandSchema | undefined {
330330
return Object.hasOwn(SCHEMA_ONLY_CLI_COMMAND_SCHEMAS, command)

0 commit comments

Comments
 (0)