Skip to content

Commit f9bf36c

Browse files
committed
refactor(flags): keyed type-inferred flag schema; option→flag rename
Replace the positional `OptionDef[]` array (key/type regex-parsed from "--x <v>" strings) with a keyed `FlagsDef` record whose `type` drives both runtime parsing and compile-time flag-type inference (`Flags<typeof DEF>`). GLOBAL_FLAGS becomes the single source; the hand-kept GlobalFlags interface (types/flags.ts) is deleted. - core: SwitchFlag|ValueFlag union, ParsedFlags/Flags inference, defineCommand infers F from spec.flags - runtime: parseFlags dispatches on def.type (switch/string/number/boolean/ array/choices) with declarative required-flag enforcement - commands: migrate every flag declaration to the keyed form - naming: option→flag throughout (OptionDef→FlagDef, OptionsDef→FlagsDef, GLOBAL_OPTIONS→GLOBAL_FLAGS, command field options→flags), plus user-facing "Options:"→"Flags:" in help and the regenerated skill reference docs Behavior-preserving aside from the intentional Options→Flags wording: vp check clean across all packages, 29 parser tests pass, reference regen byte-identical before the terminology swap.
1 parent cbd3c12 commit f9bf36c

82 files changed

Lines changed: 1753 additions & 1495 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/cli/src/commands.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Command } from "bailian-cli-core";
1+
import type { AnyCommand } from "bailian-cli-core";
22
import {
33
authLogin,
44
authStatus,
@@ -52,7 +52,7 @@ import {
5252
// ships no presets, so the map is spelled out here. Kept in its own module
5353
// (no side effects) so tools like generate-reference.ts can import it without
5454
// starting the CLI.
55-
export const commands: Record<string, Command> = {
55+
export const commands: Record<string, AnyCommand> = {
5656
"auth login": authLogin,
5757
"auth status": authStatus,
5858
"auth logout": authLogout,

packages/commands/src/commands/advisor/recommend.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import {
22
analyzeIntent,
33
buildDocLink,
4-
type Config,
54
defineCommand,
65
detectOutputFormat,
76
type GetModelsOptions,
8-
type GlobalFlags,
97
getModels,
108
type IntentProfile,
119
type PipelineStep,
@@ -217,22 +215,23 @@ export default defineCommand({
217215
"Recommend the best models for your use case (intent analysis → candidate recall → LLM ranking)",
218216
auth: "apiKey",
219217
usageArgs: "--message <text> [flags]",
220-
options: [
221-
{
222-
flag: "--message <text>",
218+
flags: {
219+
message: {
220+
type: "string",
221+
valueHint: "<text>",
223222
description: "Describe your requirements",
224223
required: true,
225224
},
226-
],
225+
},
227226
exampleArgs: [
228227
'--message "I need a visual-understanding chatbot"',
229228
'--message "Build an Agent that auto-generates animations"',
230229
'--message "Legal contract review, high precision required"',
231230
'--message "Low-cost high-concurrency online customer service" --output json',
232231
'--message "Long document summarization" --dry-run',
233232
],
234-
async run(config: Config, flags: GlobalFlags) {
235-
const userInput = flags.message as string;
233+
async run(config, flags) {
234+
const userInput = flags.message;
236235

237236
const top = 3;
238237
const format = detectOutputFormat(config.output);

packages/commands/src/commands/app/call.ts

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import {
55
appCompletionEndpoint,
66
parseSSE,
77
detectOutputFormat,
8-
type Config,
9-
type GlobalFlags,
108
type AppCompletionRequest,
119
type AppStreamChunk,
1210
type AppCompletionResponse,
@@ -17,22 +15,48 @@ export default defineCommand({
1715
description: "Call a Bailian application (agent or workflow)",
1816
auth: "apiKey",
1917
usageArgs: "--app-id <id> --prompt <text> [flags]",
20-
options: [
21-
{ flag: "--app-id <id>", description: "Application ID (required)", required: true },
22-
{ flag: "--prompt <text>", description: "Input prompt text", required: true },
23-
{
24-
flag: "--image <url>",
18+
flags: {
19+
appId: {
20+
type: "string",
21+
valueHint: "<id>",
22+
description: "Application ID (required)",
23+
required: true,
24+
},
25+
prompt: {
26+
type: "string",
27+
valueHint: "<text>",
28+
description: "Input prompt text",
29+
required: true,
30+
},
31+
image: {
32+
type: "array",
33+
valueHint: "<url>",
2534
description: "Image URL(s) to pass to the app (repeatable)",
35+
},
36+
fileId: {
2637
type: "array",
38+
valueHint: "<id>",
39+
description: "Pre-uploaded file ID(s) (repeatable)",
2740
},
28-
{ flag: "--file-id <id>", description: "Pre-uploaded file ID(s) (repeatable)", type: "array" },
29-
{ flag: "--session-id <id>", description: "Session ID for multi-turn conversation" },
30-
{ flag: "--stream", description: "Stream response (default: on in TTY)" },
31-
{ flag: "--pipeline-ids <ids>", description: "Knowledge base pipeline IDs (comma-separated)" },
32-
{ flag: "--memory-id <id>", description: "Memory ID for long-term memory" },
33-
{ flag: "--biz-params <json>", description: "Business parameters JSON (workflow variables)" },
34-
{ flag: "--has-thoughts", description: "Show agent thinking process" },
35-
],
41+
sessionId: {
42+
type: "string",
43+
valueHint: "<id>",
44+
description: "Session ID for multi-turn conversation",
45+
},
46+
stream: { type: "switch", description: "Stream response (default: on in TTY)" },
47+
pipelineIds: {
48+
type: "string",
49+
valueHint: "<ids>",
50+
description: "Knowledge base pipeline IDs (comma-separated)",
51+
},
52+
memoryId: { type: "string", valueHint: "<id>", description: "Memory ID for long-term memory" },
53+
bizParams: {
54+
type: "string",
55+
valueHint: "<json>",
56+
description: "Business parameters JSON (workflow variables)",
57+
},
58+
hasThoughts: { type: "switch", description: "Show agent thinking process" },
59+
},
3660
exampleArgs: [
3761
'--app-id abc123 --prompt "Hello"',
3862
'--app-id abc123 --prompt "Describe this image" --image https://example.com/photo.jpg',
@@ -41,12 +65,11 @@ export default defineCommand({
4165
'--app-id abc123 --prompt "Search for materials" --pipeline-ids pipe1,pipe2',
4266
'--app-id abc123 --prompt "Start" --biz-params \'{"key":"value"}\'',
4367
],
44-
async run(config: Config, flags: GlobalFlags) {
45-
const appId = flags.appId as string;
46-
const prompt = flags.prompt as string;
68+
async run(config, flags) {
69+
const appId = flags.appId;
70+
const prompt = flags.prompt;
4771

48-
const shouldStream =
49-
flags.stream === true || (flags.stream === undefined && process.stdout.isTTY);
72+
const shouldStream = flags.stream || process.stdout.isTTY;
5073
const format = detectOutputFormat(config.output);
5174

5275
const body: AppCompletionRequest = {
@@ -57,17 +80,17 @@ export default defineCommand({
5780
};
5881

5982
if (flags.sessionId) {
60-
body.input.session_id = flags.sessionId as string;
83+
body.input.session_id = flags.sessionId;
6184
}
6285

6386
// Pass image URLs via image_list
64-
const imageUrls = flags.image as string[] | undefined;
87+
const imageUrls = flags.image;
6588
if (imageUrls && imageUrls.length > 0) {
6689
body.input.image_list = imageUrls;
6790
}
6891

6992
// Pass pre-uploaded file IDs
70-
const fileIds = flags.fileId as string[] | undefined;
93+
const fileIds = flags.fileId;
7194
if (fileIds && fileIds.length > 0) {
7295
body.input.file_ids = fileIds;
7396
}
@@ -77,20 +100,20 @@ export default defineCommand({
77100
}
78101

79102
if (flags.pipelineIds) {
80-
const ids = (flags.pipelineIds as string)
103+
const ids = flags.pipelineIds
81104
.split(",")
82105
.map((s) => s.trim())
83106
.filter(Boolean);
84107
body.parameters!.rag_options = { pipeline_ids: ids };
85108
}
86109

87110
if (flags.memoryId) {
88-
body.parameters!.memory_id = flags.memoryId as string;
111+
body.parameters!.memory_id = flags.memoryId;
89112
}
90113

91114
if (flags.bizParams) {
92115
try {
93-
body.input.biz_params = JSON.parse(flags.bizParams as string);
116+
body.input.biz_params = JSON.parse(flags.bizParams);
94117
} catch {
95118
process.stderr.write("Error: --biz-params must be valid JSON\n");
96119
process.exit(1);

packages/commands/src/commands/app/list.ts

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import {
33
callConsoleGateway,
44
resolveConsoleGatewayCredential,
55
detectOutputFormat,
6-
type Config,
7-
type GlobalFlags,
86
} from "bailian-cli-core";
97
import { emitResult } from "bailian-cli-runtime";
108

@@ -14,37 +12,35 @@ export default defineCommand({
1412
description: "List Bailian applications",
1513
auth: "console",
1614
usageArgs: "[flags]",
17-
options: [
18-
{
19-
flag: "--name <name>",
15+
flags: {
16+
name: {
17+
type: "string",
18+
valueHint: "<name>",
2019
description: "Filter by app name (keyword search)",
2120
},
22-
{
23-
flag: "--page <n>",
24-
description: "Page number (default: 1)",
21+
page: {
2522
type: "number",
23+
valueHint: "<n>",
24+
description: "Page number (default: 1)",
2625
},
27-
{
28-
flag: "--page-size <n>",
29-
description: "Results per page (default: 30)",
26+
pageSize: {
3027
type: "number",
28+
valueHint: "<n>",
29+
description: "Results per page (default: 30)",
3130
},
32-
{ flag: "--console-region <region>", description: "Console region" },
33-
{
34-
flag: "--console-site <site>",
31+
consoleRegion: { type: "string", valueHint: "<region>", description: "Console region" },
32+
consoleSite: {
33+
type: "string",
34+
valueHint: "<site>",
3535
description: "Console site: domestic, international",
3636
},
37-
{
38-
flag: "--console-switch-agent <uid>",
39-
description: "Switch agent UID",
40-
type: "number",
41-
},
42-
],
37+
consoleSwitchAgent: { type: "number", valueHint: "<uid>", description: "Switch agent UID" },
38+
},
4339
exampleArgs: ["", "--name customer service", "--page 2 --page-size 10", "--output json"],
44-
async run(config: Config, flags: GlobalFlags) {
45-
const name = (flags.name as string) || "";
46-
const pageNo = (flags.page as number) || 1;
47-
const pageSize = (flags.pageSize as number) || 30;
40+
async run(config, flags) {
41+
const name = flags.name || "";
42+
const pageNo = flags.page || 1;
43+
const pageSize = flags.pageSize || 30;
4844
const format = detectOutputFormat(config.output);
4945

5046
const credential = await resolveConsoleGatewayCredential(config);
Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import {
2-
defineCommand,
3-
readConfigFile,
4-
writeConfigFile,
5-
type Config,
6-
type GlobalFlags,
7-
} from "bailian-cli-core";
1+
import { defineCommand, readConfigFile, writeConfigFile } from "bailian-cli-core";
82
import { printQuickStart } from "bailian-cli-runtime";
93
import { emitBare } from "bailian-cli-runtime";
104
import {
@@ -17,21 +11,22 @@ export default defineCommand({
1711
description: "Authenticate with API key or console browser login (credentials can coexist)",
1812
auth: "none",
1913
usageArgs: "--api-key <key> | --console",
20-
options: [
21-
{ flag: "--api-key <key>", description: "DashScope API key to store" },
22-
{
23-
flag: "--base-url <url>",
14+
flags: {
15+
apiKey: { type: "string", valueHint: "<key>", description: "DashScope API key to store" },
16+
baseUrl: {
17+
type: "string",
18+
valueHint: "<url>",
2419
description: "DashScope API base URL (used with --api-key for validation)",
2520
},
26-
{
27-
flag: "--console",
21+
console: {
22+
type: "switch",
2823
description:
2924
"Sign in via browser; use --console-site to choose domestic (default) or international",
3025
},
31-
],
26+
},
3227
exampleArgs: ["--api-key sk-xxxxx", "--console"],
3328
validate: (f) => (!f.console && !f.apiKey ? "Provide --api-key or --console" : undefined),
34-
async run(config: Config, flags: GlobalFlags) {
29+
async run(config, flags) {
3530
if (flags.console) {
3631
if (config.dryRun) {
3732
emitBare(
@@ -46,26 +41,23 @@ export default defineCommand({
4641
return;
4742
}
4843

49-
const envKey = process.env.DASHSCOPE_API_KEY;
50-
if (envKey && !flags.apiKey) {
51-
process.stderr.write(`Warning: DASHSCOPE_API_KEY is already set in environment.\n`);
52-
}
53-
54-
const key = flags.apiKey as string;
44+
// --api-key path; validate() guarantees apiKey on the non-console branch.
45+
if (flags.apiKey) {
46+
const key = flags.apiKey;
47+
const baseUrl = flags.baseUrl || undefined;
48+
const effectiveConfig = baseUrl ? { ...config, baseUrl } : config;
5549

56-
const baseUrl = (flags.baseUrl as string) || undefined;
57-
const effectiveConfig = baseUrl ? { ...config, baseUrl } : config;
58-
59-
if (!config.dryRun) {
50+
if (config.dryRun) {
51+
emitBare("Would validate and save API key.");
52+
return;
53+
}
6054
if (baseUrl) {
6155
const existing = readConfigFile() as Record<string, unknown>;
6256
existing.base_url = baseUrl;
6357
await writeConfigFile(existing);
6458
}
6559
await validateAndPersistApiKey(effectiveConfig, key, effectiveConfig.baseUrl);
6660
printQuickStart();
67-
} else {
68-
emitBare("Would validate and save API key.");
6961
}
7062
},
7163
});

packages/commands/src/commands/auth/logout.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import {
44
readConfigFile,
55
writeConfigFile,
66
getConfigPath,
7-
type Config,
8-
type GlobalFlags,
97
} from "bailian-cli-core";
108
import { emitBare } from "bailian-cli-runtime";
119

@@ -21,16 +19,15 @@ export default defineCommand({
2119
description: "Clear stored credentials",
2220
auth: "none",
2321
usageArgs: "[--console] [--yes] [--dry-run]",
24-
options: [
25-
{
26-
flag: "--console",
22+
flags: {
23+
console: {
24+
type: "switch",
2725
description: "Only clear the console access_token, keep api_key intact",
28-
type: "boolean",
2926
},
30-
{ flag: "--yes", description: "Skip confirmation prompt" },
31-
],
27+
yes: { type: "switch", description: "Skip confirmation prompt" },
28+
},
3229
exampleArgs: ["", "--console", "--dry-run", "--yes"],
33-
async run(config: Config, flags: GlobalFlags) {
30+
async run(config, flags) {
3431
const file = readConfigFile();
3532

3633
if (flags.console) {

0 commit comments

Comments
 (0)