@taurgis/bonsai 3.2.0 → 4.0.0
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/README.md +9 -6
- package/agents/agents/salesforce-docs-researcher.agent.md +17 -4
- package/agents/instructions/salesforce-research.instructions.md +2 -1
- package/bin/cli.mjs +13 -18
- package/dist/base-command.d.ts +59 -12
- package/dist/base-command.js +179 -51
- package/dist/commands/config/base.js +12 -2
- package/dist/commands/config/get.js +8 -12
- package/dist/commands/config/index.js +2 -2
- package/dist/commands/config/list.js +11 -17
- package/dist/commands/config/set.d.ts +2 -1
- package/dist/commands/config/set.js +35 -28
- package/dist/commands/config/unset.d.ts +2 -1
- package/dist/commands/config/unset.js +26 -25
- package/dist/commands/fetch.d.ts +7 -15
- package/dist/commands/fetch.js +61 -401
- package/dist/commands/import.d.ts +4 -9
- package/dist/commands/import.js +56 -284
- package/dist/commands/inspect.d.ts +7 -1
- package/dist/commands/inspect.js +112 -52
- package/dist/commands/list.d.ts +18 -3
- package/dist/commands/list.js +121 -46
- package/dist/commands/prune.d.ts +6 -1
- package/dist/commands/prune.js +89 -78
- package/dist/commands/status.d.ts +3 -2
- package/dist/commands/status.js +62 -79
- package/dist/hooks/command-not-found/suggest.d.ts +2 -1
- package/dist/hooks/command-not-found/suggest.js +78 -41
- package/dist/lib/argv.d.ts +29 -3
- package/dist/lib/argv.js +147 -54
- package/dist/lib/batch.d.ts +41 -0
- package/dist/lib/batch.js +39 -0
- package/dist/lib/cache-view.d.ts +21 -0
- package/dist/lib/cache-view.js +30 -0
- package/dist/lib/cli-emit.d.ts +28 -0
- package/dist/lib/cli-emit.js +44 -0
- package/dist/lib/cli-error-policy.d.ts +57 -0
- package/dist/lib/cli-error-policy.js +74 -0
- package/dist/lib/cli-flag-manifest.d.ts +12 -0
- package/dist/lib/cli-flag-manifest.js +15 -0
- package/dist/lib/cli-presentation.d.ts +41 -0
- package/dist/lib/cli-presentation.js +53 -0
- package/dist/lib/cli-result-types.d.ts +112 -0
- package/dist/lib/cli-result-types.js +2 -0
- package/dist/lib/config/index.d.ts +23 -5
- package/dist/lib/config/index.js +60 -5
- package/dist/lib/config/io.d.ts +9 -0
- package/dist/lib/config/io.js +71 -21
- package/dist/lib/config/schema.d.ts +2 -0
- package/dist/lib/config/schema.js +7 -0
- package/dist/lib/config-persist.d.ts +28 -0
- package/dist/lib/config-persist.js +29 -0
- package/dist/lib/envelope.d.ts +41 -3
- package/dist/lib/envelope.js +154 -4
- package/dist/lib/help-preflight.d.ts +5 -8
- package/dist/lib/help-preflight.js +13 -32
- package/dist/lib/json-meta.d.ts +0 -2
- package/dist/lib/json-meta.js +21 -25
- package/dist/lib/limit-flag.d.ts +11 -1
- package/dist/lib/limit-flag.js +19 -6
- package/dist/lib/parse-error-ux.d.ts +5 -0
- package/dist/lib/parse-error-ux.js +73 -0
- package/dist/lib/prune-flags.d.ts +30 -0
- package/dist/lib/prune-flags.js +86 -0
- package/dist/lib/research/artifact-index.d.ts +11 -2
- package/dist/lib/research/artifact-index.js +14 -5
- package/dist/lib/research/artifact.js +20 -2
- package/dist/lib/research/browser.d.ts +53 -2
- package/dist/lib/research/browser.js +202 -58
- package/dist/lib/research/capture.d.ts +24 -2
- package/dist/lib/research/capture.js +24 -4
- package/dist/lib/research/cli-io.d.ts +40 -0
- package/dist/lib/research/cli-io.js +27 -0
- package/dist/lib/research/compress.d.ts +7 -0
- package/dist/lib/research/compress.js +7 -3
- package/dist/lib/research/docs/capabilities.d.ts +15 -0
- package/dist/lib/research/docs/capabilities.js +5 -0
- package/dist/lib/research/docs/clean-dom.d.ts +2 -0
- package/dist/lib/research/docs/clean-dom.js +2 -0
- package/dist/lib/research/docs/code-blocks.d.ts +2 -0
- package/dist/lib/research/docs/code-blocks.js +2 -0
- package/dist/lib/research/docs/detect.d.ts +4 -0
- package/dist/lib/research/docs/detect.js +4 -0
- package/dist/lib/research/docs/machine-readable.d.ts +18 -0
- package/dist/lib/research/docs/machine-readable.js +10 -0
- package/dist/lib/research/docs/markdown-source.d.ts +20 -0
- package/dist/lib/research/docs/markdown-source.js +19 -2
- package/dist/lib/research/docs/quality-gates.d.ts +5 -0
- package/dist/lib/research/docs/quality-gates.js +4 -0
- package/dist/lib/research/docs/rsc.d.ts +9 -2
- package/dist/lib/research/docs/rsc.js +5 -2
- package/dist/lib/research/docs/section-artifacts.d.ts +12 -0
- package/dist/lib/research/docs/section-artifacts.js +12 -0
- package/dist/lib/research/docs/sections.d.ts +18 -0
- package/dist/lib/research/docs/sections.js +17 -1
- package/dist/lib/research/docs/source-map.d.ts +28 -0
- package/dist/lib/research/docs/source-map.js +27 -0
- package/dist/lib/research/docs/validate.d.ts +35 -2
- package/dist/lib/research/docs/validate.js +47 -2
- package/dist/lib/research/extract.d.ts +16 -0
- package/dist/lib/research/extract.js +12 -1
- package/dist/lib/research/fetch-command-service.d.ts +36 -0
- package/dist/lib/research/fetch-command-service.js +367 -0
- package/dist/lib/research/fetch-result.d.ts +114 -0
- package/dist/lib/research/fetch-result.js +212 -0
- package/dist/lib/research/fetcher.d.ts +46 -8
- package/dist/lib/research/fetcher.js +61 -31
- package/dist/lib/research/freshness.d.ts +54 -11
- package/dist/lib/research/freshness.js +91 -31
- package/dist/lib/research/import-command-service.d.ts +56 -0
- package/dist/lib/research/import-command-service.js +402 -0
- package/dist/lib/research/keywords.js +5 -1
- package/dist/lib/research/markdown.d.ts +12 -1
- package/dist/lib/research/markdown.js +13 -5
- package/dist/lib/research/metadata-filters.d.ts +18 -0
- package/dist/lib/research/metadata-filters.js +37 -0
- package/dist/lib/research/metadata-flags.d.ts +34 -0
- package/dist/lib/research/metadata-flags.js +45 -0
- package/dist/lib/research/persist-artifact.d.ts +23 -0
- package/dist/lib/research/persist-artifact.js +27 -0
- package/dist/lib/research/prompt-injection.d.ts +9 -0
- package/dist/lib/research/prompt-injection.js +59 -14
- package/dist/lib/research/proxy.d.ts +14 -8
- package/dist/lib/research/proxy.js +14 -10
- package/dist/lib/research/resolve-target.d.ts +2 -0
- package/dist/lib/research/resolve-target.js +1 -1
- package/dist/lib/research/revalidate.d.ts +49 -20
- package/dist/lib/research/revalidate.js +80 -15
- package/dist/lib/research/schema.d.ts +7 -0
- package/dist/lib/research/schema.js +2 -0
- package/dist/lib/research/secret-scan.d.ts +6 -0
- package/dist/lib/research/secret-scan.js +8 -0
- package/dist/lib/research/secure-write.d.ts +4 -0
- package/dist/lib/research/secure-write.js +31 -2
- package/dist/lib/research/storage.d.ts +9 -8
- package/dist/lib/research/storage.js +34 -28
- package/dist/lib/research/summarize.d.ts +15 -0
- package/dist/lib/research/summarize.js +11 -0
- package/dist/lib/research/url.d.ts +9 -6
- package/dist/lib/research/url.js +33 -21
- package/dist/lib/text.d.ts +19 -8
- package/dist/lib/text.js +32 -9
- package/dist/lib/value-flags.d.ts +14 -0
- package/dist/lib/value-flags.js +28 -0
- package/dist/sites/coveo.d.ts +10 -0
- package/dist/sites/coveo.js +10 -0
- package/dist/sites/index.d.ts +16 -0
- package/dist/sites/index.js +16 -4
- package/dist/sites/markdown-twin.d.ts +31 -0
- package/dist/sites/markdown-twin.js +56 -0
- package/dist/sites/salesforce/fetch-page.d.ts +8 -2
- package/dist/sites/salesforce/fetch-page.js +14 -3
- package/dist/sites/salesforce/help-tooling-markdown.d.ts +30 -0
- package/dist/sites/salesforce/help-tooling-markdown.js +74 -0
- package/dist/sites/salesforce/index.d.ts +1 -0
- package/dist/sites/salesforce/index.js +1 -0
- package/dist/sites/salesforce-developer/fetch-page.d.ts +6 -1
- package/dist/sites/salesforce-developer/fetch-page.js +6 -1
- package/dist/sites/salesforce-developer/index.d.ts +1 -0
- package/dist/sites/salesforce-developer/index.js +1 -0
- package/dist/sites/salesforce-developer/route-markdown.d.ts +18 -6
- package/dist/sites/salesforce-developer/route-markdown.js +29 -67
- package/dist/sites/salesforce-doc-fetch.d.ts +39 -5
- package/dist/sites/salesforce-doc-fetch.js +52 -7
- package/dist/sites/salesforce-dom-probe.d.ts +20 -2
- package/dist/sites/salesforce-dom-probe.js +20 -2
- package/dist/sites/types.d.ts +14 -8
- package/dist/sites/types.js +3 -0
- package/oclif.manifest.json +216 -102
- package/package.json +20 -7
- package/agents/agents/official-docs-researcher.agent.md +0 -87
- package/agents/instructions/web-research.instructions.md +0 -44
- package/agents/skills/web-research/SKILL.md +0 -118
package/dist/lib/argv.js
CHANGED
|
@@ -1,51 +1,106 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EXIT_USAGE } from './cli-error-policy.js';
|
|
2
|
+
import { buildCliErrorEnvelope } from './envelope.js';
|
|
3
|
+
import { sanitizeForTerminal } from './text.js';
|
|
4
|
+
/** Shared MISSING_COMMAND copy for flag-only argv preflight. */
|
|
5
|
+
function missingCommandDetails(bin, swallowed) {
|
|
6
|
+
if (swallowed) {
|
|
7
|
+
return {
|
|
8
|
+
code: 'MISSING_COMMAND',
|
|
9
|
+
message: [
|
|
10
|
+
`Missing URL or command. ${swallowed.flag} consumed ${swallowed.url} as its value, so there was no URL left to fetch.`,
|
|
11
|
+
`Run ${bin} --help for usage.`,
|
|
12
|
+
].join('\n'),
|
|
13
|
+
suggestions: [
|
|
14
|
+
`Pass the URL as the command (flags after): ${bin} ${swallowed.url}`,
|
|
15
|
+
`Or a named command: ${bin} list`,
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
code: 'MISSING_COMMAND',
|
|
21
|
+
message: `Missing URL or command. Run ${bin} --help for usage.`,
|
|
22
|
+
suggestions: [`Pass a URL: ${bin} https://example.com`, `Or a command: ${bin} list`],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Boolean flags registered on every command via BaseCommand.baseFlags. oclif only merges those after
|
|
27
|
+
* it picks a command, so `bonsai --read-only list` would otherwise treat `--read-only` as the
|
|
28
|
+
* command id. Strip and re-append them after the command/URL, same pattern as `--json`.
|
|
29
|
+
*/
|
|
30
|
+
const GLOBAL_BOOLEAN_FLAGS = new Set(['--read-only', '--plan', '--toon']);
|
|
2
31
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
32
|
+
* When a value-taking flag is the only "command" and its value looks like a URL, the user almost
|
|
33
|
+
* certainly put the URL where the flag value belongs (e.g. `bonsai --tags https://example.com`).
|
|
5
34
|
*/
|
|
6
|
-
function
|
|
35
|
+
function findSwallowedUrlFlag(argv, valueTakingFlags) {
|
|
36
|
+
if (!argv?.length)
|
|
37
|
+
return null;
|
|
38
|
+
for (let i = 0; i < argv.length - 1; i++) {
|
|
39
|
+
const flag = argv[i];
|
|
40
|
+
if (!valueTakingFlags.has(flag))
|
|
41
|
+
continue;
|
|
42
|
+
const value = argv[i + 1];
|
|
43
|
+
if (value.startsWith('-'))
|
|
44
|
+
continue;
|
|
45
|
+
if (looksLikeUrl(value))
|
|
46
|
+
return { flag, url: value };
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
function missingUsageExit(json, argv, valueTakingFlags) {
|
|
51
|
+
const swallowed = findSwallowedUrlFlag(argv, valueTakingFlags);
|
|
52
|
+
// `swallowed.url` is raw user input echoed straight back into the MISSING_COMMAND message and its
|
|
53
|
+
// "pass the URL as the command" suggestion — untrusted per the repo's trust-boundary rules, same
|
|
54
|
+
// reasoning as BaseCommand.error(). This preflight path fires before oclif ever dispatches a
|
|
55
|
+
// command, so there is no `this.jsonEnabled()` to call — but `json` is already known here, so gate
|
|
56
|
+
// on it the same way: sanitize only the human-mode message, keep `--json` byte-for-byte.
|
|
57
|
+
const details = missingCommandDetails('bonsai', swallowed && !json ? { ...swallowed, url: sanitizeForTerminal(swallowed.url) } : swallowed);
|
|
7
58
|
return {
|
|
8
|
-
exitCode:
|
|
9
|
-
|
|
59
|
+
exitCode: EXIT_USAGE,
|
|
60
|
+
json,
|
|
61
|
+
envelope: buildCliErrorEnvelope({
|
|
10
62
|
command: 'bonsai',
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
data: null,
|
|
63
|
+
message: details.message,
|
|
64
|
+
code: details.code,
|
|
65
|
+
suggestions: details.suggestions,
|
|
15
66
|
}),
|
|
16
67
|
};
|
|
17
68
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
'--
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Index of the first positional command/URL token, skipping flags (and value-flag operands)
|
|
71
|
+
* plus root meta tokens that never name a command (`--help`, `--json`, globals).
|
|
72
|
+
*/
|
|
73
|
+
function firstPositionalIndex(argv, valueTakingFlags) {
|
|
74
|
+
for (let i = 0; i < argv.length; i++) {
|
|
75
|
+
const token = argv[i];
|
|
76
|
+
if (token === '--help' || token === '--json' || GLOBAL_BOOLEAN_FLAGS.has(token))
|
|
77
|
+
continue;
|
|
78
|
+
if (token.startsWith('-')) {
|
|
79
|
+
if (valueTakingFlags.has(token))
|
|
80
|
+
i++;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
return i;
|
|
84
|
+
}
|
|
85
|
+
return -1;
|
|
86
|
+
}
|
|
87
|
+
/** True when argv selects a command, URL, or root `--version` action (not flag-only usage). */
|
|
88
|
+
function hasCommandToken(argv, valueTakingFlags) {
|
|
89
|
+
return argv.includes('--version') || firstPositionalIndex(argv, valueTakingFlags) !== -1;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Normalize raw process argv for oclif. `valueTakingFlags` must come from the composition root
|
|
93
|
+
* (`cli-flag-manifest`) — this module stays free of command registry imports.
|
|
94
|
+
*/
|
|
95
|
+
export function normalizeArgv(rawArgv, options) {
|
|
96
|
+
const { valueTakingFlags, knownCommandRoots } = options;
|
|
97
|
+
// AXI "content first": a truly bare invocation (`bonsai`, no args/flags at all) shows live cache
|
|
98
|
+
// data instead of oclif's default root help — `bonsai help`, `--help`, and `-h` remain the
|
|
99
|
+
// explicit path to the command reference (all of them are non-empty argv and skip this branch).
|
|
100
|
+
// oclif has no built-in "default command" concept for empty argv (see oclif/oclif#277), so this
|
|
101
|
+
// is a one-line argv rewrite, the same technique the URL-shorthand rewrite below already uses.
|
|
102
|
+
if (rawArgv.length === 0) {
|
|
103
|
+
return { argv: ['list'] };
|
|
49
104
|
}
|
|
50
105
|
// oclif's JSON flag is command-scoped, so `bonsai list --json` works but
|
|
51
106
|
// `bonsai --json list` is otherwise parsed as an unknown command named
|
|
@@ -60,23 +115,28 @@ export function normalizeArgv(rawArgv) {
|
|
|
60
115
|
}
|
|
61
116
|
const helpRequested = tokens.includes('--help');
|
|
62
117
|
let core = tokens.filter((arg) => arg !== '--help');
|
|
118
|
+
// Relocate base boolean flags so they survive command resolution (see GLOBAL_BOOLEAN_FLAGS).
|
|
119
|
+
const relocatedGlobals = [];
|
|
120
|
+
core = core.filter((arg) => {
|
|
121
|
+
if (!GLOBAL_BOOLEAN_FLAGS.has(arg))
|
|
122
|
+
return true;
|
|
123
|
+
if (!relocatedGlobals.includes(arg))
|
|
124
|
+
relocatedGlobals.push(arg);
|
|
125
|
+
return false;
|
|
126
|
+
});
|
|
63
127
|
// Treat URL-shaped tokens as the `fetch` shorthand. Match both `https://...` and scheme-only
|
|
64
128
|
// forms like `javascript:` or `data:` so fetch can reject unsupported protocols instead of oclif
|
|
65
129
|
// reporting a misleading "command not found". If the invocation begins with a flag, allow common
|
|
66
130
|
// flag-before-argument usage such as `bonsai --format detailed https://example.com`.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
firstNonFlagArgIndex = i;
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
const rootFetchShape = firstNonFlagArgIndex !== -1 && looksLikeUrl(core[firstNonFlagArgIndex]);
|
|
131
|
+
// Exclude tokens whose part before the first `:` names a real command (`config:get`) — oclif
|
|
132
|
+
// joins namespaced command ids with `:` regardless of the display-only topicSeparator, so those
|
|
133
|
+
// are commands, not URL schemes, and must reach normal command dispatch instead of a misleading
|
|
134
|
+
// "Invalid URL" error.
|
|
135
|
+
const firstNonFlagArgIndex = firstPositionalIndex(core, valueTakingFlags);
|
|
136
|
+
const firstArg = firstNonFlagArgIndex !== -1 ? core[firstNonFlagArgIndex] : undefined;
|
|
137
|
+
const rootFetchShape = firstArg !== undefined &&
|
|
138
|
+
looksLikeUrl(firstArg) &&
|
|
139
|
+
!knownCommandRoots.has(firstArg.split(':')[0]);
|
|
80
140
|
if (rootFetchShape) {
|
|
81
141
|
const url = core[firstNonFlagArgIndex];
|
|
82
142
|
core = [
|
|
@@ -88,10 +148,43 @@ export function normalizeArgv(rawArgv) {
|
|
|
88
148
|
}
|
|
89
149
|
if (helpRequested)
|
|
90
150
|
core.push('--help');
|
|
151
|
+
core.push(...relocatedGlobals);
|
|
91
152
|
if (jsonMode)
|
|
92
153
|
core.push('--json');
|
|
154
|
+
// Flag-only argv (`--json`, `--read-only`, `--tags https://…`) never resolves a command.
|
|
155
|
+
// Exit here so command_not_found does not special-case dash-prefixed ids.
|
|
156
|
+
// Truly empty argv already returned above; `--help`/`--version` stay with oclif here.
|
|
157
|
+
if (!helpRequested && core.length > 0 && !hasCommandToken(core, valueTakingFlags)) {
|
|
158
|
+
return {
|
|
159
|
+
argv: jsonMode ? ['--json'] : [],
|
|
160
|
+
earlyExit: missingUsageExit(jsonMode, rawArgv, valueTakingFlags),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
93
163
|
return { argv: core };
|
|
94
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Non-flag positional tokens from a (typically already-normalized) argv. Skips `--help`/`--json`
|
|
167
|
+
* and any dash-prefixed flags so multi-segment command ids (`config get`) stay intact. Shared by
|
|
168
|
+
* help-preflight and json-meta — both run after `normalizeArgv` has already folded `help X` →
|
|
169
|
+
* `X --help` and `-h` → `--help`.
|
|
170
|
+
*/
|
|
171
|
+
export function positionalArgvTokens(argv, valueTakingFlags) {
|
|
172
|
+
const tokens = [];
|
|
173
|
+
for (let i = 0; i < argv.length; i++) {
|
|
174
|
+
const arg = argv[i];
|
|
175
|
+
if (arg === '--')
|
|
176
|
+
break;
|
|
177
|
+
if (arg === '--help' || arg === '--json')
|
|
178
|
+
continue;
|
|
179
|
+
if (arg.startsWith('-')) {
|
|
180
|
+
if (!arg.includes('=') && valueTakingFlags.has(arg))
|
|
181
|
+
i++;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
tokens.push(arg);
|
|
185
|
+
}
|
|
186
|
+
return tokens;
|
|
187
|
+
}
|
|
95
188
|
function looksLikeUrl(arg) {
|
|
96
189
|
return arg.includes('://') || /^[a-z][a-z0-9+.-]*:/i.test(arg);
|
|
97
190
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collapse a multi-URL command's per-URL rows into the CLI's single-vs-array return
|
|
3
|
+
* contract, and mark {@link EXIT_RUNTIME_FAILURE} when any row is a failure outcome.
|
|
4
|
+
*
|
|
5
|
+
* @param results - Per-URL result rows.
|
|
6
|
+
* @param isFailure - Predicate marking a row as a failure outcome.
|
|
7
|
+
* @returns The sole row when there is one URL; otherwise the full array.
|
|
8
|
+
*/
|
|
9
|
+
export declare function finalizeBatch<T>(results: T[], isFailure: (row: T) => boolean): T | T[];
|
|
10
|
+
/**
|
|
11
|
+
* status/inspect batch rows: a miss or a validation error row is a failure outcome.
|
|
12
|
+
*
|
|
13
|
+
* @param row - Batch row with a `status` field.
|
|
14
|
+
* @returns `true` when the row should fail the batch exit code.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isBatchReadFailure(row: {
|
|
17
|
+
status: string;
|
|
18
|
+
}): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Sparse validation-failure row for multi-URL status/inspect. Only the fields agents need —
|
|
21
|
+
* no fake cacheKey/freshness/metadata padding.
|
|
22
|
+
*
|
|
23
|
+
* @param url - Input URL that failed validation.
|
|
24
|
+
* @param err - Error-like object with optional code/message/suggestions/ref.
|
|
25
|
+
* @returns Sparse error row for the batch result array.
|
|
26
|
+
*/
|
|
27
|
+
export declare function urlValidationErrorRow(url: string, err: {
|
|
28
|
+
code?: string;
|
|
29
|
+
message?: string;
|
|
30
|
+
suggestions?: string[];
|
|
31
|
+
ref?: string;
|
|
32
|
+
}): {
|
|
33
|
+
status: "error";
|
|
34
|
+
normalizedUrl: string;
|
|
35
|
+
error: {
|
|
36
|
+
code: string;
|
|
37
|
+
message: string;
|
|
38
|
+
suggestions?: string[];
|
|
39
|
+
ref?: string;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { cliErrorFields } from './envelope.js';
|
|
2
|
+
import { EXIT_RUNTIME_FAILURE } from './cli-error-policy.js';
|
|
3
|
+
/**
|
|
4
|
+
* Collapse a multi-URL command's per-URL rows into the CLI's single-vs-array return
|
|
5
|
+
* contract, and mark {@link EXIT_RUNTIME_FAILURE} when any row is a failure outcome.
|
|
6
|
+
*
|
|
7
|
+
* @param results - Per-URL result rows.
|
|
8
|
+
* @param isFailure - Predicate marking a row as a failure outcome.
|
|
9
|
+
* @returns The sole row when there is one URL; otherwise the full array.
|
|
10
|
+
*/
|
|
11
|
+
export function finalizeBatch(results, isFailure) {
|
|
12
|
+
if (results.some(isFailure))
|
|
13
|
+
process.exitCode = EXIT_RUNTIME_FAILURE;
|
|
14
|
+
return results.length === 1 ? results[0] : results;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* status/inspect batch rows: a miss or a validation error row is a failure outcome.
|
|
18
|
+
*
|
|
19
|
+
* @param row - Batch row with a `status` field.
|
|
20
|
+
* @returns `true` when the row should fail the batch exit code.
|
|
21
|
+
*/
|
|
22
|
+
export function isBatchReadFailure(row) {
|
|
23
|
+
return row.status === 'miss' || row.status === 'error';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Sparse validation-failure row for multi-URL status/inspect. Only the fields agents need —
|
|
27
|
+
* no fake cacheKey/freshness/metadata padding.
|
|
28
|
+
*
|
|
29
|
+
* @param url - Input URL that failed validation.
|
|
30
|
+
* @param err - Error-like object with optional code/message/suggestions/ref.
|
|
31
|
+
* @returns Sparse error row for the batch result array.
|
|
32
|
+
*/
|
|
33
|
+
export function urlValidationErrorRow(url, err) {
|
|
34
|
+
return {
|
|
35
|
+
status: 'error',
|
|
36
|
+
normalizedUrl: url,
|
|
37
|
+
error: cliErrorFields(err),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type HumanField } from './cli-presentation.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shared URL / cache-key / path header used by status and inspect human output, plus any
|
|
4
|
+
* command-specific extra rows, formatted as label/value lines.
|
|
5
|
+
*
|
|
6
|
+
* @param target - Normalized URL, cache key, and store roots.
|
|
7
|
+
* @param extra - Optional additional label/value rows.
|
|
8
|
+
* @param artifactPath - Optional explicit path; defaults to the write-root artifact path.
|
|
9
|
+
* @returns Formatted human-output lines.
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatCacheTargetHeader(target: {
|
|
12
|
+
normalizedUrl: string;
|
|
13
|
+
cacheKey: string;
|
|
14
|
+
roots: {
|
|
15
|
+
writeRoot: string;
|
|
16
|
+
};
|
|
17
|
+
}, extra?: HumanField[], artifactPath?: string): string[];
|
|
18
|
+
/** Stderr tip pointing at the fetch shorthand when a URL has no cache entry. */
|
|
19
|
+
export declare function cacheMissHint(cliBin: string, normalizedUrl: string): string;
|
|
20
|
+
/** Visual row separator between per-URL blocks in multi-URL human output; null for single URLs. */
|
|
21
|
+
export declare function batchSeparator(multi: boolean): string | null;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { colors } from './color.js';
|
|
2
|
+
import { formatHumanFields } from './cli-presentation.js';
|
|
3
|
+
import { getArtifactPath } from './research/storage.js';
|
|
4
|
+
/**
|
|
5
|
+
* Shared URL / cache-key / path header used by status and inspect human output, plus any
|
|
6
|
+
* command-specific extra rows, formatted as label/value lines.
|
|
7
|
+
*
|
|
8
|
+
* @param target - Normalized URL, cache key, and store roots.
|
|
9
|
+
* @param extra - Optional additional label/value rows.
|
|
10
|
+
* @param artifactPath - Optional explicit path; defaults to the write-root artifact path.
|
|
11
|
+
* @returns Formatted human-output lines.
|
|
12
|
+
*/
|
|
13
|
+
export function formatCacheTargetHeader(target, extra = [], artifactPath) {
|
|
14
|
+
const path = artifactPath ?? getArtifactPath(target.roots.writeRoot, target.cacheKey);
|
|
15
|
+
return formatHumanFields([
|
|
16
|
+
['URL', colors.bold(target.normalizedUrl)],
|
|
17
|
+
['Cache Key', colors.bold(target.cacheKey)],
|
|
18
|
+
['Cache Path', colors.gray(path)],
|
|
19
|
+
...extra,
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
/** Stderr tip pointing at the fetch shorthand when a URL has no cache entry. */
|
|
23
|
+
export function cacheMissHint(cliBin, normalizedUrl) {
|
|
24
|
+
return `Cache miss — run: ${cliBin} ${normalizedUrl}`;
|
|
25
|
+
}
|
|
26
|
+
const BATCH_SEPARATOR_WIDTH = 40;
|
|
27
|
+
/** Visual row separator between per-URL blocks in multi-URL human output; null for single URLs. */
|
|
28
|
+
export function batchSeparator(multi) {
|
|
29
|
+
return multi ? '='.repeat(BATCH_SEPARATOR_WIDTH) : null;
|
|
30
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Preflight early-exit payload used before oclif command dispatch. */
|
|
2
|
+
export interface PreflightExit {
|
|
3
|
+
exitCode: number;
|
|
4
|
+
json: boolean;
|
|
5
|
+
envelope: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Print a preflight usage/error result (JSON envelope on stdout, or oclif-style human error) and exit.
|
|
9
|
+
*
|
|
10
|
+
* @param result - Exit code, JSON mode, and envelope to print.
|
|
11
|
+
* @returns Never — calls `process.exit()`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function exitWithPreflight(result: PreflightExit): never;
|
|
14
|
+
/**
|
|
15
|
+
* Command-not-found hook: print JSON error, set {@link EXIT_USAGE}, return envelope (no process.exit).
|
|
16
|
+
*
|
|
17
|
+
* @param options.command - Command id for the envelope.
|
|
18
|
+
* @param options.message - Human-readable error message.
|
|
19
|
+
* @param options.code - Stable error code.
|
|
20
|
+
* @param options.suggestions - Optional recovery tips.
|
|
21
|
+
* @returns The printed error envelope.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeCommandNotFoundJson(options: {
|
|
24
|
+
command: string;
|
|
25
|
+
message: string;
|
|
26
|
+
code: string;
|
|
27
|
+
suggestions?: string[];
|
|
28
|
+
}): Record<string, unknown>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { buildCliErrorEnvelope } from './envelope.js';
|
|
2
|
+
import { EXIT_USAGE } from './cli-error-policy.js';
|
|
3
|
+
const JSON_STDOUT_INDENT = 2;
|
|
4
|
+
/** Print the envelope as pretty JSON on stdout (the machine-readable channel). */
|
|
5
|
+
function printJsonEnvelope(envelope) {
|
|
6
|
+
console.log(JSON.stringify(envelope, null, JSON_STDOUT_INDENT));
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Print a preflight usage/error result (JSON envelope on stdout, or oclif-style human error) and exit.
|
|
10
|
+
*
|
|
11
|
+
* @param result - Exit code, JSON mode, and envelope to print.
|
|
12
|
+
* @returns Never — calls `process.exit()`.
|
|
13
|
+
*/
|
|
14
|
+
export function exitWithPreflight(result) {
|
|
15
|
+
process.exitCode = result.exitCode;
|
|
16
|
+
const message = String(result.envelope.stderr ?? '');
|
|
17
|
+
if (result.json) {
|
|
18
|
+
printJsonEnvelope(result.envelope);
|
|
19
|
+
}
|
|
20
|
+
else if (message) {
|
|
21
|
+
console.error(` › Error: ${message.replaceAll('\n', '\n › ')}`);
|
|
22
|
+
}
|
|
23
|
+
process.exit();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Command-not-found hook: print JSON error, set {@link EXIT_USAGE}, return envelope (no process.exit).
|
|
27
|
+
*
|
|
28
|
+
* @param options.command - Command id for the envelope.
|
|
29
|
+
* @param options.message - Human-readable error message.
|
|
30
|
+
* @param options.code - Stable error code.
|
|
31
|
+
* @param options.suggestions - Optional recovery tips.
|
|
32
|
+
* @returns The printed error envelope.
|
|
33
|
+
*/
|
|
34
|
+
export function writeCommandNotFoundJson(options) {
|
|
35
|
+
const envelope = buildCliErrorEnvelope({
|
|
36
|
+
command: options.command,
|
|
37
|
+
message: options.message,
|
|
38
|
+
code: options.code,
|
|
39
|
+
suggestions: options.suggestions,
|
|
40
|
+
});
|
|
41
|
+
process.exitCode = EXIT_USAGE;
|
|
42
|
+
printJsonEnvelope(envelope);
|
|
43
|
+
return envelope;
|
|
44
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Process succeeded. */
|
|
2
|
+
export declare const EXIT_OK = 0;
|
|
3
|
+
/** Runtime / batch failure (agents treat as failed). */
|
|
4
|
+
export declare const EXIT_RUNTIME_FAILURE = 1;
|
|
5
|
+
/** Usage / validation failure (flags, URLs, missing args). */
|
|
6
|
+
export declare const EXIT_USAGE = 2;
|
|
7
|
+
/** Stale content served after failed revalidation; success envelope may still be `ok: true`. */
|
|
8
|
+
export declare const EXIT_STALE_SERVED = 5;
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the process/envelope exit code from an oclif CLIError or plain Error.
|
|
11
|
+
*
|
|
12
|
+
* @param err - Error-like object with optional `oclif.exit` or `exitCode`.
|
|
13
|
+
* @returns Exit code; defaults to {@link EXIT_RUNTIME_FAILURE}.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveExitCode(err: {
|
|
16
|
+
oclif?: {
|
|
17
|
+
exit?: number;
|
|
18
|
+
};
|
|
19
|
+
exitCode?: number;
|
|
20
|
+
}): number;
|
|
21
|
+
/** Normalized error fields shared by human pretty-print and the `--json` envelope. */
|
|
22
|
+
export interface PreparedCliError {
|
|
23
|
+
exitCode: number;
|
|
24
|
+
code: string | undefined;
|
|
25
|
+
message: string | undefined;
|
|
26
|
+
suggestions: string[] | undefined;
|
|
27
|
+
ref: string | undefined;
|
|
28
|
+
stderr: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Normalize a thrown value into the fields humans and `--json` both need: stable code,
|
|
32
|
+
* suggestions (including fallbacks), and stderr lines that mirror human pretty-print.
|
|
33
|
+
*
|
|
34
|
+
* @param err - Thrown value (Error, CLIError, or unknown).
|
|
35
|
+
* @param options.bin - CLI binary name for help suggestions.
|
|
36
|
+
* @param options.command - Command id for help suggestions.
|
|
37
|
+
* @returns Prepared fields for exit handling and envelope construction.
|
|
38
|
+
*/
|
|
39
|
+
export declare function prepareCliError(err: unknown, options: {
|
|
40
|
+
bin: string;
|
|
41
|
+
command: string;
|
|
42
|
+
}): PreparedCliError;
|
|
43
|
+
/**
|
|
44
|
+
* Attach stable code + fallback suggestions onto a mutable error (human pretty-print path).
|
|
45
|
+
*
|
|
46
|
+
* @param err - Mutable error object receiving `code` / `suggestions`.
|
|
47
|
+
* @param options.bin - CLI binary name for help suggestions.
|
|
48
|
+
* @param options.command - Command id for help suggestions.
|
|
49
|
+
*/
|
|
50
|
+
export declare function enrichErrorForDisplay(err: {
|
|
51
|
+
code?: string;
|
|
52
|
+
suggestions?: string[];
|
|
53
|
+
message?: string;
|
|
54
|
+
}, options: {
|
|
55
|
+
bin: string;
|
|
56
|
+
command: string;
|
|
57
|
+
}): void;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { formatErrorForJson, normalizeCliErrorMessage, stableErrorCodeFrom, } from './envelope.js';
|
|
2
|
+
/** Process succeeded. */
|
|
3
|
+
export const EXIT_OK = 0;
|
|
4
|
+
/** Runtime / batch failure (agents treat as failed). */
|
|
5
|
+
export const EXIT_RUNTIME_FAILURE = 1;
|
|
6
|
+
/** Usage / validation failure (flags, URLs, missing args). */
|
|
7
|
+
export const EXIT_USAGE = 2;
|
|
8
|
+
/** Stale content served after failed revalidation; success envelope may still be `ok: true`. */
|
|
9
|
+
export const EXIT_STALE_SERVED = 5;
|
|
10
|
+
/**
|
|
11
|
+
* Resolves the process/envelope exit code from an oclif CLIError or plain Error.
|
|
12
|
+
*
|
|
13
|
+
* @param err - Error-like object with optional `oclif.exit` or `exitCode`.
|
|
14
|
+
* @returns Exit code; defaults to {@link EXIT_RUNTIME_FAILURE}.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveExitCode(err) {
|
|
17
|
+
return err?.oclif?.exit ?? err?.exitCode ?? EXIT_RUNTIME_FAILURE;
|
|
18
|
+
}
|
|
19
|
+
/** Default recovery tips when a throw site set a stable code but no suggestions. */
|
|
20
|
+
function fallbackSuggestionsForCode(code, bin, command) {
|
|
21
|
+
const help = command === bin ? `${bin} --help` : `${bin} ${command} --help`;
|
|
22
|
+
switch (code) {
|
|
23
|
+
case 'UNKNOWN_FLAG':
|
|
24
|
+
case 'INVALID_FLAG_VALUE':
|
|
25
|
+
case 'MISSING_FLAG_VALUE':
|
|
26
|
+
case 'DUPLICATE_FLAG':
|
|
27
|
+
case 'MISSING_ARGUMENT':
|
|
28
|
+
case 'UNEXPECTED_ARGUMENT':
|
|
29
|
+
return [`Check usage: ${help}`];
|
|
30
|
+
case 'INVALID_DURATION':
|
|
31
|
+
return ['Use a whole number plus a unit, e.g. 2h, 7d, or 6m.'];
|
|
32
|
+
default:
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Normalize a thrown value into the fields humans and `--json` both need: stable code,
|
|
38
|
+
* suggestions (including fallbacks), and stderr lines that mirror human pretty-print.
|
|
39
|
+
*
|
|
40
|
+
* @param err - Thrown value (Error, CLIError, or unknown).
|
|
41
|
+
* @param options.bin - CLI binary name for help suggestions.
|
|
42
|
+
* @param options.command - Command id for help suggestions.
|
|
43
|
+
* @returns Prepared fields for exit handling and envelope construction.
|
|
44
|
+
*/
|
|
45
|
+
export function prepareCliError(err, options) {
|
|
46
|
+
const e = err;
|
|
47
|
+
const exitCode = resolveExitCode(e);
|
|
48
|
+
const code = stableErrorCodeFrom(e);
|
|
49
|
+
const message = typeof e?.message === 'string' ? normalizeCliErrorMessage(e.message) : undefined;
|
|
50
|
+
const suggestions = e.suggestions?.length
|
|
51
|
+
? e.suggestions
|
|
52
|
+
: fallbackSuggestionsForCode(code, options.bin, options.command);
|
|
53
|
+
const stderr = message || code || suggestions?.length || e?.ref
|
|
54
|
+
? formatErrorForJson({ ...e, message, code, suggestions })
|
|
55
|
+
: String(err);
|
|
56
|
+
return { exitCode, code, message, suggestions, ref: e.ref, stderr };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Attach stable code + fallback suggestions onto a mutable error (human pretty-print path).
|
|
60
|
+
*
|
|
61
|
+
* @param err - Mutable error object receiving `code` / `suggestions`.
|
|
62
|
+
* @param options.bin - CLI binary name for help suggestions.
|
|
63
|
+
* @param options.command - Command id for help suggestions.
|
|
64
|
+
*/
|
|
65
|
+
export function enrichErrorForDisplay(err, options) {
|
|
66
|
+
if (!err.code) {
|
|
67
|
+
const code = stableErrorCodeFrom(err);
|
|
68
|
+
if (code)
|
|
69
|
+
err.code = code;
|
|
70
|
+
}
|
|
71
|
+
if (err.code && !err.suggestions?.length) {
|
|
72
|
+
err.suggestions = fallbackSuggestionsForCode(err.code, options.bin, options.command);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composition-root flag manifest: every CLI token that consumes a following argv value.
|
|
3
|
+
* Built from command class metadata so argv normalization stays free of command imports.
|
|
4
|
+
*/
|
|
5
|
+
export declare const VALUE_TAKING_FLAG_TOKENS: ReadonlySet<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Root segment of every registered command id (`config:get` → `config`). oclif joins namespaced
|
|
8
|
+
* command ids with `:` regardless of the display-only `topicSeparator` setting, so a token like
|
|
9
|
+
* `config:get` is a real command, not a URL — argv normalization checks this set before assuming
|
|
10
|
+
* `word:` is a URL scheme.
|
|
11
|
+
*/
|
|
12
|
+
export declare const KNOWN_COMMAND_ROOT_TOKENS: ReadonlySet<string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseCommand } from '../base-command.js';
|
|
2
|
+
import { commands } from '../commands.js';
|
|
3
|
+
import { valueTakingFlagTokensFromCommands } from './value-flags.js';
|
|
4
|
+
/**
|
|
5
|
+
* Composition-root flag manifest: every CLI token that consumes a following argv value.
|
|
6
|
+
* Built from command class metadata so argv normalization stays free of command imports.
|
|
7
|
+
*/
|
|
8
|
+
export const VALUE_TAKING_FLAG_TOKENS = valueTakingFlagTokensFromCommands(commands, BaseCommand.baseFlags);
|
|
9
|
+
/**
|
|
10
|
+
* Root segment of every registered command id (`config:get` → `config`). oclif joins namespaced
|
|
11
|
+
* command ids with `:` regardless of the display-only `topicSeparator` setting, so a token like
|
|
12
|
+
* `config:get` is a real command, not a URL — argv normalization checks this set before assuming
|
|
13
|
+
* `word:` is a URL scheme.
|
|
14
|
+
*/
|
|
15
|
+
export const KNOWN_COMMAND_ROOT_TOKENS = new Set(Object.keys(commands).map((id) => id.split(':')[0]));
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Shared flag/help copy so identical flags read identically across commands. */
|
|
2
|
+
export declare const CLI_FLAG_DESCRIPTIONS: {
|
|
3
|
+
readonly freshnessTierPolicy: "freshness tier policy";
|
|
4
|
+
readonly statusFreshnessTierPolicy: "freshness tier policy to evaluate; when omitted, uses the cached entry's own tier";
|
|
5
|
+
readonly fetchTtl: "TTL duration for freshness (e.g. \"2h\", \"7d\", \"6m\")";
|
|
6
|
+
readonly importTtl: "TTL duration for imported note freshness (e.g. \"2h\", \"7d\", \"6m\")";
|
|
7
|
+
readonly statusTtl: "TTL duration to evaluate freshness (e.g. \"2h\", \"7d\", \"6m\")";
|
|
8
|
+
readonly maxAge: "maximum cache age to accept (e.g. \"2h\", \"7d\", \"6m\")";
|
|
9
|
+
readonly fetchStorage: "override where this result is cached (secrets always stored globally)";
|
|
10
|
+
readonly importStorage: "override where this note is cached (secrets always stored globally)";
|
|
11
|
+
readonly fetchTopic: "main research topic for metadata (max 200 chars)";
|
|
12
|
+
readonly importTopic: "main topic for this research note (max 200 chars)";
|
|
13
|
+
readonly filterTopic: "exact topic (case-insensitive)";
|
|
14
|
+
readonly fetchTags: "taxonomic tags for this research (can be repeated, max 100 chars each)";
|
|
15
|
+
readonly importTags: "taxonomic tags (can be repeated, max 100 chars each)";
|
|
16
|
+
readonly filterTags: "tags to require (must match all)";
|
|
17
|
+
readonly format: "output format";
|
|
18
|
+
readonly readOnly: "(alias: --plan) block filesystem writes/deletes; network fetches still run; also honored via BONSAI_READ_ONLY/BONSAI_PLAN_MODE";
|
|
19
|
+
readonly toon: "emit the same envelope as --json, encoded as TOON (fewer tokens); cannot be combined with --json";
|
|
20
|
+
readonly sourceUrlGlob: "source URL glob (case-insensitive, supports * wildcard)";
|
|
21
|
+
readonly listArtifactType: "artifact type; section children are omitted from list - use inspect to see them";
|
|
22
|
+
readonly pruneArtifactType: "artifact type to prune, including section children";
|
|
23
|
+
readonly listFull: "include every metadata field (cache key, path, artifact type, tags, capture method, quality notes, timestamps); default output is a minimal row (source URLs, topic, freshness, token estimate)";
|
|
24
|
+
};
|
|
25
|
+
/** One human-readable label/value pair for CLI stdout. */
|
|
26
|
+
export type HumanField = readonly [label: string, value: string];
|
|
27
|
+
/**
|
|
28
|
+
* Format one cyan-padded label/value line for human CLI output.
|
|
29
|
+
*
|
|
30
|
+
* @param label - Field label (without trailing colon).
|
|
31
|
+
* @param value - Field value.
|
|
32
|
+
* @returns A single formatted line.
|
|
33
|
+
*/
|
|
34
|
+
export declare function formatHumanField(label: string, value: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Format many label/value lines for human CLI output.
|
|
37
|
+
*
|
|
38
|
+
* @param fields - Label/value pairs.
|
|
39
|
+
* @returns Formatted lines in the same order.
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatHumanFields(fields: readonly HumanField[]): string[];
|