incur 0.4.8 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Cli.d.ts +65 -19
- package/dist/Cli.d.ts.map +1 -1
- package/dist/Cli.js +294 -66
- package/dist/Cli.js.map +1 -1
- package/dist/Completions.d.ts +2 -1
- package/dist/Completions.d.ts.map +1 -1
- package/dist/Completions.js +52 -13
- package/dist/Completions.js.map +1 -1
- package/dist/Formatter.d.ts.map +1 -1
- package/dist/Formatter.js +6 -5
- package/dist/Formatter.js.map +1 -1
- package/dist/Help.d.ts +5 -0
- package/dist/Help.d.ts.map +1 -1
- package/dist/Help.js +19 -5
- package/dist/Help.js.map +1 -1
- package/dist/Mcp.d.ts +21 -0
- package/dist/Mcp.d.ts.map +1 -1
- package/dist/Mcp.js +25 -8
- package/dist/Mcp.js.map +1 -1
- package/dist/Parser.d.ts +14 -0
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +127 -1
- package/dist/Parser.js.map +1 -1
- package/dist/Skill.d.ts.map +1 -1
- package/dist/Skill.js +5 -2
- package/dist/Skill.js.map +1 -1
- package/dist/Skillgen.d.ts.map +1 -1
- package/dist/Skillgen.js +4 -38
- package/dist/Skillgen.js.map +1 -1
- package/dist/SyncMcp.d.ts.map +1 -1
- package/dist/SyncMcp.js +75 -8
- package/dist/SyncMcp.js.map +1 -1
- package/dist/SyncSkills.d.ts +9 -0
- package/dist/SyncSkills.d.ts.map +1 -1
- package/dist/SyncSkills.js +13 -74
- package/dist/SyncSkills.js.map +1 -1
- package/dist/bin.d.ts +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/internal/command.d.ts +2 -0
- package/dist/internal/command.d.ts.map +1 -1
- package/dist/internal/command.js +6 -5
- package/dist/internal/command.js.map +1 -1
- package/dist/internal/cta.d.ts +22 -0
- package/dist/internal/cta.d.ts.map +1 -0
- package/dist/internal/cta.js +25 -0
- package/dist/internal/cta.js.map +1 -0
- package/dist/internal/json.d.ts +5 -0
- package/dist/internal/json.d.ts.map +1 -0
- package/dist/internal/json.js +13 -0
- package/dist/internal/json.js.map +1 -0
- package/dist/internal/yaml.d.ts +12 -0
- package/dist/internal/yaml.d.ts.map +1 -0
- package/dist/internal/yaml.js +20 -0
- package/dist/internal/yaml.js.map +1 -0
- package/dist/middleware.d.ts +8 -4
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +1 -1
- package/dist/middleware.js.map +1 -1
- package/package.json +1 -1
- package/src/Cli.test-d.ts +71 -0
- package/src/Cli.test.ts +1164 -65
- package/src/Cli.ts +456 -101
- package/src/Completions.test.ts +84 -0
- package/src/Completions.ts +48 -9
- package/src/Formatter.test.ts +17 -0
- package/src/Formatter.ts +7 -5
- package/src/Help.test.ts +31 -0
- package/src/Help.ts +42 -4
- package/src/Mcp.test.ts +193 -0
- package/src/Mcp.ts +49 -8
- package/src/Parser.test.ts +173 -0
- package/src/Parser.ts +132 -1
- package/src/Skill.test.ts +6 -0
- package/src/Skill.ts +8 -5
- package/src/Skillgen.test.ts +55 -6
- package/src/Skillgen.ts +9 -35
- package/src/SyncMcp.test.ts +89 -0
- package/src/SyncMcp.ts +72 -8
- package/src/SyncSkills.test.ts +78 -1
- package/src/SyncSkills.ts +20 -78
- package/src/bun-compile.test.ts +5 -0
- package/src/e2e.test.ts +162 -8
- package/src/internal/command.ts +8 -4
- package/src/internal/cta.ts +58 -0
- package/src/internal/json.ts +16 -0
- package/src/internal/yaml.ts +23 -0
- package/src/lazy-imports.test.ts +94 -0
- package/src/middleware.ts +12 -3
package/src/Cli.ts
CHANGED
|
@@ -2,7 +2,6 @@ import * as fs from 'node:fs/promises'
|
|
|
2
2
|
import * as os from 'node:os'
|
|
3
3
|
import * as path from 'node:path'
|
|
4
4
|
import { estimateTokenCount, sliceByTokens } from 'tokenx'
|
|
5
|
-
import { parse as yamlParse, stringify as yamlStringify } from 'yaml'
|
|
6
5
|
import { z } from 'zod'
|
|
7
6
|
|
|
8
7
|
import * as Completions from './Completions.js'
|
|
@@ -21,9 +20,12 @@ import {
|
|
|
21
20
|
shells,
|
|
22
21
|
} from './internal/command.js'
|
|
23
22
|
import * as Command from './internal/command.js'
|
|
23
|
+
import { formatCtaBlock, type FormattedCta, type FormattedCtaBlock } from './internal/cta.js'
|
|
24
24
|
import { isRecord, suggest, toKebab } from './internal/helpers.js'
|
|
25
|
+
import * as Json from './internal/json.js'
|
|
25
26
|
import { detectRunner } from './internal/pm.js'
|
|
26
27
|
import type { OneOf } from './internal/types.js'
|
|
28
|
+
import * as Yaml from './internal/yaml.js'
|
|
27
29
|
import * as Mcp from './Mcp.js'
|
|
28
30
|
import type { Context as MiddlewareContext, Handler as MiddlewareHandler } from './middleware.js'
|
|
29
31
|
import * as Openapi from './Openapi.js'
|
|
@@ -35,11 +37,14 @@ import * as Skill from './Skill.js'
|
|
|
35
37
|
import * as SyncMcp from './SyncMcp.js'
|
|
36
38
|
import * as SyncSkills from './SyncSkills.js'
|
|
37
39
|
|
|
40
|
+
const destructiveCommandHint = 'Confirm with the user before executing this destructive command.'
|
|
41
|
+
|
|
38
42
|
/** A CLI application instance. Also used as a command group when mounted on a parent CLI. */
|
|
39
43
|
export type Cli<
|
|
40
44
|
commands extends CommandsMap = {},
|
|
41
45
|
vars extends z.ZodObject<any> | undefined = undefined,
|
|
42
46
|
env extends z.ZodObject<any> | undefined = undefined,
|
|
47
|
+
globals extends z.ZodObject<any> | undefined = undefined,
|
|
43
48
|
> = {
|
|
44
49
|
/** Registers a root command or mounts a sub-CLI as a command group. */
|
|
45
50
|
command: {
|
|
@@ -56,12 +61,18 @@ export type Cli<
|
|
|
56
61
|
): Cli<
|
|
57
62
|
commands & { [key in name]: { args: InferOutput<args>; options: InferOutput<options> } },
|
|
58
63
|
vars,
|
|
59
|
-
env
|
|
64
|
+
env,
|
|
65
|
+
globals
|
|
60
66
|
>
|
|
61
67
|
/** Mounts a sub-CLI as a command group. */
|
|
62
68
|
<const name extends string, const sub extends CommandsMap>(
|
|
63
|
-
cli: Cli<sub, any, any> & { name: name },
|
|
64
|
-
): Cli<
|
|
69
|
+
cli: Cli<sub, any, any, any> & { name: name },
|
|
70
|
+
): Cli<
|
|
71
|
+
commands & { [key in keyof sub & string as `${name} ${key}`]: sub[key] },
|
|
72
|
+
vars,
|
|
73
|
+
env,
|
|
74
|
+
globals
|
|
75
|
+
>
|
|
65
76
|
/** Mounts a root CLI as a single command. */
|
|
66
77
|
<
|
|
67
78
|
const name extends string,
|
|
@@ -72,7 +83,8 @@ export type Cli<
|
|
|
72
83
|
): Cli<
|
|
73
84
|
commands & { [key in name]: { args: InferOutput<args>; options: InferOutput<opts> } },
|
|
74
85
|
vars,
|
|
75
|
-
env
|
|
86
|
+
env,
|
|
87
|
+
globals
|
|
76
88
|
>
|
|
77
89
|
/** Mounts a fetch handler as a command, optionally with OpenAPI spec for typed subcommands. */
|
|
78
90
|
<const name extends string>(
|
|
@@ -85,7 +97,7 @@ export type Cli<
|
|
|
85
97
|
openapiConfig?: Openapi.Config | undefined
|
|
86
98
|
outputPolicy?: OutputPolicy | undefined
|
|
87
99
|
},
|
|
88
|
-
): Cli<commands, vars, env>
|
|
100
|
+
): Cli<commands, vars, env, globals>
|
|
89
101
|
}
|
|
90
102
|
/** A short description of the CLI. */
|
|
91
103
|
description?: string | undefined
|
|
@@ -98,7 +110,7 @@ export type Cli<
|
|
|
98
110
|
/** Parses argv, runs the matched command, and writes the output envelope to stdout. */
|
|
99
111
|
serve(argv?: string[], options?: serve.Options): Promise<void>
|
|
100
112
|
/** Registers middleware that runs around every command. */
|
|
101
|
-
use(handler: MiddlewareHandler<vars, env>): Cli<commands, vars, env>
|
|
113
|
+
use(handler: MiddlewareHandler<vars, env, globals>): Cli<commands, vars, env, globals>
|
|
102
114
|
/** The vars schema, if declared. Use `typeof cli.vars` with `middleware<vars, env>()` for typed middleware. */
|
|
103
115
|
vars: vars
|
|
104
116
|
}
|
|
@@ -163,10 +175,16 @@ export function create<
|
|
|
163
175
|
const opts extends z.ZodObject<any> | undefined = undefined,
|
|
164
176
|
const output extends z.ZodType | undefined = undefined,
|
|
165
177
|
const vars extends z.ZodObject<any> | undefined = undefined,
|
|
178
|
+
const globals extends z.ZodObject<any> | undefined = undefined,
|
|
166
179
|
>(
|
|
167
180
|
name: string,
|
|
168
|
-
definition: create.Options<args, env, opts, output, vars> & { run: Function },
|
|
169
|
-
): Cli<
|
|
181
|
+
definition: create.Options<args, env, opts, output, vars, globals> & { run: Function },
|
|
182
|
+
): Cli<
|
|
183
|
+
{ [key in typeof name]: { args: InferOutput<args>; options: InferOutput<opts> } },
|
|
184
|
+
vars,
|
|
185
|
+
env,
|
|
186
|
+
globals
|
|
187
|
+
>
|
|
170
188
|
/** Creates a router CLI that registers subcommands. */
|
|
171
189
|
export function create<
|
|
172
190
|
const args extends z.ZodObject<any> | undefined = undefined,
|
|
@@ -174,7 +192,11 @@ export function create<
|
|
|
174
192
|
const opts extends z.ZodObject<any> | undefined = undefined,
|
|
175
193
|
const output extends z.ZodType | undefined = undefined,
|
|
176
194
|
const vars extends z.ZodObject<any> | undefined = undefined,
|
|
177
|
-
|
|
195
|
+
const globals extends z.ZodObject<any> | undefined = undefined,
|
|
196
|
+
>(
|
|
197
|
+
name: string,
|
|
198
|
+
definition?: create.Options<args, env, opts, output, vars, globals>,
|
|
199
|
+
): Cli<{}, vars, env, globals>
|
|
178
200
|
/** Creates a CLI with a root handler from a single options object. Can still register subcommands. */
|
|
179
201
|
export function create<
|
|
180
202
|
const args extends z.ZodObject<any> | undefined = undefined,
|
|
@@ -182,14 +204,19 @@ export function create<
|
|
|
182
204
|
const opts extends z.ZodObject<any> | undefined = undefined,
|
|
183
205
|
const output extends z.ZodType | undefined = undefined,
|
|
184
206
|
const vars extends z.ZodObject<any> | undefined = undefined,
|
|
207
|
+
const globals extends z.ZodObject<any> | undefined = undefined,
|
|
185
208
|
>(
|
|
186
|
-
definition: create.Options<args, env, opts, output, vars> & {
|
|
209
|
+
definition: create.Options<args, env, opts, output, vars, globals> & {
|
|
210
|
+
name: string
|
|
211
|
+
run: Function
|
|
212
|
+
},
|
|
187
213
|
): Cli<
|
|
188
214
|
{
|
|
189
215
|
[key in (typeof definition)['name']]: { args: InferOutput<args>; options: InferOutput<opts> }
|
|
190
216
|
},
|
|
191
217
|
vars,
|
|
192
|
-
env
|
|
218
|
+
env,
|
|
219
|
+
globals
|
|
193
220
|
>
|
|
194
221
|
/** Creates a router CLI from a single options object (e.g. package.json). */
|
|
195
222
|
export function create<
|
|
@@ -198,7 +225,10 @@ export function create<
|
|
|
198
225
|
const opts extends z.ZodObject<any> | undefined = undefined,
|
|
199
226
|
const output extends z.ZodType | undefined = undefined,
|
|
200
227
|
const vars extends z.ZodObject<any> | undefined = undefined,
|
|
201
|
-
|
|
228
|
+
const globals extends z.ZodObject<any> | undefined = undefined,
|
|
229
|
+
>(
|
|
230
|
+
definition: create.Options<args, env, opts, output, vars, globals> & { name: string },
|
|
231
|
+
): Cli<{}, vars, env, globals>
|
|
202
232
|
export function create(
|
|
203
233
|
nameOrDefinition: string | (any & { name: string }),
|
|
204
234
|
definition?: any,
|
|
@@ -214,7 +244,9 @@ export function create(
|
|
|
214
244
|
const commands = new Map<string, CommandEntry>()
|
|
215
245
|
const middlewares: MiddlewareHandler[] = []
|
|
216
246
|
const pending: Promise<void>[] = []
|
|
217
|
-
const mcpHandler = createMcpHttpHandler(name, def.version ?? '0.0.0'
|
|
247
|
+
const mcpHandler = createMcpHttpHandler(name, def.version ?? '0.0.0', {
|
|
248
|
+
stateless: def.mcp?.stateless,
|
|
249
|
+
})
|
|
218
250
|
|
|
219
251
|
if (def.openapi && rootFetch) {
|
|
220
252
|
pending.push(
|
|
@@ -249,12 +281,14 @@ export function create(
|
|
|
249
281
|
basePath: def.basePath,
|
|
250
282
|
config: def.openapiConfig,
|
|
251
283
|
})
|
|
252
|
-
|
|
284
|
+
const entry = {
|
|
253
285
|
_group: true,
|
|
254
286
|
description: def.description,
|
|
255
287
|
commands: generated as Map<string, CommandEntry>,
|
|
256
288
|
...(def.outputPolicy ? { outputPolicy: def.outputPolicy } : undefined),
|
|
257
|
-
} as InternalGroup
|
|
289
|
+
} as InternalGroup
|
|
290
|
+
assertNoGlobalOptionConflicts(nameOrCli, entry, toGlobals.get(cli))
|
|
291
|
+
commands.set(nameOrCli, entry)
|
|
258
292
|
})(),
|
|
259
293
|
)
|
|
260
294
|
return cli
|
|
@@ -268,6 +302,7 @@ export function create(
|
|
|
268
302
|
} as InternalFetchGateway)
|
|
269
303
|
return cli
|
|
270
304
|
}
|
|
305
|
+
assertNoGlobalOptionConflicts(nameOrCli, def, toGlobals.get(cli))
|
|
271
306
|
commands.set(nameOrCli, def)
|
|
272
307
|
if (def.aliases)
|
|
273
308
|
for (const a of def.aliases) commands.set(a, { _alias: true, target: nameOrCli })
|
|
@@ -275,6 +310,7 @@ export function create(
|
|
|
275
310
|
}
|
|
276
311
|
const mountedRootDef = toRootDefinition.get(nameOrCli)
|
|
277
312
|
if (mountedRootDef) {
|
|
313
|
+
assertNoGlobalOptionConflicts(nameOrCli.name, mountedRootDef, toGlobals.get(cli))
|
|
278
314
|
commands.set(nameOrCli.name, mountedRootDef)
|
|
279
315
|
const rootAliases = toRootAliases.get(nameOrCli)
|
|
280
316
|
if (rootAliases)
|
|
@@ -285,21 +321,25 @@ export function create(
|
|
|
285
321
|
const subCommands = toCommands.get(sub)!
|
|
286
322
|
const subOutputPolicy = toOutputPolicy.get(sub)
|
|
287
323
|
const subMiddlewares = toMiddlewares.get(sub)
|
|
288
|
-
|
|
324
|
+
const entry = {
|
|
289
325
|
_group: true,
|
|
290
326
|
description: sub.description,
|
|
291
327
|
commands: subCommands,
|
|
292
328
|
...(subOutputPolicy ? { outputPolicy: subOutputPolicy } : undefined),
|
|
293
329
|
...(subMiddlewares?.length ? { middlewares: subMiddlewares } : undefined),
|
|
294
|
-
}
|
|
330
|
+
} as InternalGroup
|
|
331
|
+
assertNoGlobalOptionConflicts(sub.name, entry, toGlobals.get(cli))
|
|
332
|
+
commands.set(sub.name, entry)
|
|
295
333
|
return cli
|
|
296
334
|
},
|
|
297
335
|
|
|
298
336
|
async fetch(req: Request) {
|
|
299
337
|
if (pending.length > 0) await Promise.all(pending)
|
|
338
|
+
const globalsDesc = toGlobals.get(cli)
|
|
300
339
|
return fetchImpl(name, commands, req, {
|
|
301
340
|
description: def.description,
|
|
302
341
|
envSchema: def.env,
|
|
342
|
+
globals: globalsDesc,
|
|
303
343
|
mcpHandler,
|
|
304
344
|
middlewares,
|
|
305
345
|
name,
|
|
@@ -311,13 +351,16 @@ export function create(
|
|
|
311
351
|
|
|
312
352
|
async serve(argv = process.argv.slice(2), serveOptions: serve.Options = {}) {
|
|
313
353
|
if (pending.length > 0) await Promise.all(pending)
|
|
354
|
+
const globalsDesc = toGlobals.get(cli)
|
|
314
355
|
return serveImpl(name, commands, argv, {
|
|
315
356
|
...serveOptions,
|
|
316
357
|
aliases: def.aliases,
|
|
358
|
+
banner: def.banner,
|
|
317
359
|
config: def.config,
|
|
318
360
|
description: def.description,
|
|
319
361
|
envSchema: def.env,
|
|
320
362
|
format: def.format,
|
|
363
|
+
globals: globalsDesc,
|
|
321
364
|
mcp: def.mcp,
|
|
322
365
|
middlewares,
|
|
323
366
|
outputPolicy: def.outputPolicy,
|
|
@@ -340,6 +383,44 @@ export function create(
|
|
|
340
383
|
if (def.options) toRootOptions.set(cli, def.options)
|
|
341
384
|
if (def.config !== undefined) toConfigEnabled.set(cli, true)
|
|
342
385
|
if (def.outputPolicy) toOutputPolicy.set(cli, def.outputPolicy)
|
|
386
|
+
if (def.globals) {
|
|
387
|
+
toGlobals.set(cli, { schema: def.globals, alias: def.globalAlias as any })
|
|
388
|
+
const builtinNames = [
|
|
389
|
+
'verbose',
|
|
390
|
+
'format',
|
|
391
|
+
'json',
|
|
392
|
+
'llms',
|
|
393
|
+
'llmsFull',
|
|
394
|
+
'mcp',
|
|
395
|
+
'help',
|
|
396
|
+
'version',
|
|
397
|
+
'schema',
|
|
398
|
+
'filterOutput',
|
|
399
|
+
'tokenLimit',
|
|
400
|
+
'tokenOffset',
|
|
401
|
+
'tokenCount',
|
|
402
|
+
...(def.config?.flag
|
|
403
|
+
? [def.config.flag, `no${def.config.flag[0].toUpperCase()}${def.config.flag.slice(1)}`]
|
|
404
|
+
: []),
|
|
405
|
+
]
|
|
406
|
+
const globalKeys = Object.keys(def.globals.shape)
|
|
407
|
+
for (const key of globalKeys) {
|
|
408
|
+
if (builtinNames.includes(key))
|
|
409
|
+
throw new Error(
|
|
410
|
+
`Global option '${key}' conflicts with a built-in flag. Choose a different name.`,
|
|
411
|
+
)
|
|
412
|
+
}
|
|
413
|
+
// Check globalAlias values against reserved short aliases
|
|
414
|
+
const reservedShorts = new Set(['h'])
|
|
415
|
+
if (def.globalAlias) {
|
|
416
|
+
for (const [name, short] of Object.entries(def.globalAlias as Record<string, string>)) {
|
|
417
|
+
if (reservedShorts.has(short))
|
|
418
|
+
throw new Error(
|
|
419
|
+
`Global alias '-${short}' for '${name}' conflicts with a built-in short flag. Choose a different alias.`,
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
343
424
|
toMiddlewares.set(cli, middlewares)
|
|
344
425
|
toCommands.set(cli, commands)
|
|
345
426
|
return cli
|
|
@@ -353,6 +434,7 @@ export declare namespace create {
|
|
|
353
434
|
options extends z.ZodObject<any> | undefined = undefined,
|
|
354
435
|
output extends z.ZodType | undefined = undefined,
|
|
355
436
|
vars extends z.ZodObject<any> | undefined = undefined,
|
|
437
|
+
globals extends z.ZodObject<any> | undefined = undefined,
|
|
356
438
|
> = {
|
|
357
439
|
/** Map of option names to single-char aliases. */
|
|
358
440
|
alias?: options extends z.ZodObject<any>
|
|
@@ -360,6 +442,19 @@ export declare namespace create {
|
|
|
360
442
|
: Record<string, string> | undefined
|
|
361
443
|
/** Alternative binary names for this CLI (e.g. shorter aliases in package.json `bin`). Shell completions are registered for all names. */
|
|
362
444
|
aliases?: string[] | undefined
|
|
445
|
+
/**
|
|
446
|
+
* Text to display above root help output (e.g. branding, live status). Only called when the CLI is invoked with no subcommand. Errors are silently swallowed.
|
|
447
|
+
*
|
|
448
|
+
* Pass a function for all consumers, or an object with `mode` to target `'human'`, `'agent'`, or `'all'` (default).
|
|
449
|
+
*/
|
|
450
|
+
banner?:
|
|
451
|
+
| (() => string | undefined | Promise<string | undefined>)
|
|
452
|
+
| {
|
|
453
|
+
render: () => string | undefined | Promise<string | undefined>
|
|
454
|
+
/** @default 'all' */
|
|
455
|
+
mode?: 'all' | 'human' | 'agent' | undefined
|
|
456
|
+
}
|
|
457
|
+
| undefined
|
|
363
458
|
/** Zod schema for positional arguments. */
|
|
364
459
|
args?: args | undefined
|
|
365
460
|
/** Enable config-file defaults for command options. */
|
|
@@ -382,6 +477,8 @@ export declare namespace create {
|
|
|
382
477
|
| undefined
|
|
383
478
|
/** A short description of what the CLI does. */
|
|
384
479
|
description?: string | undefined
|
|
480
|
+
/** Marks the root command as destructive when generating agent skills. */
|
|
481
|
+
destructive?: boolean | undefined
|
|
385
482
|
/** Zod schema for environment variables. Keys are the variable names (e.g. `NPM_TOKEN`). */
|
|
386
483
|
env?: env | undefined
|
|
387
484
|
/** Usage examples for this command. */
|
|
@@ -394,6 +491,14 @@ export declare namespace create {
|
|
|
394
491
|
openapiConfig?: Openapi.Config | undefined
|
|
395
492
|
/** Default output format. Overridden by `--format` or `--json`. */
|
|
396
493
|
format?: Formatter.Format | undefined
|
|
494
|
+
/** Plain text hint displayed after examples and before global options. */
|
|
495
|
+
hint?: string | undefined
|
|
496
|
+
/** Map of global option names to single-char aliases. */
|
|
497
|
+
globalAlias?: globals extends z.ZodObject<any>
|
|
498
|
+
? Partial<Record<keyof z.output<globals>, string>>
|
|
499
|
+
: Record<string, string> | undefined
|
|
500
|
+
/** Zod schema for global options available to all commands. Parsed before command resolution and passed to middleware and command handlers. */
|
|
501
|
+
globals?: globals | undefined
|
|
397
502
|
/** Zod schema for named options/flags. */
|
|
398
503
|
options?: options | undefined
|
|
399
504
|
/** Zod schema for the return value. */
|
|
@@ -446,13 +551,17 @@ export declare namespace create {
|
|
|
446
551
|
| Promise<InferReturn<output>>
|
|
447
552
|
| AsyncGenerator<InferReturn<output>, unknown, unknown>)
|
|
448
553
|
| undefined
|
|
449
|
-
/** Options for
|
|
554
|
+
/** Options for MCP integration. */
|
|
450
555
|
mcp?:
|
|
451
556
|
| {
|
|
452
557
|
/** Target specific agents by default (e.g. `['claude-code', 'cursor']`). */
|
|
453
558
|
agents?: string[] | undefined
|
|
454
559
|
/** Override the command agents will run to start the MCP server. Auto-detected if omitted. */
|
|
455
560
|
command?: string | undefined
|
|
561
|
+
/** Instructions describing how to use the server and its features. */
|
|
562
|
+
instructions?: string | undefined
|
|
563
|
+
/** Disable HTTP MCP session management. Defaults to `true`. */
|
|
564
|
+
stateless?: boolean | undefined
|
|
456
565
|
}
|
|
457
566
|
| undefined
|
|
458
567
|
/** Options for the built-in `skills add` command. */
|
|
@@ -504,6 +613,20 @@ async function serveImpl(
|
|
|
504
613
|
stdout(s.endsWith('\n') ? s : `${s}\n`)
|
|
505
614
|
}
|
|
506
615
|
|
|
616
|
+
async function writeBanner() {
|
|
617
|
+
if (!options.banner || help) return
|
|
618
|
+
const banner =
|
|
619
|
+
typeof options.banner === 'function'
|
|
620
|
+
? { render: options.banner, mode: 'all' as const }
|
|
621
|
+
: options.banner
|
|
622
|
+
const mode = banner.mode ?? 'all'
|
|
623
|
+
if (mode !== 'all' && mode !== (human ? 'human' : 'agent')) return
|
|
624
|
+
try {
|
|
625
|
+
const text = await banner.render()
|
|
626
|
+
if (text) writeln(text)
|
|
627
|
+
} catch {}
|
|
628
|
+
}
|
|
629
|
+
|
|
507
630
|
let builtinFlags: ReturnType<typeof extractBuiltinFlags>
|
|
508
631
|
try {
|
|
509
632
|
builtinFlags = extractBuiltinFlags(argv, { configFlag })
|
|
@@ -531,9 +654,35 @@ async function serveImpl(
|
|
|
531
654
|
schema,
|
|
532
655
|
configPath,
|
|
533
656
|
configDisabled,
|
|
534
|
-
rest
|
|
657
|
+
rest,
|
|
535
658
|
} = builtinFlags
|
|
536
659
|
|
|
660
|
+
let globals: Record<string, unknown> = {}
|
|
661
|
+
let filtered = rest
|
|
662
|
+
|
|
663
|
+
function parseGlobalOptions(validate: boolean) {
|
|
664
|
+
if (!options.globals) return true
|
|
665
|
+
try {
|
|
666
|
+
const result = Parser.parseGlobals(rest, options.globals.schema, options.globals.alias, {
|
|
667
|
+
validate,
|
|
668
|
+
})
|
|
669
|
+
if (validate) globals = result.parsed
|
|
670
|
+
filtered = result.rest
|
|
671
|
+
return true
|
|
672
|
+
} catch (error) {
|
|
673
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
674
|
+
if (human) writeln(formatHumanError({ code: 'UNKNOWN', message }))
|
|
675
|
+
else writeln(Formatter.format({ code: 'UNKNOWN', message }, 'toon'))
|
|
676
|
+
exit(1)
|
|
677
|
+
return false
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
if (!parseGlobalOptions(false)) return
|
|
682
|
+
|
|
683
|
+
// Pre-load yaml for the sync formatting paths below (yaml is loaded lazily -- see internal/yaml.ts).
|
|
684
|
+
if (formatFlag === 'yaml') await Yaml.load()
|
|
685
|
+
|
|
537
686
|
// --mcp: start as MCP stdio server
|
|
538
687
|
if (mcpFlag) {
|
|
539
688
|
await Mcp.serve(name, options.version ?? '0.0.0', commands, {
|
|
@@ -541,6 +690,7 @@ async function serveImpl(
|
|
|
541
690
|
env: options.envSchema,
|
|
542
691
|
vars: options.vars,
|
|
543
692
|
version: options.version,
|
|
693
|
+
...(options.mcp?.instructions ? { instructions: options.mcp.instructions } : undefined),
|
|
544
694
|
})
|
|
545
695
|
return
|
|
546
696
|
}
|
|
@@ -557,7 +707,15 @@ async function serveImpl(
|
|
|
557
707
|
stdout(names.map((n) => Completions.register(completeShell, n)).join('\n'))
|
|
558
708
|
} else {
|
|
559
709
|
const index = Number(process.env._COMPLETE_INDEX ?? words.length - 1)
|
|
560
|
-
const candidates = Completions.complete(
|
|
710
|
+
const candidates = Completions.complete(
|
|
711
|
+
commands,
|
|
712
|
+
options.rootCommand,
|
|
713
|
+
words,
|
|
714
|
+
index,
|
|
715
|
+
options.globals
|
|
716
|
+
? { schema: options.globals.schema, alias: options.globals.alias }
|
|
717
|
+
: undefined,
|
|
718
|
+
)
|
|
561
719
|
// Add built-in commands (completions, mcp, skills) to completions
|
|
562
720
|
const current = words[index] ?? ''
|
|
563
721
|
const nonFlags = words.slice(0, index).filter((w) => !w.startsWith('-'))
|
|
@@ -630,27 +788,41 @@ async function serveImpl(
|
|
|
630
788
|
}
|
|
631
789
|
|
|
632
790
|
const scopedRoot = prefix.length === 0 ? options.rootCommand : undefined
|
|
791
|
+
// Markdown skill output renders scopedName separately. Passing prefix again
|
|
792
|
+
// to those collect helpers would double the group segment in command names
|
|
793
|
+
// (e.g. "cli auth auth login" instead of "cli auth login").
|
|
794
|
+
const collectPrefix = prefix.length > 0 ? ([] as string[]) : prefix
|
|
633
795
|
|
|
634
796
|
if (llmsFull) {
|
|
635
797
|
if (!formatExplicit || formatFlag === 'md') {
|
|
636
798
|
const groups = new Map<string, string>()
|
|
637
|
-
const cmds = collectSkillCommands(scopedCommands,
|
|
799
|
+
const cmds = collectSkillCommands(scopedCommands, collectPrefix, groups, scopedRoot)
|
|
638
800
|
const scopedName = prefix.length > 0 ? `${name} ${prefix.join(' ')}` : name
|
|
639
801
|
writeln(Skill.generate(scopedName, cmds, groups))
|
|
640
802
|
return
|
|
641
803
|
}
|
|
642
|
-
writeln(
|
|
804
|
+
writeln(
|
|
805
|
+
Formatter.format(
|
|
806
|
+
buildManifest(scopedCommands, prefix, options.globals?.schema),
|
|
807
|
+
formatFlag,
|
|
808
|
+
),
|
|
809
|
+
)
|
|
643
810
|
return
|
|
644
811
|
}
|
|
645
812
|
|
|
646
813
|
if (!formatExplicit || formatFlag === 'md') {
|
|
647
814
|
const groups = new Map<string, string>()
|
|
648
|
-
const cmds = collectSkillCommands(scopedCommands,
|
|
815
|
+
const cmds = collectSkillCommands(scopedCommands, collectPrefix, groups, scopedRoot)
|
|
649
816
|
const scopedName = prefix.length > 0 ? `${name} ${prefix.join(' ')}` : name
|
|
650
817
|
writeln(Skill.index(scopedName, cmds, scopedDescription))
|
|
651
818
|
return
|
|
652
819
|
}
|
|
653
|
-
writeln(
|
|
820
|
+
writeln(
|
|
821
|
+
Formatter.format(
|
|
822
|
+
buildIndexManifest(scopedCommands, prefix, options.globals?.schema),
|
|
823
|
+
formatFlag,
|
|
824
|
+
),
|
|
825
|
+
)
|
|
654
826
|
return
|
|
655
827
|
}
|
|
656
828
|
|
|
@@ -930,12 +1102,14 @@ async function serveImpl(
|
|
|
930
1102
|
) {
|
|
931
1103
|
// Root command with args but none provided (human mode) — show help
|
|
932
1104
|
const cmd = options.rootCommand
|
|
1105
|
+
await writeBanner()
|
|
933
1106
|
writeln(
|
|
934
1107
|
Help.formatCommand(name, {
|
|
935
1108
|
alias: cmd.alias as Record<string, string> | undefined,
|
|
936
1109
|
aliases: options.aliases,
|
|
937
1110
|
configFlag,
|
|
938
1111
|
description: cmd.description ?? options.description,
|
|
1112
|
+
globals: options.globals,
|
|
939
1113
|
version: options.version,
|
|
940
1114
|
args: cmd.args,
|
|
941
1115
|
env: cmd.env,
|
|
@@ -953,11 +1127,13 @@ async function serveImpl(
|
|
|
953
1127
|
if (options.rootCommand || options.rootFetch) {
|
|
954
1128
|
// Root command/fetch with no args — treat as root invocation
|
|
955
1129
|
} else {
|
|
1130
|
+
await writeBanner()
|
|
956
1131
|
writeln(
|
|
957
1132
|
Help.formatRoot(name, {
|
|
958
1133
|
aliases: options.aliases,
|
|
959
1134
|
configFlag,
|
|
960
1135
|
description: options.description,
|
|
1136
|
+
globals: options.globals,
|
|
961
1137
|
version: options.version,
|
|
962
1138
|
commands: collectHelpCommands(commands),
|
|
963
1139
|
root: true,
|
|
@@ -1018,6 +1194,7 @@ async function serveImpl(
|
|
|
1018
1194
|
aliases: options.aliases,
|
|
1019
1195
|
configFlag,
|
|
1020
1196
|
description: cmd.description ?? options.description,
|
|
1197
|
+
globals: options.globals,
|
|
1021
1198
|
version: options.version,
|
|
1022
1199
|
args: cmd.args,
|
|
1023
1200
|
env: cmd.env,
|
|
@@ -1036,6 +1213,7 @@ async function serveImpl(
|
|
|
1036
1213
|
aliases: isRoot ? options.aliases : undefined,
|
|
1037
1214
|
configFlag,
|
|
1038
1215
|
description: helpDesc,
|
|
1216
|
+
globals: options.globals,
|
|
1039
1217
|
version: isRoot ? options.version : undefined,
|
|
1040
1218
|
commands: collectHelpCommands(helpCmds),
|
|
1041
1219
|
root: isRoot,
|
|
@@ -1056,6 +1234,7 @@ async function serveImpl(
|
|
|
1056
1234
|
aliases: isRootCmd ? options.aliases : cmd.aliases,
|
|
1057
1235
|
configFlag,
|
|
1058
1236
|
description: cmd.description,
|
|
1237
|
+
globals: options.globals,
|
|
1059
1238
|
version: isRootCmd ? options.version : undefined,
|
|
1060
1239
|
args: cmd.args,
|
|
1061
1240
|
env: cmd.env,
|
|
@@ -1079,6 +1258,7 @@ async function serveImpl(
|
|
|
1079
1258
|
Help.formatRoot(`${name} ${resolved.path}`, {
|
|
1080
1259
|
configFlag,
|
|
1081
1260
|
description: resolved.description,
|
|
1261
|
+
globals: options.globals,
|
|
1082
1262
|
commands: collectHelpCommands(resolved.commands),
|
|
1083
1263
|
}),
|
|
1084
1264
|
)
|
|
@@ -1104,6 +1284,7 @@ async function serveImpl(
|
|
|
1104
1284
|
if (cmd.env) result.env = Schema.toJsonSchema(cmd.env)
|
|
1105
1285
|
if (cmd.options) result.options = Schema.toJsonSchema(cmd.options)
|
|
1106
1286
|
if (cmd.output) result.output = Schema.toJsonSchema(cmd.output)
|
|
1287
|
+
if (options.globals?.schema) result.globals = Schema.toJsonSchema(options.globals.schema)
|
|
1107
1288
|
writeln(Formatter.format(result, format))
|
|
1108
1289
|
return
|
|
1109
1290
|
}
|
|
@@ -1113,6 +1294,7 @@ async function serveImpl(
|
|
|
1113
1294
|
Help.formatRoot(`${name} ${resolved.path}`, {
|
|
1114
1295
|
configFlag,
|
|
1115
1296
|
description: resolved.description,
|
|
1297
|
+
globals: options.globals,
|
|
1116
1298
|
commands: collectHelpCommands(resolved.commands),
|
|
1117
1299
|
}),
|
|
1118
1300
|
)
|
|
@@ -1124,6 +1306,7 @@ async function serveImpl(
|
|
|
1124
1306
|
// Resolve effective format: explicit --format/--json → command default → CLI default → toon
|
|
1125
1307
|
const resolvedFormat = 'command' in resolved && (resolved as any).command.format
|
|
1126
1308
|
const format = formatExplicit ? formatFlag : resolvedFormat || options.format || 'toon'
|
|
1309
|
+
if (format === 'yaml') await Yaml.load()
|
|
1127
1310
|
|
|
1128
1311
|
// Fall back to root fetch/command when no subcommand matches,
|
|
1129
1312
|
// but only if the token doesn't look like a typo of a known command.
|
|
@@ -1285,6 +1468,7 @@ async function serveImpl(
|
|
|
1285
1468
|
|
|
1286
1469
|
// Fetch gateway execution path
|
|
1287
1470
|
if ('fetchGateway' in effective) {
|
|
1471
|
+
if (!parseGlobalOptions(true)) return
|
|
1288
1472
|
const { fetchGateway, path, rest: fetchRest } = effective
|
|
1289
1473
|
const fetchMiddleware = [
|
|
1290
1474
|
...(options.middlewares ?? []),
|
|
@@ -1370,6 +1554,7 @@ async function serveImpl(
|
|
|
1370
1554
|
error: errorFn,
|
|
1371
1555
|
format,
|
|
1372
1556
|
formatExplicit,
|
|
1557
|
+
globals,
|
|
1373
1558
|
name,
|
|
1374
1559
|
set(key: string, value: unknown) {
|
|
1375
1560
|
varsMap[key] = value
|
|
@@ -1420,7 +1605,9 @@ async function serveImpl(
|
|
|
1420
1605
|
return
|
|
1421
1606
|
}
|
|
1422
1607
|
|
|
1423
|
-
const { command, path, rest } = effective
|
|
1608
|
+
const { command, path, rest: commandRest } = effective
|
|
1609
|
+
|
|
1610
|
+
if (!parseGlobalOptions(true)) return
|
|
1424
1611
|
|
|
1425
1612
|
// Collect middleware: root CLI + groups traversed + per-command
|
|
1426
1613
|
const allMiddleware = [
|
|
@@ -1433,7 +1620,7 @@ async function serveImpl(
|
|
|
1433
1620
|
|
|
1434
1621
|
if (human)
|
|
1435
1622
|
emitDeprecationWarnings(
|
|
1436
|
-
|
|
1623
|
+
commandRest,
|
|
1437
1624
|
command.options,
|
|
1438
1625
|
command.alias as Record<string, string> | undefined,
|
|
1439
1626
|
)
|
|
@@ -1463,13 +1650,14 @@ async function serveImpl(
|
|
|
1463
1650
|
|
|
1464
1651
|
const result = await Command.execute(command, {
|
|
1465
1652
|
agent: !human,
|
|
1466
|
-
argv:
|
|
1653
|
+
argv: commandRest,
|
|
1467
1654
|
defaults,
|
|
1468
1655
|
displayName,
|
|
1469
1656
|
env: options.envSchema,
|
|
1470
1657
|
envSource: options.env,
|
|
1471
1658
|
format,
|
|
1472
1659
|
formatExplicit,
|
|
1660
|
+
globals,
|
|
1473
1661
|
inputOptions: {},
|
|
1474
1662
|
middlewares: allMiddleware,
|
|
1475
1663
|
name,
|
|
@@ -1558,6 +1746,8 @@ declare namespace fetchImpl {
|
|
|
1558
1746
|
description?: string | undefined
|
|
1559
1747
|
/** CLI-level env schema. */
|
|
1560
1748
|
envSchema?: z.ZodObject<any> | undefined
|
|
1749
|
+
/** Global options schema and alias map. */
|
|
1750
|
+
globals?: GlobalsDescriptor | undefined
|
|
1561
1751
|
/** Group-level middleware collected during command resolution. */
|
|
1562
1752
|
groupMiddlewares?: MiddlewareHandler[] | undefined
|
|
1563
1753
|
mcpHandler?:
|
|
@@ -1582,7 +1772,11 @@ declare namespace fetchImpl {
|
|
|
1582
1772
|
}
|
|
1583
1773
|
|
|
1584
1774
|
/** @internal Creates a lazy MCP HTTP handler scoped to a CLI instance. */
|
|
1585
|
-
function createMcpHttpHandler(
|
|
1775
|
+
function createMcpHttpHandler(
|
|
1776
|
+
name: string,
|
|
1777
|
+
version: string,
|
|
1778
|
+
options: createMcpHttpHandler.Options = {},
|
|
1779
|
+
) {
|
|
1586
1780
|
let transport: any
|
|
1587
1781
|
|
|
1588
1782
|
return async (
|
|
@@ -1594,8 +1788,12 @@ function createMcpHttpHandler(name: string, version: string) {
|
|
|
1594
1788
|
vars?: z.ZodObject<any> | undefined
|
|
1595
1789
|
},
|
|
1596
1790
|
): Promise<Response> => {
|
|
1791
|
+
const stateless = options.stateless ?? true
|
|
1792
|
+
if (stateless && req.method !== 'POST')
|
|
1793
|
+
return new Response(null, { status: 405, headers: { Allow: 'POST' } })
|
|
1794
|
+
|
|
1597
1795
|
if (!transport) {
|
|
1598
|
-
const { McpServer, WebStandardStreamableHTTPServerTransport } =
|
|
1796
|
+
const { fromJsonSchema, McpServer, WebStandardStreamableHTTPServerTransport } =
|
|
1599
1797
|
await import('@modelcontextprotocol/server')
|
|
1600
1798
|
|
|
1601
1799
|
const server = new McpServer({ name, version })
|
|
@@ -1612,6 +1810,9 @@ function createMcpHttpHandler(name: string, version: string) {
|
|
|
1612
1810
|
{
|
|
1613
1811
|
...(tool.description ? { description: tool.description } : undefined),
|
|
1614
1812
|
...(hasInput ? { inputSchema: z.object(mergedShape) } : undefined),
|
|
1813
|
+
...(tool.outputSchema
|
|
1814
|
+
? { outputSchema: fromJsonSchema(tool.outputSchema) }
|
|
1815
|
+
: undefined),
|
|
1615
1816
|
},
|
|
1616
1817
|
async (...callArgs: any[]) => {
|
|
1617
1818
|
const params = hasInput ? (callArgs[0] as Record<string, unknown>) : {}
|
|
@@ -1626,16 +1827,26 @@ function createMcpHttpHandler(name: string, version: string) {
|
|
|
1626
1827
|
)
|
|
1627
1828
|
}
|
|
1628
1829
|
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1830
|
+
const transportOptions = stateless
|
|
1831
|
+
? { enableJsonResponse: true }
|
|
1832
|
+
: {
|
|
1833
|
+
sessionIdGenerator: () => crypto.randomUUID(),
|
|
1834
|
+
enableJsonResponse: true,
|
|
1835
|
+
}
|
|
1836
|
+
transport = new WebStandardStreamableHTTPServerTransport(transportOptions)
|
|
1633
1837
|
await server.connect(transport)
|
|
1634
1838
|
}
|
|
1635
1839
|
return transport.handleRequest(req)
|
|
1636
1840
|
}
|
|
1637
1841
|
}
|
|
1638
1842
|
|
|
1843
|
+
declare namespace createMcpHttpHandler {
|
|
1844
|
+
type Options = {
|
|
1845
|
+
/** Disable HTTP MCP session management. Defaults to `true`. */
|
|
1846
|
+
stateless?: boolean | undefined
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1639
1850
|
function isOpenapiRoute(segments: string[]) {
|
|
1640
1851
|
if (segments.length === 1)
|
|
1641
1852
|
return (
|
|
@@ -1677,7 +1888,7 @@ async function fetchImpl(
|
|
|
1677
1888
|
if (req.method === 'GET' && isOpenapiRoute(segments)) {
|
|
1678
1889
|
const spec = generatedOpenapi(name, commands, options)
|
|
1679
1890
|
const yaml = segments[0] === 'openapi.yml' || segments[0] === 'openapi.yaml'
|
|
1680
|
-
return new Response(yaml ?
|
|
1891
|
+
return new Response(yaml ? (await Yaml.load()).stringify(spec) : JSON.stringify(spec), {
|
|
1681
1892
|
status: 200,
|
|
1682
1893
|
headers: {
|
|
1683
1894
|
'content-type': yaml ? 'application/yaml' : 'application/json',
|
|
@@ -1701,6 +1912,8 @@ async function fetchImpl(
|
|
|
1701
1912
|
segments.length >= 3 &&
|
|
1702
1913
|
req.method === 'GET'
|
|
1703
1914
|
) {
|
|
1915
|
+
// Pre-load yaml for the sync call paths below (`Skill.split`, frontmatter parsing).
|
|
1916
|
+
await Yaml.load()
|
|
1704
1917
|
const groups = new Map<string, string>()
|
|
1705
1918
|
const cmds = collectSkillCommands(commands, [], groups, options.rootCommand)
|
|
1706
1919
|
|
|
@@ -1709,7 +1922,7 @@ async function fetchImpl(
|
|
|
1709
1922
|
const files = Skill.split(name, cmds, 1, groups)
|
|
1710
1923
|
const skills = files.map((f) => {
|
|
1711
1924
|
const fmMatch = f.content.match(/^---\n([\s\S]*?)\n---/)
|
|
1712
|
-
const meta = fmMatch ? (
|
|
1925
|
+
const meta = fmMatch ? (Yaml.loadSync().parse(fmMatch[1]!) as Record<string, string>) : {}
|
|
1713
1926
|
return {
|
|
1714
1927
|
name: f.dir || name,
|
|
1715
1928
|
description: meta.description ?? '',
|
|
@@ -1750,7 +1963,7 @@ async function fetchImpl(
|
|
|
1750
1963
|
}
|
|
1751
1964
|
|
|
1752
1965
|
function jsonResponse(body: unknown, status: number) {
|
|
1753
|
-
return new Response(
|
|
1966
|
+
return new Response(Json.stringify(body), {
|
|
1754
1967
|
status,
|
|
1755
1968
|
headers: { 'content-type': 'application/json' },
|
|
1756
1969
|
})
|
|
@@ -1823,7 +2036,7 @@ async function executeCommand(
|
|
|
1823
2036
|
options: fetchImpl.Options,
|
|
1824
2037
|
): Promise<Response> {
|
|
1825
2038
|
function jsonResponse(body: unknown, status: number) {
|
|
1826
|
-
return new Response(
|
|
2039
|
+
return new Response(Json.stringify(body), {
|
|
1827
2040
|
status,
|
|
1828
2041
|
headers: { 'content-type': 'application/json' },
|
|
1829
2042
|
})
|
|
@@ -1835,13 +2048,40 @@ async function executeCommand(
|
|
|
1835
2048
|
...((command.middleware as MiddlewareHandler[] | undefined) ?? []),
|
|
1836
2049
|
]
|
|
1837
2050
|
|
|
2051
|
+
let globals: Record<string, unknown> = {}
|
|
2052
|
+
let commandInputOptions = inputOptions
|
|
2053
|
+
if (options.globals) {
|
|
2054
|
+
const globalKeys = new Set(Object.keys(options.globals.schema.shape))
|
|
2055
|
+
const rawGlobals: Record<string, unknown> = {}
|
|
2056
|
+
commandInputOptions = {}
|
|
2057
|
+
for (const [key, value] of Object.entries(inputOptions)) {
|
|
2058
|
+
if (globalKeys.has(key)) rawGlobals[key] = value
|
|
2059
|
+
else commandInputOptions[key] = value
|
|
2060
|
+
}
|
|
2061
|
+
try {
|
|
2062
|
+
globals = options.globals.schema.parse(rawGlobals)
|
|
2063
|
+
} catch (error: any) {
|
|
2064
|
+
const issues: any[] = error?.issues ?? error?.error?.issues ?? []
|
|
2065
|
+
const message = issues.map((i: any) => i.message).join('; ') || 'Validation failed'
|
|
2066
|
+
return jsonResponse(
|
|
2067
|
+
{
|
|
2068
|
+
ok: false,
|
|
2069
|
+
error: { code: 'VALIDATION_ERROR', message },
|
|
2070
|
+
meta: { command: path, duration: `${Math.round(performance.now() - start)}ms` },
|
|
2071
|
+
},
|
|
2072
|
+
400,
|
|
2073
|
+
)
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
|
|
1838
2077
|
const result = await Command.execute(command, {
|
|
1839
2078
|
agent: true,
|
|
1840
2079
|
argv: rest,
|
|
1841
2080
|
env: options.envSchema,
|
|
1842
2081
|
format: 'json',
|
|
1843
2082
|
formatExplicit: true,
|
|
1844
|
-
|
|
2083
|
+
globals,
|
|
2084
|
+
inputOptions: commandInputOptions,
|
|
1845
2085
|
middlewares: allMiddleware,
|
|
1846
2086
|
name: options.name ?? path,
|
|
1847
2087
|
parseMode: 'split',
|
|
@@ -1854,39 +2094,78 @@ async function executeCommand(
|
|
|
1854
2094
|
|
|
1855
2095
|
// Streaming path — async generator → NDJSON response
|
|
1856
2096
|
if ('stream' in result) {
|
|
2097
|
+
const iterator = result.stream
|
|
2098
|
+
const encoder = new TextEncoder()
|
|
2099
|
+
const meta = (cta?: FormattedCtaBlock | undefined) => ({
|
|
2100
|
+
command: path,
|
|
2101
|
+
duration: `${Math.round(performance.now() - start)}ms`,
|
|
2102
|
+
...(cta ? { cta } : undefined),
|
|
2103
|
+
})
|
|
2104
|
+
const errorRecord = (err: ErrorResult) => ({
|
|
2105
|
+
type: 'error',
|
|
2106
|
+
ok: false,
|
|
2107
|
+
error: {
|
|
2108
|
+
code: err.code,
|
|
2109
|
+
message: err.message,
|
|
2110
|
+
...(err.retryable !== undefined ? { retryable: err.retryable } : undefined),
|
|
2111
|
+
},
|
|
2112
|
+
meta: meta(formatCtaBlock(options.name ?? path, err.cta)),
|
|
2113
|
+
})
|
|
1857
2114
|
const stream = new ReadableStream({
|
|
1858
|
-
async
|
|
1859
|
-
|
|
2115
|
+
async cancel() {
|
|
2116
|
+
await iterator.return(undefined)
|
|
2117
|
+
},
|
|
2118
|
+
async pull(controller) {
|
|
1860
2119
|
try {
|
|
1861
|
-
|
|
2120
|
+
const { value, done } = await iterator.next()
|
|
2121
|
+
if (done) {
|
|
2122
|
+
if (isSentinel(value) && value[sentinel] === 'error') {
|
|
2123
|
+
controller.enqueue(encoder.encode(Json.stringify(errorRecord(value)) + '\n'))
|
|
2124
|
+
controller.close()
|
|
2125
|
+
return
|
|
2126
|
+
}
|
|
2127
|
+
const cta =
|
|
2128
|
+
isSentinel(value) && value[sentinel] === 'ok'
|
|
2129
|
+
? formatCtaBlock(options.name ?? path, value.cta)
|
|
2130
|
+
: undefined
|
|
1862
2131
|
controller.enqueue(
|
|
1863
|
-
encoder.encode(
|
|
2132
|
+
encoder.encode(
|
|
2133
|
+
Json.stringify({
|
|
2134
|
+
type: 'done',
|
|
2135
|
+
ok: true,
|
|
2136
|
+
meta: meta(cta),
|
|
2137
|
+
}) + '\n',
|
|
2138
|
+
),
|
|
1864
2139
|
)
|
|
2140
|
+
controller.close()
|
|
2141
|
+
return
|
|
1865
2142
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
)
|
|
2143
|
+
|
|
2144
|
+
if (isSentinel(value) && value[sentinel] === 'error') {
|
|
2145
|
+
controller.enqueue(encoder.encode(Json.stringify(errorRecord(value)) + '\n'))
|
|
2146
|
+
await iterator.return(undefined)
|
|
2147
|
+
controller.close()
|
|
2148
|
+
return
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
controller.enqueue(encoder.encode(Json.stringify({ type: 'chunk', data: value }) + '\n'))
|
|
1875
2152
|
} catch (error) {
|
|
1876
2153
|
controller.enqueue(
|
|
1877
2154
|
encoder.encode(
|
|
1878
|
-
|
|
2155
|
+
Json.stringify({
|
|
1879
2156
|
type: 'error',
|
|
1880
2157
|
ok: false,
|
|
1881
2158
|
error: {
|
|
1882
|
-
code: 'UNKNOWN',
|
|
2159
|
+
code: error instanceof IncurError ? error.code : 'UNKNOWN',
|
|
1883
2160
|
message: error instanceof Error ? error.message : String(error),
|
|
2161
|
+
...(error instanceof IncurError ? { retryable: error.retryable } : undefined),
|
|
1884
2162
|
},
|
|
2163
|
+
meta: meta(),
|
|
1885
2164
|
}) + '\n',
|
|
1886
2165
|
),
|
|
1887
2166
|
)
|
|
2167
|
+
controller.close()
|
|
1888
2168
|
}
|
|
1889
|
-
controller.close()
|
|
1890
2169
|
},
|
|
1891
2170
|
})
|
|
1892
2171
|
return new Response(stream, {
|
|
@@ -1906,6 +2185,7 @@ async function executeCommand(
|
|
|
1906
2185
|
...(result.error.retryable !== undefined
|
|
1907
2186
|
? { retryable: result.error.retryable }
|
|
1908
2187
|
: undefined),
|
|
2188
|
+
...(result.error.fieldErrors ? { fieldErrors: result.error.fieldErrors } : undefined),
|
|
1909
2189
|
},
|
|
1910
2190
|
meta: {
|
|
1911
2191
|
command: path,
|
|
@@ -2107,6 +2387,8 @@ declare namespace serveImpl {
|
|
|
2107
2387
|
envSchema?: z.ZodObject<any> | undefined
|
|
2108
2388
|
/** CLI-level default output format. */
|
|
2109
2389
|
format?: Formatter.Format | undefined
|
|
2390
|
+
/** Global options schema and alias map. */
|
|
2391
|
+
globals?: GlobalsDescriptor | undefined
|
|
2110
2392
|
/** Middleware handlers registered on the root CLI. */
|
|
2111
2393
|
middlewares?: MiddlewareHandler[] | undefined
|
|
2112
2394
|
/** CLI-level default output policy. */
|
|
@@ -2115,6 +2397,16 @@ declare namespace serveImpl {
|
|
|
2115
2397
|
| {
|
|
2116
2398
|
agents?: string[] | undefined
|
|
2117
2399
|
command?: string | undefined
|
|
2400
|
+
instructions?: string | undefined
|
|
2401
|
+
stateless?: boolean | undefined
|
|
2402
|
+
}
|
|
2403
|
+
| undefined
|
|
2404
|
+
/** Banner config, called before root help. */
|
|
2405
|
+
banner?:
|
|
2406
|
+
| (() => string | undefined | Promise<string | undefined>)
|
|
2407
|
+
| {
|
|
2408
|
+
render: () => string | undefined | Promise<string | undefined>
|
|
2409
|
+
mode?: 'all' | 'human' | 'agent' | undefined
|
|
2118
2410
|
}
|
|
2119
2411
|
| undefined
|
|
2120
2412
|
/** Root command handler, invoked when no subcommand matches. */
|
|
@@ -2528,6 +2820,41 @@ function resolveAlias(
|
|
|
2528
2820
|
return entry
|
|
2529
2821
|
}
|
|
2530
2822
|
|
|
2823
|
+
/** @internal Validates command options against CLI-level global options. */
|
|
2824
|
+
function assertNoGlobalOptionConflicts(
|
|
2825
|
+
path: string,
|
|
2826
|
+
entry: CommandEntry,
|
|
2827
|
+
globals: GlobalsDescriptor | undefined,
|
|
2828
|
+
) {
|
|
2829
|
+
if (!globals || isFetchGateway(entry) || isAlias(entry)) return
|
|
2830
|
+
if (isGroup(entry)) {
|
|
2831
|
+
for (const [name, child] of entry.commands)
|
|
2832
|
+
assertNoGlobalOptionConflicts(`${path} ${name}`, child, globals)
|
|
2833
|
+
return
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
if (entry.options) {
|
|
2837
|
+
const globalKeys = Object.keys(globals.schema.shape)
|
|
2838
|
+
const optionKeys = Object.keys(entry.options.shape)
|
|
2839
|
+
for (const key of optionKeys) {
|
|
2840
|
+
if (globalKeys.includes(key))
|
|
2841
|
+
throw new Error(
|
|
2842
|
+
`Command '${path}' option '${key}' conflicts with a global option. Choose a different name.`,
|
|
2843
|
+
)
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
if (globals.alias && entry.alias) {
|
|
2848
|
+
const globalAliasValues = new Set(Object.values(globals.alias))
|
|
2849
|
+
for (const [name, short] of Object.entries(entry.alias)) {
|
|
2850
|
+
if (short && globalAliasValues.has(short))
|
|
2851
|
+
throw new Error(
|
|
2852
|
+
`Command '${path}' alias '-${short}' for '${name}' conflicts with a global alias. Choose a different alias.`,
|
|
2853
|
+
)
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2531
2858
|
/** @internal Maps CLI instances to their command maps. */
|
|
2532
2859
|
export const toCommands = new WeakMap<Cli, Map<string, CommandEntry>>()
|
|
2533
2860
|
|
|
@@ -2546,6 +2873,15 @@ export const toConfigEnabled = new WeakMap<Cli, boolean>()
|
|
|
2546
2873
|
/** @internal Maps CLI instances to their output policy. */
|
|
2547
2874
|
const toOutputPolicy = new WeakMap<Cli, OutputPolicy>()
|
|
2548
2875
|
|
|
2876
|
+
/** Descriptor for a CLI's custom global options schema and aliases. */
|
|
2877
|
+
export type GlobalsDescriptor = {
|
|
2878
|
+
schema: z.ZodObject<any>
|
|
2879
|
+
alias?: Record<string, string> | undefined
|
|
2880
|
+
}
|
|
2881
|
+
|
|
2882
|
+
/** @internal Maps CLI instances to their globals schema and alias map. */
|
|
2883
|
+
const toGlobals = new WeakMap<Cli, GlobalsDescriptor>()
|
|
2884
|
+
|
|
2549
2885
|
/** @internal Maps root CLI instances to their command aliases. */
|
|
2550
2886
|
const toRootAliases = new WeakMap<Root, string[]>()
|
|
2551
2887
|
|
|
@@ -2667,7 +3003,7 @@ async function handleStreaming(
|
|
|
2667
3003
|
return
|
|
2668
3004
|
}
|
|
2669
3005
|
}
|
|
2670
|
-
if (useJsonl) ctx.writeln(
|
|
3006
|
+
if (useJsonl) ctx.writeln(Json.stringify({ type: 'chunk', data: value }))
|
|
2671
3007
|
else if (ctx.renderOutput)
|
|
2672
3008
|
ctx.writeln(ctx.truncate(Formatter.format(value, ctx.format)).text)
|
|
2673
3009
|
}
|
|
@@ -2719,6 +3055,7 @@ async function handleStreaming(
|
|
|
2719
3055
|
error: {
|
|
2720
3056
|
code: error instanceof IncurError ? error.code : 'UNKNOWN',
|
|
2721
3057
|
message: error instanceof Error ? error.message : String(error),
|
|
3058
|
+
...(error instanceof IncurError ? { retryable: error.retryable } : undefined),
|
|
2722
3059
|
},
|
|
2723
3060
|
}),
|
|
2724
3061
|
)
|
|
@@ -2802,6 +3139,7 @@ async function handleStreaming(
|
|
|
2802
3139
|
error: {
|
|
2803
3140
|
code: error instanceof IncurError ? error.code : 'UNKNOWN',
|
|
2804
3141
|
message: error instanceof Error ? error.message : String(error),
|
|
3142
|
+
...(error instanceof IncurError ? { retryable: error.retryable } : undefined),
|
|
2805
3143
|
},
|
|
2806
3144
|
meta: {
|
|
2807
3145
|
command: ctx.path,
|
|
@@ -2813,36 +3151,16 @@ async function handleStreaming(
|
|
|
2813
3151
|
}
|
|
2814
3152
|
}
|
|
2815
3153
|
|
|
2816
|
-
/** @internal Formats a CTA block into the output envelope shape. */
|
|
2817
|
-
function formatCtaBlock(name: string, block: CtaBlock | undefined): FormattedCtaBlock | undefined {
|
|
2818
|
-
if (!block || block.commands.length === 0) return undefined
|
|
2819
|
-
return {
|
|
2820
|
-
description:
|
|
2821
|
-
block.description ??
|
|
2822
|
-
(block.commands.length === 1 ? 'Suggested command:' : 'Suggested commands:'),
|
|
2823
|
-
commands: block.commands.map((c) => formatCta(name, c)),
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
|
|
2827
|
-
/** @internal Formats a CTA by prefixing the CLI name. Handles string and object forms. */
|
|
2828
|
-
function formatCta(name: string, cta: Cta): FormattedCta {
|
|
2829
|
-
if (typeof cta === 'string') return { command: `${name} ${cta}` }
|
|
2830
|
-
const prefix = cta.command === name || cta.command.startsWith(`${name} `) ? '' : `${name} `
|
|
2831
|
-
let cmd = `${prefix}${cta.command}`
|
|
2832
|
-
if (cta.args)
|
|
2833
|
-
for (const [key, value] of Object.entries(cta.args))
|
|
2834
|
-
cmd += value === true ? ` <${key}>` : ` ${value}`
|
|
2835
|
-
if (cta.options)
|
|
2836
|
-
for (const [key, value] of Object.entries(cta.options))
|
|
2837
|
-
cmd += value === true ? ` --${key} <${key}>` : ` --${key} ${value}`
|
|
2838
|
-
return { command: cmd, ...(cta.description ? { description: cta.description } : undefined) }
|
|
2839
|
-
}
|
|
2840
|
-
|
|
2841
3154
|
/** @internal Builds the `--llms` index manifest (name + description only) from the command tree. */
|
|
2842
|
-
function buildIndexManifest(
|
|
3155
|
+
function buildIndexManifest(
|
|
3156
|
+
commands: Map<string, CommandEntry>,
|
|
3157
|
+
prefix: string[] = [],
|
|
3158
|
+
globalsSchema?: z.ZodObject<any>,
|
|
3159
|
+
) {
|
|
2843
3160
|
return {
|
|
2844
3161
|
version: 'incur.v1',
|
|
2845
3162
|
commands: collectIndexCommands(commands, prefix).sort((a, b) => a.name.localeCompare(b.name)),
|
|
3163
|
+
...(globalsSchema ? { globals: Schema.toJsonSchema(globalsSchema) } : undefined),
|
|
2846
3164
|
}
|
|
2847
3165
|
}
|
|
2848
3166
|
|
|
@@ -2869,10 +3187,15 @@ function collectIndexCommands(
|
|
|
2869
3187
|
}
|
|
2870
3188
|
|
|
2871
3189
|
/** @internal Builds the `--llms` manifest from the command tree. */
|
|
2872
|
-
function buildManifest(
|
|
3190
|
+
function buildManifest(
|
|
3191
|
+
commands: Map<string, CommandEntry>,
|
|
3192
|
+
prefix: string[] = [],
|
|
3193
|
+
globalsSchema?: z.ZodObject<any>,
|
|
3194
|
+
) {
|
|
2873
3195
|
return {
|
|
2874
3196
|
version: 'incur.v1',
|
|
2875
3197
|
commands: collectCommands(commands, prefix).sort((a, b) => a.name.localeCompare(b.name)),
|
|
3198
|
+
...(globalsSchema ? { globals: Schema.toJsonSchema(globalsSchema) } : undefined),
|
|
2876
3199
|
}
|
|
2877
3200
|
}
|
|
2878
3201
|
|
|
@@ -2925,11 +3248,11 @@ function collectCommands(
|
|
|
2925
3248
|
}
|
|
2926
3249
|
|
|
2927
3250
|
/** @internal Recursively collects leaf commands as `Skill.CommandInfo` for `--llms --format md`. */
|
|
2928
|
-
function collectSkillCommands(
|
|
3251
|
+
export function collectSkillCommands(
|
|
2929
3252
|
commands: Map<string, CommandEntry>,
|
|
2930
3253
|
prefix: string[],
|
|
2931
3254
|
groups: Map<string, string>,
|
|
2932
|
-
rootCommand?:
|
|
3255
|
+
rootCommand?: SkillCommandSource | undefined,
|
|
2933
3256
|
): Skill.CommandInfo[] {
|
|
2934
3257
|
const result: Skill.CommandInfo[] = []
|
|
2935
3258
|
if (rootCommand) {
|
|
@@ -2938,6 +3261,7 @@ function collectSkillCommands(
|
|
|
2938
3261
|
if (rootCommand.args) cmd.args = rootCommand.args
|
|
2939
3262
|
if (rootCommand.env) cmd.env = rootCommand.env
|
|
2940
3263
|
if (rootCommand.hint) cmd.hint = rootCommand.hint
|
|
3264
|
+
if (isDestructive(rootCommand)) cmd.hint = appendDestructiveHint(cmd.hint)
|
|
2941
3265
|
if (rootCommand.options) cmd.options = rootCommand.options
|
|
2942
3266
|
if (rootCommand.output) cmd.output = rootCommand.output
|
|
2943
3267
|
const examples = formatExamples(rootCommand.examples)
|
|
@@ -2961,6 +3285,7 @@ function collectSkillCommands(
|
|
|
2961
3285
|
if (entry.args) cmd.args = entry.args
|
|
2962
3286
|
if (entry.env) cmd.env = entry.env
|
|
2963
3287
|
if (entry.hint) cmd.hint = entry.hint
|
|
3288
|
+
if (isDestructive(entry)) cmd.hint = appendDestructiveHint(cmd.hint)
|
|
2964
3289
|
if (entry.options) cmd.options = entry.options
|
|
2965
3290
|
if (entry.output) cmd.output = entry.output
|
|
2966
3291
|
const examples = formatExamples(entry.examples)
|
|
@@ -2977,6 +3302,29 @@ function collectSkillCommands(
|
|
|
2977
3302
|
return result.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''))
|
|
2978
3303
|
}
|
|
2979
3304
|
|
|
3305
|
+
type SkillCommandSource = Pick<
|
|
3306
|
+
CommandDefinition<any, any, any, any, any, any>,
|
|
3307
|
+
| 'args'
|
|
3308
|
+
| 'description'
|
|
3309
|
+
| 'destructive'
|
|
3310
|
+
| 'env'
|
|
3311
|
+
| 'examples'
|
|
3312
|
+
| 'hint'
|
|
3313
|
+
| 'mcp'
|
|
3314
|
+
| 'options'
|
|
3315
|
+
| 'output'
|
|
3316
|
+
>
|
|
3317
|
+
|
|
3318
|
+
function isDestructive(command: SkillCommandSource): boolean {
|
|
3319
|
+
return command.destructive === true || command.mcp?.annotations?.destructiveHint === true
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
function appendDestructiveHint(hint: string | undefined): string {
|
|
3323
|
+
if (!hint) return destructiveCommandHint
|
|
3324
|
+
if (hint.includes(destructiveCommandHint)) return hint
|
|
3325
|
+
return `${hint} ${destructiveCommandHint}`
|
|
3326
|
+
}
|
|
3327
|
+
|
|
2980
3328
|
/** @internal Formats examples into `{ command, description }` objects. `command` is the args/options suffix only. */
|
|
2981
3329
|
export function formatExamples(
|
|
2982
3330
|
examples: Example<any, any>[] | undefined,
|
|
@@ -2993,6 +3341,18 @@ export function formatExamples(
|
|
|
2993
3341
|
})
|
|
2994
3342
|
}
|
|
2995
3343
|
|
|
3344
|
+
/** @internal Parses YAML frontmatter from generated skill Markdown. */
|
|
3345
|
+
export function parseSkillFrontmatter(content: string): {
|
|
3346
|
+
description?: string | undefined
|
|
3347
|
+
name?: string | undefined
|
|
3348
|
+
} {
|
|
3349
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/)
|
|
3350
|
+
if (!match) return {}
|
|
3351
|
+
const meta = Yaml.loadSync().parse(match[1]!)
|
|
3352
|
+
if (!meta || typeof meta !== 'object') return {}
|
|
3353
|
+
return meta as { description?: string | undefined; name?: string | undefined }
|
|
3354
|
+
}
|
|
3355
|
+
|
|
2996
3356
|
/** @internal Builds separate args, env, and options JSON Schemas. */
|
|
2997
3357
|
function buildInputSchema(
|
|
2998
3358
|
args: z.ZodObject<any> | undefined,
|
|
@@ -3121,12 +3481,23 @@ type CommandDefinition<
|
|
|
3121
3481
|
args?: args | undefined
|
|
3122
3482
|
/** Zod schema for environment variables. Keys are the variable names (e.g. `NPM_TOKEN`). */
|
|
3123
3483
|
env?: env | undefined
|
|
3484
|
+
/** Marks this command as destructive when generating agent skills. */
|
|
3485
|
+
destructive?: boolean | undefined
|
|
3124
3486
|
/** Usage examples for this command. */
|
|
3125
3487
|
examples?: Example<args, options>[] | undefined
|
|
3126
3488
|
/** Default output format. Overridden by `--format` or `--json`. */
|
|
3127
3489
|
format?: Formatter.Format | undefined
|
|
3128
3490
|
/** Plain text hint displayed after examples and before global options. */
|
|
3129
3491
|
hint?: string | undefined
|
|
3492
|
+
/** MCP-specific metadata exposed when this command is served as a tool. */
|
|
3493
|
+
mcp?:
|
|
3494
|
+
| {
|
|
3495
|
+
/** MCP tool annotations that describe tool behavior to clients. */
|
|
3496
|
+
annotations?: Mcp.ToolAnnotations | undefined
|
|
3497
|
+
/** Tool-specific instructions surfaced to MCP clients. */
|
|
3498
|
+
instructions?: string | undefined
|
|
3499
|
+
}
|
|
3500
|
+
| undefined
|
|
3130
3501
|
/** Zod schema for the command's return value. */
|
|
3131
3502
|
output?: output | undefined
|
|
3132
3503
|
/**
|
|
@@ -3179,22 +3550,6 @@ type CommandDefinition<
|
|
|
3179
3550
|
| AsyncGenerator<InferReturn<output>, unknown, unknown>
|
|
3180
3551
|
}
|
|
3181
3552
|
|
|
3182
|
-
/** @internal A formatted CTA block as it appears in the output envelope. */
|
|
3183
|
-
type FormattedCtaBlock = {
|
|
3184
|
-
/** Formatted command suggestions. */
|
|
3185
|
-
commands: FormattedCta[]
|
|
3186
|
-
/** Human-readable label for the CTA block. */
|
|
3187
|
-
description: string
|
|
3188
|
-
}
|
|
3189
|
-
|
|
3190
|
-
/** @internal A formatted CTA as it appears in the output envelope. */
|
|
3191
|
-
type FormattedCta = {
|
|
3192
|
-
/** The full command string with args and options folded in. */
|
|
3193
|
-
command: string
|
|
3194
|
-
/** A short description of what the command does. */
|
|
3195
|
-
description?: string | undefined
|
|
3196
|
-
}
|
|
3197
|
-
|
|
3198
3553
|
/** @internal Scans argv for deprecated flags and writes warnings to stderr. */
|
|
3199
3554
|
function emitDeprecationWarnings(
|
|
3200
3555
|
argv: string[],
|