@robinmordasiewicz/f5xc-xcsh 6.46.0 → 6.48.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/dist/index.js +436 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45354,8 +45354,8 @@ function getLogoModeFromEnv(envPrefix) {
|
|
|
45354
45354
|
var CLI_NAME = "xcsh";
|
|
45355
45355
|
var CLI_FULL_NAME = "F5 Distributed Cloud Shell";
|
|
45356
45356
|
function getVersion() {
|
|
45357
|
-
if ("6.
|
|
45358
|
-
return "6.
|
|
45357
|
+
if ("6.48.0") {
|
|
45358
|
+
return "6.48.0";
|
|
45359
45359
|
}
|
|
45360
45360
|
if (process.env.XCSH_VERSION) {
|
|
45361
45361
|
return process.env.XCSH_VERSION;
|
|
@@ -47744,6 +47744,24 @@ var DebugProtocolImpl = class {
|
|
|
47744
47744
|
stack: error instanceof Error ? error.stack : void 0
|
|
47745
47745
|
});
|
|
47746
47746
|
}
|
|
47747
|
+
/**
|
|
47748
|
+
* Emit headless mode event
|
|
47749
|
+
*/
|
|
47750
|
+
headless(event, data = {}) {
|
|
47751
|
+
this.emit("headless", event, data);
|
|
47752
|
+
}
|
|
47753
|
+
/**
|
|
47754
|
+
* Emit command execution event
|
|
47755
|
+
*/
|
|
47756
|
+
command(event, data = {}) {
|
|
47757
|
+
this.emit("command", event, data);
|
|
47758
|
+
}
|
|
47759
|
+
/**
|
|
47760
|
+
* Emit completion event
|
|
47761
|
+
*/
|
|
47762
|
+
completion(event, data = {}) {
|
|
47763
|
+
this.emit("completion", event, data);
|
|
47764
|
+
}
|
|
47747
47765
|
/**
|
|
47748
47766
|
* Get all captured events
|
|
47749
47767
|
*/
|
|
@@ -51207,6 +51225,9 @@ function isCustomDomain(name) {
|
|
|
51207
51225
|
const canonical = resolveDomainAlias(name);
|
|
51208
51226
|
return customDomains.has(canonical);
|
|
51209
51227
|
}
|
|
51228
|
+
function getDomainAliases() {
|
|
51229
|
+
return new Map(domainAliases);
|
|
51230
|
+
}
|
|
51210
51231
|
|
|
51211
51232
|
// src/extensions/types.ts
|
|
51212
51233
|
var RESERVED_API_ACTIONS = /* @__PURE__ */ new Set([
|
|
@@ -53104,6 +53125,109 @@ async function executeAPICommand(session, ctx, cmd) {
|
|
|
53104
53125
|
};
|
|
53105
53126
|
}
|
|
53106
53127
|
}
|
|
53128
|
+
function getCommandSuggestions(input, session) {
|
|
53129
|
+
const ctx = session.getContextPath();
|
|
53130
|
+
const suggestions = [];
|
|
53131
|
+
if (ctx.isRoot()) {
|
|
53132
|
+
for (const domain of customDomains.all()) {
|
|
53133
|
+
if (!input || domain.name.toLowerCase().startsWith(input.toLowerCase())) {
|
|
53134
|
+
suggestions.push({
|
|
53135
|
+
text: domain.name,
|
|
53136
|
+
description: domain.description,
|
|
53137
|
+
category: "domain"
|
|
53138
|
+
});
|
|
53139
|
+
}
|
|
53140
|
+
}
|
|
53141
|
+
for (const [alias, canonical] of getDomainAliases()) {
|
|
53142
|
+
if (!input || alias.toLowerCase().startsWith(input.toLowerCase())) {
|
|
53143
|
+
const domain = customDomains.get(canonical);
|
|
53144
|
+
suggestions.push({
|
|
53145
|
+
text: alias,
|
|
53146
|
+
description: domain ? `${domain.description} (alias)` : `Alias for ${canonical}`,
|
|
53147
|
+
category: "domain"
|
|
53148
|
+
});
|
|
53149
|
+
}
|
|
53150
|
+
}
|
|
53151
|
+
for (const extDomain of extensionRegistry.getExtendedDomains()) {
|
|
53152
|
+
if (isCustomDomain(extDomain) || isValidDomain(extDomain)) continue;
|
|
53153
|
+
if (!input || extDomain.toLowerCase().startsWith(input.toLowerCase())) {
|
|
53154
|
+
const merged = extensionRegistry.getMergedDomain(extDomain);
|
|
53155
|
+
suggestions.push({
|
|
53156
|
+
text: extDomain,
|
|
53157
|
+
description: merged?.description ?? `${extDomain} commands`,
|
|
53158
|
+
category: "domain"
|
|
53159
|
+
});
|
|
53160
|
+
}
|
|
53161
|
+
}
|
|
53162
|
+
allDomains().forEach((domain) => {
|
|
53163
|
+
if (isCustomDomain(domain)) return;
|
|
53164
|
+
if (!input || domain.toLowerCase().startsWith(input.toLowerCase())) {
|
|
53165
|
+
const merged = extensionRegistry.getMergedDomain(domain);
|
|
53166
|
+
const hasExt = merged?.hasExtension ? " (+ext)" : "";
|
|
53167
|
+
suggestions.push({
|
|
53168
|
+
text: domain,
|
|
53169
|
+
description: `Navigate to ${domain} domain${hasExt}`,
|
|
53170
|
+
category: "domain"
|
|
53171
|
+
});
|
|
53172
|
+
}
|
|
53173
|
+
});
|
|
53174
|
+
BUILTIN_COMMANDS.forEach((cmd) => {
|
|
53175
|
+
if (!input || cmd.toLowerCase().startsWith(input.toLowerCase())) {
|
|
53176
|
+
suggestions.push({
|
|
53177
|
+
text: cmd,
|
|
53178
|
+
description: getBuiltinDescription(cmd),
|
|
53179
|
+
category: "builtin"
|
|
53180
|
+
});
|
|
53181
|
+
}
|
|
53182
|
+
});
|
|
53183
|
+
}
|
|
53184
|
+
if (ctx.isDomain() && !ctx.isAction()) {
|
|
53185
|
+
const domain = ctx.domain ?? "";
|
|
53186
|
+
const extCmds = extensionRegistry.getExtensionCommandNames(domain);
|
|
53187
|
+
for (const cmd of extCmds) {
|
|
53188
|
+
if (!input || cmd.toLowerCase().startsWith(input.toLowerCase())) {
|
|
53189
|
+
const cmdDef = extensionRegistry.getExtensionCommand(
|
|
53190
|
+
domain,
|
|
53191
|
+
cmd
|
|
53192
|
+
);
|
|
53193
|
+
suggestions.push({
|
|
53194
|
+
text: cmd,
|
|
53195
|
+
description: cmdDef?.description ?? `${cmd} command`,
|
|
53196
|
+
category: "extension"
|
|
53197
|
+
});
|
|
53198
|
+
}
|
|
53199
|
+
}
|
|
53200
|
+
const commonActions = ["list", "get", "create", "delete", "update"];
|
|
53201
|
+
commonActions.forEach((action) => {
|
|
53202
|
+
if (!input || action.toLowerCase().startsWith(input.toLowerCase())) {
|
|
53203
|
+
suggestions.push({
|
|
53204
|
+
text: action,
|
|
53205
|
+
description: `${action} ${domain} resources`,
|
|
53206
|
+
category: "action"
|
|
53207
|
+
});
|
|
53208
|
+
}
|
|
53209
|
+
});
|
|
53210
|
+
}
|
|
53211
|
+
return suggestions;
|
|
53212
|
+
}
|
|
53213
|
+
function getBuiltinDescription(cmd) {
|
|
53214
|
+
const descriptions = /* @__PURE__ */ new Map([
|
|
53215
|
+
["help", "Show help information"],
|
|
53216
|
+
["clear", "Clear the screen"],
|
|
53217
|
+
["quit", "Exit the shell"],
|
|
53218
|
+
["exit", "Navigate up or exit"],
|
|
53219
|
+
["back", "Navigate up one level"],
|
|
53220
|
+
["..", "Navigate up one level"],
|
|
53221
|
+
["root", "Navigate to root"],
|
|
53222
|
+
["/", "Navigate to root"],
|
|
53223
|
+
["context", "Show current context"],
|
|
53224
|
+
["ctx", "Show current context"],
|
|
53225
|
+
["history", "Show command history"],
|
|
53226
|
+
["version", "Show version info"],
|
|
53227
|
+
["domains", "List available domains"]
|
|
53228
|
+
]);
|
|
53229
|
+
return descriptions.get(cmd) ?? "Built-in command";
|
|
53230
|
+
}
|
|
53107
53231
|
|
|
53108
53232
|
// src/repl/App.tsx
|
|
53109
53233
|
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -53457,13 +53581,314 @@ function App2({ initialSession } = {}) {
|
|
|
53457
53581
|
] });
|
|
53458
53582
|
}
|
|
53459
53583
|
|
|
53584
|
+
// src/headless/controller.ts
|
|
53585
|
+
import * as readline from "readline";
|
|
53586
|
+
|
|
53587
|
+
// src/headless/protocol.ts
|
|
53588
|
+
function parseInput2(line) {
|
|
53589
|
+
try {
|
|
53590
|
+
const parsed = JSON.parse(line);
|
|
53591
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
53592
|
+
return null;
|
|
53593
|
+
}
|
|
53594
|
+
const obj = parsed;
|
|
53595
|
+
if (typeof obj.type !== "string") {
|
|
53596
|
+
return null;
|
|
53597
|
+
}
|
|
53598
|
+
const validTypes = [
|
|
53599
|
+
"command",
|
|
53600
|
+
"completion_request",
|
|
53601
|
+
"interrupt",
|
|
53602
|
+
"exit"
|
|
53603
|
+
];
|
|
53604
|
+
if (!validTypes.includes(obj.type)) {
|
|
53605
|
+
return null;
|
|
53606
|
+
}
|
|
53607
|
+
const result = {
|
|
53608
|
+
type: obj.type
|
|
53609
|
+
};
|
|
53610
|
+
if (typeof obj.value === "string") {
|
|
53611
|
+
result.value = obj.value;
|
|
53612
|
+
}
|
|
53613
|
+
if (typeof obj.partial === "string") {
|
|
53614
|
+
result.partial = obj.partial;
|
|
53615
|
+
}
|
|
53616
|
+
return result;
|
|
53617
|
+
} catch {
|
|
53618
|
+
return null;
|
|
53619
|
+
}
|
|
53620
|
+
}
|
|
53621
|
+
function formatOutput2(output) {
|
|
53622
|
+
return JSON.stringify({
|
|
53623
|
+
...output,
|
|
53624
|
+
timestamp: output.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
53625
|
+
});
|
|
53626
|
+
}
|
|
53627
|
+
function createOutputMessage(content, format = "text") {
|
|
53628
|
+
return {
|
|
53629
|
+
type: "output",
|
|
53630
|
+
content,
|
|
53631
|
+
format,
|
|
53632
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
53633
|
+
};
|
|
53634
|
+
}
|
|
53635
|
+
function createPromptMessage(prompt) {
|
|
53636
|
+
return {
|
|
53637
|
+
type: "prompt",
|
|
53638
|
+
prompt,
|
|
53639
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
53640
|
+
};
|
|
53641
|
+
}
|
|
53642
|
+
function createCompletionResponse(suggestions) {
|
|
53643
|
+
return {
|
|
53644
|
+
type: "completion_response",
|
|
53645
|
+
suggestions,
|
|
53646
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
53647
|
+
};
|
|
53648
|
+
}
|
|
53649
|
+
function createErrorMessage(message, code = 1) {
|
|
53650
|
+
return {
|
|
53651
|
+
type: "error",
|
|
53652
|
+
message,
|
|
53653
|
+
code,
|
|
53654
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
53655
|
+
};
|
|
53656
|
+
}
|
|
53657
|
+
function createEventMessage(event, data = {}) {
|
|
53658
|
+
return {
|
|
53659
|
+
type: "event",
|
|
53660
|
+
event,
|
|
53661
|
+
data,
|
|
53662
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
53663
|
+
};
|
|
53664
|
+
}
|
|
53665
|
+
function createExitMessage(code = 0) {
|
|
53666
|
+
return {
|
|
53667
|
+
type: "exit",
|
|
53668
|
+
code,
|
|
53669
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
53670
|
+
};
|
|
53671
|
+
}
|
|
53672
|
+
|
|
53673
|
+
// src/headless/controller.ts
|
|
53674
|
+
var HeadlessController = class {
|
|
53675
|
+
session;
|
|
53676
|
+
rl = null;
|
|
53677
|
+
running = false;
|
|
53678
|
+
constructor() {
|
|
53679
|
+
this.session = new REPLSession();
|
|
53680
|
+
}
|
|
53681
|
+
/**
|
|
53682
|
+
* Initialize the headless session
|
|
53683
|
+
*/
|
|
53684
|
+
async initialize() {
|
|
53685
|
+
await this.session.initialize();
|
|
53686
|
+
debugProtocol.session("init", { mode: "headless" });
|
|
53687
|
+
emitSessionState(this.session);
|
|
53688
|
+
this.emitEvent(
|
|
53689
|
+
"session_initialized",
|
|
53690
|
+
this.getSessionState()
|
|
53691
|
+
);
|
|
53692
|
+
}
|
|
53693
|
+
/**
|
|
53694
|
+
* Get current session state for output
|
|
53695
|
+
*/
|
|
53696
|
+
getSessionState() {
|
|
53697
|
+
const ctx = this.session.getContextPath();
|
|
53698
|
+
return {
|
|
53699
|
+
authenticated: this.session.isAuthenticated(),
|
|
53700
|
+
tokenValidated: this.session.isTokenValidated(),
|
|
53701
|
+
namespace: this.session.getNamespace(),
|
|
53702
|
+
serverUrl: this.session.getServerUrl(),
|
|
53703
|
+
activeProfile: this.session.getActiveProfileName(),
|
|
53704
|
+
context: {
|
|
53705
|
+
domain: ctx.domain,
|
|
53706
|
+
action: ctx.action
|
|
53707
|
+
}
|
|
53708
|
+
};
|
|
53709
|
+
}
|
|
53710
|
+
/**
|
|
53711
|
+
* Build prompt string based on current context
|
|
53712
|
+
*/
|
|
53713
|
+
buildPrompt() {
|
|
53714
|
+
const ctx = this.session.getContextPath();
|
|
53715
|
+
if (ctx.isRoot()) {
|
|
53716
|
+
return `${CLI_NAME}> `;
|
|
53717
|
+
}
|
|
53718
|
+
if (ctx.isAction()) {
|
|
53719
|
+
return `${CLI_NAME}:${ctx.domain}/${ctx.action}> `;
|
|
53720
|
+
}
|
|
53721
|
+
return `${CLI_NAME}:${ctx.domain}> `;
|
|
53722
|
+
}
|
|
53723
|
+
/**
|
|
53724
|
+
* Write output to stdout
|
|
53725
|
+
*/
|
|
53726
|
+
write(output) {
|
|
53727
|
+
console.log(formatOutput2(output));
|
|
53728
|
+
}
|
|
53729
|
+
/**
|
|
53730
|
+
* Emit an event
|
|
53731
|
+
*/
|
|
53732
|
+
emitEvent(event, data = {}) {
|
|
53733
|
+
this.write(createEventMessage(event, data));
|
|
53734
|
+
}
|
|
53735
|
+
/**
|
|
53736
|
+
* Send prompt
|
|
53737
|
+
*/
|
|
53738
|
+
sendPrompt() {
|
|
53739
|
+
this.write(createPromptMessage(this.buildPrompt()));
|
|
53740
|
+
}
|
|
53741
|
+
/**
|
|
53742
|
+
* Handle a command input
|
|
53743
|
+
*/
|
|
53744
|
+
async handleCommand(value) {
|
|
53745
|
+
debugProtocol.session("command_start", { command: value });
|
|
53746
|
+
try {
|
|
53747
|
+
const result = await executeCommand(value, this.session);
|
|
53748
|
+
if (result.output.length > 0) {
|
|
53749
|
+
const content = result.output.join("\n");
|
|
53750
|
+
let format = "text";
|
|
53751
|
+
if (content.startsWith("{") || content.startsWith("[")) {
|
|
53752
|
+
format = "json";
|
|
53753
|
+
} else if (content.includes(": ") && content.includes("\n")) {
|
|
53754
|
+
format = "yaml";
|
|
53755
|
+
}
|
|
53756
|
+
this.write(createOutputMessage(content, format));
|
|
53757
|
+
}
|
|
53758
|
+
if (result.shouldExit) {
|
|
53759
|
+
this.running = false;
|
|
53760
|
+
this.write(createExitMessage(0));
|
|
53761
|
+
return;
|
|
53762
|
+
}
|
|
53763
|
+
if (result.contextChanged) {
|
|
53764
|
+
this.emitEvent("context_changed", {
|
|
53765
|
+
context: {
|
|
53766
|
+
domain: this.session.getContextPath().domain,
|
|
53767
|
+
action: this.session.getContextPath().action
|
|
53768
|
+
}
|
|
53769
|
+
});
|
|
53770
|
+
}
|
|
53771
|
+
if (result.error) {
|
|
53772
|
+
this.write(createErrorMessage(result.error, 1));
|
|
53773
|
+
}
|
|
53774
|
+
debugProtocol.session("command_complete", {
|
|
53775
|
+
command: value,
|
|
53776
|
+
success: !result.error
|
|
53777
|
+
});
|
|
53778
|
+
} catch (error) {
|
|
53779
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
53780
|
+
this.write(createErrorMessage(message, 1));
|
|
53781
|
+
debugProtocol.error("command_failed", error, { command: value });
|
|
53782
|
+
}
|
|
53783
|
+
this.sendPrompt();
|
|
53784
|
+
}
|
|
53785
|
+
/**
|
|
53786
|
+
* Handle completion request
|
|
53787
|
+
*/
|
|
53788
|
+
handleCompletionRequest(partial) {
|
|
53789
|
+
debugProtocol.session("completion_request", { partial });
|
|
53790
|
+
const rawSuggestions = getCommandSuggestions(partial, this.session);
|
|
53791
|
+
const suggestions = rawSuggestions.map((s) => ({
|
|
53792
|
+
text: s.text,
|
|
53793
|
+
description: s.description,
|
|
53794
|
+
category: s.category
|
|
53795
|
+
}));
|
|
53796
|
+
this.write(createCompletionResponse(suggestions));
|
|
53797
|
+
}
|
|
53798
|
+
/**
|
|
53799
|
+
* Handle interrupt signal
|
|
53800
|
+
*/
|
|
53801
|
+
handleInterrupt() {
|
|
53802
|
+
debugProtocol.session("interrupt", {});
|
|
53803
|
+
this.emitEvent("interrupted", {});
|
|
53804
|
+
this.sendPrompt();
|
|
53805
|
+
}
|
|
53806
|
+
/**
|
|
53807
|
+
* Handle exit request
|
|
53808
|
+
*/
|
|
53809
|
+
handleExit() {
|
|
53810
|
+
this.running = false;
|
|
53811
|
+
this.write(createExitMessage(0));
|
|
53812
|
+
}
|
|
53813
|
+
/**
|
|
53814
|
+
* Process a single input message
|
|
53815
|
+
*/
|
|
53816
|
+
async processInput(input) {
|
|
53817
|
+
switch (input.type) {
|
|
53818
|
+
case "command":
|
|
53819
|
+
if (input.value !== void 0) {
|
|
53820
|
+
await this.handleCommand(input.value);
|
|
53821
|
+
} else {
|
|
53822
|
+
this.write(
|
|
53823
|
+
createErrorMessage(
|
|
53824
|
+
'Missing "value" for command input',
|
|
53825
|
+
1
|
|
53826
|
+
)
|
|
53827
|
+
);
|
|
53828
|
+
this.sendPrompt();
|
|
53829
|
+
}
|
|
53830
|
+
break;
|
|
53831
|
+
case "completion_request":
|
|
53832
|
+
this.handleCompletionRequest(input.partial ?? "");
|
|
53833
|
+
break;
|
|
53834
|
+
case "interrupt":
|
|
53835
|
+
this.handleInterrupt();
|
|
53836
|
+
break;
|
|
53837
|
+
case "exit":
|
|
53838
|
+
this.handleExit();
|
|
53839
|
+
break;
|
|
53840
|
+
default:
|
|
53841
|
+
this.write(
|
|
53842
|
+
createErrorMessage(`Unknown input type: ${input.type}`, 1)
|
|
53843
|
+
);
|
|
53844
|
+
this.sendPrompt();
|
|
53845
|
+
}
|
|
53846
|
+
}
|
|
53847
|
+
/**
|
|
53848
|
+
* Run the headless controller
|
|
53849
|
+
* Reads JSON messages from stdin, processes them, and writes responses to stdout
|
|
53850
|
+
*/
|
|
53851
|
+
async run() {
|
|
53852
|
+
await this.initialize();
|
|
53853
|
+
this.rl = readline.createInterface({
|
|
53854
|
+
input: process.stdin,
|
|
53855
|
+
output: process.stdout,
|
|
53856
|
+
terminal: false
|
|
53857
|
+
});
|
|
53858
|
+
this.running = true;
|
|
53859
|
+
this.sendPrompt();
|
|
53860
|
+
for await (const line of this.rl) {
|
|
53861
|
+
if (!this.running) break;
|
|
53862
|
+
const trimmed = line.trim();
|
|
53863
|
+
if (!trimmed) continue;
|
|
53864
|
+
const input = parseInput2(trimmed);
|
|
53865
|
+
if (!input) {
|
|
53866
|
+
this.write(
|
|
53867
|
+
createErrorMessage(`Invalid JSON input: ${trimmed}`, 1)
|
|
53868
|
+
);
|
|
53869
|
+
this.sendPrompt();
|
|
53870
|
+
continue;
|
|
53871
|
+
}
|
|
53872
|
+
await this.processInput(input);
|
|
53873
|
+
}
|
|
53874
|
+
this.rl?.close();
|
|
53875
|
+
}
|
|
53876
|
+
/**
|
|
53877
|
+
* Stop the controller
|
|
53878
|
+
*/
|
|
53879
|
+
stop() {
|
|
53880
|
+
this.running = false;
|
|
53881
|
+
this.rl?.close();
|
|
53882
|
+
}
|
|
53883
|
+
};
|
|
53884
|
+
|
|
53460
53885
|
// src/index.tsx
|
|
53461
53886
|
var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
|
|
53462
53887
|
var program2 = new Command();
|
|
53463
53888
|
program2.configureHelp({
|
|
53464
53889
|
formatHelp: () => formatRootHelp().join("\n")
|
|
53465
53890
|
});
|
|
53466
|
-
program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CLI for F5 XC").version(CLI_VERSION, "-v, --version", "Show version number").option("--no-color", "Disable color output").option("--logo <mode>", "Logo display mode: image, ascii, none").option("-o, --output <format>", "Output format (json, yaml, table)").option("--spec", "Output command specification as JSON (for AI)").option("-h, --help", "Show help").argument("[command...]", "Command to execute non-interactively").allowUnknownOption(true).helpOption(false).action(
|
|
53891
|
+
program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CLI for F5 XC").version(CLI_VERSION, "-v, --version", "Show version number").option("--no-color", "Disable color output").option("--logo <mode>", "Logo display mode: image, ascii, none").option("-o, --output <format>", "Output format (json, yaml, table)").option("--spec", "Output command specification as JSON (for AI)").option("--headless", "Run in headless JSON protocol mode (for AI agents)").option("-h, --help", "Show help").argument("[command...]", "Command to execute non-interactively").allowUnknownOption(true).helpOption(false).action(
|
|
53467
53892
|
async (commandArgs, options) => {
|
|
53468
53893
|
if (options.help && commandArgs.length === 0) {
|
|
53469
53894
|
formatRootHelp().forEach((line) => console.log(line));
|
|
@@ -53485,6 +53910,11 @@ program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CL
|
|
|
53485
53910
|
if (options.spec && commandArgs.length > 0) {
|
|
53486
53911
|
commandArgs.push("--spec");
|
|
53487
53912
|
}
|
|
53913
|
+
if (options.headless) {
|
|
53914
|
+
const controller = new HeadlessController();
|
|
53915
|
+
await controller.run();
|
|
53916
|
+
return;
|
|
53917
|
+
}
|
|
53488
53918
|
if (commandArgs.length === 0) {
|
|
53489
53919
|
if (!process.stdin.isTTY) {
|
|
53490
53920
|
console.error(
|
|
@@ -53493,6 +53923,9 @@ program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CL
|
|
|
53493
53923
|
console.error(
|
|
53494
53924
|
"Use: xcsh <command> for non-interactive execution."
|
|
53495
53925
|
);
|
|
53926
|
+
console.error(
|
|
53927
|
+
"Or use: xcsh --headless for AI agent JSON protocol mode."
|
|
53928
|
+
);
|
|
53496
53929
|
process.exit(1);
|
|
53497
53930
|
}
|
|
53498
53931
|
const cliLogoMode = options.logo && isValidLogoMode(options.logo) ? options.logo : void 0;
|