-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathargs.ts
142 lines (125 loc) · 4.31 KB
/
args.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// @ts-types="npm:@types/command-line-args"
import commandLineArgs from "command-line-args";
// @ts-types="npm:@types/command-line-usage";
import commandLineUsage from "command-line-usage";
import * as z from "@/common/myZod.ts";
import { ConfigSchema } from "@/common/configModels.ts";
// Replicates Python's strtobool for handling boolean values
function strToBool(value: string): boolean {
const truthyValues = ["true", "1", "yes", "y"];
const falsyValues = ["false", "0", "no", "n"];
if (truthyValues.includes(value.toLowerCase())) {
return true;
} else if (falsyValues.includes(value.toLowerCase())) {
return false;
} else {
throw new Error(`Invalid boolean value: ${value}`);
}
}
// Converts the ConfigSchema to CLI arguments
function configToArgs() {
const configGroups: commandLineUsage.OptionList[] = [];
// Iterate and create groups from top-level arguments
for (const [groupName, params] of Object.entries(ConfigSchema.shape)) {
const groupOptions = createGroupOptions(groupName, params.shape);
configGroups.push({ header: groupName, optionList: groupOptions });
}
return configGroups;
}
// Creates inner arg options for argument groups
function createGroupOptions(groupName: string, shape: z.ZodRawShape) {
return Object.entries(shape).map(([key, value]) => {
const option: commandLineUsage.OptionDefinition = {
name: key.replaceAll("_", "-"),
group: groupName,
};
setArgType(option, value);
return option;
});
}
// Converts a Zod schema type to a command-line-args type
function setArgType(
option: commandLineUsage.OptionDefinition,
zodType: z.ZodTypeAny,
) {
// Get constructor name for switch
const typeName = zodType.constructor.name;
switch (typeName) {
case "ZodString":
option["type"] = String;
break;
case "ZodNumber":
option["type"] = Number;
break;
case "ZodBoolean":
option["type"] = strToBool;
break;
case "ZodOptional":
setArgType(
option,
(zodType as z.ZodOptional<z.ZodTypeAny>).unwrap(),
);
break;
case "ZodNullable":
setArgType(
option,
(zodType as z.ZodNullable<z.ZodTypeAny>).unwrap(),
);
break;
case "ZodUnion":
setArgType(
option,
(zodType as z.ZodUnion<[z.ZodTypeAny, ...z.ZodTypeAny[]]>)._def
.options[0],
);
break;
case "ZodEffects":
setArgType(
option,
(zodType as z.ZodEffects<z.ZodTypeAny>).innerType(),
);
break;
case "ZodArray":
option["multiple"] = true;
setArgType(option, (zodType as z.ZodArray<z.ZodTypeAny>).element);
break;
}
}
// Parses global arguments from Deno.args
export function parseArgs() {
// Define option groups
const helpGroup: commandLineUsage.Section = {
header: "Support",
optionList: [{
name: "help",
type: Boolean,
description: "Prints this menu",
group: "support",
}],
};
const epilog: commandLineUsage.Section = {
header: "Epilog",
content: "- strtobool flags require an explicit value. " +
"Example: --flash-attention true",
raw: true,
};
const configGroups = configToArgs();
const optionGroups = [...configGroups, helpGroup];
const usage = commandLineUsage([...optionGroups, epilog]);
const cliOptions: commandLineUsage.OptionDefinition[] = optionGroups
.flatMap((option) => option.optionList ?? []);
// Parse the options
const args = commandLineArgs(cliOptions, { argv: Deno.args });
// Replace keys with underscores for config parsing
for (const groupName of Object.keys(args)) {
const groupArgs = args[groupName];
if (groupArgs && typeof groupArgs === "object") {
args[groupName] = Object.fromEntries(
Object.entries(groupArgs).map((
[k, v],
) => [k.replaceAll("-", "_"), v]),
);
}
}
return { args, usage };
}