@treeseed/cli 0.4.8 → 0.4.10
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/handlers/config-ui.d.ts +72 -0
- package/dist/cli/handlers/config-ui.js +785 -0
- package/dist/cli/handlers/config.js +105 -35
- package/dist/cli/handlers/export.d.ts +2 -0
- package/dist/cli/handlers/export.js +28 -0
- package/dist/cli/help-ui.d.ts +3 -0
- package/dist/cli/help-ui.js +490 -0
- package/dist/cli/help.d.ts +26 -0
- package/dist/cli/help.js +332 -91
- package/dist/cli/operations-registry.js +678 -28
- package/dist/cli/operations-types.d.ts +37 -2
- package/dist/cli/registry.d.ts +1 -0
- package/dist/cli/registry.js +2 -0
- package/dist/cli/runtime.js +22 -9
- package/dist/cli/ui/framework.d.ts +159 -0
- package/dist/cli/ui/framework.js +296 -0
- package/dist/cli/ui/mouse.d.ts +11 -0
- package/dist/cli/ui/mouse.js +72 -0
- package/package.json +7 -4
package/dist/cli/help.d.ts
CHANGED
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
import type { TreeseedOperationSpec } from './operations-types.ts';
|
|
2
|
+
export type TreeseedHelpEntryAccent = 'command' | 'flag' | 'argument' | 'example' | 'alias' | 'related';
|
|
3
|
+
export type TreeseedHelpEntry = {
|
|
4
|
+
label: string;
|
|
5
|
+
summary?: string;
|
|
6
|
+
accent?: TreeseedHelpEntryAccent;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
targetCommand?: string;
|
|
9
|
+
};
|
|
10
|
+
export type TreeseedHelpSection = {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
entries?: TreeseedHelpEntry[];
|
|
14
|
+
lines?: string[];
|
|
15
|
+
};
|
|
16
|
+
export type TreeseedHelpView = {
|
|
17
|
+
kind: 'top' | 'command' | 'unknown';
|
|
18
|
+
title: string;
|
|
19
|
+
subtitle?: string;
|
|
20
|
+
badge?: string;
|
|
21
|
+
sidebarTitle: string;
|
|
22
|
+
sections: TreeseedHelpSection[];
|
|
23
|
+
statusPrimary: string;
|
|
24
|
+
statusSecondary: string;
|
|
25
|
+
exitCode: number;
|
|
26
|
+
};
|
|
2
27
|
export declare function renderUsage(spec: TreeseedOperationSpec): string;
|
|
3
28
|
export declare function suggestTreeseedCommands(input: string): string[];
|
|
29
|
+
export declare function buildTreeseedHelpView(commandName?: string | null): TreeseedHelpView;
|
|
4
30
|
export declare function renderTreeseedHelp(commandName?: string | null): string;
|
package/dist/cli/help.js
CHANGED
|
@@ -7,6 +7,88 @@ const GROUP_ORDER = [
|
|
|
7
7
|
"Utilities",
|
|
8
8
|
"Passthrough"
|
|
9
9
|
];
|
|
10
|
+
function formatExecutionMode(spec) {
|
|
11
|
+
switch (spec.executionMode) {
|
|
12
|
+
case "handler":
|
|
13
|
+
return "cli handler";
|
|
14
|
+
case "adapter":
|
|
15
|
+
return "sdk adapter";
|
|
16
|
+
case "delegate":
|
|
17
|
+
return `delegated to ${spec.delegateTo ?? "runtime"}`;
|
|
18
|
+
default:
|
|
19
|
+
return spec.executionMode;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function formatOptionSummary(spec, flags, description) {
|
|
23
|
+
const option = (spec.options ?? []).find((candidate) => candidate.flags === flags);
|
|
24
|
+
if (!option) {
|
|
25
|
+
return description;
|
|
26
|
+
}
|
|
27
|
+
const traits = [];
|
|
28
|
+
if (option.kind === "enum" && (option.values?.length ?? 0) > 0) {
|
|
29
|
+
traits.push(`values: ${(option.values ?? []).join(", ")}`);
|
|
30
|
+
}
|
|
31
|
+
if (option.repeatable) {
|
|
32
|
+
traits.push("repeatable");
|
|
33
|
+
}
|
|
34
|
+
if (traits.length === 0) {
|
|
35
|
+
return description;
|
|
36
|
+
}
|
|
37
|
+
return `${description} (${traits.join("; ")})`;
|
|
38
|
+
}
|
|
39
|
+
function automationNotes(spec) {
|
|
40
|
+
if ((spec.help?.automationNotes?.length ?? 0) > 0) {
|
|
41
|
+
return spec.help?.automationNotes ?? [];
|
|
42
|
+
}
|
|
43
|
+
const lines = [
|
|
44
|
+
`Execution path: ${formatExecutionMode(spec)}.`,
|
|
45
|
+
`Provider: ${spec.provider}.`
|
|
46
|
+
];
|
|
47
|
+
if ((spec.options ?? []).some((option) => option.name === "json")) {
|
|
48
|
+
lines.push("Machine use: supports --json output for scripts and agents.");
|
|
49
|
+
} else {
|
|
50
|
+
lines.push("Machine use: human-oriented command with no dedicated --json surface.");
|
|
51
|
+
}
|
|
52
|
+
return lines;
|
|
53
|
+
}
|
|
54
|
+
function normalizeStructuredExamples(spec) {
|
|
55
|
+
if ((spec.help?.examples?.length ?? 0) > 0) {
|
|
56
|
+
return spec.help?.examples ?? [];
|
|
57
|
+
}
|
|
58
|
+
return (spec.examples ?? []).map((entry, index) => typeof entry === "string" ? {
|
|
59
|
+
command: entry,
|
|
60
|
+
title: `Example ${index + 1}`,
|
|
61
|
+
description: `Run ${spec.name} with a representative argument set.`
|
|
62
|
+
} : entry);
|
|
63
|
+
}
|
|
64
|
+
function detailMap(details) {
|
|
65
|
+
return new Map((details ?? []).map((entry) => [entry.name, entry.detail]));
|
|
66
|
+
}
|
|
67
|
+
function relatedMap(details) {
|
|
68
|
+
return new Map((details ?? []).map((entry) => [entry.name, entry.why]));
|
|
69
|
+
}
|
|
70
|
+
function commandSectionEntries(spec) {
|
|
71
|
+
const entries = [
|
|
72
|
+
{ label: "Command path", summary: `treeseed ${spec.name}` },
|
|
73
|
+
{ label: "Group", summary: spec.group },
|
|
74
|
+
{ label: "Workflow position", summary: spec.help?.workflowPosition ?? "general" },
|
|
75
|
+
{ label: "Execution", summary: formatExecutionMode(spec) },
|
|
76
|
+
{ label: "Provider", summary: spec.provider },
|
|
77
|
+
{ label: "Aliases", summary: spec.aliases.length > 0 ? spec.aliases.join(", ") : "none" }
|
|
78
|
+
];
|
|
79
|
+
return entries;
|
|
80
|
+
}
|
|
81
|
+
function exampleEntries(spec) {
|
|
82
|
+
return normalizeStructuredExamples(spec).flatMap((entry) => [
|
|
83
|
+
{
|
|
84
|
+
label: entry.command,
|
|
85
|
+
summary: `${entry.title}: ${entry.description}`,
|
|
86
|
+
accent: "example"
|
|
87
|
+
},
|
|
88
|
+
...entry.result ? [{ label: "Result", summary: entry.result }] : [],
|
|
89
|
+
...entry.why ? [{ label: "Why", summary: entry.why }] : []
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
10
92
|
function levenshtein(left, right) {
|
|
11
93
|
const rows = Array.from({ length: left.length + 1 }, () => new Array(right.length + 1).fill(0));
|
|
12
94
|
for (let i = 0; i <= left.length; i += 1) rows[i][0] = i;
|
|
@@ -28,12 +110,46 @@ function groupedCommands() {
|
|
|
28
110
|
const groups = /* @__PURE__ */ new Map();
|
|
29
111
|
for (const group of GROUP_ORDER) groups.set(group, []);
|
|
30
112
|
for (const spec of TRESEED_OPERATION_SPECS) {
|
|
113
|
+
if (spec.helpVisible === false) continue;
|
|
31
114
|
const entries = groups.get(spec.group) ?? [];
|
|
32
115
|
entries.push(spec);
|
|
33
116
|
groups.set(spec.group, entries);
|
|
34
117
|
}
|
|
118
|
+
for (const entries of groups.values()) {
|
|
119
|
+
entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
120
|
+
}
|
|
35
121
|
return groups;
|
|
36
122
|
}
|
|
123
|
+
function specEntries(specs) {
|
|
124
|
+
return specs.map((spec) => ({
|
|
125
|
+
label: spec.name,
|
|
126
|
+
summary: spec.help?.workflowPosition ? `${spec.help.workflowPosition} \u2022 ${spec.summary}` : spec.summary,
|
|
127
|
+
accent: "command",
|
|
128
|
+
targetCommand: spec.name
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
function sectionLines(lines) {
|
|
132
|
+
return (lines ?? []).filter((line) => line.trim().length > 0);
|
|
133
|
+
}
|
|
134
|
+
function entryLines(entries) {
|
|
135
|
+
if (entries.length === 0) {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
const labelWidth = Math.max(
|
|
139
|
+
0,
|
|
140
|
+
Math.min(
|
|
141
|
+
28,
|
|
142
|
+
entries.reduce((max, entry) => Math.max(max, entry.label.length), 0)
|
|
143
|
+
)
|
|
144
|
+
);
|
|
145
|
+
return entries.map((entry) => {
|
|
146
|
+
if (!entry.summary) {
|
|
147
|
+
return ` ${entry.label}`;
|
|
148
|
+
}
|
|
149
|
+
const spacer = entry.label.length < labelWidth ? " ".repeat(labelWidth - entry.label.length) : " ";
|
|
150
|
+
return ` ${entry.label}${spacer} ${entry.summary}`;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
37
153
|
function renderUsage(spec) {
|
|
38
154
|
if (spec.usage) return spec.usage;
|
|
39
155
|
const args = (spec.arguments ?? []).map((arg) => arg.required ? `<${arg.name}>` : `[${arg.name}]`);
|
|
@@ -45,110 +161,235 @@ function suggestTreeseedCommands(input) {
|
|
|
45
161
|
if (!normalized) return [];
|
|
46
162
|
return listTreeseedOperationNames().map((name) => ({ name, score: levenshtein(normalized, name) })).sort((left, right) => left.score - right.score || left.name.localeCompare(right.name)).slice(0, 3).map((entry) => entry.name);
|
|
47
163
|
}
|
|
48
|
-
function
|
|
164
|
+
function buildTreeseedHelpView(commandName) {
|
|
49
165
|
if (!commandName) {
|
|
50
166
|
const groups = groupedCommands();
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"",
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"",
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
" - Use `--json` on guidance and main workflow commands when an AI agent or script needs machine-readable output."
|
|
99
|
-
];
|
|
100
|
-
return sections2.filter(Boolean).join("\n");
|
|
101
|
-
}
|
|
102
|
-
if (commandName === "agents") {
|
|
103
|
-
return [
|
|
104
|
-
"agents Run the Treeseed agent runtime namespace.",
|
|
105
|
-
"",
|
|
106
|
-
"Usage",
|
|
107
|
-
" treeseed agents <command>",
|
|
108
|
-
" treeseed agents --help",
|
|
109
|
-
"",
|
|
110
|
-
"Notes",
|
|
111
|
-
" - Delegates to the integrated `@treeseed/core` agent runtime.",
|
|
112
|
-
" - Use `treeseed agents --help` to list supported agent subcommands."
|
|
113
|
-
].join("\n");
|
|
167
|
+
const featuredCommands = TRESEED_OPERATION_SPECS.filter((spec2) => spec2.helpVisible !== false && spec2.helpFeatured).sort((left, right) => left.name.localeCompare(right.name));
|
|
168
|
+
const sections2 = [];
|
|
169
|
+
if (featuredCommands.length > 0) {
|
|
170
|
+
sections2.push({
|
|
171
|
+
id: "featured",
|
|
172
|
+
title: "Featured Commands",
|
|
173
|
+
entries: specEntries(featuredCommands)
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
for (const group of GROUP_ORDER) {
|
|
177
|
+
const entries = groups.get(group) ?? [];
|
|
178
|
+
if (entries.length === 0) continue;
|
|
179
|
+
sections2.push({
|
|
180
|
+
id: `group:${group}`,
|
|
181
|
+
title: group,
|
|
182
|
+
entries: specEntries(entries)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
sections2.push({
|
|
186
|
+
id: "help",
|
|
187
|
+
title: "Help",
|
|
188
|
+
lines: [
|
|
189
|
+
"treeseed --help",
|
|
190
|
+
"treeseed help <command>",
|
|
191
|
+
"treeseed <command> --help"
|
|
192
|
+
]
|
|
193
|
+
});
|
|
194
|
+
sections2.push({
|
|
195
|
+
id: "notes",
|
|
196
|
+
title: "Notes",
|
|
197
|
+
lines: [
|
|
198
|
+
"Workspace-only commands must be run inside a Treeseed workspace; the CLI resolves the project root from ancestor directories when possible.",
|
|
199
|
+
"Help text is generated from the CLI command registry.",
|
|
200
|
+
"Use --json on supported workflow and utility commands when an AI agent or script needs machine-readable output."
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
return {
|
|
204
|
+
kind: "top",
|
|
205
|
+
title: "Treeseed CLI",
|
|
206
|
+
subtitle: "Command surface over the Treeseed SDK workflow operations, local adapters, and delegated runtime namespaces.",
|
|
207
|
+
badge: `${listTreeseedOperationNames().length} commands`,
|
|
208
|
+
sidebarTitle: "Sections",
|
|
209
|
+
sections: sections2,
|
|
210
|
+
statusPrimary: "Up/Down selects a section. PgUp/PgDn scroll. Enter, q, or Esc exits help.",
|
|
211
|
+
statusSecondary: "All commands, groups, and summaries are derived from the registry.",
|
|
212
|
+
exitCode: 0
|
|
213
|
+
};
|
|
114
214
|
}
|
|
115
215
|
const spec = findTreeseedOperation(commandName);
|
|
116
216
|
if (!spec) {
|
|
117
217
|
const suggestions = suggestTreeseedCommands(commandName);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
218
|
+
return {
|
|
219
|
+
kind: "unknown",
|
|
220
|
+
title: `Unknown treeseed command: ${commandName}`,
|
|
221
|
+
subtitle: suggestions.length > 0 ? `Closest matches: ${suggestions.map((item) => `\`${item}\``).join(", ")}` : "No close registry matches were found.",
|
|
222
|
+
badge: "Unknown command",
|
|
223
|
+
sidebarTitle: "Next Steps",
|
|
224
|
+
sections: [
|
|
225
|
+
...suggestions.length > 0 ? [{
|
|
226
|
+
id: "suggestions",
|
|
227
|
+
title: "Suggestions",
|
|
228
|
+
entries: suggestions.map((item) => ({ label: item, summary: "View this command help.", accent: "command", targetCommand: item }))
|
|
229
|
+
}] : [],
|
|
230
|
+
{
|
|
231
|
+
id: "help",
|
|
232
|
+
title: "Help",
|
|
233
|
+
lines: ["Run `treeseed help` to see the full command list."]
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
statusPrimary: "Enter, q, or Esc exits help.",
|
|
237
|
+
statusSecondary: "Unknown-command suggestions come from the same registry used by parsing and execution.",
|
|
238
|
+
exitCode: 1
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const sections = [
|
|
242
|
+
...(spec.help?.longSummary?.length ?? 0) > 0 || spec.description ? [{
|
|
243
|
+
id: "overview",
|
|
244
|
+
title: "Overview",
|
|
245
|
+
lines: spec.help?.longSummary ?? [spec.description ?? spec.summary]
|
|
246
|
+
}] : [],
|
|
247
|
+
...(spec.help?.whenToUse?.length ?? 0) > 0 ? [{
|
|
248
|
+
id: "when-to-use",
|
|
249
|
+
title: "When To Use",
|
|
250
|
+
lines: spec.help?.whenToUse ?? []
|
|
251
|
+
}] : [],
|
|
252
|
+
...(spec.help?.beforeYouRun?.length ?? 0) > 0 ? [{
|
|
253
|
+
id: "before-you-run",
|
|
254
|
+
title: "Before You Run",
|
|
255
|
+
lines: spec.help?.beforeYouRun ?? []
|
|
256
|
+
}] : [],
|
|
257
|
+
{
|
|
258
|
+
id: "command",
|
|
259
|
+
title: "Command",
|
|
260
|
+
entries: commandSectionEntries(spec)
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: "usage",
|
|
264
|
+
title: "Usage",
|
|
265
|
+
lines: [renderUsage(spec)]
|
|
121
266
|
}
|
|
122
|
-
|
|
123
|
-
|
|
267
|
+
];
|
|
268
|
+
if ((spec.arguments ?? []).length > 0) {
|
|
269
|
+
const argumentDetails = detailMap(spec.help?.argumentDetails);
|
|
270
|
+
sections.push({
|
|
271
|
+
id: "arguments",
|
|
272
|
+
title: "Arguments",
|
|
273
|
+
entries: (spec.arguments ?? []).map((arg) => ({
|
|
274
|
+
label: arg.required ? `<${arg.name}>` : `[${arg.name}]`,
|
|
275
|
+
summary: `${arg.description} (${arg.required ? "required" : "optional"})${argumentDetails.get(arg.name) ? ` ${argumentDetails.get(arg.name)}` : ""}`,
|
|
276
|
+
accent: "argument",
|
|
277
|
+
required: arg.required
|
|
278
|
+
}))
|
|
279
|
+
});
|
|
280
|
+
} else {
|
|
281
|
+
sections.push({
|
|
282
|
+
id: "arguments",
|
|
283
|
+
title: "Arguments",
|
|
284
|
+
lines: ["This command does not take positional arguments."]
|
|
285
|
+
});
|
|
124
286
|
}
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
287
|
+
if ((spec.options ?? []).length > 0) {
|
|
288
|
+
const optionDetails = detailMap(spec.help?.optionDetails);
|
|
289
|
+
sections.push({
|
|
290
|
+
id: "options",
|
|
291
|
+
title: "Options",
|
|
292
|
+
entries: (spec.options ?? []).map((option) => ({
|
|
293
|
+
label: option.flags,
|
|
294
|
+
summary: `${formatOptionSummary(spec, option.flags, option.description)}${optionDetails.get(option.flags) ? ` ${optionDetails.get(option.flags)}` : ""}`,
|
|
295
|
+
accent: "flag"
|
|
296
|
+
}))
|
|
297
|
+
});
|
|
298
|
+
} else {
|
|
299
|
+
sections.push({
|
|
300
|
+
id: "options",
|
|
301
|
+
title: "Options",
|
|
302
|
+
lines: ["This command does not define CLI options."]
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
if (spec.aliases.length > 0) {
|
|
306
|
+
sections.push({
|
|
307
|
+
id: "aliases",
|
|
308
|
+
title: "Aliases",
|
|
309
|
+
entries: spec.aliases.map((alias) => ({ label: alias, accent: "alias", targetCommand: alias }))
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
if (normalizeStructuredExamples(spec).length > 0) {
|
|
313
|
+
sections.push({
|
|
314
|
+
id: "examples",
|
|
315
|
+
title: "Examples",
|
|
316
|
+
entries: exampleEntries(spec)
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if ((spec.help?.outcomes?.length ?? 0) > 0 || (spec.notes?.length ?? 0) > 0) {
|
|
320
|
+
sections.push({
|
|
321
|
+
id: "behavior",
|
|
322
|
+
title: "Behavior",
|
|
323
|
+
lines: [...spec.help?.outcomes ?? [], ...spec.notes ?? []]
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
sections.push({
|
|
327
|
+
id: "automation",
|
|
328
|
+
title: "Automation",
|
|
329
|
+
lines: automationNotes(spec)
|
|
132
330
|
});
|
|
331
|
+
if ((spec.help?.warnings?.length ?? 0) > 0) {
|
|
332
|
+
sections.push({
|
|
333
|
+
id: "warnings",
|
|
334
|
+
title: "Warnings",
|
|
335
|
+
lines: spec.help?.warnings ?? []
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
if ((spec.related ?? []).length > 0) {
|
|
339
|
+
const relatedDetails = relatedMap(spec.help?.relatedDetails);
|
|
340
|
+
sections.push({
|
|
341
|
+
id: "related",
|
|
342
|
+
title: "Related",
|
|
343
|
+
entries: (spec.related ?? []).map((related) => ({
|
|
344
|
+
label: related,
|
|
345
|
+
summary: relatedDetails.get(related) ?? "Related command.",
|
|
346
|
+
accent: "related",
|
|
347
|
+
targetCommand: related
|
|
348
|
+
}))
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
if ((spec.help?.seeAlso?.length ?? 0) > 0) {
|
|
352
|
+
sections.push({
|
|
353
|
+
id: "see-also",
|
|
354
|
+
title: "See Also",
|
|
355
|
+
entries: (spec.help?.seeAlso ?? []).filter((name, index, entries) => entries.indexOf(name) === index && !spec.related.includes(name)).map((name) => ({
|
|
356
|
+
label: name,
|
|
357
|
+
summary: `Additional next step from the ${spec.name} reference surface.`,
|
|
358
|
+
accent: "related",
|
|
359
|
+
targetCommand: name
|
|
360
|
+
}))
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
kind: "command",
|
|
365
|
+
title: `${spec.name} ${spec.summary}`,
|
|
366
|
+
subtitle: spec.help?.workflowPosition ? `${spec.group} \u2022 ${spec.help.workflowPosition}` : spec.group,
|
|
367
|
+
badge: spec.provider,
|
|
368
|
+
sidebarTitle: spec.name,
|
|
369
|
+
sections,
|
|
370
|
+
statusPrimary: "Up/Down selects a section. PgUp/PgDn scroll. Enter opens linked commands. b/[ goes back. f/] goes forward.",
|
|
371
|
+
statusSecondary: "This view is generated from the same command registry used by parsing and execution.",
|
|
372
|
+
exitCode: 0
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function renderTreeseedHelp(commandName) {
|
|
376
|
+
const view = buildTreeseedHelpView(commandName);
|
|
133
377
|
const sections = [
|
|
134
|
-
|
|
135
|
-
|
|
378
|
+
view.title,
|
|
379
|
+
view.subtitle ?? "",
|
|
136
380
|
"",
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
(spec.related ?? []).length > 0 ? `
|
|
147
|
-
Related: ${spec.related.map((item) => `\`${item}\``).join(", ")}` : ""
|
|
148
|
-
];
|
|
149
|
-
return sections.filter(Boolean).join("\n");
|
|
381
|
+
...view.sections.flatMap((section) => {
|
|
382
|
+
const lines = [
|
|
383
|
+
...entryLines(section.entries ?? []),
|
|
384
|
+
...sectionLines(section.lines).map((line) => ` ${line}`)
|
|
385
|
+
];
|
|
386
|
+
return lines.length > 0 ? [formatSection(section.title, lines), ""] : [];
|
|
387
|
+
})
|
|
388
|
+
].filter(Boolean);
|
|
389
|
+
return sections.join("\n").trimEnd();
|
|
150
390
|
}
|
|
151
391
|
export {
|
|
392
|
+
buildTreeseedHelpView,
|
|
152
393
|
renderTreeseedHelp,
|
|
153
394
|
renderUsage,
|
|
154
395
|
suggestTreeseedCommands
|