Team Ai
Datasetpublic

Brunobkr/llama.cpp_AlgMor24_github

ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.

sourceHugging Faceupdated 2mo agoView on Hugging Face
0likes3.1kdownloads
index.js936 linesDownload Raw Back to esm
1import { inspect, parseArgs, } from 'node:util';2import { cliui } from '@isaacs/cliui/min';3import { basename } from 'node:path';4export const isConfigType = (t) => typeof t === 'string' &&5    (t === 'string' || t === 'number' || t === 'boolean');6const isValidValue = (v, type, multi) => {7    if (multi) {8        if (!Array.isArray(v))9            return false;10        return !v.some((v) => !isValidValue(v, type, false));11    }12    if (Array.isArray(v))13        return false;14    return typeof v === type;15};16const isValidOption = (v, vo) => !!vo &&17    (Array.isArray(v) ? v.every(x => isValidOption(x, vo)) : vo.includes(v));18/**19 * Determine whether an unknown object is a {@link ConfigOption} based only20 * on its `type` and `multiple` property21 */22export const isConfigOptionOfType = (o, type, multi) => !!o &&23    typeof o === 'object' &&24    'type' in o &&25    isConfigType(o.type) &&26    o.type === type &&27    !!o.multiple === multi;28/**29 * Determine whether an unknown object is a {@link ConfigOption} based on30 * it having all valid properties31 */32export const isConfigOption = (o, type, multi) => isConfigOptionOfType(o, type, multi) &&33    undefOrType(o.short, 'string') &&34    undefOrType(o.description, 'string') &&35    undefOrType(o.hint, 'string') &&36    undefOrType(o.validate, 'function') &&37    (o.type === 'boolean' ?38        o.validOptions === undefined39        : undefOrTypeArray(o.validOptions, o.type)) &&40    (o.default === undefined || isValidValue(o.default, type, multi));41const isHeading = (r) => r.type === 'heading';42const isDescription = (r) => r.type === 'description';43const width = Math.min(process?.stdout?.columns ?? 80, 80);44// indentation spaces from heading level45const indent = (n) => (n - 1) * 2;46const toEnvKey = (pref, key) => [pref, key.replace(/[^a-zA-Z0-9]+/g, ' ')]47    .join(' ')48    .trim()49    .toUpperCase()50    .replace(/ /g, '_');51const toEnvVal = (value, delim = '\n') => {52    const str = typeof value === 'string' ? value53        : typeof value === 'boolean' ?54            value ? '1'55                : '0'56            : typeof value === 'number' ? String(value)57                : Array.isArray(value) ?58                    value.map((v) => toEnvVal(v)).join(delim)59                    : /* c8 ignore start */ undefined;60    if (typeof str !== 'string') {61        throw new Error(`could not serialize value to environment: ${JSON.stringify(value)}`, { cause: { code: 'JACKSPEAK' } });62    }63    /* c8 ignore stop */64    return str;65};66const fromEnvVal = (env, type, multiple, delim = '\n') => (multiple ?67    env ? env.split(delim).map(v => fromEnvVal(v, type, false))68        : []69    : type === 'string' ? env70        : type === 'boolean' ? env === '1'71            : +env.trim());72const undefOrType = (v, t) => v === undefined || typeof v === t;73const undefOrTypeArray = (v, t) => v === undefined || (Array.isArray(v) && v.every(x => typeof x === t));74// print the value type, for error message reporting75const valueType = (v) => typeof v === 'string' ? 'string'76    : typeof v === 'boolean' ? 'boolean'77        : typeof v === 'number' ? 'number'78            : Array.isArray(v) ?79                `${joinTypes([...new Set(v.map(v => valueType(v)))])}[]`80                : `${v.type}${v.multiple ? '[]' : ''}`;81const joinTypes = (types) => types.length === 1 && typeof types[0] === 'string' ?82    types[0]83    : `(${types.join('|')})`;84const validateFieldMeta = (field, fieldMeta) => {85    if (fieldMeta) {86        if (field.type !== undefined && field.type !== fieldMeta.type) {87            throw new TypeError(`invalid type`, {88                cause: {89                    found: field.type,90                    wanted: [fieldMeta.type, undefined],91                },92            });93        }94        if (field.multiple !== undefined &&95            !!field.multiple !== fieldMeta.multiple) {96            throw new TypeError(`invalid multiple`, {97                cause: {98                    found: field.multiple,99                    wanted: [fieldMeta.multiple, undefined],100                },101            });102        }103        return fieldMeta;104    }105    if (!isConfigType(field.type)) {106        throw new TypeError(`invalid type`, {107            cause: {108                found: field.type,109                wanted: ['string', 'number', 'boolean'],110            },111        });112    }113    return {114        type: field.type,115        multiple: !!field.multiple,116    };117};118const validateField = (o, type, multiple) => {119    const validateValidOptions = (def, validOptions) => {120        if (!undefOrTypeArray(validOptions, type)) {121            throw new TypeError('invalid validOptions', {122                cause: {123                    found: validOptions,124                    wanted: valueType({ type, multiple: true }),125                },126            });127        }128        if (def !== undefined && validOptions !== undefined) {129            const valid = Array.isArray(def) ?130                def.every(v => validOptions.includes(v))131                : validOptions.includes(def);132            if (!valid) {133                throw new TypeError('invalid default value not in validOptions', {134                    cause: {135                        found: def,136                        wanted: validOptions,137                    },138                });139            }140        }141    };142    if (o.default !== undefined &&143        !isValidValue(o.default, type, multiple)) {144        throw new TypeError('invalid default value', {145            cause: {146                found: o.default,147                wanted: valueType({ type, multiple }),148            },149        });150    }151    if (isConfigOptionOfType(o, 'number', false) ||152        isConfigOptionOfType(o, 'number', true)) {153        validateValidOptions(o.default, o.validOptions);154    }155    else if (isConfigOptionOfType(o, 'string', false) ||156        isConfigOptionOfType(o, 'string', true)) {157        validateValidOptions(o.default, o.validOptions);158    }159    else if (isConfigOptionOfType(o, 'boolean', false) ||160        isConfigOptionOfType(o, 'boolean', true)) {161        if (o.hint !== undefined) {162            throw new TypeError('cannot provide hint for flag');163        }164        if (o.validOptions !== undefined) {165            throw new TypeError('cannot provide validOptions for flag');166        }167    }168    return o;169};170const toParseArgsOptionsConfig = (options) => {171    return Object.entries(options).reduce((acc, [longOption, o]) => {172        const p = {173            type: 'string',174            multiple: !!o.multiple,175            ...(typeof o.short === 'string' ? { short: o.short } : undefined),176        };177        const setNoBool = () => {178            if (!longOption.startsWith('no-') && !options[`no-${longOption}`]) {179                acc[`no-${longOption}`] = {180                    type: 'boolean',181                    multiple: !!o.multiple,182                };183            }184        };185        const setDefault = (def, fn) => {186            if (def !== undefined) {187                p.default = fn(def);188            }189        };190        if (isConfigOption(o, 'number', false)) {191            setDefault(o.default, String);192        }193        else if (isConfigOption(o, 'number', true)) {194            setDefault(o.default, d => d.map(v => String(v)));195        }196        else if (isConfigOption(o, 'string', false) ||197            isConfigOption(o, 'string', true)) {198            setDefault(o.default, v => v);199        }200        else if (isConfigOption(o, 'boolean', false) ||201            isConfigOption(o, 'boolean', true)) {202            p.type = 'boolean';203            setDefault(o.default, v => v);204            setNoBool();205        }206        acc[longOption] = p;207        return acc;208    }, {});209};210/**211 * Class returned by the {@link jack} function and all configuration212 * definition methods.  This is what gets chained together.213 */214export class Jack {215    #configSet;216    #shorts;217    #options;218    #fields = [];219    #env;220    #envPrefix;221    #allowPositionals;222    #usage;223    #usageMarkdown;224    constructor(options = {}) {225        this.#options = options;226        this.#allowPositionals = options.allowPositionals !== false;227        this.#env =228            this.#options.env === undefined ? process.env : this.#options.env;229        this.#envPrefix = options.envPrefix;230        // We need to fib a little, because it's always the same object, but it231        // starts out as having an empty config set.  Then each method that adds232        // fields returns `this as Jack<C & { ...newConfigs }>`233        this.#configSet = Object.create(null);234        this.#shorts = Object.create(null);235    }236    /**237     * Resulting definitions, suitable to be passed to Node's `util.parseArgs`,238     * but also including `description` and `short` fields, if set.239     */240    get definitions() {241        return this.#configSet;242    }243    /** map of `{ <short>: <long> }` strings for each short name defined */244    get shorts() {245        return this.#shorts;246    }247    /**248     * options passed to the {@link Jack} constructor249     */250    get jackOptions() {251        return this.#options;252    }253    /**254     * the data used to generate {@link Jack#usage} and255     * {@link Jack#usageMarkdown} content.256     */257    get usageFields() {258        return this.#fields;259    }260    /**261     * Set the default value (which will still be overridden by env or cli)262     * as if from a parsed config file. The optional `source` param, if263     * provided, will be included in error messages if a value is invalid or264     * unknown.265     */266    setConfigValues(values, source = '') {267        try {268            this.validate(values);269        }270        catch (er) {271            if (source && er instanceof Error) {272                /* c8 ignore next */273                const cause = typeof er.cause === 'object' ? er.cause : {};274                er.cause = { ...cause, path: source };275                Error.captureStackTrace(er, this.setConfigValues);276            }277            throw er;278        }279        for (const [field, value] of Object.entries(values)) {280            const my = this.#configSet[field];281            // already validated, just for TS's benefit282            /* c8 ignore start */283            if (!my) {284                throw new Error('unexpected field in config set: ' + field, {285                    cause: {286                        code: 'JACKSPEAK',287                        found: field,288                    },289                });290            }291            /* c8 ignore stop */292            my.default = value;293        }294        return this;295    }296    /**297     * Parse a string of arguments, and return the resulting298     * `{ values, positionals }` object.299     *300     * If an {@link JackOptions#envPrefix} is set, then it will read default301     * values from the environment, and write the resulting values back302     * to the environment as well.303     *304     * Environment values always take precedence over any other value, except305     * an explicit CLI setting.306     */307    parse(args = process.argv) {308        this.loadEnvDefaults();309        const p = this.parseRaw(args);310        this.applyDefaults(p);311        this.writeEnv(p);312        return p;313    }314    loadEnvDefaults() {315        if (this.#envPrefix) {316            for (const [field, my] of Object.entries(this.#configSet)) {317                const ek = toEnvKey(this.#envPrefix, field);318                const env = this.#env[ek];319                if (env !== undefined) {320                    my.default = fromEnvVal(env, my.type, !!my.multiple, my.delim);321                }322            }323        }324    }325    applyDefaults(p) {326        for (const [field, c] of Object.entries(this.#configSet)) {327            if (c.default !== undefined && !(field in p.values)) {328                //@ts-ignore329                p.values[field] = c.default;330            }331        }332    }333    /**334     * Only parse the command line arguments passed in.335     * Does not strip off the `node script.js` bits, so it must be just the336     * arguments you wish to have parsed.337     * Does not read from or write to the environment, or set defaults.338     */339    parseRaw(args) {340        if (args === process.argv) {341            args = args.slice(process._eval !== undefined ? 1 : 2);342        }343        const result = parseArgs({344            args,345            options: toParseArgsOptionsConfig(this.#configSet),346            // always strict, but using our own logic347            strict: false,348            allowPositionals: this.#allowPositionals,349            tokens: true,350        });351        const p = {352            values: {},353            positionals: [],354        };355        for (const token of result.tokens) {356            if (token.kind === 'positional') {357                p.positionals.push(token.value);358                if (this.#options.stopAtPositional ||359                    this.#options.stopAtPositionalTest?.(token.value)) {360                    p.positionals.push(...args.slice(token.index + 1));361                    break;362                }363            }364            else if (token.kind === 'option') {365                let value = undefined;366                if (token.name.startsWith('no-')) {367                    const my = this.#configSet[token.name];368                    const pname = token.name.substring('no-'.length);369                    const pos = this.#configSet[pname];370                    if (pos &&371                        pos.type === 'boolean' &&372                        (!my ||373                            (my.type === 'boolean' && !!my.multiple === !!pos.multiple))) {374                        value = false;375                        token.name = pname;376                    }377                }378                const my = this.#configSet[token.name];379                if (!my) {380                    throw new Error(`Unknown option '${token.rawName}'. ` +381                        `To specify a positional argument starting with a '-', ` +382                        `place it at the end of the command after '--', as in ` +383                        `'-- ${token.rawName}'`, {384                        cause: {385                            code: 'JACKSPEAK',386                            found: token.rawName + (token.value ? `=${token.value}` : ''),387                        },388                    });389                }390                if (value === undefined) {391                    if (token.value === undefined) {392                        if (my.type !== 'boolean') {393                            throw new Error(`No value provided for ${token.rawName}, expected ${my.type}`, {394                                cause: {395                                    code: 'JACKSPEAK',396                                    name: token.rawName,397                                    wanted: valueType(my),398                                },399                            });400                        }401                        value = true;402                    }403                    else {404                        if (my.type === 'boolean') {405                            throw new Error(`Flag ${token.rawName} does not take a value, received '${token.value}'`, { cause: { code: 'JACKSPEAK', found: token } });406                        }407                        if (my.type === 'string') {408                            value = token.value;409                        }410                        else {411                            value = +token.value;412                            if (value !== value) {413                                throw new Error(`Invalid value '${token.value}' provided for ` +414                                    `'${token.rawName}' option, expected number`, {415                                    cause: {416                                        code: 'JACKSPEAK',417                                        name: token.rawName,418                                        found: token.value,419                                        wanted: 'number',420                                    },421                                });422                            }423                        }424                    }425                }426                if (my.multiple) {427                    const pv = p.values;428                    const tn = pv[token.name] ?? [];429                    pv[token.name] = tn;430                    tn.push(value);431                }432                else {433                    const pv = p.values;434                    pv[token.name] = value;435                }436            }437        }438        for (const [field, value] of Object.entries(p.values)) {439            const valid = this.#configSet[field]?.validate;440            const validOptions = this.#configSet[field]?.validOptions;441            const cause = validOptions && !isValidOption(value, validOptions) ?442                { name: field, found: value, validOptions }443                : valid && !valid(value) ? { name: field, found: value }444                    : undefined;445            if (cause) {446                throw new Error(`Invalid value provided for --${field}: ${JSON.stringify(value)}`, { cause: { ...cause, code: 'JACKSPEAK' } });447            }448        }449        return p;450    }451    /**452     * do not set fields as 'no-foo' if 'foo' exists and both are bools453     * just set foo.454     */455    #noNoFields(f, val, s = f) {456        if (!f.startsWith('no-') || typeof val !== 'boolean')457            return;458        const yes = f.substring('no-'.length);459        // recurse so we get the core config key we care about.460        this.#noNoFields(yes, val, s);461        if (this.#configSet[yes]?.type === 'boolean') {462            throw new Error(`do not set '${s}', instead set '${yes}' as desired.`, { cause: { code: 'JACKSPEAK', found: s, wanted: yes } });463        }464    }465    /**466     * Validate that any arbitrary object is a valid configuration `values`467     * object.  Useful when loading config files or other sources.468     */469    validate(o) {470        if (!o || typeof o !== 'object') {471            throw new Error('Invalid config: not an object', {472                cause: { code: 'JACKSPEAK', found: o },473            });474        }475        const opts = o;476        for (const field in o) {477            const value = opts[field];478            /* c8 ignore next - for TS */479            if (value === undefined)480                continue;481            this.#noNoFields(field, value);482            const config = this.#configSet[field];483            if (!config) {484                throw new Error(`Unknown config option: ${field}`, {485                    cause: { code: 'JACKSPEAK', found: field },486                });487            }488            if (!isValidValue(value, config.type, !!config.multiple)) {489                throw new Error(`Invalid value ${valueType(value)} for ${field}, expected ${valueType(config)}`, {490                    cause: {491                        code: 'JACKSPEAK',492                        name: field,493                        found: value,494                        wanted: valueType(config),495                    },496                });497            }498            const cause = config.validOptions && !isValidOption(value, config.validOptions) ?499                { name: field, found: value, validOptions: config.validOptions }500                : config.validate && !config.validate(value) ?501                    { name: field, found: value }502                    : undefined;503            if (cause) {504                throw new Error(`Invalid config value for ${field}: ${JSON.stringify(value)}`, {505                    cause: { ...cause, code: 'JACKSPEAK' },506                });507            }508        }509    }510    writeEnv(p) {511        if (!this.#env || !this.#envPrefix)512            return;513        for (const [field, value] of Object.entries(p.values)) {514            const my = this.#configSet[field];515            this.#env[toEnvKey(this.#envPrefix, field)] = toEnvVal(value, my?.delim);516        }517    }518    /**519     * Add a heading to the usage output banner520     */521    heading(text, level, { pre = false } = {}) {522        if (level === undefined) {523            level = this.#fields.some(r => isHeading(r)) ? 2 : 1;524        }525        this.#fields.push({ type: 'heading', text, level, pre });526        return this;527    }528    /**529     * Add a long-form description to the usage output at this position.530     */531    description(text, { pre } = {}) {532        this.#fields.push({ type: 'description', text, pre });533        return this;534    }535    /**536     * Add one or more number fields.537     */538    num(fields) {539        return this.#addFieldsWith(fields, 'number', false);540    }541    /**542     * Add one or more multiple number fields.543     */544    numList(fields) {545        return this.#addFieldsWith(fields, 'number', true);546    }547    /**548     * Add one or more string option fields.549     */550    opt(fields) {551        return this.#addFieldsWith(fields, 'string', false);552    }553    /**554     * Add one or more multiple string option fields.555     */556    optList(fields) {557        return this.#addFieldsWith(fields, 'string', true);558    }559    /**560     * Add one or more flag fields.561     */562    flag(fields) {563        return this.#addFieldsWith(fields, 'boolean', false);564    }565    /**566     * Add one or more multiple flag fields.567     */568    flagList(fields) {569        return this.#addFieldsWith(fields, 'boolean', true);570    }571    /**572     * Generic field definition method. Similar to flag/flagList/number/etc,573     * but you must specify the `type` (and optionally `multiple` and `delim`)574     * fields on each one, or Jack won't know how to define them.575     */576    addFields(fields) {577        return this.#addFields(this, fields);578    }579    #addFieldsWith(fields, type, multiple) {580        return this.#addFields(this, fields, {581            type,582            multiple,583        });584    }585    #addFields(next, fields, opt) {586        Object.assign(next.#configSet, Object.fromEntries(Object.entries(fields).map(([name, field]) => {587            this.#validateName(name, field);588            const { type, multiple } = validateFieldMeta(field, opt);589            const value = { ...field, type, multiple };590            validateField(value, type, multiple);591            next.#fields.push({ type: 'config', name, value });592            return [name, value];593        })));594        return next;595    }596    #validateName(name, field) {597        if (!/^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(name)) {598            throw new TypeError(`Invalid option name: ${name}, ` +599                `must be '-' delimited ASCII alphanumeric`);600        }601        if (this.#configSet[name]) {602            throw new TypeError(`Cannot redefine option ${name}`);603        }604        if (this.#shorts[name]) {605            throw new TypeError(`Cannot redefine option ${name}, already ` +606                `in use for ${this.#shorts[name]}`);607        }608        if (field.short) {609            if (!/^[a-zA-Z0-9]$/.test(field.short)) {610                throw new TypeError(`Invalid ${name} short option: ${field.short}, ` +611                    'must be 1 ASCII alphanumeric character');612            }613            if (this.#shorts[field.short]) {614                throw new TypeError(`Invalid ${name} short option: ${field.short}, ` +615                    `already in use for ${this.#shorts[field.short]}`);616            }617            this.#shorts[field.short] = name;618            this.#shorts[name] = name;619        }620    }621    /**622     * Return the usage banner for the given configuration623     */624    usage() {625        if (this.#usage)626            return this.#usage;627        let headingLevel = 1;628        //@ts-ignore629        const ui = cliui({ width });630        const first = this.#fields[0];631        let start = first?.type === 'heading' ? 1 : 0;632        if (first?.type === 'heading') {633            ui.div({634                padding: [0, 0, 0, 0],635                text: normalize(first.text),636            });637        }638        ui.div({ padding: [0, 0, 0, 0], text: 'Usage:' });639        if (this.#options.usage) {640            ui.div({641                text: this.#options.usage,642                padding: [0, 0, 0, 2],643            });644        }645        else {646            const cmd = basename(String(process.argv[1]));647            const shortFlags = [];648            const shorts = [];649            const flags = [];650            const opts = [];651            for (const [field, config] of Object.entries(this.#configSet)) {652                if (config.short) {653                    if (config.type === 'boolean')654                        shortFlags.push(config.short);655                    else656                        shorts.push([config.short, config.hint || field]);657                }658                else {659                    if (config.type === 'boolean')660                        flags.push(field);661                    else662                        opts.push([field, config.hint || field]);663                }664            }665            const sf = shortFlags.length ? ' -' + shortFlags.join('') : '';666            const so = shorts.map(([k, v]) => ` --${k}=<${v}>`).join('');667            const lf = flags.map(k => ` --${k}`).join('');668            const lo = opts.map(([k, v]) => ` --${k}=<${v}>`).join('');669            const usage = `${cmd}${sf}${so}${lf}${lo}`.trim();670            ui.div({671                text: usage,672                padding: [0, 0, 0, 2],673            });674        }675        ui.div({ padding: [0, 0, 0, 0], text: '' });676        const maybeDesc = this.#fields[start];677        if (maybeDesc && isDescription(maybeDesc)) {678            const print = normalize(maybeDesc.text, maybeDesc.pre);679            start++;680            ui.div({ padding: [0, 0, 0, 0], text: print });681            ui.div({ padding: [0, 0, 0, 0], text: '' });682        }683        const { rows, maxWidth } = this.#usageRows(start);684        // every heading/description after the first gets indented by 2685        // extra spaces.686        for (const row of rows) {687            if (row.left) {688                // If the row is too long, don't wrap it689                // Bump the right-hand side down a line to make room690                const configIndent = indent(Math.max(headingLevel, 2));691                if (row.left.length > maxWidth - 3) {692                    ui.div({ text: row.left, padding: [0, 0, 0, configIndent] });693                    ui.div({ text: row.text, padding: [0, 0, 0, maxWidth] });694                }695                else {696                    ui.div({697                        text: row.left,698                        padding: [0, 1, 0, configIndent],699                        width: maxWidth,700                    }, { padding: [0, 0, 0, 0], text: row.text });701                }702                if (row.skipLine) {703                    ui.div({ padding: [0, 0, 0, 0], text: '' });704                }705            }706            else {707                if (isHeading(row)) {708                    const { level } = row;709                    headingLevel = level;710                    // only h1 and h2 have bottom padding711                    // h3-h6 do not712                    const b = level <= 2 ? 1 : 0;713                    ui.div({ ...row, padding: [0, 0, b, indent(level)] });714                }715                else {716                    ui.div({ ...row, padding: [0, 0, 1, indent(headingLevel + 1)] });717                }718            }719        }720        return (this.#usage = ui.toString());721    }722    /**723     * Return the usage banner markdown for the given configuration724     */725    usageMarkdown() {726        if (this.#usageMarkdown)727            return this.#usageMarkdown;728        const out = [];729        let headingLevel = 1;730        const first = this.#fields[0];731        let start = first?.type === 'heading' ? 1 : 0;732        if (first?.type === 'heading') {733            out.push(`# ${normalizeOneLine(first.text)}`);734        }735        out.push('Usage:');736        if (this.#options.usage) {737            out.push(normalizeMarkdown(this.#options.usage, true));738        }739        else {740            const cmd = basename(String(process.argv[1]));741            const shortFlags = [];742            const shorts = [];743            const flags = [];744            const opts = [];745            for (const [field, config] of Object.entries(this.#configSet)) {746                if (config.short) {747                    if (config.type === 'boolean')748                        shortFlags.push(config.short);749                    else750                        shorts.push([config.short, config.hint || field]);751                }752                else {753                    if (config.type === 'boolean')754                        flags.push(field);755                    else756                        opts.push([field, config.hint || field]);757                }758            }759            const sf = shortFlags.length ? ' -' + shortFlags.join('') : '';760            const so = shorts.map(([k, v]) => ` --${k}=<${v}>`).join('');761            const lf = flags.map(k => ` --${k}`).join('');762            const lo = opts.map(([k, v]) => ` --${k}=<${v}>`).join('');763            const usage = `${cmd}${sf}${so}${lf}${lo}`.trim();764            out.push(normalizeMarkdown(usage, true));765        }766        const maybeDesc = this.#fields[start];767        if (maybeDesc && isDescription(maybeDesc)) {768            out.push(normalizeMarkdown(maybeDesc.text, maybeDesc.pre));769            start++;770        }771        const { rows } = this.#usageRows(start);772        // heading level in markdown is number of # ahead of text773        for (const row of rows) {774            if (row.left) {775                out.push('#'.repeat(headingLevel + 1) +776                    ' ' +777                    normalizeOneLine(row.left, true));778                if (row.text)779                    out.push(normalizeMarkdown(row.text));780            }781            else if (isHeading(row)) {782                const { level } = row;783                headingLevel = level;784                out.push(`${'#'.repeat(headingLevel)} ${normalizeOneLine(row.text, row.pre)}`);785            }786            else {787                out.push(normalizeMarkdown(row.text, !!row.pre));788            }789        }790        return (this.#usageMarkdown = out.join('\n\n') + '\n');791    }792    #usageRows(start) {793        // turn each config type into a row, and figure out the width of the794        // left hand indentation for the option descriptions.795        const maxMax = Math.max(12, Math.min(26, Math.floor(width / 3)));796        let maxWidth = 8;797        let prev = undefined;798        const rows = [];799        for (const field of this.#fields.slice(start)) {800            if (field.type !== 'config') {801                if (prev?.type === 'config')802                    prev.skipLine = true;803                prev = undefined;804                field.text = normalize(field.text, !!field.pre);805                rows.push(field);806                continue;807            }808            const { value } = field;809            const desc = value.description || '';810            const mult = value.multiple ? 'Can be set multiple times' : '';811            const opts = value.validOptions?.length ?812                'Valid options: ' +813                    value.validOptions.map(v => JSON.stringify(v)).join(', ')814                : '';815            const dmDelim = desc.includes('\n') ? '\n\n' : '\n';816            const extra = [opts, mult].join(dmDelim).trim();817            const text = (normalize(desc) + dmDelim + extra).trim();818            const hint = value.hint ||819                (value.type === 'number' ? 'n'820                    : value.type === 'string' ? field.name821                        : undefined);822            const short = !value.short ? ''823                : value.type === 'boolean' ? `-${value.short} `824                    : `-${value.short}<${hint}> `;825            const left = value.type === 'boolean' ?826                `${short}--${field.name}`827                : `${short}--${field.name}=<${hint}>`;828            const row = { text, left, type: 'config' };829            if (text.length > width - maxMax) {830                row.skipLine = true;831            }832            if (prev && left.length > maxMax)833                prev.skipLine = true;834            prev = row;835            const len = left.length + 4;836            if (len > maxWidth && len < maxMax) {837                maxWidth = len;838            }839            rows.push(row);840        }841        return { rows, maxWidth };842    }843    /**844     * Return the configuration options as a plain object845     */846    toJSON() {847        return Object.fromEntries(Object.entries(this.#configSet).map(([field, def]) => [848            field,849            {850                type: def.type,851                ...(def.multiple ? { multiple: true } : {}),852                ...(def.delim ? { delim: def.delim } : {}),853                ...(def.short ? { short: def.short } : {}),854                ...(def.description ?855                    { description: normalize(def.description) }856                    : {}),857                ...(def.validate ? { validate: def.validate } : {}),858                ...(def.validOptions ? { validOptions: def.validOptions } : {}),859                ...(def.default !== undefined ? { default: def.default } : {}),860                ...(def.hint ? { hint: def.hint } : {}),861            },862        ]));863    }864    /**865     * Custom printer for `util.inspect`866     */867    [inspect.custom](_, options) {868        return `Jack ${inspect(this.toJSON(), options)}`;869    }870}871/**872 * Main entry point. Create and return a {@link Jack} object.873 */874export const jack = (options = {}) => new Jack(options);875// Unwrap and un-indent, so we can wrap description876// strings however makes them look nice in the code.877const normalize = (s, pre = false) => {878    if (pre)879        // prepend a ZWSP to each line so cliui doesn't strip it.880        return s881            .split('\n')882            .map(l => `\u200b${l}`)883            .join('\n');884    return s885        .split(/^\s*```\s*$/gm)886        .map((s, i) => {887        if (i % 2 === 1) {888            if (!s.trim()) {889                return `\`\`\`\n\`\`\`\n`;890            }891            // outdent the ``` blocks, but preserve whitespace otherwise.892            const split = s.split('\n');893            // throw out the \n at the start and end894            split.pop();895            split.shift();896            const si = split.reduce((shortest, l) => {897                /* c8 ignore next */898                const ind = l.match(/^\s*/)?.[0] ?? '';899                if (ind.length)900                    return Math.min(ind.length, shortest);901                else902                    return shortest;903            }, Infinity);904            /* c8 ignore next */905            const i = isFinite(si) ? si : 0;906            return ('\n```\n' +907                split.map(s => `\u200b${s.substring(i)}`).join('\n') +908                '\n```\n');909        }910        return (s911            // remove single line breaks, except for lists912            .replace(/([^\n])\n[ \t]*([^\n])/g, (_, $1, $2) => !/^[-*]/.test($2) ? `${$1} ${$2}` : `${$1}\n${$2}`)913            // normalize mid-line whitespace914            .replace(/([^\n])[ \t]+([^\n])/g, '$1 $2')915            // two line breaks are enough916            .replace(/\n{3,}/g, '\n\n')917            // remove any spaces at the start of a line918            .replace(/\n[ \t]+/g, '\n')919            .trim());920    })921        .join('\n');922};923// normalize for markdown printing, remove leading spaces on lines924const normalizeMarkdown = (s, pre = false) => {925    const n = normalize(s, pre).replace(/\\/g, '\\\\');926    return pre ?927        `\`\`\`\n${n.replace(/\u200b/g, '')}\n\`\`\``928        : n.replace(/\n +/g, '\n').trim();929};930const normalizeOneLine = (s, pre = false) => {931    const n = normalize(s, pre)932        .replace(/[\s\u200b]+/g, ' ')933        .trim();934    return pre ? `\`${n}\`` : n;935};936//# sourceMappingURL=index.js.map
Brunobkr/llama.cpp_AlgMor24_github · Team Ai