@qodalis/cli 2.0.0-beta.12 → 2.0.0-beta.14
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/assets/cli-panel.css +78 -1
- package/package.json +2 -2
- package/public-api.d.mts +195 -22
- package/public-api.d.ts +195 -22
- package/public-api.js +1027 -453
- package/public-api.js.map +1 -1
- package/public-api.mjs +1023 -455
- package/public-api.mjs.map +1 -1
- package/wasm/qodalis_cli_wasm_bg.wasm +0 -0
package/public-api.js
CHANGED
|
@@ -409,10 +409,31 @@ var ICliPingServerService_TOKEN = "cli-ping-server-service";
|
|
|
409
409
|
var CliModuleRegistry_TOKEN = "cli-module-registry";
|
|
410
410
|
var CliBackgroundServiceRegistry_TOKEN = "cli-background-service-registry";
|
|
411
411
|
var CliPackageManagerService_TOKEN = "cli-package-manager-service";
|
|
412
|
+
var CliKeyValueStore_TOKEN = "cli-key-value-store";
|
|
413
|
+
var SyntaxHighlighterRegistry_TOKEN = "syntax-highlighter-registry";
|
|
412
414
|
|
|
413
415
|
// src/lib/version.ts
|
|
414
|
-
var LIBRARY_VERSION = "2.0.0-beta.
|
|
416
|
+
var LIBRARY_VERSION = "2.0.0-beta.14";
|
|
415
417
|
var API_VERSION = 2;
|
|
418
|
+
var ANONYMOUS = "\0anonymous";
|
|
419
|
+
function aliasOwner(context2) {
|
|
420
|
+
let auth;
|
|
421
|
+
try {
|
|
422
|
+
auth = context2.services.get(cliCore.ICliAuthorizationService_TOKEN);
|
|
423
|
+
} catch {
|
|
424
|
+
auth = void 0;
|
|
425
|
+
}
|
|
426
|
+
if (!auth) return void 0;
|
|
427
|
+
return auth.getPrincipal()?.name ?? ANONYMOUS;
|
|
428
|
+
}
|
|
429
|
+
function aliasesFor(state, owner) {
|
|
430
|
+
if (owner === void 0) return state?.aliases ?? {};
|
|
431
|
+
return state?.aliasesByUser?.[owner] ?? {};
|
|
432
|
+
}
|
|
433
|
+
function withAliases(state, owner, aliases) {
|
|
434
|
+
if (owner === void 0) return { aliases };
|
|
435
|
+
return { aliasesByUser: { ...state?.aliasesByUser ?? {}, [owner]: aliases } };
|
|
436
|
+
}
|
|
416
437
|
var CliAliasCommandProcessor = class {
|
|
417
438
|
constructor() {
|
|
418
439
|
this.command = "alias";
|
|
@@ -429,26 +450,33 @@ var CliAliasCommandProcessor = class {
|
|
|
429
450
|
},
|
|
430
451
|
storeName: "aliases"
|
|
431
452
|
};
|
|
453
|
+
/** Shared aliases (used when no auth module is loaded) */
|
|
432
454
|
this.userAliases = {};
|
|
455
|
+
this.aliasState = {};
|
|
433
456
|
this.processors = [
|
|
434
457
|
{
|
|
435
458
|
command: "ls",
|
|
436
459
|
description: "List all aliases",
|
|
437
460
|
processCommand: async (_, context2) => {
|
|
438
461
|
const { writer } = context2;
|
|
462
|
+
const visible = this.aliasesFor(context2);
|
|
439
463
|
writer.writeln("Aliases:");
|
|
440
|
-
Object.entries(
|
|
464
|
+
Object.entries(visible).forEach(
|
|
441
465
|
([alias, command2]) => {
|
|
442
466
|
writer.writeInfo(` ${alias} -> ${command2}`);
|
|
443
467
|
}
|
|
444
468
|
);
|
|
445
|
-
if (Object.keys(
|
|
469
|
+
if (Object.keys(visible).length === 0) {
|
|
446
470
|
writer.writeInfo(" No aliases defined");
|
|
447
471
|
}
|
|
448
472
|
}
|
|
449
473
|
}
|
|
450
474
|
];
|
|
451
475
|
}
|
|
476
|
+
/** Aliases visible to the current principal */
|
|
477
|
+
aliasesFor(context2) {
|
|
478
|
+
return aliasesFor(this.aliasState, aliasOwner(context2));
|
|
479
|
+
}
|
|
452
480
|
writeDescription(context2) {
|
|
453
481
|
const { writer, translator: t } = context2;
|
|
454
482
|
writer.writeln(t.t("cli.alias.long_description", "Create shortcut aliases for frequently used commands"));
|
|
@@ -474,7 +502,7 @@ var CliAliasCommandProcessor = class {
|
|
|
474
502
|
);
|
|
475
503
|
}
|
|
476
504
|
async processCommand(command2, context2) {
|
|
477
|
-
const registry = context2.services.
|
|
505
|
+
const registry = context2.services.getRequired(
|
|
478
506
|
CliProcessorsRegistry_TOKEN
|
|
479
507
|
);
|
|
480
508
|
const { writer } = context2;
|
|
@@ -494,18 +522,20 @@ var CliAliasCommandProcessor = class {
|
|
|
494
522
|
}
|
|
495
523
|
context2.writer.writeInfo(`${alias} -> ${command2.args[alias]}`);
|
|
496
524
|
}
|
|
497
|
-
context2
|
|
498
|
-
|
|
499
|
-
|
|
525
|
+
const owner = aliasOwner(context2);
|
|
526
|
+
context2.state.updateState(
|
|
527
|
+
withAliases(this.aliasState, owner, {
|
|
528
|
+
...aliasesFor(this.aliasState, owner),
|
|
500
529
|
...command2.args
|
|
501
|
-
}
|
|
502
|
-
|
|
530
|
+
})
|
|
531
|
+
);
|
|
503
532
|
await context2.state.persist();
|
|
504
533
|
}
|
|
505
534
|
async initialize(context2) {
|
|
506
535
|
this.stateSubscription?.unsubscribe();
|
|
507
|
-
this.stateSubscription = context2.state.select((x) => x
|
|
508
|
-
this.
|
|
536
|
+
this.stateSubscription = context2.state.select((x) => x).subscribe((state) => {
|
|
537
|
+
this.aliasState = state ?? {};
|
|
538
|
+
this.userAliases = this.aliasState.aliases ?? {};
|
|
509
539
|
});
|
|
510
540
|
}
|
|
511
541
|
};
|
|
@@ -1333,7 +1363,9 @@ var CliEvalCommandProcessor = class {
|
|
|
1333
1363
|
this.acceptsRawInput = true;
|
|
1334
1364
|
this.metadata = {
|
|
1335
1365
|
icon: "\u{1F9EE}",
|
|
1336
|
-
module: "misc"
|
|
1366
|
+
module: "misc",
|
|
1367
|
+
// Enforced only when an auth module is loaded (eval also needs allowEval)
|
|
1368
|
+
requiredPermissions: ["system:eval"]
|
|
1337
1369
|
};
|
|
1338
1370
|
}
|
|
1339
1371
|
async processCommand(command, context) {
|
|
@@ -2448,7 +2480,9 @@ var CliUnAliasCommandProcessor = class {
|
|
|
2448
2480
|
async processCommand(command2, context2) {
|
|
2449
2481
|
const { writer } = context2;
|
|
2450
2482
|
const aliasToRemove = command2.value;
|
|
2451
|
-
const
|
|
2483
|
+
const state = context2.state.getState();
|
|
2484
|
+
const owner = aliasOwner(context2);
|
|
2485
|
+
const aliases = aliasesFor(state, owner);
|
|
2452
2486
|
if (!aliases[aliasToRemove]) {
|
|
2453
2487
|
writer.writeError(`Alias ${aliasToRemove} not found`);
|
|
2454
2488
|
context2.process.exit(-1);
|
|
@@ -2458,9 +2492,7 @@ var CliUnAliasCommandProcessor = class {
|
|
|
2458
2492
|
Object.keys(aliases).filter((alias) => alias !== aliasToRemove).forEach((alias) => {
|
|
2459
2493
|
updated[alias] = aliases[alias];
|
|
2460
2494
|
});
|
|
2461
|
-
context2.state.updateState(
|
|
2462
|
-
aliases: updated
|
|
2463
|
-
});
|
|
2495
|
+
context2.state.updateState(withAliases(state, owner, updated));
|
|
2464
2496
|
await context2.state.persist();
|
|
2465
2497
|
}
|
|
2466
2498
|
};
|
|
@@ -2814,7 +2846,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
2814
2846
|
];
|
|
2815
2847
|
}
|
|
2816
2848
|
async processCommand(command2, context2) {
|
|
2817
|
-
const registry = context2.services.
|
|
2849
|
+
const registry = context2.services.getRequired(
|
|
2818
2850
|
CliProcessorsRegistry_TOKEN
|
|
2819
2851
|
);
|
|
2820
2852
|
const pluginCategories = cliCore.resolveConfigurationCategories(registry);
|
|
@@ -2911,10 +2943,10 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
2911
2943
|
if (stateKey === "system") {
|
|
2912
2944
|
const langOption = options.find((o) => o.key === "language");
|
|
2913
2945
|
if (langOption) {
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2946
|
+
const translator = context2.services.get(
|
|
2947
|
+
cliCore.ICliTranslationService_TOKEN
|
|
2948
|
+
);
|
|
2949
|
+
if (translator) {
|
|
2918
2950
|
const locales = translator.getAvailableLocales();
|
|
2919
2951
|
if (locales.length > 0) {
|
|
2920
2952
|
langOption.options = locales.map((l) => ({
|
|
@@ -2922,7 +2954,6 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
2922
2954
|
value: l
|
|
2923
2955
|
}));
|
|
2924
2956
|
}
|
|
2925
|
-
} catch {
|
|
2926
2957
|
}
|
|
2927
2958
|
}
|
|
2928
2959
|
}
|
|
@@ -3067,13 +3098,10 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
3067
3098
|
}
|
|
3068
3099
|
}
|
|
3069
3100
|
if (settings["language"]) {
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
translator.setLocale(settings["language"]);
|
|
3075
|
-
} catch {
|
|
3076
|
-
}
|
|
3101
|
+
const translator = context2.services.get(
|
|
3102
|
+
cliCore.ICliTranslationService_TOKEN
|
|
3103
|
+
);
|
|
3104
|
+
translator?.setLocale(settings["language"]);
|
|
3077
3105
|
}
|
|
3078
3106
|
if (context2.terminal?.options) {
|
|
3079
3107
|
if (settings["cursorBlink"] !== void 0) {
|
|
@@ -3103,7 +3131,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
3103
3131
|
aliases: ["ls"],
|
|
3104
3132
|
description: "List all configuration options and their current values",
|
|
3105
3133
|
processCommand: async (_, context2) => {
|
|
3106
|
-
const registry = context2.services.
|
|
3134
|
+
const registry = context2.services.getRequired(
|
|
3107
3135
|
CliProcessorsRegistry_TOKEN
|
|
3108
3136
|
);
|
|
3109
3137
|
const allOptions = this.getAllOptions(registry);
|
|
@@ -3165,7 +3193,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
3165
3193
|
}
|
|
3166
3194
|
const category = path.substring(0, dotIndex);
|
|
3167
3195
|
const key = path.substring(dotIndex + 1);
|
|
3168
|
-
const registry = context2.services.
|
|
3196
|
+
const registry = context2.services.getRequired(
|
|
3169
3197
|
CliProcessorsRegistry_TOKEN
|
|
3170
3198
|
);
|
|
3171
3199
|
const allOptions = this.getAllOptions(registry);
|
|
@@ -3217,7 +3245,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
3217
3245
|
}
|
|
3218
3246
|
const category = path.substring(0, dotIndex);
|
|
3219
3247
|
const key = path.substring(dotIndex + 1);
|
|
3220
|
-
const registry = context2.services.
|
|
3248
|
+
const registry = context2.services.getRequired(
|
|
3221
3249
|
CliProcessorsRegistry_TOKEN
|
|
3222
3250
|
);
|
|
3223
3251
|
const allOptions = this.getAllOptions(registry);
|
|
@@ -3277,7 +3305,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
|
|
|
3277
3305
|
t.t("cli.configure.system_reset", "System configuration reset to defaults")
|
|
3278
3306
|
);
|
|
3279
3307
|
} else {
|
|
3280
|
-
const registry = context2.services.
|
|
3308
|
+
const registry = context2.services.getRequired(
|
|
3281
3309
|
CliProcessorsRegistry_TOKEN
|
|
3282
3310
|
);
|
|
3283
3311
|
const categories2 = cliCore.resolveConfigurationCategories(registry);
|
|
@@ -3673,7 +3701,7 @@ var CliHelpCommandProcessor = class {
|
|
|
3673
3701
|
async processCommand(command2, context2) {
|
|
3674
3702
|
const { writer } = context2;
|
|
3675
3703
|
const t = context2.translator;
|
|
3676
|
-
const registry = context2.services.
|
|
3704
|
+
const registry = context2.services.getRequired(
|
|
3677
3705
|
CliProcessorsRegistry_TOKEN
|
|
3678
3706
|
);
|
|
3679
3707
|
const [_, ...commandsToHelp] = command2.command.split(" ");
|
|
@@ -3773,24 +3801,23 @@ var CliHelpCommandProcessor = class {
|
|
|
3773
3801
|
writeProcessorDescription(processor, context2) {
|
|
3774
3802
|
const { writer } = context2;
|
|
3775
3803
|
const t = context2.translator;
|
|
3776
|
-
const icon = processor.metadata?.icon || "";
|
|
3777
|
-
const name = `${BOLD}${writer.wrapInColor(processor.command, cliCore.CliForegroundColor.Cyan)}${RESET}`;
|
|
3778
3804
|
const version = `${DIM}v${processor.version || "1.0.0"}${RESET}`;
|
|
3779
|
-
|
|
3780
|
-
writer.writeln(` ${icon}${icon ? " " : ""}${name} ${version}`);
|
|
3805
|
+
const headerLines = [];
|
|
3781
3806
|
if (processor.description) {
|
|
3782
|
-
|
|
3783
|
-
processor.description,
|
|
3784
|
-
processor.command,
|
|
3785
|
-
context2
|
|
3807
|
+
headerLines.push(
|
|
3808
|
+
this.translateDescription(processor.description, processor.command, context2)
|
|
3786
3809
|
);
|
|
3787
|
-
writer.writeln(` ${desc}`);
|
|
3788
3810
|
}
|
|
3789
3811
|
if (processor.aliases?.length) {
|
|
3790
|
-
|
|
3791
|
-
|
|
3812
|
+
headerLines.push(
|
|
3813
|
+
`${DIM}${t.t("cli.help.aliases", "Aliases:")}${RESET} ${processor.aliases.map((a) => writer.wrapInColor(a, cliCore.CliForegroundColor.Magenta)).join(", ")}`
|
|
3792
3814
|
);
|
|
3793
3815
|
}
|
|
3816
|
+
writer.writeln();
|
|
3817
|
+
writer.writeBox(headerLines, {
|
|
3818
|
+
title: `${writer.wrapInColor(processor.command, cliCore.CliForegroundColor.Cyan)} ${version}`,
|
|
3819
|
+
borderColor: cliCore.CliForegroundColor.White
|
|
3820
|
+
});
|
|
3794
3821
|
if (processor.originalProcessor) {
|
|
3795
3822
|
writer.writeln();
|
|
3796
3823
|
writer.writeln(
|
|
@@ -3956,20 +3983,13 @@ var CliVersionCommandProcessor = class {
|
|
|
3956
3983
|
writer.writeln(
|
|
3957
3984
|
writer.wrapInColor(getCliNameArt(context2.terminal.cols), cliCore.CliForegroundColor.Cyan)
|
|
3958
3985
|
);
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
}
|
|
3967
|
-
writer.writeln(
|
|
3968
|
-
` ${DIM2}Framework${RESET2} ${writer.wrapInColor(framework, cliCore.CliForegroundColor.Cyan)}`
|
|
3969
|
-
);
|
|
3970
|
-
writer.writeln(
|
|
3971
|
-
` ${DIM2}Docs${RESET2} ${writer.wrapInColor("https://cli.qodalis.com/docs/", cliCore.CliForegroundColor.Blue)}`
|
|
3972
|
-
);
|
|
3986
|
+
const framework = context2.services.get("cli-framework") ?? "vanilla";
|
|
3987
|
+
writer.writeBox([
|
|
3988
|
+
`${DIM2}CLI${RESET2} ${writer.wrapInColor(`v${LIBRARY_VERSION}`, cliCore.CliForegroundColor.Green)}`,
|
|
3989
|
+
`${DIM2}Core${RESET2} ${writer.wrapInColor(`v${cliCore.LIBRARY_VERSION}`, cliCore.CliForegroundColor.Green)}`,
|
|
3990
|
+
`${DIM2}Framework${RESET2} ${writer.wrapInColor(framework, cliCore.CliForegroundColor.Cyan)}`,
|
|
3991
|
+
`${DIM2}Docs${RESET2} ${writer.wrapInColor("https://cli.qodalis.com/docs/", cliCore.CliForegroundColor.Blue)}`
|
|
3992
|
+
], { borderColor: cliCore.CliForegroundColor.White });
|
|
3973
3993
|
writer.writeln();
|
|
3974
3994
|
}
|
|
3975
3995
|
writeDescription(context2) {
|
|
@@ -4027,11 +4047,7 @@ function collectSystemInfo(context2) {
|
|
|
4027
4047
|
const lines = [];
|
|
4028
4048
|
lines.push(`- **CLI Version:** ${LIBRARY_VERSION}`);
|
|
4029
4049
|
lines.push(`- **Core Version:** ${cliCore.LIBRARY_VERSION}`);
|
|
4030
|
-
|
|
4031
|
-
try {
|
|
4032
|
-
framework = context2.services.get("cli-framework");
|
|
4033
|
-
} catch {
|
|
4034
|
-
}
|
|
4050
|
+
const framework = context2.services.get("cli-framework") ?? "vanilla";
|
|
4035
4051
|
lines.push(`- **Framework:** ${framework}`);
|
|
4036
4052
|
lines.push(`- **Terminal:** ${context2.terminal.cols}x${context2.terminal.rows}`);
|
|
4037
4053
|
if (typeof navigator !== "undefined") {
|
|
@@ -4103,12 +4119,8 @@ async function runInteractiveFlow(type, initialTitle, context2) {
|
|
|
4103
4119
|
`${writer.wrapInColor("\u2500\u2500 System Info (auto-attached) \u2500\u2500", cliCore.CliForegroundColor.Cyan)}`
|
|
4104
4120
|
);
|
|
4105
4121
|
writer.writeln(` CLI: ${LIBRARY_VERSION} Core: ${cliCore.LIBRARY_VERSION}`);
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
framework = context2.services.get("cli-framework");
|
|
4109
|
-
} catch {
|
|
4110
|
-
}
|
|
4111
|
-
writer.writeln(` Framework: ${framework} Terminal: ${context2.terminal.cols}x${context2.terminal.rows}`);
|
|
4122
|
+
const previewFramework = context2.services.get("cli-framework") ?? "vanilla";
|
|
4123
|
+
writer.writeln(` Framework: ${previewFramework} Terminal: ${context2.terminal.cols}x${context2.terminal.rows}`);
|
|
4112
4124
|
if (typeof navigator !== "undefined") {
|
|
4113
4125
|
writer.writeln(` Platform: ${navigator.platform} Language: ${navigator.language}`);
|
|
4114
4126
|
}
|
|
@@ -4250,7 +4262,7 @@ var CliHistoryCommandProcessor = class {
|
|
|
4250
4262
|
command: "clear",
|
|
4251
4263
|
description: "Clears the command history",
|
|
4252
4264
|
processCommand: async (_, context2) => {
|
|
4253
|
-
const commandHistory = context2.services.
|
|
4265
|
+
const commandHistory = context2.services.getRequired(
|
|
4254
4266
|
CliCommandHistory_TOKEN
|
|
4255
4267
|
);
|
|
4256
4268
|
await commandHistory.clearHistory();
|
|
@@ -4273,7 +4285,7 @@ var CliHistoryCommandProcessor = class {
|
|
|
4273
4285
|
description: "Search command history for a pattern",
|
|
4274
4286
|
parameters: searchParameters,
|
|
4275
4287
|
processCommand: async (cmd, context2) => {
|
|
4276
|
-
const commandHistory = context2.services.
|
|
4288
|
+
const commandHistory = context2.services.getRequired(
|
|
4277
4289
|
CliCommandHistory_TOKEN
|
|
4278
4290
|
);
|
|
4279
4291
|
const query = (cmd.value ?? "").trim();
|
|
@@ -4327,7 +4339,7 @@ var CliHistoryCommandProcessor = class {
|
|
|
4327
4339
|
}
|
|
4328
4340
|
async processCommand(_, context2) {
|
|
4329
4341
|
const { writer } = context2;
|
|
4330
|
-
const commandHistory = context2.services.
|
|
4342
|
+
const commandHistory = context2.services.getRequired(
|
|
4331
4343
|
CliCommandHistory_TOKEN
|
|
4332
4344
|
);
|
|
4333
4345
|
const history = commandHistory.getHistory();
|
|
@@ -4716,7 +4728,9 @@ var CliPackagesCommandProcessor = class {
|
|
|
4716
4728
|
this.metadata = {
|
|
4717
4729
|
sealed: true,
|
|
4718
4730
|
icon: "\u{1F4E6}",
|
|
4719
|
-
module: "system"
|
|
4731
|
+
module: "system",
|
|
4732
|
+
// Enforced only when an auth module is loaded
|
|
4733
|
+
requiredPermissions: ["system:packages"]
|
|
4720
4734
|
};
|
|
4721
4735
|
this.stateConfiguration = {
|
|
4722
4736
|
initialState: {
|
|
@@ -4774,7 +4788,7 @@ var CliPackagesCommandProcessor = class {
|
|
|
4774
4788
|
const { progressBar, writer } = context2;
|
|
4775
4789
|
const { signal, cleanup } = scope.createAbortSignal(context2);
|
|
4776
4790
|
progressBar.show();
|
|
4777
|
-
context2.
|
|
4791
|
+
context2.notifier.info("Browsing packages");
|
|
4778
4792
|
const prefix = packagesManager.QODALIS_COMMAND_PREFIX;
|
|
4779
4793
|
const knownShortNames = [
|
|
4780
4794
|
"browser-storage",
|
|
@@ -4967,7 +4981,7 @@ var CliPackagesCommandProcessor = class {
|
|
|
4967
4981
|
const packages = command2.value.split(" ");
|
|
4968
4982
|
for (const pkg of packages) {
|
|
4969
4983
|
if (signal.aborted) break;
|
|
4970
|
-
context2.
|
|
4984
|
+
context2.notifier.info(`Installing ${pkg}`);
|
|
4971
4985
|
await scope.addPackage(pkg, context2, signal);
|
|
4972
4986
|
}
|
|
4973
4987
|
cleanup();
|
|
@@ -5008,7 +5022,7 @@ var CliPackagesCommandProcessor = class {
|
|
|
5008
5022
|
const packages = command2.value.split(" ");
|
|
5009
5023
|
for (const pkg of packages) {
|
|
5010
5024
|
if (signal.aborted) break;
|
|
5011
|
-
context2.
|
|
5025
|
+
context2.notifier.info(`Removing ${pkg}`);
|
|
5012
5026
|
await scope.removePackage(pkg, context2);
|
|
5013
5027
|
}
|
|
5014
5028
|
cleanup();
|
|
@@ -5044,7 +5058,7 @@ var CliPackagesCommandProcessor = class {
|
|
|
5044
5058
|
const fullName = name.startsWith(prefix) ? name : `${prefix}${name}`;
|
|
5045
5059
|
progressBar.show();
|
|
5046
5060
|
progressBar.setText(`Fetching versions for ${name}`);
|
|
5047
|
-
context2.
|
|
5061
|
+
context2.notifier.info(`Fetching versions for ${name}`);
|
|
5048
5062
|
try {
|
|
5049
5063
|
const response = await scriptsLoader.getScript(
|
|
5050
5064
|
`https://registry.npmjs.org/${encodeURIComponent(fullName)}`,
|
|
@@ -5508,11 +5522,11 @@ var CliPackagesCommandProcessor = class {
|
|
|
5508
5522
|
);
|
|
5509
5523
|
}
|
|
5510
5524
|
async initialize(context2) {
|
|
5511
|
-
this.registry = context2.services.
|
|
5525
|
+
this.registry = context2.services.getRequired(
|
|
5512
5526
|
CliProcessorsRegistry_TOKEN
|
|
5513
5527
|
);
|
|
5514
|
-
const store = context2.services.
|
|
5515
|
-
|
|
5528
|
+
const store = context2.services.getRequired(
|
|
5529
|
+
CliKeyValueStore_TOKEN
|
|
5516
5530
|
);
|
|
5517
5531
|
this.packagesManager.setStore(store);
|
|
5518
5532
|
context2.services.set([{
|
|
@@ -5778,10 +5792,11 @@ var CliPackagesCommandProcessor = class {
|
|
|
5778
5792
|
}
|
|
5779
5793
|
};
|
|
5780
5794
|
var CliServerConnection = class _CliServerConnection {
|
|
5781
|
-
constructor(_config, _backgroundServices, _logger) {
|
|
5795
|
+
constructor(_config, _backgroundServices, _logger, _authService) {
|
|
5782
5796
|
this._config = _config;
|
|
5783
5797
|
this._backgroundServices = _backgroundServices;
|
|
5784
5798
|
this._logger = _logger;
|
|
5799
|
+
this._authService = _authService;
|
|
5785
5800
|
this._connected = false;
|
|
5786
5801
|
this._commands = [];
|
|
5787
5802
|
this._capabilities = null;
|
|
@@ -5790,6 +5805,8 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
5790
5805
|
this._basePath = "";
|
|
5791
5806
|
this._wsReconnectAttempts = 0;
|
|
5792
5807
|
this._wsReconnectTimer = null;
|
|
5808
|
+
/** True once this connection registered its `server-events:<name>` background service */
|
|
5809
|
+
this._eventServiceRegistered = false;
|
|
5793
5810
|
this._healthCheckTimer = null;
|
|
5794
5811
|
this._healthCheckAttempts = 0;
|
|
5795
5812
|
}
|
|
@@ -5820,10 +5837,33 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
5820
5837
|
get apiVersion() {
|
|
5821
5838
|
return this._apiVersion;
|
|
5822
5839
|
}
|
|
5840
|
+
/**
|
|
5841
|
+
* Resolve auth headers for this server connection.
|
|
5842
|
+
* Uses the auth service (which merges config headers with registered
|
|
5843
|
+
* ICliServerAuthTokenProviders), or falls back to config headers directly.
|
|
5844
|
+
*/
|
|
5845
|
+
resolveAuthHeaders() {
|
|
5846
|
+
if (this._authService) {
|
|
5847
|
+
return this._authService.getHeaders(this._config.name, this._config.headers);
|
|
5848
|
+
}
|
|
5849
|
+
return cliCore.resolveHeaders(this._config.headers);
|
|
5850
|
+
}
|
|
5851
|
+
/**
|
|
5852
|
+
* WebSocket URL for this server with auth: single-use upgrade params from
|
|
5853
|
+
* auth providers when available, otherwise headers copied into the URL.
|
|
5854
|
+
*/
|
|
5855
|
+
async buildWebSocketUrl(path) {
|
|
5856
|
+
const url = this.toWebSocketUrl(this.normalizeUrl(this._config.url)) + path;
|
|
5857
|
+
const params = await this._authService?.getWebSocketParams?.(this._config.name);
|
|
5858
|
+
if (params) {
|
|
5859
|
+
return cliCore.appendQueryParams(url, params);
|
|
5860
|
+
}
|
|
5861
|
+
return cliCore.buildAuthenticatedWebSocketUrl(url, () => this.resolveAuthHeaders());
|
|
5862
|
+
}
|
|
5823
5863
|
async connect() {
|
|
5824
5864
|
try {
|
|
5825
5865
|
const baseUrl = this.normalizeUrl(this._config.url);
|
|
5826
|
-
const negotiated = await cliCore.ServerVersionNegotiator.discover(baseUrl);
|
|
5866
|
+
const negotiated = await cliCore.ServerVersionNegotiator.discover(baseUrl, () => this.resolveAuthHeaders());
|
|
5827
5867
|
if (negotiated) {
|
|
5828
5868
|
this._apiVersion = negotiated.apiVersion;
|
|
5829
5869
|
this._basePath = negotiated.basePath;
|
|
@@ -6011,15 +6051,25 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
6011
6051
|
return;
|
|
6012
6052
|
}
|
|
6013
6053
|
const serviceName = `server-events:${this._config.name}`;
|
|
6054
|
+
if (this._eventServiceRegistered && this._backgroundServices.getStatus(serviceName)) {
|
|
6055
|
+
const status = this._backgroundServices.getStatus(serviceName).status;
|
|
6056
|
+
const restart = status === "running" ? this._backgroundServices.restart(serviceName) : this._backgroundServices.start(serviceName);
|
|
6057
|
+
restart.catch((e) => {
|
|
6058
|
+
this._logger?.debug(`Background event service failed for "${this._config.name}", falling back to direct: ${e}`);
|
|
6059
|
+
this.connectEventSocketDirect();
|
|
6060
|
+
});
|
|
6061
|
+
return;
|
|
6062
|
+
}
|
|
6014
6063
|
try {
|
|
6015
6064
|
this._backgroundServices.register({
|
|
6016
6065
|
name: serviceName,
|
|
6017
6066
|
description: `Event stream for server '${this._config.name}'`,
|
|
6018
6067
|
type: "daemon",
|
|
6019
6068
|
onStart: async (ctx) => {
|
|
6020
|
-
const
|
|
6021
|
-
|
|
6022
|
-
ctx.log(`Connecting to ${wsUrl}`);
|
|
6069
|
+
const wsUrl = await this.buildWebSocketUrl("/ws/v1/qcli/events");
|
|
6070
|
+
if (!this._connected) return;
|
|
6071
|
+
ctx.log(`Connecting to ${wsUrl.split("?")[0]}`);
|
|
6072
|
+
this.closeEventSocketDirect();
|
|
6023
6073
|
this._eventSocket = new WebSocket(wsUrl);
|
|
6024
6074
|
this._eventSocket.onopen = () => {
|
|
6025
6075
|
this._wsReconnectAttempts = 0;
|
|
@@ -6042,7 +6092,11 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
6042
6092
|
} catch {
|
|
6043
6093
|
}
|
|
6044
6094
|
};
|
|
6045
|
-
this._eventSocket.onclose = () => {
|
|
6095
|
+
this._eventSocket.onclose = (event) => {
|
|
6096
|
+
if (this.isSessionEndedClose(event)) {
|
|
6097
|
+
ctx.log("Event socket closed: session ended", "info");
|
|
6098
|
+
return;
|
|
6099
|
+
}
|
|
6046
6100
|
if (this._connected) {
|
|
6047
6101
|
ctx.log("WebSocket closed unexpectedly, scheduling reconnect", "warn");
|
|
6048
6102
|
this.scheduleWsReconnect();
|
|
@@ -6056,6 +6110,7 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
6056
6110
|
this.closeEventSocketDirect();
|
|
6057
6111
|
}
|
|
6058
6112
|
});
|
|
6113
|
+
this._eventServiceRegistered = true;
|
|
6059
6114
|
this._backgroundServices.start(serviceName).catch((e) => {
|
|
6060
6115
|
this._logger?.debug(`Background event service failed for "${this._config.name}", falling back to direct: ${e}`);
|
|
6061
6116
|
this.connectEventSocketDirect();
|
|
@@ -6066,9 +6121,13 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
6066
6121
|
}
|
|
6067
6122
|
}
|
|
6068
6123
|
connectEventSocketDirect() {
|
|
6124
|
+
void this.connectEventSocketDirectAsync();
|
|
6125
|
+
}
|
|
6126
|
+
async connectEventSocketDirectAsync() {
|
|
6069
6127
|
try {
|
|
6070
|
-
const
|
|
6071
|
-
|
|
6128
|
+
const wsUrl = await this.buildWebSocketUrl("/ws/v1/qcli/events");
|
|
6129
|
+
if (!this._connected) return;
|
|
6130
|
+
this.closeEventSocketDirect();
|
|
6072
6131
|
this._eventSocket = new WebSocket(wsUrl);
|
|
6073
6132
|
this._eventSocket.onopen = () => {
|
|
6074
6133
|
this._wsReconnectAttempts = 0;
|
|
@@ -6086,7 +6145,8 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
6086
6145
|
} catch {
|
|
6087
6146
|
}
|
|
6088
6147
|
};
|
|
6089
|
-
this._eventSocket.onclose = () => {
|
|
6148
|
+
this._eventSocket.onclose = (event) => {
|
|
6149
|
+
if (this.isSessionEndedClose(event)) return;
|
|
6090
6150
|
if (this._connected) {
|
|
6091
6151
|
this.scheduleWsReconnect();
|
|
6092
6152
|
}
|
|
@@ -6097,6 +6157,16 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
6097
6157
|
this._logger?.debug(`WebSocket not available for "${this._config.name}": ${e}`);
|
|
6098
6158
|
}
|
|
6099
6159
|
}
|
|
6160
|
+
/**
|
|
6161
|
+
* The server closes the event socket with 4401 when the session behind it
|
|
6162
|
+
* ended (logout, revoke, expiry). Retrying with the same credentials cannot
|
|
6163
|
+
* succeed; the auth layer reconnects the server when the session changes.
|
|
6164
|
+
*/
|
|
6165
|
+
isSessionEndedClose(event) {
|
|
6166
|
+
if (event?.code !== 4401) return false;
|
|
6167
|
+
this.closeEventSocketDirect();
|
|
6168
|
+
return true;
|
|
6169
|
+
}
|
|
6100
6170
|
handleServerDisconnect() {
|
|
6101
6171
|
this._connected = false;
|
|
6102
6172
|
this._commands = [];
|
|
@@ -6171,7 +6241,7 @@ var CliServerConnection = class _CliServerConnection {
|
|
|
6171
6241
|
const controller = new AbortController();
|
|
6172
6242
|
const timer = setTimeout(() => controller.abort(), timeout);
|
|
6173
6243
|
const headers = {
|
|
6174
|
-
...this.
|
|
6244
|
+
...this.resolveAuthHeaders(),
|
|
6175
6245
|
...init?.headers ?? {}
|
|
6176
6246
|
};
|
|
6177
6247
|
return fetch(url, {
|
|
@@ -6252,7 +6322,7 @@ async function executeOnServer(connection, serverName, descriptor, command2, con
|
|
|
6252
6322
|
chainCommands: commandPath && commandPath.length > 1 ? commandPath.slice(1) : []
|
|
6253
6323
|
};
|
|
6254
6324
|
const cmdLabel = commandPath && commandPath.length > 0 ? commandPath.join(" ") : descriptor.command;
|
|
6255
|
-
context2.
|
|
6325
|
+
context2.notifier.info(`executing command: ${cmdLabel} on server ${serverName}`);
|
|
6256
6326
|
try {
|
|
6257
6327
|
if (connection.capabilities?.streaming) {
|
|
6258
6328
|
const result = await connection.executeStream(
|
|
@@ -6307,6 +6377,7 @@ var CliServerProxyProcessor = class _CliServerProxyProcessor {
|
|
|
6307
6377
|
this.processors = descriptor.processors?.map(
|
|
6308
6378
|
(sub) => new _CliServerProxyProcessor(connection, sub, serverName, true, this.commandPath)
|
|
6309
6379
|
);
|
|
6380
|
+
this.acceptsRawInput = !this.processors?.length;
|
|
6310
6381
|
}
|
|
6311
6382
|
async processCommand(command2, context2) {
|
|
6312
6383
|
return executeOnServer(
|
|
@@ -6355,6 +6426,7 @@ var CliServerMultiProxyProcessor = class _CliServerMultiProxyProcessor {
|
|
|
6355
6426
|
}).filter((e) => e !== null);
|
|
6356
6427
|
return new _CliServerMultiProxyProcessor(subEntries, this.provider, this.commandPath);
|
|
6357
6428
|
});
|
|
6429
|
+
this.acceptsRawInput = !this.processors?.length;
|
|
6358
6430
|
}
|
|
6359
6431
|
async processCommand(command2, context2) {
|
|
6360
6432
|
const defaultServer = this.provider.defaultServer;
|
|
@@ -6440,14 +6512,26 @@ var CliServerMultiProxyProcessor = class _CliServerMultiProxyProcessor {
|
|
|
6440
6512
|
// src/lib/server/cli-server-manager.ts
|
|
6441
6513
|
var CliServerManager_TOKEN = "cli-server-manager";
|
|
6442
6514
|
var CliServerManager = class {
|
|
6443
|
-
constructor(registry) {
|
|
6515
|
+
constructor(registry, authService) {
|
|
6444
6516
|
this.registry = registry;
|
|
6517
|
+
this.authService = authService;
|
|
6445
6518
|
this.connections = /* @__PURE__ */ new Map();
|
|
6446
6519
|
this._defaultServer = null;
|
|
6520
|
+
/** Bare-name aliases this manager registered (only these are ever removed) */
|
|
6521
|
+
this._bareAliases = /* @__PURE__ */ new Set();
|
|
6447
6522
|
}
|
|
6448
6523
|
get defaultServer() {
|
|
6449
6524
|
return this._defaultServer;
|
|
6450
6525
|
}
|
|
6526
|
+
preferredServer() {
|
|
6527
|
+
if (this._defaultServer && this.connections.get(this._defaultServer)?.connected) {
|
|
6528
|
+
return this._defaultServer;
|
|
6529
|
+
}
|
|
6530
|
+
for (const [name, connection] of this.connections) {
|
|
6531
|
+
if (connection.connected) return name;
|
|
6532
|
+
}
|
|
6533
|
+
return null;
|
|
6534
|
+
}
|
|
6451
6535
|
setDefaultServer(name) {
|
|
6452
6536
|
if (name !== null && !this.connections.has(name)) {
|
|
6453
6537
|
throw new Error(`Unknown server: ${name}`);
|
|
@@ -6462,7 +6546,7 @@ var CliServerManager = class {
|
|
|
6462
6546
|
this._backgroundServices = backgroundServices;
|
|
6463
6547
|
for (const config of servers) {
|
|
6464
6548
|
if (config.enabled === false) continue;
|
|
6465
|
-
const connection = new CliServerConnection(config, backgroundServices, cliLogger);
|
|
6549
|
+
const connection = new CliServerConnection(config, backgroundServices, cliLogger, this.authService);
|
|
6466
6550
|
this.connections.set(config.name, connection);
|
|
6467
6551
|
connection.onDisconnect = () => {
|
|
6468
6552
|
this.handleDisconnect(config.name);
|
|
@@ -6510,6 +6594,7 @@ var CliServerManager = class {
|
|
|
6510
6594
|
await connection.connect();
|
|
6511
6595
|
if (connection.connected) {
|
|
6512
6596
|
this.registerProxyProcessors(connection, name);
|
|
6597
|
+
this.unregisterBareAliases();
|
|
6513
6598
|
this.registerBareAliases();
|
|
6514
6599
|
return { success: true, commandCount: connection.commands.length };
|
|
6515
6600
|
}
|
|
@@ -6540,11 +6625,12 @@ var CliServerManager = class {
|
|
|
6540
6625
|
this.registerBareAliases();
|
|
6541
6626
|
}
|
|
6542
6627
|
unregisterBareAliases() {
|
|
6543
|
-
for (const p of
|
|
6544
|
-
if (
|
|
6628
|
+
for (const p of this._bareAliases) {
|
|
6629
|
+
if (this.registry.processors.includes(p)) {
|
|
6545
6630
|
this.registry.unregisterProcessor(p);
|
|
6546
6631
|
}
|
|
6547
6632
|
}
|
|
6633
|
+
this._bareAliases.clear();
|
|
6548
6634
|
}
|
|
6549
6635
|
registerProxyProcessors(connection, serverName) {
|
|
6550
6636
|
for (const descriptor of connection.commands) {
|
|
@@ -6568,7 +6654,7 @@ var CliServerManager = class {
|
|
|
6568
6654
|
}
|
|
6569
6655
|
for (const [command2, servers] of commandCounts) {
|
|
6570
6656
|
const existingProcessor = this.registry.findProcessor(command2, []);
|
|
6571
|
-
if (existingProcessor && !existingProcessor
|
|
6657
|
+
if (existingProcessor && !this._bareAliases.has(existingProcessor))
|
|
6572
6658
|
continue;
|
|
6573
6659
|
if (servers.length === 1) {
|
|
6574
6660
|
const serverName = servers[0];
|
|
@@ -6590,6 +6676,7 @@ var CliServerManager = class {
|
|
|
6590
6676
|
alias.command = command2;
|
|
6591
6677
|
alias.aliases = [namespacedCommand];
|
|
6592
6678
|
this.registry.registerProcessor(alias);
|
|
6679
|
+
this._bareAliases.add(alias);
|
|
6593
6680
|
} else {
|
|
6594
6681
|
const entries = servers.map((serverName) => {
|
|
6595
6682
|
const connection = this.connections.get(serverName);
|
|
@@ -6600,6 +6687,7 @@ var CliServerManager = class {
|
|
|
6600
6687
|
});
|
|
6601
6688
|
const multi = new CliServerMultiProxyProcessor(entries, this);
|
|
6602
6689
|
this.registry.registerProcessor(multi);
|
|
6690
|
+
this._bareAliases.add(multi);
|
|
6603
6691
|
}
|
|
6604
6692
|
}
|
|
6605
6693
|
}
|
|
@@ -6745,6 +6833,28 @@ var WASM_SEARCH_PATHS = [
|
|
|
6745
6833
|
"./assets/wasm/qodalis_cli_wasm_bg.wasm",
|
|
6746
6834
|
"/wasm/qodalis_cli_wasm_bg.wasm"
|
|
6747
6835
|
];
|
|
6836
|
+
function wasmCandidates(wasmUrl, baseUri) {
|
|
6837
|
+
const baseUrl = (typeof document !== "undefined" ? document.baseURI : void 0);
|
|
6838
|
+
let base;
|
|
6839
|
+
try {
|
|
6840
|
+
base = baseUrl ? new URL(baseUrl) : void 0;
|
|
6841
|
+
} catch {
|
|
6842
|
+
base = void 0;
|
|
6843
|
+
}
|
|
6844
|
+
const resolve = (url) => {
|
|
6845
|
+
if (!base) return url;
|
|
6846
|
+
try {
|
|
6847
|
+
return new URL(url, base).href;
|
|
6848
|
+
} catch {
|
|
6849
|
+
return url;
|
|
6850
|
+
}
|
|
6851
|
+
};
|
|
6852
|
+
const candidates = [];
|
|
6853
|
+
if (wasmUrl) candidates.push(resolve(wasmUrl));
|
|
6854
|
+
if (base) candidates.push(resolve("assets/wasm/qodalis_cli_wasm_bg.wasm"));
|
|
6855
|
+
candidates.push(...WASM_SEARCH_PATHS.map(resolve));
|
|
6856
|
+
return [...new Set(candidates)];
|
|
6857
|
+
}
|
|
6748
6858
|
var wasm;
|
|
6749
6859
|
var cachedDataViewMemory0 = null;
|
|
6750
6860
|
var cachedInt32ArrayMemory0 = null;
|
|
@@ -6973,7 +7083,7 @@ async function initWasmAccelerator(wasmUrl) {
|
|
|
6973
7083
|
return accelerator;
|
|
6974
7084
|
}
|
|
6975
7085
|
try {
|
|
6976
|
-
const paths = wasmUrl
|
|
7086
|
+
const paths = wasmCandidates(wasmUrl);
|
|
6977
7087
|
const bytes = await fetchWasmBinary(paths);
|
|
6978
7088
|
await instantiateWasm(bytes);
|
|
6979
7089
|
accelerator = createWasmAccelerator();
|
|
@@ -7013,7 +7123,7 @@ var CliDebugCommandProcessor = class {
|
|
|
7013
7123
|
metadata: { icon: cliCore.CliIcon.Extension, module: "system" },
|
|
7014
7124
|
processCommand: async (_, context2) => {
|
|
7015
7125
|
const { writer } = context2;
|
|
7016
|
-
const registry = context2.services.
|
|
7126
|
+
const registry = context2.services.getRequired(
|
|
7017
7127
|
CliProcessorsRegistry_TOKEN
|
|
7018
7128
|
);
|
|
7019
7129
|
writer.writeln(
|
|
@@ -7064,12 +7174,10 @@ var CliDebugCommandProcessor = class {
|
|
|
7064
7174
|
metadata: { icon: cliCore.CliIcon.Module, module: "system" },
|
|
7065
7175
|
processCommand: async (_, context2) => {
|
|
7066
7176
|
const { writer } = context2;
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
);
|
|
7072
|
-
} catch {
|
|
7177
|
+
const moduleRegistry = context2.services.get(
|
|
7178
|
+
CliModuleRegistry_TOKEN
|
|
7179
|
+
);
|
|
7180
|
+
if (!moduleRegistry) {
|
|
7073
7181
|
writer.writeError("Module registry not available.");
|
|
7074
7182
|
return;
|
|
7075
7183
|
}
|
|
@@ -7110,7 +7218,7 @@ var CliDebugCommandProcessor = class {
|
|
|
7110
7218
|
metadata: { icon: cliCore.CliIcon.Database, module: "system" },
|
|
7111
7219
|
processCommand: async (_, context2) => {
|
|
7112
7220
|
const { writer } = context2;
|
|
7113
|
-
const storeManager = context2.services.
|
|
7221
|
+
const storeManager = context2.services.getRequired(
|
|
7114
7222
|
CliStateStoreManager_TOKEN
|
|
7115
7223
|
);
|
|
7116
7224
|
const entries = storeManager.getStoreEntries();
|
|
@@ -7189,11 +7297,7 @@ var CliDebugCommandProcessor = class {
|
|
|
7189
7297
|
writer.writeln(
|
|
7190
7298
|
` ${writer.wrapInColor("CLI Version:", cliCore.CliForegroundColor.Cyan)} ${LIBRARY_VERSION}`
|
|
7191
7299
|
);
|
|
7192
|
-
|
|
7193
|
-
try {
|
|
7194
|
-
framework = context2.services.get("cli-framework");
|
|
7195
|
-
} catch {
|
|
7196
|
-
}
|
|
7300
|
+
const framework = context2.services.get("cli-framework") ?? "vanilla";
|
|
7197
7301
|
writer.writeln(
|
|
7198
7302
|
` ${writer.wrapInColor("Framework:", cliCore.CliForegroundColor.Cyan)} ${framework}`
|
|
7199
7303
|
);
|
|
@@ -7234,7 +7338,7 @@ var CliDebugCommandProcessor = class {
|
|
|
7234
7338
|
metadata: { icon: cliCore.CliIcon.Logs, module: "system" },
|
|
7235
7339
|
processCommand: async (_, context2) => {
|
|
7236
7340
|
const { writer } = context2;
|
|
7237
|
-
const history = context2.services.
|
|
7341
|
+
const history = context2.services.getRequired(
|
|
7238
7342
|
CliCommandHistory_TOKEN
|
|
7239
7343
|
);
|
|
7240
7344
|
const commands = history.getHistory();
|
|
@@ -7323,14 +7427,14 @@ var CliDebugCommandProcessor = class {
|
|
|
7323
7427
|
writer.writeln(
|
|
7324
7428
|
` ${online ? cliCore.CliIcon.CheckIcon : cliCore.CliIcon.CrossIcon} Network: ${online ? "online" : "offline"}`
|
|
7325
7429
|
);
|
|
7326
|
-
const registry = context2.services.
|
|
7430
|
+
const registry = context2.services.getRequired(
|
|
7327
7431
|
CliProcessorsRegistry_TOKEN
|
|
7328
7432
|
);
|
|
7329
7433
|
writer.writeln(
|
|
7330
7434
|
` ${cliCore.CliIcon.CheckIcon} Processors: ${registry.processors.length} loaded`
|
|
7331
7435
|
);
|
|
7332
7436
|
try {
|
|
7333
|
-
const moduleRegistry = context2.services.
|
|
7437
|
+
const moduleRegistry = context2.services.getRequired(
|
|
7334
7438
|
CliModuleRegistry_TOKEN
|
|
7335
7439
|
);
|
|
7336
7440
|
const modules = moduleRegistry.getAll();
|
|
@@ -7346,7 +7450,7 @@ var CliDebugCommandProcessor = class {
|
|
|
7346
7450
|
writer.writeln(
|
|
7347
7451
|
` ${wasmActive ? cliCore.CliIcon.CheckIcon : cliCore.CliIcon.WarningIcon} WASM Accelerator: ${wasmActive ? "loaded" : "using JS fallback"}`
|
|
7348
7452
|
);
|
|
7349
|
-
const historyService = context2.services.
|
|
7453
|
+
const historyService = context2.services.getRequired(
|
|
7350
7454
|
CliCommandHistory_TOKEN
|
|
7351
7455
|
);
|
|
7352
7456
|
writer.writeln(
|
|
@@ -7360,13 +7464,13 @@ var CliDebugCommandProcessor = class {
|
|
|
7360
7464
|
metadata: { icon: cliCore.CliIcon.Save, module: "system" },
|
|
7361
7465
|
processCommand: async (_, context2) => {
|
|
7362
7466
|
const { writer } = context2;
|
|
7363
|
-
const registry = context2.services.
|
|
7467
|
+
const registry = context2.services.getRequired(
|
|
7364
7468
|
CliProcessorsRegistry_TOKEN
|
|
7365
7469
|
);
|
|
7366
|
-
const history = context2.services.
|
|
7470
|
+
const history = context2.services.getRequired(
|
|
7367
7471
|
CliCommandHistory_TOKEN
|
|
7368
7472
|
);
|
|
7369
|
-
const storeManager = context2.services.
|
|
7473
|
+
const storeManager = context2.services.getRequired(
|
|
7370
7474
|
CliStateStoreManager_TOKEN
|
|
7371
7475
|
);
|
|
7372
7476
|
const report = {
|
|
@@ -7399,7 +7503,7 @@ var CliDebugCommandProcessor = class {
|
|
|
7399
7503
|
state: storeManager.getStoreEntries()
|
|
7400
7504
|
};
|
|
7401
7505
|
try {
|
|
7402
|
-
const moduleRegistry = context2.services.
|
|
7506
|
+
const moduleRegistry = context2.services.getRequired(
|
|
7403
7507
|
CliModuleRegistry_TOKEN
|
|
7404
7508
|
);
|
|
7405
7509
|
report["modules"] = moduleRegistry.getAll().map((m) => ({
|
|
@@ -7417,7 +7521,7 @@ var CliDebugCommandProcessor = class {
|
|
|
7417
7521
|
report["services"] = container.getRegisteredTokens();
|
|
7418
7522
|
}
|
|
7419
7523
|
try {
|
|
7420
|
-
const serverManager = context2.services.
|
|
7524
|
+
const serverManager = context2.services.getRequired(
|
|
7421
7525
|
CliServerManager_TOKEN
|
|
7422
7526
|
);
|
|
7423
7527
|
if (serverManager && serverManager.connections.size > 0) {
|
|
@@ -7441,13 +7545,9 @@ var CliDebugCommandProcessor = class {
|
|
|
7441
7545
|
metadata: { icon: cliCore.CliIcon.Server, module: "system" },
|
|
7442
7546
|
processCommand: async (_, context2) => {
|
|
7443
7547
|
const { writer } = context2;
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
CliServerManager_TOKEN
|
|
7448
|
-
);
|
|
7449
|
-
} catch {
|
|
7450
|
-
}
|
|
7548
|
+
const manager = context2.services.get(
|
|
7549
|
+
CliServerManager_TOKEN
|
|
7550
|
+
);
|
|
7451
7551
|
if (!manager || manager.connections.size === 0) {
|
|
7452
7552
|
writer.writeInfo("No servers configured.");
|
|
7453
7553
|
return;
|
|
@@ -7487,70 +7587,48 @@ var CliDebugCommandProcessor = class {
|
|
|
7487
7587
|
}
|
|
7488
7588
|
async processCommand(_, context2) {
|
|
7489
7589
|
const { writer } = context2;
|
|
7490
|
-
const registry = context2.services.
|
|
7590
|
+
const registry = context2.services.getRequired(
|
|
7491
7591
|
CliProcessorsRegistry_TOKEN
|
|
7492
7592
|
);
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
cliCore.CliForegroundColor.Yellow
|
|
7497
|
-
)
|
|
7498
|
-
);
|
|
7499
|
-
writer.writeDivider({ char: "=" });
|
|
7500
|
-
writer.writeln(
|
|
7501
|
-
` ${writer.wrapInColor("Core Version:", cliCore.CliForegroundColor.Cyan)} ${cliCore.LIBRARY_VERSION}`
|
|
7502
|
-
);
|
|
7503
|
-
writer.writeln(
|
|
7504
|
-
` ${writer.wrapInColor("CLI Version:", cliCore.CliForegroundColor.Cyan)} ${LIBRARY_VERSION}`
|
|
7593
|
+
const summaryFramework = context2.services.get("cli-framework") ?? "vanilla";
|
|
7594
|
+
const summaryModuleRegistry = context2.services.get(
|
|
7595
|
+
CliModuleRegistry_TOKEN
|
|
7505
7596
|
);
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
framework = context2.services.get("cli-framework");
|
|
7509
|
-
} catch {
|
|
7510
|
-
}
|
|
7511
|
-
writer.writeln(
|
|
7512
|
-
` ${writer.wrapInColor("Framework:", cliCore.CliForegroundColor.Cyan)} ${framework}`
|
|
7513
|
-
);
|
|
7514
|
-
writer.writeln(
|
|
7515
|
-
` ${writer.wrapInColor("Terminal:", cliCore.CliForegroundColor.Cyan)} ${context2.terminal.cols}x${context2.terminal.rows}`
|
|
7597
|
+
const summaryServerManager = context2.services.get(
|
|
7598
|
+
CliServerManager_TOKEN
|
|
7516
7599
|
);
|
|
7517
|
-
|
|
7518
|
-
|
|
7600
|
+
const history = context2.services.getRequired(
|
|
7601
|
+
CliCommandHistory_TOKEN
|
|
7519
7602
|
);
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
)
|
|
7524
|
-
writer.
|
|
7525
|
-
|
|
7603
|
+
const wasmStatus = isWasmAccelerated() ? "active" : "inactive (JS fallback)";
|
|
7604
|
+
const lines = [
|
|
7605
|
+
`${writer.wrapInColor("Core Version:", cliCore.CliForegroundColor.Cyan)} ${cliCore.LIBRARY_VERSION}`,
|
|
7606
|
+
`${writer.wrapInColor("CLI Version:", cliCore.CliForegroundColor.Cyan)} ${LIBRARY_VERSION}`,
|
|
7607
|
+
`${writer.wrapInColor("Framework:", cliCore.CliForegroundColor.Cyan)} ${summaryFramework}`,
|
|
7608
|
+
`${writer.wrapInColor("Terminal:", cliCore.CliForegroundColor.Cyan)} ${context2.terminal.cols}x${context2.terminal.rows}`,
|
|
7609
|
+
`${writer.wrapInColor("Processors:", cliCore.CliForegroundColor.Cyan)} ${registry.processors.length}`
|
|
7610
|
+
];
|
|
7611
|
+
if (summaryModuleRegistry) {
|
|
7612
|
+
lines.push(
|
|
7613
|
+
`${writer.wrapInColor("Modules:", cliCore.CliForegroundColor.Cyan)} ${summaryModuleRegistry.getAll().length}`
|
|
7526
7614
|
);
|
|
7527
|
-
} catch {
|
|
7528
7615
|
}
|
|
7529
|
-
|
|
7530
|
-
const
|
|
7531
|
-
|
|
7616
|
+
if (summaryServerManager && summaryServerManager.connections.size > 0) {
|
|
7617
|
+
const connected = Array.from(
|
|
7618
|
+
summaryServerManager.connections.values()
|
|
7619
|
+
).filter((c) => c.connected).length;
|
|
7620
|
+
lines.push(
|
|
7621
|
+
`${writer.wrapInColor("Servers:", cliCore.CliForegroundColor.Cyan)} ${connected}/${summaryServerManager.connections.size} connected`
|
|
7532
7622
|
);
|
|
7533
|
-
if (serverManager && serverManager.connections.size > 0) {
|
|
7534
|
-
const connected = Array.from(
|
|
7535
|
-
serverManager.connections.values()
|
|
7536
|
-
).filter((c) => c.connected).length;
|
|
7537
|
-
writer.writeln(
|
|
7538
|
-
` ${writer.wrapInColor("Servers:", cliCore.CliForegroundColor.Cyan)} ${connected}/${serverManager.connections.size} connected`
|
|
7539
|
-
);
|
|
7540
|
-
}
|
|
7541
|
-
} catch {
|
|
7542
7623
|
}
|
|
7543
|
-
|
|
7544
|
-
|
|
7624
|
+
lines.push(
|
|
7625
|
+
`${writer.wrapInColor("History:", cliCore.CliForegroundColor.Cyan)} ${history.getHistory().length} commands`,
|
|
7626
|
+
`${writer.wrapInColor("WASM Accelerator:", cliCore.CliForegroundColor.Cyan)} ${wasmStatus}`
|
|
7545
7627
|
);
|
|
7546
|
-
writer.
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
writer.writeln(
|
|
7551
|
-
` ${writer.wrapInColor("WASM Accelerator:", cliCore.CliForegroundColor.Cyan)} ${wasmStatus}`
|
|
7552
|
-
);
|
|
7553
|
-
writer.writeDivider({ char: "=" });
|
|
7628
|
+
writer.writeBox(lines, {
|
|
7629
|
+
title: "CLI Debug Info",
|
|
7630
|
+
borderColor: cliCore.CliForegroundColor.Yellow
|
|
7631
|
+
});
|
|
7554
7632
|
writer.writeln();
|
|
7555
7633
|
writer.writeln(`${cliCore.CliIcon.Light} Subcommands:`);
|
|
7556
7634
|
for (const sub of this.processors || []) {
|
|
@@ -8136,7 +8214,7 @@ var CliNanoCommandProcessor = class {
|
|
|
8136
8214
|
this.replaceWith = "";
|
|
8137
8215
|
this.statusMessage = void 0;
|
|
8138
8216
|
try {
|
|
8139
|
-
this.fs = context2.services.
|
|
8217
|
+
this.fs = context2.services.getRequired(FS_TOKEN);
|
|
8140
8218
|
} catch {
|
|
8141
8219
|
this.fs = null;
|
|
8142
8220
|
}
|
|
@@ -8475,8 +8553,8 @@ var CliNanoCommandProcessor = class {
|
|
|
8475
8553
|
return;
|
|
8476
8554
|
}
|
|
8477
8555
|
try {
|
|
8478
|
-
const registry = this.context.services.
|
|
8479
|
-
|
|
8556
|
+
const registry = this.context.services.getRequired(
|
|
8557
|
+
SyntaxHighlighterRegistry_TOKEN
|
|
8480
8558
|
);
|
|
8481
8559
|
const ext = "." + filePath.split(".").pop()?.toLowerCase();
|
|
8482
8560
|
const highlighter = registry.getByExtension(ext);
|
|
@@ -8741,7 +8819,9 @@ var CliServicesCommandProcessor = class {
|
|
|
8741
8819
|
this.metadata = {
|
|
8742
8820
|
sealed: true,
|
|
8743
8821
|
icon: "\u2699",
|
|
8744
|
-
module: "system"
|
|
8822
|
+
module: "system",
|
|
8823
|
+
// Enforced only when an auth module is loaded
|
|
8824
|
+
requiredPermissions: ["system:services"]
|
|
8745
8825
|
};
|
|
8746
8826
|
this.processors = [
|
|
8747
8827
|
// ── list ──────────────────────────────────────────────
|
|
@@ -9113,7 +9193,7 @@ var CliPsCommandProcessor = class {
|
|
|
9113
9193
|
async processCommand(_command, context2) {
|
|
9114
9194
|
let registry;
|
|
9115
9195
|
try {
|
|
9116
|
-
registry = context2.services.
|
|
9196
|
+
registry = context2.services.getRequired(
|
|
9117
9197
|
CliProcessRegistry_TOKEN
|
|
9118
9198
|
);
|
|
9119
9199
|
} catch {
|
|
@@ -9152,7 +9232,7 @@ var CliKillCommandProcessor = class {
|
|
|
9152
9232
|
async processCommand(command2, context2) {
|
|
9153
9233
|
let registry;
|
|
9154
9234
|
try {
|
|
9155
|
-
registry = context2.services.
|
|
9235
|
+
registry = context2.services.getRequired(
|
|
9156
9236
|
CliProcessRegistry_TOKEN
|
|
9157
9237
|
);
|
|
9158
9238
|
} catch {
|
|
@@ -9267,11 +9347,10 @@ var CliHtopCommandProcessor = class {
|
|
|
9267
9347
|
this.errorTimeout = null;
|
|
9268
9348
|
}
|
|
9269
9349
|
async processCommand(_command, context2) {
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
9274
|
-
} catch {
|
|
9350
|
+
this.registry = context2.services.get(
|
|
9351
|
+
CliProcessRegistry_TOKEN
|
|
9352
|
+
) ?? null;
|
|
9353
|
+
if (!this.registry) {
|
|
9275
9354
|
context2.writer.writeError("Process registry not available");
|
|
9276
9355
|
return;
|
|
9277
9356
|
}
|
|
@@ -10411,7 +10490,7 @@ var CliPingCommandProcessor = class {
|
|
|
10411
10490
|
context2.writer.writeln(
|
|
10412
10491
|
`PING ${host} (${url}):`
|
|
10413
10492
|
);
|
|
10414
|
-
context2.
|
|
10493
|
+
context2.notifier.info(`ping ${host}`);
|
|
10415
10494
|
const times = [];
|
|
10416
10495
|
let transmitted = 0;
|
|
10417
10496
|
let received = 0;
|
|
@@ -10426,18 +10505,17 @@ var CliPingCommandProcessor = class {
|
|
|
10426
10505
|
transmitted++;
|
|
10427
10506
|
const start = performance.now();
|
|
10428
10507
|
try {
|
|
10429
|
-
const response = await fetch(url, {
|
|
10508
|
+
const response = await context2.http.fetch(url, {
|
|
10430
10509
|
method: "HEAD",
|
|
10431
10510
|
mode: "no-cors",
|
|
10432
|
-
cache: "no-store"
|
|
10433
|
-
signal: context2.signal
|
|
10511
|
+
cache: "no-store"
|
|
10434
10512
|
});
|
|
10435
10513
|
const elapsed = performance.now() - start;
|
|
10436
10514
|
const ms = elapsed.toFixed(1);
|
|
10437
10515
|
received++;
|
|
10438
10516
|
times.push(elapsed);
|
|
10439
10517
|
const status = response.type === "opaque" ? "ok" : `status=${response.status}`;
|
|
10440
|
-
context2.
|
|
10518
|
+
context2.notifier.info(`ping ${host}: seq=${seq} time=${ms}ms`);
|
|
10441
10519
|
context2.writer.writeln(
|
|
10442
10520
|
`${url}: seq=${seq} ${status} time=${ms} ms`
|
|
10443
10521
|
);
|
|
@@ -10571,7 +10649,7 @@ var CliExportCommandProcessor = class {
|
|
|
10571
10649
|
this.metadata = { icon: "\u{1F4E6}", module: "system" };
|
|
10572
10650
|
}
|
|
10573
10651
|
async processCommand(command2, context2) {
|
|
10574
|
-
const env = context2.services.
|
|
10652
|
+
const env = context2.services.getRequired(
|
|
10575
10653
|
ICliEnvironment_TOKEN
|
|
10576
10654
|
);
|
|
10577
10655
|
const raw = (command2.value || "").trim();
|
|
@@ -10625,7 +10703,7 @@ var CliUnsetCommandProcessor = class {
|
|
|
10625
10703
|
this.metadata = { icon: "\u{1F5D1}\uFE0F", module: "system" };
|
|
10626
10704
|
}
|
|
10627
10705
|
async processCommand(command2, context2) {
|
|
10628
|
-
const env = context2.services.
|
|
10706
|
+
const env = context2.services.getRequired(
|
|
10629
10707
|
ICliEnvironment_TOKEN
|
|
10630
10708
|
);
|
|
10631
10709
|
const varName = (command2.value || "").trim();
|
|
@@ -10659,7 +10737,7 @@ var CliEnvCommandProcessor = class {
|
|
|
10659
10737
|
this.metadata = { icon: "\u{1F30D}", module: "system" };
|
|
10660
10738
|
}
|
|
10661
10739
|
async processCommand(command2, context2) {
|
|
10662
|
-
const env = context2.services.
|
|
10740
|
+
const env = context2.services.getRequired(
|
|
10663
10741
|
ICliEnvironment_TOKEN
|
|
10664
10742
|
);
|
|
10665
10743
|
const varName = (command2.value || "").trim();
|
|
@@ -10907,16 +10985,9 @@ var CliCommandExecutionContext = class {
|
|
|
10907
10985
|
this.createInterval = (cb, ms) => context2.createInterval(cb, ms);
|
|
10908
10986
|
this.createTimeout = (cb, ms) => context2.createTimeout(cb, ms);
|
|
10909
10987
|
this.backgroundServices = context2.backgroundServices;
|
|
10910
|
-
this.
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
this.context.setStatusText(text);
|
|
10914
|
-
}
|
|
10915
|
-
clearStatusText() {
|
|
10916
|
-
this.context.clearStatusText();
|
|
10917
|
-
}
|
|
10918
|
-
getStatusText() {
|
|
10919
|
-
return this.context.getStatusText();
|
|
10988
|
+
this.http = context2.http;
|
|
10989
|
+
this.notifier = context2.notifier;
|
|
10990
|
+
this.state = context2.services.getRequired(CliStateStoreManager_TOKEN).getProcessorStateStore(processor);
|
|
10920
10991
|
}
|
|
10921
10992
|
get promptLength() {
|
|
10922
10993
|
return this.context.promptLength;
|
|
@@ -11466,6 +11537,175 @@ var CliBackgroundServiceRegistry = class {
|
|
|
11466
11537
|
}
|
|
11467
11538
|
}
|
|
11468
11539
|
};
|
|
11540
|
+
var CliHttpClient = class {
|
|
11541
|
+
constructor(signal) {
|
|
11542
|
+
this.signal = signal;
|
|
11543
|
+
}
|
|
11544
|
+
async fetch(url, init) {
|
|
11545
|
+
return fetch(url, {
|
|
11546
|
+
...init,
|
|
11547
|
+
signal: this.mergeSignal(init?.signal)
|
|
11548
|
+
});
|
|
11549
|
+
}
|
|
11550
|
+
async get(url, options) {
|
|
11551
|
+
return this.jsonRequest("GET", url, void 0, options);
|
|
11552
|
+
}
|
|
11553
|
+
async post(url, body, options) {
|
|
11554
|
+
return this.jsonRequest("POST", url, body, options);
|
|
11555
|
+
}
|
|
11556
|
+
async put(url, body, options) {
|
|
11557
|
+
return this.jsonRequest("PUT", url, body, options);
|
|
11558
|
+
}
|
|
11559
|
+
async patch(url, body, options) {
|
|
11560
|
+
return this.jsonRequest("PATCH", url, body, options);
|
|
11561
|
+
}
|
|
11562
|
+
async delete(url, options) {
|
|
11563
|
+
return this.jsonRequest("DELETE", url, void 0, options);
|
|
11564
|
+
}
|
|
11565
|
+
async head(url, options) {
|
|
11566
|
+
const { timeout, signal: callerSignal, ...fetchOptions } = options ?? {};
|
|
11567
|
+
let timeoutController;
|
|
11568
|
+
let timeoutId;
|
|
11569
|
+
if (timeout) {
|
|
11570
|
+
timeoutController = new AbortController();
|
|
11571
|
+
timeoutId = setTimeout(() => timeoutController.abort(), timeout);
|
|
11572
|
+
}
|
|
11573
|
+
try {
|
|
11574
|
+
return await fetch(url, {
|
|
11575
|
+
...fetchOptions,
|
|
11576
|
+
method: "HEAD",
|
|
11577
|
+
signal: this.mergeSignal(callerSignal, timeoutController?.signal)
|
|
11578
|
+
});
|
|
11579
|
+
} finally {
|
|
11580
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
11581
|
+
}
|
|
11582
|
+
}
|
|
11583
|
+
async options(url, options) {
|
|
11584
|
+
return this.jsonRequest("OPTIONS", url, void 0, options);
|
|
11585
|
+
}
|
|
11586
|
+
// ── Internals ────────────────────────────────────────────────────
|
|
11587
|
+
async jsonRequest(method, url, body, options) {
|
|
11588
|
+
const { timeout, ...fetchOptions } = options ?? {};
|
|
11589
|
+
const headers = new Headers(fetchOptions.headers);
|
|
11590
|
+
let resolvedBody;
|
|
11591
|
+
if (body !== void 0 && body !== null) {
|
|
11592
|
+
if (this.isRawBody(body)) {
|
|
11593
|
+
resolvedBody = body;
|
|
11594
|
+
} else {
|
|
11595
|
+
resolvedBody = JSON.stringify(body);
|
|
11596
|
+
if (!headers.has("Content-Type")) {
|
|
11597
|
+
headers.set("Content-Type", "application/json");
|
|
11598
|
+
}
|
|
11599
|
+
}
|
|
11600
|
+
}
|
|
11601
|
+
let timeoutId;
|
|
11602
|
+
let timeoutController;
|
|
11603
|
+
if (timeout) {
|
|
11604
|
+
timeoutController = new AbortController();
|
|
11605
|
+
timeoutId = setTimeout(() => timeoutController.abort(), timeout);
|
|
11606
|
+
}
|
|
11607
|
+
const signal = this.mergeSignal(
|
|
11608
|
+
fetchOptions.signal,
|
|
11609
|
+
timeoutController?.signal
|
|
11610
|
+
);
|
|
11611
|
+
try {
|
|
11612
|
+
const response = await fetch(url, {
|
|
11613
|
+
...fetchOptions,
|
|
11614
|
+
method,
|
|
11615
|
+
headers,
|
|
11616
|
+
body: resolvedBody,
|
|
11617
|
+
signal
|
|
11618
|
+
});
|
|
11619
|
+
if (!response.ok) {
|
|
11620
|
+
let errorMessage = `${response.status} ${response.statusText}`;
|
|
11621
|
+
let errorBody;
|
|
11622
|
+
try {
|
|
11623
|
+
errorBody = await response.json();
|
|
11624
|
+
const parsed = errorBody;
|
|
11625
|
+
if (parsed.error) {
|
|
11626
|
+
errorMessage = parsed.error;
|
|
11627
|
+
} else if (parsed.message) {
|
|
11628
|
+
errorMessage = parsed.message;
|
|
11629
|
+
}
|
|
11630
|
+
} catch {
|
|
11631
|
+
}
|
|
11632
|
+
throw new cliCore.CliHttpError(
|
|
11633
|
+
errorMessage,
|
|
11634
|
+
response.status,
|
|
11635
|
+
response.statusText,
|
|
11636
|
+
errorBody
|
|
11637
|
+
);
|
|
11638
|
+
}
|
|
11639
|
+
const text = await response.text();
|
|
11640
|
+
if (!text) {
|
|
11641
|
+
return void 0;
|
|
11642
|
+
}
|
|
11643
|
+
return JSON.parse(text);
|
|
11644
|
+
} finally {
|
|
11645
|
+
if (timeoutId !== void 0) {
|
|
11646
|
+
clearTimeout(timeoutId);
|
|
11647
|
+
}
|
|
11648
|
+
}
|
|
11649
|
+
}
|
|
11650
|
+
isRawBody(body) {
|
|
11651
|
+
return typeof body === "string" || body instanceof FormData || body instanceof Blob || body instanceof ArrayBuffer || body instanceof URLSearchParams || body instanceof ReadableStream;
|
|
11652
|
+
}
|
|
11653
|
+
/**
|
|
11654
|
+
* Merge the command signal with any additional signals (caller, timeout).
|
|
11655
|
+
* Uses AbortSignal.any() when available, falls back to a manual composite
|
|
11656
|
+
* controller for older browsers (pre-Chrome 116 / Safari 17.4).
|
|
11657
|
+
*/
|
|
11658
|
+
mergeSignal(...additional) {
|
|
11659
|
+
const signals = [];
|
|
11660
|
+
if (this.signal) signals.push(this.signal);
|
|
11661
|
+
for (const s of additional) {
|
|
11662
|
+
if (s) signals.push(s);
|
|
11663
|
+
}
|
|
11664
|
+
if (signals.length === 0) return void 0;
|
|
11665
|
+
if (signals.length === 1) return signals[0];
|
|
11666
|
+
if (typeof AbortSignal.any === "function") {
|
|
11667
|
+
return AbortSignal.any(signals);
|
|
11668
|
+
}
|
|
11669
|
+
const controller = new AbortController();
|
|
11670
|
+
for (const s of signals) {
|
|
11671
|
+
if (s.aborted) {
|
|
11672
|
+
controller.abort(s.reason);
|
|
11673
|
+
return controller.signal;
|
|
11674
|
+
}
|
|
11675
|
+
s.addEventListener("abort", () => controller.abort(s.reason), { once: true });
|
|
11676
|
+
}
|
|
11677
|
+
return controller.signal;
|
|
11678
|
+
}
|
|
11679
|
+
};
|
|
11680
|
+
var CliNotifier = class {
|
|
11681
|
+
constructor() {
|
|
11682
|
+
this._change$ = new rxjs.Subject();
|
|
11683
|
+
this.change$ = this._change$.asObservable();
|
|
11684
|
+
}
|
|
11685
|
+
get current() {
|
|
11686
|
+
return this._current;
|
|
11687
|
+
}
|
|
11688
|
+
info(message) {
|
|
11689
|
+
this.set("info", message);
|
|
11690
|
+
}
|
|
11691
|
+
success(message) {
|
|
11692
|
+
this.set("success", message);
|
|
11693
|
+
}
|
|
11694
|
+
warn(message) {
|
|
11695
|
+
this.set("warn", message);
|
|
11696
|
+
}
|
|
11697
|
+
error(message) {
|
|
11698
|
+
this.set("error", message);
|
|
11699
|
+
}
|
|
11700
|
+
clear() {
|
|
11701
|
+
this._current = void 0;
|
|
11702
|
+
this._change$.next(void 0);
|
|
11703
|
+
}
|
|
11704
|
+
set(level, message) {
|
|
11705
|
+
this._current = { level, message, timestamp: Date.now() };
|
|
11706
|
+
this._change$.next(this._current);
|
|
11707
|
+
}
|
|
11708
|
+
};
|
|
11469
11709
|
|
|
11470
11710
|
// src/lib/context/cli-fullscreen-manager.ts
|
|
11471
11711
|
var CliFullScreenManager = class {
|
|
@@ -14427,7 +14667,7 @@ var CliTerminalLineRenderer = class {
|
|
|
14427
14667
|
*/
|
|
14428
14668
|
getPromptString(options) {
|
|
14429
14669
|
const name = options.userName ?? "";
|
|
14430
|
-
let promptStart = options.hideUserName
|
|
14670
|
+
let promptStart = options.hideUserName ? "" : name ? `\x1B[32m${name}\x1B[0m:` : options.anonymousName ? `\x1B[90m${options.anonymousName}\x1B[0m:` : "";
|
|
14431
14671
|
if (options.contextProcessor) {
|
|
14432
14672
|
promptStart = `${options.contextProcessor}`;
|
|
14433
14673
|
}
|
|
@@ -14489,7 +14729,6 @@ var CliExecutionContext = class {
|
|
|
14489
14729
|
* Set by the command executor at start/end of executeCommand().
|
|
14490
14730
|
*/
|
|
14491
14731
|
this.isExecuting = false;
|
|
14492
|
-
this.statusTextChange$ = new rxjs.Subject();
|
|
14493
14732
|
this.lineBuffer = new CliLineBuffer();
|
|
14494
14733
|
this.modeStack = [];
|
|
14495
14734
|
this.timerManager = new CliTimerManager();
|
|
@@ -14534,6 +14773,8 @@ var CliExecutionContext = class {
|
|
|
14534
14773
|
this.logger.setCliLogLevel(cliOptions?.logLevel || cliCore.CliLogLevel.ERROR);
|
|
14535
14774
|
this.commandHistory = deps.commandHistory;
|
|
14536
14775
|
this.lineRenderer = new CliTerminalLineRenderer(terminal, this.writer);
|
|
14776
|
+
this.http = new CliHttpClient();
|
|
14777
|
+
this.notifier = new CliNotifier();
|
|
14537
14778
|
this.backgroundServices = new CliBackgroundServiceRegistry(
|
|
14538
14779
|
this.state,
|
|
14539
14780
|
deps.services,
|
|
@@ -14544,17 +14785,6 @@ var CliExecutionContext = class {
|
|
|
14544
14785
|
this.backgroundServices
|
|
14545
14786
|
);
|
|
14546
14787
|
}
|
|
14547
|
-
setStatusText(text) {
|
|
14548
|
-
this._statusText = text;
|
|
14549
|
-
this.statusTextChange$.next(text);
|
|
14550
|
-
}
|
|
14551
|
-
clearStatusText() {
|
|
14552
|
-
this._statusText = void 0;
|
|
14553
|
-
this.statusTextChange$.next(void 0);
|
|
14554
|
-
}
|
|
14555
|
-
getStatusText() {
|
|
14556
|
-
return this._statusText;
|
|
14557
|
-
}
|
|
14558
14788
|
// -- Public API (ICliExecutionContext) --
|
|
14559
14789
|
writeToTerminal(text) {
|
|
14560
14790
|
this.terminal.write(text);
|
|
@@ -14748,15 +14978,13 @@ var CliExecutionContext = class {
|
|
|
14748
14978
|
}
|
|
14749
14979
|
// -- CommandLineModeHost interface --
|
|
14750
14980
|
getPromptOptions() {
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
hideUserName = config?.hideUserName ?? false;
|
|
14755
|
-
} catch {
|
|
14756
|
-
}
|
|
14981
|
+
const usersConfig = this.services.get("cli-users-module-config");
|
|
14982
|
+
const hideUserName = usersConfig?.hideUserName ?? false;
|
|
14983
|
+
const anonymousName = usersConfig && !this.userSession ? (usersConfig.anonymousName ?? "anonymous") || void 0 : void 0;
|
|
14757
14984
|
return {
|
|
14758
14985
|
userName: this.userSession?.displayName,
|
|
14759
14986
|
hideUserName,
|
|
14987
|
+
anonymousName,
|
|
14760
14988
|
contextProcessor: this.contextProcessor?.command,
|
|
14761
14989
|
pathProvider: this.promptPathProvider
|
|
14762
14990
|
};
|
|
@@ -15001,10 +15229,8 @@ var contextGlobalParameter = {
|
|
|
15001
15229
|
// src/lib/executor/cli-io-redirect-handler.ts
|
|
15002
15230
|
var FS_TOKEN2 = "cli-file-system-service";
|
|
15003
15231
|
async function writeOutputToFile(filePath, context2) {
|
|
15004
|
-
|
|
15005
|
-
|
|
15006
|
-
fs = context2.services.get(FS_TOKEN2);
|
|
15007
|
-
} catch {
|
|
15232
|
+
const fs = context2.services.get(FS_TOKEN2);
|
|
15233
|
+
if (!fs) {
|
|
15008
15234
|
context2.writer.writeError(
|
|
15009
15235
|
"> redirect requires @qodalis/cli-files plugin"
|
|
15010
15236
|
);
|
|
@@ -15028,10 +15254,8 @@ async function writeOutputToFile(filePath, context2) {
|
|
|
15028
15254
|
}
|
|
15029
15255
|
}
|
|
15030
15256
|
async function appendOutputToFile(filePath, context2) {
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
fs = context2.services.get(FS_TOKEN2);
|
|
15034
|
-
} catch {
|
|
15257
|
+
const fs = context2.services.get(FS_TOKEN2);
|
|
15258
|
+
if (!fs) {
|
|
15035
15259
|
context2.writer.writeError(
|
|
15036
15260
|
">> redirect requires @qodalis/cli-files plugin"
|
|
15037
15261
|
);
|
|
@@ -15057,10 +15281,8 @@ async function appendOutputToFile(filePath, context2) {
|
|
|
15057
15281
|
async function writeStderrToFile(filePath, context2, capturingWriter) {
|
|
15058
15282
|
const stderr = capturingWriter?.getCapturedStderr();
|
|
15059
15283
|
if (!stderr) return;
|
|
15060
|
-
|
|
15061
|
-
|
|
15062
|
-
fs = context2.services.get(FS_TOKEN2);
|
|
15063
|
-
} catch {
|
|
15284
|
+
const fs = context2.services.get(FS_TOKEN2);
|
|
15285
|
+
if (!fs) {
|
|
15064
15286
|
context2.writer.writeError(
|
|
15065
15287
|
"2> redirect requires @qodalis/cli-files plugin"
|
|
15066
15288
|
);
|
|
@@ -15081,10 +15303,8 @@ async function writeStderrToFile(filePath, context2, capturingWriter) {
|
|
|
15081
15303
|
async function appendStderrToFile(filePath, context2, capturingWriter) {
|
|
15082
15304
|
const stderr = capturingWriter?.getCapturedStderr();
|
|
15083
15305
|
if (!stderr) return;
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
fs = context2.services.get(FS_TOKEN2);
|
|
15087
|
-
} catch {
|
|
15306
|
+
const fs = context2.services.get(FS_TOKEN2);
|
|
15307
|
+
if (!fs) {
|
|
15088
15308
|
context2.writer.writeError(
|
|
15089
15309
|
"2>> redirect requires @qodalis/cli-files plugin"
|
|
15090
15310
|
);
|
|
@@ -15104,10 +15324,8 @@ async function appendStderrToFile(filePath, context2, capturingWriter) {
|
|
|
15104
15324
|
}
|
|
15105
15325
|
async function tryExecuteScript(filePath, context2, executeCommand) {
|
|
15106
15326
|
const FS_TOKEN3 = "cli-file-system-service";
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
fs = context2.services.get(FS_TOKEN3);
|
|
15110
|
-
} catch {
|
|
15327
|
+
const fs = context2.services.get(FS_TOKEN3);
|
|
15328
|
+
if (!fs) {
|
|
15111
15329
|
return false;
|
|
15112
15330
|
}
|
|
15113
15331
|
const resolved = fs.resolvePath(filePath);
|
|
@@ -15184,10 +15402,8 @@ function substituteVars(input, variables) {
|
|
|
15184
15402
|
return result;
|
|
15185
15403
|
}
|
|
15186
15404
|
function expandEnvironmentVars(command2, context2) {
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
env = context2.services.get(ICliEnvironment_TOKEN);
|
|
15190
|
-
} catch {
|
|
15405
|
+
const env = context2.services.get(ICliEnvironment_TOKEN);
|
|
15406
|
+
if (!env) {
|
|
15191
15407
|
return command2;
|
|
15192
15408
|
}
|
|
15193
15409
|
const parts = command2.split("'");
|
|
@@ -15332,7 +15548,7 @@ var CliCommandExecutor = class {
|
|
|
15332
15548
|
}
|
|
15333
15549
|
} finally {
|
|
15334
15550
|
rootContext.isExecuting = false;
|
|
15335
|
-
rootContext.
|
|
15551
|
+
rootContext.notifier?.clear();
|
|
15336
15552
|
}
|
|
15337
15553
|
}
|
|
15338
15554
|
async executeSingleCommand(command2, data, context2) {
|
|
@@ -15340,8 +15556,8 @@ var CliCommandExecutor = class {
|
|
|
15340
15556
|
command2 = expandEnvironmentVars(command2, context2);
|
|
15341
15557
|
const assignMatch = command2.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
15342
15558
|
if (assignMatch) {
|
|
15343
|
-
|
|
15344
|
-
|
|
15559
|
+
const env = context2.services.get(ICliEnvironment_TOKEN);
|
|
15560
|
+
if (env) {
|
|
15345
15561
|
let val = assignMatch[2];
|
|
15346
15562
|
if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
|
|
15347
15563
|
val = val.slice(1, -1);
|
|
@@ -15350,15 +15566,13 @@ var CliCommandExecutor = class {
|
|
|
15350
15566
|
process.start();
|
|
15351
15567
|
process.end();
|
|
15352
15568
|
return;
|
|
15353
|
-
} catch {
|
|
15354
15569
|
}
|
|
15355
15570
|
}
|
|
15356
15571
|
process.start();
|
|
15357
15572
|
let processEntry;
|
|
15358
|
-
|
|
15359
|
-
|
|
15573
|
+
const procRegistry = context2.services.get(CliProcessRegistry_TOKEN);
|
|
15574
|
+
if (procRegistry) {
|
|
15360
15575
|
processEntry = procRegistry.register(command2);
|
|
15361
|
-
} catch {
|
|
15362
15576
|
}
|
|
15363
15577
|
const parsed = this.commandParser.parse(command2);
|
|
15364
15578
|
let { commandName } = parsed;
|
|
@@ -15381,7 +15595,7 @@ var CliCommandExecutor = class {
|
|
|
15381
15595
|
}
|
|
15382
15596
|
if (!processor) {
|
|
15383
15597
|
const aliasProcessor = this.registry.findProcessor("alias", []);
|
|
15384
|
-
const aliases = aliasProcessor?.userAliases ?? {};
|
|
15598
|
+
const aliases = aliasProcessor?.aliasesFor?.(context2) ?? aliasProcessor?.userAliases ?? {};
|
|
15385
15599
|
if (aliases[mainCommand]) {
|
|
15386
15600
|
this.completeProcess(processEntry, context2, 0);
|
|
15387
15601
|
return await this.executeSingleCommand(
|
|
@@ -15438,13 +15652,21 @@ var CliCommandExecutor = class {
|
|
|
15438
15652
|
}
|
|
15439
15653
|
const value = processor.acceptsRawInput || processor.valueRequired ? cliCore.getRightOfWord(commandName, processor.command) : void 0;
|
|
15440
15654
|
commandToProcess.value = value;
|
|
15655
|
+
const blockedBy = await this.runGuards(commandToProcess, processor, context2);
|
|
15656
|
+
if (blockedBy) {
|
|
15657
|
+
context2.writer.writeError(blockedBy);
|
|
15658
|
+
this.failProcess(processEntry, context2);
|
|
15659
|
+
context2.process.exit(-1, { silent: true });
|
|
15660
|
+
return;
|
|
15661
|
+
}
|
|
15441
15662
|
const hasPositionalInput = !!value || !!data;
|
|
15442
15663
|
const hasNamedArgs = Object.keys(args).length > 0;
|
|
15443
15664
|
if (processor.valueRequired && !hasPositionalInput && !hasNamedArgs) {
|
|
15444
15665
|
context2.writer.writeError(
|
|
15445
15666
|
`Value required: ${context2.writer.wrapInColor(`${commandName} <value>`, cliCore.CliForegroundColor.Cyan)}`
|
|
15446
15667
|
);
|
|
15447
|
-
|
|
15668
|
+
this.failProcess(processEntry, context2);
|
|
15669
|
+
context2.process.exit(-1, { silent: true });
|
|
15448
15670
|
return;
|
|
15449
15671
|
}
|
|
15450
15672
|
if (!this.validateBeforeExecution(context2, processor, args, hasPositionalInput)) {
|
|
@@ -15460,7 +15682,8 @@ var CliCommandExecutor = class {
|
|
|
15460
15682
|
context2.writer.writeError(
|
|
15461
15683
|
validationResult?.message || "An error occurred while validating the command."
|
|
15462
15684
|
);
|
|
15463
|
-
|
|
15685
|
+
this.failProcess(processEntry, context2);
|
|
15686
|
+
context2.process.exit(-1, { silent: true });
|
|
15464
15687
|
return;
|
|
15465
15688
|
}
|
|
15466
15689
|
}
|
|
@@ -15471,6 +15694,7 @@ var CliCommandExecutor = class {
|
|
|
15471
15694
|
);
|
|
15472
15695
|
const commandAbortController = new AbortController();
|
|
15473
15696
|
commandContext.signal = commandAbortController.signal;
|
|
15697
|
+
commandContext.http = new CliHttpClient(commandAbortController.signal);
|
|
15474
15698
|
const abortSub = context2.onAbort.subscribe(() => {
|
|
15475
15699
|
commandAbortController.abort();
|
|
15476
15700
|
});
|
|
@@ -15523,6 +15747,10 @@ var CliCommandExecutor = class {
|
|
|
15523
15747
|
"Process exited successfully with code 0"
|
|
15524
15748
|
);
|
|
15525
15749
|
}
|
|
15750
|
+
} else if (cliCore.isCliAccessDeniedError(e)) {
|
|
15751
|
+
this.failProcess(processEntry, context2);
|
|
15752
|
+
context2.writer.writeError(e.message);
|
|
15753
|
+
context2.process.exit(-1);
|
|
15526
15754
|
} else {
|
|
15527
15755
|
this.failProcess(processEntry, context2);
|
|
15528
15756
|
context2.writer.writeError(`Error executing command: ${e}`);
|
|
@@ -15535,19 +15763,13 @@ var CliCommandExecutor = class {
|
|
|
15535
15763
|
}
|
|
15536
15764
|
completeProcess(processEntry, context2, exitCode) {
|
|
15537
15765
|
if (!processEntry) return;
|
|
15538
|
-
|
|
15539
|
-
|
|
15540
|
-
procRegistry.complete(processEntry.pid, exitCode);
|
|
15541
|
-
} catch {
|
|
15542
|
-
}
|
|
15766
|
+
const procRegistry = context2.services.get(CliProcessRegistry_TOKEN);
|
|
15767
|
+
procRegistry?.complete(processEntry.pid, exitCode);
|
|
15543
15768
|
}
|
|
15544
15769
|
failProcess(processEntry, context2) {
|
|
15545
15770
|
if (!processEntry) return;
|
|
15546
|
-
|
|
15547
|
-
|
|
15548
|
-
procRegistry.fail(processEntry.pid);
|
|
15549
|
-
} catch {
|
|
15550
|
-
}
|
|
15771
|
+
const failRegistry = context2.services.get(CliProcessRegistry_TOKEN);
|
|
15772
|
+
failRegistry?.fail(processEntry.pid);
|
|
15551
15773
|
}
|
|
15552
15774
|
async showHelp(command2, context2) {
|
|
15553
15775
|
try {
|
|
@@ -15613,6 +15835,52 @@ var CliCommandExecutor = class {
|
|
|
15613
15835
|
* parameter. In that case the global handler must be skipped so the
|
|
15614
15836
|
* processor can handle the flag itself.
|
|
15615
15837
|
*/
|
|
15838
|
+
/**
|
|
15839
|
+
* Runs all registered {@link ICliCommandGuard}s that apply to this command,
|
|
15840
|
+
* in priority order. Returns the block message of the first guard that
|
|
15841
|
+
* denies the command, or `undefined` when every guard allows it.
|
|
15842
|
+
* A guard that throws is treated as a denial (fail closed).
|
|
15843
|
+
*/
|
|
15844
|
+
async runGuards(command2, processor, context2) {
|
|
15845
|
+
let guards;
|
|
15846
|
+
try {
|
|
15847
|
+
guards = context2.services.getAll(cliCore.ICliCommandGuard_TOKEN);
|
|
15848
|
+
} catch {
|
|
15849
|
+
return void 0;
|
|
15850
|
+
}
|
|
15851
|
+
if (!guards.length) {
|
|
15852
|
+
return void 0;
|
|
15853
|
+
}
|
|
15854
|
+
const ordered = [...guards].sort(
|
|
15855
|
+
(a, b) => (a.priority ?? 0) - (b.priority ?? 0)
|
|
15856
|
+
);
|
|
15857
|
+
for (const guard of ordered) {
|
|
15858
|
+
let result;
|
|
15859
|
+
try {
|
|
15860
|
+
if (guard.appliesTo && !await guard.appliesTo(processor, command2, context2)) {
|
|
15861
|
+
continue;
|
|
15862
|
+
}
|
|
15863
|
+
result = await guard.canActivate(command2, processor, context2);
|
|
15864
|
+
} catch (e) {
|
|
15865
|
+
return `${processor.command}: blocked by guard '${guard.name}' (${e?.message ?? e})`;
|
|
15866
|
+
}
|
|
15867
|
+
const denial = this.guardDenial(result, processor.command);
|
|
15868
|
+
if (denial) {
|
|
15869
|
+
return denial;
|
|
15870
|
+
}
|
|
15871
|
+
}
|
|
15872
|
+
return void 0;
|
|
15873
|
+
}
|
|
15874
|
+
guardDenial(result, commandName) {
|
|
15875
|
+
const denied = `${commandName}: permission denied`;
|
|
15876
|
+
if (result === void 0 || result === true) return void 0;
|
|
15877
|
+
if (result === false) return denied;
|
|
15878
|
+
if (typeof result === "string") return result || denied;
|
|
15879
|
+
if (typeof result === "object" && result !== null) {
|
|
15880
|
+
return result.allowed ? void 0 : result.message || denied;
|
|
15881
|
+
}
|
|
15882
|
+
return void 0;
|
|
15883
|
+
}
|
|
15616
15884
|
processorOwnsParameter(processor, globalParam) {
|
|
15617
15885
|
const globalNames = /* @__PURE__ */ new Set([
|
|
15618
15886
|
globalParam.name,
|
|
@@ -15629,29 +15897,94 @@ var CliCommandExecutor = class {
|
|
|
15629
15897
|
// src/lib/services/cli-service-container.ts
|
|
15630
15898
|
var CliServiceContainer = class {
|
|
15631
15899
|
constructor() {
|
|
15632
|
-
/** Stores single-value providers (resolved
|
|
15900
|
+
/** Stores single-value providers (resolved singletons). */
|
|
15633
15901
|
this.services = /* @__PURE__ */ new Map();
|
|
15634
15902
|
/** Stores multi-provider arrays. */
|
|
15635
15903
|
this.multiServices = /* @__PURE__ */ new Map();
|
|
15904
|
+
/** Tokens that cannot be overwritten by subsequent `set()` calls. */
|
|
15905
|
+
this.sealedTokens = /* @__PURE__ */ new Set();
|
|
15906
|
+
/** Stores provider recipes for transient tokens (re-resolved on every get). */
|
|
15907
|
+
this.transientRecipes = /* @__PURE__ */ new Map();
|
|
15636
15908
|
}
|
|
15637
15909
|
/**
|
|
15638
15910
|
* Retrieve a service by its token.
|
|
15911
|
+
* Returns `undefined` when no provider is registered for the token.
|
|
15912
|
+
* For multi-provider tokens, returns the last registered value (use `getAll` for the full array).
|
|
15639
15913
|
*
|
|
15640
15914
|
* @param token The token used to register the service.
|
|
15641
|
-
* @returns The resolved service instance
|
|
15642
|
-
* @throws Error if the token has not been registered.
|
|
15915
|
+
* @returns The resolved service instance, or `undefined` if not registered.
|
|
15643
15916
|
*/
|
|
15644
15917
|
get(token) {
|
|
15918
|
+
if (this.transientRecipes.has(token)) {
|
|
15919
|
+
return this.resolveProvider(this.transientRecipes.get(token));
|
|
15920
|
+
}
|
|
15645
15921
|
if (this.multiServices.has(token)) {
|
|
15646
|
-
|
|
15922
|
+
const arr = this.multiServices.get(token);
|
|
15923
|
+
return arr[arr.length - 1];
|
|
15647
15924
|
}
|
|
15648
15925
|
if (this.services.has(token)) {
|
|
15649
15926
|
return this.services.get(token);
|
|
15650
15927
|
}
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15928
|
+
return void 0;
|
|
15929
|
+
}
|
|
15930
|
+
/**
|
|
15931
|
+
* Retrieve all registered services for a multi-provider token.
|
|
15932
|
+
* Returns an empty array when no provider is registered for the token.
|
|
15933
|
+
*
|
|
15934
|
+
* @param token The token used to register the service.
|
|
15935
|
+
* @returns Array of all resolved service instances.
|
|
15936
|
+
*/
|
|
15937
|
+
getAll(token) {
|
|
15938
|
+
if (this.multiServices.has(token)) {
|
|
15939
|
+
return this.multiServices.get(token);
|
|
15940
|
+
}
|
|
15941
|
+
const single = this.get(token);
|
|
15942
|
+
return single !== void 0 ? [single] : [];
|
|
15943
|
+
}
|
|
15944
|
+
/**
|
|
15945
|
+
* Retrieve a service by its token, throwing if not registered.
|
|
15946
|
+
* Use this when the service is required and its absence is a programming error.
|
|
15947
|
+
* For multi-provider tokens, returns the last registered value (use `getAll` for the full array).
|
|
15948
|
+
*
|
|
15949
|
+
* @param token The token used to register the service.
|
|
15950
|
+
* @returns The resolved service instance.
|
|
15951
|
+
* @throws Error if the token has not been registered.
|
|
15952
|
+
*/
|
|
15953
|
+
getRequired(token) {
|
|
15954
|
+
const value = this.get(token);
|
|
15955
|
+
if (value === void 0 && !this.has(token)) {
|
|
15956
|
+
throw new Error(
|
|
15957
|
+
`CliServiceContainer: No provider found for token "${this.tokenToString(token)}".`
|
|
15958
|
+
);
|
|
15959
|
+
}
|
|
15960
|
+
return value;
|
|
15961
|
+
}
|
|
15962
|
+
/**
|
|
15963
|
+
* Check whether a service is registered for the given token.
|
|
15964
|
+
*/
|
|
15965
|
+
has(token) {
|
|
15966
|
+
return this.services.has(token) || this.multiServices.has(token) || this.transientRecipes.has(token);
|
|
15967
|
+
}
|
|
15968
|
+
/**
|
|
15969
|
+
* Mark a token as sealed so it cannot be overwritten by future `set()` calls.
|
|
15970
|
+
* Only available on the concrete container — not exposed on `ICliServiceProvider`.
|
|
15971
|
+
*/
|
|
15972
|
+
seal(token) {
|
|
15973
|
+
this.sealedTokens.add(token);
|
|
15974
|
+
}
|
|
15975
|
+
/**
|
|
15976
|
+
* Mark multiple tokens as sealed at once.
|
|
15977
|
+
*/
|
|
15978
|
+
sealAll(tokens) {
|
|
15979
|
+
for (const token of tokens) {
|
|
15980
|
+
this.sealedTokens.add(token);
|
|
15981
|
+
}
|
|
15982
|
+
}
|
|
15983
|
+
/**
|
|
15984
|
+
* Check whether a token is sealed.
|
|
15985
|
+
*/
|
|
15986
|
+
isSealed(token) {
|
|
15987
|
+
return this.sealedTokens.has(token);
|
|
15655
15988
|
}
|
|
15656
15989
|
/**
|
|
15657
15990
|
* Register one or more providers.
|
|
@@ -15673,13 +16006,13 @@ var CliServiceContainer = class {
|
|
|
15673
16006
|
getRegisteredTokens() {
|
|
15674
16007
|
const tokens = [];
|
|
15675
16008
|
for (const key of this.services.keys()) {
|
|
15676
|
-
tokens.push(
|
|
15677
|
-
|
|
15678
|
-
|
|
16009
|
+
tokens.push(this.tokenToString(key));
|
|
16010
|
+
}
|
|
16011
|
+
for (const key of this.transientRecipes.keys()) {
|
|
16012
|
+
tokens.push(`${this.tokenToString(key)} (transient)`);
|
|
15679
16013
|
}
|
|
15680
16014
|
for (const key of this.multiServices.keys()) {
|
|
15681
|
-
|
|
15682
|
-
tokens.push(`${name} (multi)`);
|
|
16015
|
+
tokens.push(`${this.tokenToString(key)} (multi)`);
|
|
15683
16016
|
}
|
|
15684
16017
|
return tokens;
|
|
15685
16018
|
}
|
|
@@ -15690,20 +16023,34 @@ var CliServiceContainer = class {
|
|
|
15690
16023
|
const details = [];
|
|
15691
16024
|
for (const [key, value] of this.services.entries()) {
|
|
15692
16025
|
details.push({
|
|
15693
|
-
token:
|
|
16026
|
+
token: this.tokenToString(key),
|
|
15694
16027
|
type: this.describeValue(value),
|
|
15695
16028
|
multi: false
|
|
15696
16029
|
});
|
|
15697
16030
|
}
|
|
16031
|
+
for (const [key, provider] of this.transientRecipes.entries()) {
|
|
16032
|
+
const className = provider["useClass"]?.name ?? provider["useFactory"]?.name ?? "transient";
|
|
16033
|
+
details.push({
|
|
16034
|
+
token: this.tokenToString(key),
|
|
16035
|
+
type: `transient(${className})`,
|
|
16036
|
+
multi: false
|
|
16037
|
+
});
|
|
16038
|
+
}
|
|
15698
16039
|
for (const [key, values] of this.multiServices.entries()) {
|
|
15699
16040
|
details.push({
|
|
15700
|
-
token:
|
|
16041
|
+
token: this.tokenToString(key),
|
|
15701
16042
|
type: `[${values.map((v) => this.describeValue(v)).join(", ")}]`,
|
|
15702
16043
|
multi: true
|
|
15703
16044
|
});
|
|
15704
16045
|
}
|
|
15705
16046
|
return details;
|
|
15706
16047
|
}
|
|
16048
|
+
/**
|
|
16049
|
+
* Convert a token to a human-readable string for diagnostics/errors.
|
|
16050
|
+
*/
|
|
16051
|
+
tokenToString(token) {
|
|
16052
|
+
return typeof token === "string" ? token : typeof token === "function" ? token.name : String(token);
|
|
16053
|
+
}
|
|
15707
16054
|
/**
|
|
15708
16055
|
* Describe a resolved value for diagnostic display.
|
|
15709
16056
|
*/
|
|
@@ -15723,27 +16070,45 @@ var CliServiceContainer = class {
|
|
|
15723
16070
|
* Register a single provider.
|
|
15724
16071
|
*/
|
|
15725
16072
|
registerProvider(provider) {
|
|
15726
|
-
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15730
|
-
|
|
16073
|
+
if (!provider.multi && this.sealedTokens.has(provider.provide)) {
|
|
16074
|
+
throw new Error(
|
|
16075
|
+
`CliServiceContainer: Cannot override sealed service "${this.tokenToString(provider.provide)}".`
|
|
16076
|
+
);
|
|
16077
|
+
}
|
|
16078
|
+
if (provider["transient"] && !provider.multi) {
|
|
16079
|
+
this.transientRecipes.set(provider.provide, provider);
|
|
16080
|
+
this.services.delete(provider.provide);
|
|
15731
16081
|
} else {
|
|
15732
|
-
this.
|
|
16082
|
+
const value = this.resolveProvider(provider);
|
|
16083
|
+
if (provider.multi) {
|
|
16084
|
+
const existing = this.multiServices.get(provider.provide) ?? [];
|
|
16085
|
+
existing.push(value);
|
|
16086
|
+
this.multiServices.set(provider.provide, existing);
|
|
16087
|
+
} else {
|
|
16088
|
+
this.services.set(provider.provide, value);
|
|
16089
|
+
this.transientRecipes.delete(provider.provide);
|
|
16090
|
+
}
|
|
16091
|
+
}
|
|
16092
|
+
if (provider.sealed) {
|
|
16093
|
+
this.sealedTokens.add(provider.provide);
|
|
15733
16094
|
}
|
|
15734
16095
|
}
|
|
15735
16096
|
/**
|
|
15736
16097
|
* Resolve a provider definition to a concrete value.
|
|
16098
|
+
*
|
|
16099
|
+
* Note: `deps` are resolved eagerly at registration time, so
|
|
16100
|
+
* dependency tokens must be registered before the provider that needs them.
|
|
15737
16101
|
*/
|
|
15738
16102
|
resolveProvider(provider) {
|
|
15739
16103
|
if ("useValue" in provider) {
|
|
15740
16104
|
return provider.useValue;
|
|
15741
16105
|
}
|
|
16106
|
+
const deps = (provider["deps"] ?? []).map((dep) => this.getRequired(dep));
|
|
15742
16107
|
if ("useFactory" in provider) {
|
|
15743
|
-
return provider.useFactory();
|
|
16108
|
+
return provider.useFactory(...deps);
|
|
15744
16109
|
}
|
|
15745
16110
|
if ("useClass" in provider) {
|
|
15746
|
-
return new provider.useClass();
|
|
16111
|
+
return new provider.useClass(...deps);
|
|
15747
16112
|
}
|
|
15748
16113
|
throw new Error(
|
|
15749
16114
|
"CliServiceContainer: Provider must specify useValue, useFactory, or useClass."
|
|
@@ -15884,10 +16249,10 @@ var welcomeModule = {
|
|
|
15884
16249
|
async onAfterBoot(context2) {
|
|
15885
16250
|
const config = this.config || {};
|
|
15886
16251
|
let showOption = config.show;
|
|
15887
|
-
|
|
15888
|
-
|
|
15889
|
-
|
|
15890
|
-
|
|
16252
|
+
const storeManager = context2.services.get(
|
|
16253
|
+
CliStateStoreManager_TOKEN
|
|
16254
|
+
);
|
|
16255
|
+
if (storeManager) {
|
|
15891
16256
|
const configureStore = storeManager.getStateStore(
|
|
15892
16257
|
cliCore.CLI_CONFIGURE_STORE_NAME
|
|
15893
16258
|
);
|
|
@@ -15896,7 +16261,6 @@ var welcomeModule = {
|
|
|
15896
16261
|
if (state?.["system"]?.["welcomeMessage"]) {
|
|
15897
16262
|
showOption = state["system"]["welcomeMessage"];
|
|
15898
16263
|
}
|
|
15899
|
-
} catch {
|
|
15900
16264
|
}
|
|
15901
16265
|
if (showOption) {
|
|
15902
16266
|
if (!shouldDisplayWelcomeMessage(showOption)) {
|
|
@@ -15924,11 +16288,11 @@ var welcomeModule = {
|
|
|
15924
16288
|
recordWelcomeMessageDisplay();
|
|
15925
16289
|
context2.showPrompt();
|
|
15926
16290
|
let showGreeting = true;
|
|
15927
|
-
|
|
15928
|
-
|
|
15929
|
-
|
|
15930
|
-
|
|
15931
|
-
const configureStore =
|
|
16291
|
+
const greetingStoreManager = context2.services.get(
|
|
16292
|
+
CliStateStoreManager_TOKEN
|
|
16293
|
+
);
|
|
16294
|
+
if (greetingStoreManager) {
|
|
16295
|
+
const configureStore = greetingStoreManager.getStateStore(
|
|
15932
16296
|
cliCore.CLI_CONFIGURE_STORE_NAME
|
|
15933
16297
|
);
|
|
15934
16298
|
await configureStore.initialize();
|
|
@@ -15936,7 +16300,6 @@ var welcomeModule = {
|
|
|
15936
16300
|
if (configState?.["system"]?.["greeting"] === false) {
|
|
15937
16301
|
showGreeting = false;
|
|
15938
16302
|
}
|
|
15939
|
-
} catch {
|
|
15940
16303
|
}
|
|
15941
16304
|
if (showGreeting) {
|
|
15942
16305
|
await context2.textAnimator?.showText(getGreetingBasedOnTime(), {
|
|
@@ -16040,6 +16403,18 @@ var CliBoot = class {
|
|
|
16040
16403
|
if (module.services && module.services.length > 0) {
|
|
16041
16404
|
this.services.set(module.services);
|
|
16042
16405
|
}
|
|
16406
|
+
if (module.guards && module.guards.length > 0) {
|
|
16407
|
+
this.services.set(
|
|
16408
|
+
module.guards.map((guard) => ({
|
|
16409
|
+
provide: cliCore.ICliCommandGuard_TOKEN,
|
|
16410
|
+
useValue: guard,
|
|
16411
|
+
multi: true
|
|
16412
|
+
}))
|
|
16413
|
+
);
|
|
16414
|
+
}
|
|
16415
|
+
if (module.permissions && module.permissions.length > 0) {
|
|
16416
|
+
this.services.get(cliCore.ICliPermissionRegistry_TOKEN)?.register(module.permissions, module.name);
|
|
16417
|
+
}
|
|
16043
16418
|
if (module.translations) {
|
|
16044
16419
|
for (const [locale, translations] of Object.entries(module.translations)) {
|
|
16045
16420
|
context2.translator.addTranslations(locale, translations);
|
|
@@ -16056,8 +16431,8 @@ var CliBoot = class {
|
|
|
16056
16431
|
}
|
|
16057
16432
|
}
|
|
16058
16433
|
if (module.onSetup) {
|
|
16059
|
-
const kvStore = context2.services.
|
|
16060
|
-
|
|
16434
|
+
const kvStore = context2.services.getRequired(
|
|
16435
|
+
CliKeyValueStore_TOKEN
|
|
16061
16436
|
);
|
|
16062
16437
|
const setupKey = `cli-module-setup:${module.name}`;
|
|
16063
16438
|
const setupState = await kvStore.get(setupKey);
|
|
@@ -16087,19 +16462,47 @@ var CliBoot = class {
|
|
|
16087
16462
|
this.registry.registerProcessor(processor);
|
|
16088
16463
|
}
|
|
16089
16464
|
await this.initializeProcessorsInternal(context2, filtered);
|
|
16465
|
+
this.adoptMergedSubProcessors(filtered);
|
|
16090
16466
|
}
|
|
16091
16467
|
this.bootedModules.add(module.name);
|
|
16092
16468
|
if (!this.moduleRegistry.has(module.name)) {
|
|
16093
16469
|
this.moduleRegistry.track(module);
|
|
16094
16470
|
}
|
|
16095
16471
|
}
|
|
16472
|
+
/**
|
|
16473
|
+
* Sub-processors of an `extendsProcessor` processor are merged into the
|
|
16474
|
+
* processor it extends, so they belong to that one: re-parent them so they
|
|
16475
|
+
* inherit its access rules (`requiredPermissions` etc.) and help/root
|
|
16476
|
+
* lookups resolve to the registered processor.
|
|
16477
|
+
*/
|
|
16478
|
+
adoptMergedSubProcessors(processors) {
|
|
16479
|
+
for (const processor of processors) {
|
|
16480
|
+
if (!processor.extendsProcessor) continue;
|
|
16481
|
+
const name = processor.command.toLowerCase();
|
|
16482
|
+
const host = this.registry.processors.find(
|
|
16483
|
+
(p) => p.command.toLowerCase() === name
|
|
16484
|
+
);
|
|
16485
|
+
if (!host || host === processor) continue;
|
|
16486
|
+
for (const sub of processor.processors ?? []) {
|
|
16487
|
+
if (host.processors?.includes(sub)) {
|
|
16488
|
+
sub.parent = host;
|
|
16489
|
+
}
|
|
16490
|
+
}
|
|
16491
|
+
}
|
|
16492
|
+
}
|
|
16096
16493
|
buildCoreModule() {
|
|
16097
16494
|
return {
|
|
16098
16495
|
apiVersion: API_VERSION,
|
|
16099
16496
|
name: "@qodalis/cli-core",
|
|
16100
16497
|
version: cliCore.LIBRARY_VERSION,
|
|
16101
16498
|
description: "Core CLI services and utilities",
|
|
16102
|
-
processors: [...builtinProcessors]
|
|
16499
|
+
processors: [...builtinProcessors],
|
|
16500
|
+
permissions: [
|
|
16501
|
+
{ name: "system:packages", description: "Install, update and remove packages (pkg)" },
|
|
16502
|
+
{ name: "system:services", description: "Start and stop background services" },
|
|
16503
|
+
{ name: "system:eval", description: "Evaluate JavaScript (eval, also requires allowEval)" },
|
|
16504
|
+
{ name: "shell:execute", description: "Open a remote shell on a server (ssh)" }
|
|
16505
|
+
]
|
|
16103
16506
|
};
|
|
16104
16507
|
}
|
|
16105
16508
|
/**
|
|
@@ -16231,6 +16634,29 @@ var CliDragDropService = class {
|
|
|
16231
16634
|
}
|
|
16232
16635
|
};
|
|
16233
16636
|
|
|
16637
|
+
// src/lib/services/cli-permission-registry.ts
|
|
16638
|
+
var CliPermissionRegistry = class {
|
|
16639
|
+
constructor() {
|
|
16640
|
+
this.definitions = /* @__PURE__ */ new Map();
|
|
16641
|
+
}
|
|
16642
|
+
register(definitions, module) {
|
|
16643
|
+
for (const def of definitions ?? []) {
|
|
16644
|
+
const name = def?.name?.trim();
|
|
16645
|
+
if (!name) continue;
|
|
16646
|
+
const key = name.toLowerCase();
|
|
16647
|
+
if (!this.definitions.has(key)) {
|
|
16648
|
+
this.definitions.set(key, { ...def, name, module: def.module ?? module });
|
|
16649
|
+
}
|
|
16650
|
+
}
|
|
16651
|
+
}
|
|
16652
|
+
list() {
|
|
16653
|
+
return [...this.definitions.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
16654
|
+
}
|
|
16655
|
+
get(name) {
|
|
16656
|
+
return this.definitions.get(name.trim().toLowerCase());
|
|
16657
|
+
}
|
|
16658
|
+
};
|
|
16659
|
+
|
|
16234
16660
|
// src/lib/addons/overlay.ts
|
|
16235
16661
|
var OverlayAddon = class {
|
|
16236
16662
|
constructor() {
|
|
@@ -16437,16 +16863,19 @@ var CliStateStore = class {
|
|
|
16437
16863
|
this.state$.next(this.initialState);
|
|
16438
16864
|
}
|
|
16439
16865
|
async persist() {
|
|
16440
|
-
const keyValueStore = this.services.
|
|
16441
|
-
|
|
16866
|
+
const keyValueStore = this.services.getRequired(
|
|
16867
|
+
CliKeyValueStore_TOKEN
|
|
16442
16868
|
);
|
|
16443
16869
|
await keyValueStore.set(this.storageKey, this.getState());
|
|
16444
16870
|
}
|
|
16445
16871
|
async initialize() {
|
|
16872
|
+
const keyValueStore = this.services.get(
|
|
16873
|
+
CliKeyValueStore_TOKEN
|
|
16874
|
+
);
|
|
16875
|
+
if (!keyValueStore) {
|
|
16876
|
+
return;
|
|
16877
|
+
}
|
|
16446
16878
|
try {
|
|
16447
|
-
const keyValueStore = this.services.get(
|
|
16448
|
-
"cli-key-value-store"
|
|
16449
|
-
);
|
|
16450
16879
|
const state = await keyValueStore.get(this.storageKey);
|
|
16451
16880
|
if (state) {
|
|
16452
16881
|
this.state$.next(state);
|
|
@@ -16513,6 +16942,39 @@ var CliStateStoreManager = class {
|
|
|
16513
16942
|
this.stores.clear();
|
|
16514
16943
|
}
|
|
16515
16944
|
};
|
|
16945
|
+
var CliServerAuthService = class {
|
|
16946
|
+
constructor(services) {
|
|
16947
|
+
this.services = services;
|
|
16948
|
+
}
|
|
16949
|
+
getHeaders(serverName, configHeaders) {
|
|
16950
|
+
const merged = {
|
|
16951
|
+
...cliCore.resolveHeaders(configHeaders)
|
|
16952
|
+
};
|
|
16953
|
+
const providers = this.services.getAll(
|
|
16954
|
+
cliCore.ICliServerAuthTokenProvider_TOKEN
|
|
16955
|
+
);
|
|
16956
|
+
for (const provider of providers) {
|
|
16957
|
+
Object.assign(merged, provider.getHeaders(serverName));
|
|
16958
|
+
}
|
|
16959
|
+
return merged;
|
|
16960
|
+
}
|
|
16961
|
+
async getWebSocketParams(serverName) {
|
|
16962
|
+
const providers = this.services.getAll(
|
|
16963
|
+
cliCore.ICliServerAuthTokenProvider_TOKEN
|
|
16964
|
+
);
|
|
16965
|
+
let handled = false;
|
|
16966
|
+
const merged = {};
|
|
16967
|
+
for (const provider of providers) {
|
|
16968
|
+
if (!provider.getWebSocketParams) continue;
|
|
16969
|
+
const params = await provider.getWebSocketParams(serverName);
|
|
16970
|
+
if (params) {
|
|
16971
|
+
handled = true;
|
|
16972
|
+
Object.assign(merged, params);
|
|
16973
|
+
}
|
|
16974
|
+
}
|
|
16975
|
+
return handled ? merged : void 0;
|
|
16976
|
+
}
|
|
16977
|
+
};
|
|
16516
16978
|
|
|
16517
16979
|
// src/lib/completion/cli-command-completion-provider.ts
|
|
16518
16980
|
var CliCommandCompletionProvider = class {
|
|
@@ -16660,12 +17122,10 @@ var CliPackageNameCompletionProvider = class {
|
|
|
16660
17122
|
if (!INSTALLED_PKG_SUBCOMMANDS.has(subCommand)) {
|
|
16661
17123
|
return [];
|
|
16662
17124
|
}
|
|
16663
|
-
|
|
16664
|
-
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
);
|
|
16668
|
-
} catch {
|
|
17125
|
+
const manager = this.services.get(
|
|
17126
|
+
CliPackageManagerService_TOKEN
|
|
17127
|
+
);
|
|
17128
|
+
if (!manager) {
|
|
16669
17129
|
return [];
|
|
16670
17130
|
}
|
|
16671
17131
|
const packages = await manager.getPackages();
|
|
@@ -16868,7 +17328,7 @@ var ServerListProcessor = class {
|
|
|
16868
17328
|
this.description = "Show configured servers and their connection status";
|
|
16869
17329
|
}
|
|
16870
17330
|
async processCommand(_command, context2) {
|
|
16871
|
-
const manager = context2.services.
|
|
17331
|
+
const manager = context2.services.getRequired(
|
|
16872
17332
|
CliServerManager_TOKEN
|
|
16873
17333
|
);
|
|
16874
17334
|
if (!manager || manager.connections.size === 0) {
|
|
@@ -16907,7 +17367,7 @@ var ServerStatusProcessor = class {
|
|
|
16907
17367
|
context2.process.exit(1);
|
|
16908
17368
|
return;
|
|
16909
17369
|
}
|
|
16910
|
-
const manager = context2.services.
|
|
17370
|
+
const manager = context2.services.getRequired(
|
|
16911
17371
|
CliServerManager_TOKEN
|
|
16912
17372
|
);
|
|
16913
17373
|
const connection = manager?.getConnection(serverName);
|
|
@@ -16917,7 +17377,7 @@ var ServerStatusProcessor = class {
|
|
|
16917
17377
|
return;
|
|
16918
17378
|
}
|
|
16919
17379
|
context2.spinner?.show(`Pinging ${serverName}...`);
|
|
16920
|
-
context2.
|
|
17380
|
+
context2.notifier.info(`Pinging ${serverName}`);
|
|
16921
17381
|
const reachable = await connection.ping();
|
|
16922
17382
|
context2.spinner?.hide();
|
|
16923
17383
|
if (reachable) {
|
|
@@ -16948,7 +17408,7 @@ var ServerReconnectProcessor = class {
|
|
|
16948
17408
|
context2.process.exit(1);
|
|
16949
17409
|
return;
|
|
16950
17410
|
}
|
|
16951
|
-
const manager = context2.services.
|
|
17411
|
+
const manager = context2.services.getRequired(
|
|
16952
17412
|
CliServerManager_TOKEN
|
|
16953
17413
|
);
|
|
16954
17414
|
if (!manager) {
|
|
@@ -16957,7 +17417,7 @@ var ServerReconnectProcessor = class {
|
|
|
16957
17417
|
return;
|
|
16958
17418
|
}
|
|
16959
17419
|
context2.spinner?.show(`Reconnecting to ${serverName}...`);
|
|
16960
|
-
context2.
|
|
17420
|
+
context2.notifier.info(`Reconnecting to ${serverName}`);
|
|
16961
17421
|
const result = await manager.reconnect(serverName);
|
|
16962
17422
|
context2.spinner?.hide();
|
|
16963
17423
|
if (result.success) {
|
|
@@ -16987,7 +17447,7 @@ var ServerDefaultProcessor = class {
|
|
|
16987
17447
|
];
|
|
16988
17448
|
}
|
|
16989
17449
|
async processCommand(command2, context2) {
|
|
16990
|
-
const manager = context2.services.
|
|
17450
|
+
const manager = context2.services.getRequired(
|
|
16991
17451
|
CliServerManager_TOKEN
|
|
16992
17452
|
);
|
|
16993
17453
|
if (!manager) {
|
|
@@ -17023,8 +17483,6 @@ var ServerDefaultProcessor = class {
|
|
|
17023
17483
|
}
|
|
17024
17484
|
}
|
|
17025
17485
|
};
|
|
17026
|
-
|
|
17027
|
-
// src/lib/server/cli-ssh-command-processor.ts
|
|
17028
17486
|
var CliSshCommandProcessor = class {
|
|
17029
17487
|
constructor() {
|
|
17030
17488
|
this.command = "ssh";
|
|
@@ -17033,7 +17491,9 @@ var CliSshCommandProcessor = class {
|
|
|
17033
17491
|
this.valueRequired = false;
|
|
17034
17492
|
this.metadata = {
|
|
17035
17493
|
module: "@qodalis/cli-server",
|
|
17036
|
-
icon: "\u{1F5A5}"
|
|
17494
|
+
icon: "\u{1F5A5}",
|
|
17495
|
+
// Enforced only when an auth module is loaded; the server checks it too
|
|
17496
|
+
requiredPermissions: [cliCore.CliServerPermissions.ShellExecute]
|
|
17037
17497
|
};
|
|
17038
17498
|
this.parameters = [
|
|
17039
17499
|
{
|
|
@@ -17043,12 +17503,9 @@ var CliSshCommandProcessor = class {
|
|
|
17043
17503
|
type: "string"
|
|
17044
17504
|
}
|
|
17045
17505
|
];
|
|
17046
|
-
this.socket = null;
|
|
17047
|
-
this.context = null;
|
|
17048
|
-
this.resolved = false;
|
|
17049
17506
|
}
|
|
17050
17507
|
async processCommand(command2, context2) {
|
|
17051
|
-
const manager = context2.services.
|
|
17508
|
+
const manager = context2.services.getRequired(
|
|
17052
17509
|
CliServerManager_TOKEN
|
|
17053
17510
|
);
|
|
17054
17511
|
if (!manager) {
|
|
@@ -17077,26 +17534,34 @@ var CliSshCommandProcessor = class {
|
|
|
17077
17534
|
await this.executeInteractive(connection, serverName, context2);
|
|
17078
17535
|
}
|
|
17079
17536
|
}
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
}
|
|
17091
|
-
}
|
|
17092
|
-
onDispose(_context) {
|
|
17093
|
-
if (this.socket) {
|
|
17094
|
-
if (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING) {
|
|
17095
|
-
this.socket.close();
|
|
17537
|
+
/**
|
|
17538
|
+
* Full-screen handler for one session: input, resize and disposal go to
|
|
17539
|
+
* that session's socket only.
|
|
17540
|
+
*/
|
|
17541
|
+
fullScreenHandler(session) {
|
|
17542
|
+
const handler = Object.create(this);
|
|
17543
|
+
handler.onData = async (data) => {
|
|
17544
|
+
if (session.socket?.readyState === WebSocket.OPEN) {
|
|
17545
|
+
const msg = { type: "stdin", data };
|
|
17546
|
+
session.socket.send(JSON.stringify(msg));
|
|
17096
17547
|
}
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17548
|
+
};
|
|
17549
|
+
handler.onResize = (cols, rows) => {
|
|
17550
|
+
if (session.socket?.readyState === WebSocket.OPEN) {
|
|
17551
|
+
const msg = { type: "resize", cols, rows };
|
|
17552
|
+
session.socket.send(JSON.stringify(msg));
|
|
17553
|
+
}
|
|
17554
|
+
};
|
|
17555
|
+
handler.onDispose = () => {
|
|
17556
|
+
session.disposed = true;
|
|
17557
|
+
if (session.socket) {
|
|
17558
|
+
if (session.socket.readyState === WebSocket.OPEN || session.socket.readyState === WebSocket.CONNECTING) {
|
|
17559
|
+
session.socket.close();
|
|
17560
|
+
}
|
|
17561
|
+
session.socket = null;
|
|
17562
|
+
}
|
|
17563
|
+
};
|
|
17564
|
+
return handler;
|
|
17100
17565
|
}
|
|
17101
17566
|
async resolveServer(command2, shellServers, context2) {
|
|
17102
17567
|
const empty = { serverName: null, oneShotCmd: null, connection: null };
|
|
@@ -17122,7 +17587,7 @@ var CliSshCommandProcessor = class {
|
|
|
17122
17587
|
const candidateName = parts[0];
|
|
17123
17588
|
const entry2 = shellServers.find((s) => s.name === candidateName);
|
|
17124
17589
|
if (entry2) {
|
|
17125
|
-
const oneShotCmd = parts.slice(1).join(" ") || null;
|
|
17590
|
+
const oneShotCmd = this.remoteCommandFromRaw(command2.rawCommand, candidateName) ?? (parts.slice(1).join(" ") || null);
|
|
17126
17591
|
return {
|
|
17127
17592
|
serverName: candidateName,
|
|
17128
17593
|
oneShotCmd,
|
|
@@ -17142,7 +17607,7 @@ var CliSshCommandProcessor = class {
|
|
|
17142
17607
|
connection: shellServers[0].connection
|
|
17143
17608
|
};
|
|
17144
17609
|
}
|
|
17145
|
-
const manager = context2.services.
|
|
17610
|
+
const manager = context2.services.getRequired(
|
|
17146
17611
|
CliServerManager_TOKEN
|
|
17147
17612
|
);
|
|
17148
17613
|
if (manager?.defaultServer) {
|
|
@@ -17176,41 +17641,57 @@ var CliSshCommandProcessor = class {
|
|
|
17176
17641
|
};
|
|
17177
17642
|
}
|
|
17178
17643
|
async executeInteractive(connection, serverName, context2) {
|
|
17179
|
-
|
|
17644
|
+
const session = { socket: null, resolved: false, disposed: false };
|
|
17180
17645
|
const cols = context2.terminal.cols;
|
|
17181
17646
|
const rows = context2.terminal.rows;
|
|
17182
|
-
const wsUrl = this.buildShellUrl(connection, cols, rows);
|
|
17647
|
+
const wsUrl = await this.buildShellUrl(connection, cols, rows);
|
|
17183
17648
|
context2.spinner?.show(`Connecting to ${serverName}...`);
|
|
17184
|
-
|
|
17649
|
+
let fullScreen = false;
|
|
17185
17650
|
return new Promise((resolve) => {
|
|
17651
|
+
const signal = context2.signal;
|
|
17186
17652
|
const resolveOnce = () => {
|
|
17187
|
-
|
|
17188
|
-
|
|
17653
|
+
signal?.removeEventListener("abort", onAbort);
|
|
17654
|
+
if (!session.resolved) {
|
|
17655
|
+
session.resolved = true;
|
|
17189
17656
|
resolve();
|
|
17190
17657
|
}
|
|
17191
17658
|
};
|
|
17659
|
+
const onAbort = () => {
|
|
17660
|
+
context2.spinner?.hide();
|
|
17661
|
+
this.cleanup(session);
|
|
17662
|
+
if (fullScreen) context2.exitFullScreenMode();
|
|
17663
|
+
context2.process.exit(130, { silent: true });
|
|
17664
|
+
resolveOnce();
|
|
17665
|
+
};
|
|
17666
|
+
if (signal?.aborted) {
|
|
17667
|
+
onAbort();
|
|
17668
|
+
return;
|
|
17669
|
+
}
|
|
17670
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
17192
17671
|
try {
|
|
17193
|
-
|
|
17672
|
+
session.socket = new WebSocket(wsUrl);
|
|
17194
17673
|
} catch (e) {
|
|
17195
17674
|
context2.spinner?.hide();
|
|
17196
17675
|
context2.writer.writeError(
|
|
17197
17676
|
`Failed to connect to '${serverName}': ${e.message}`
|
|
17198
17677
|
);
|
|
17199
|
-
context2.process.exit(1);
|
|
17678
|
+
context2.process.exit(1, { silent: true });
|
|
17200
17679
|
resolveOnce();
|
|
17201
17680
|
return;
|
|
17202
17681
|
}
|
|
17203
|
-
|
|
17682
|
+
session.socket.onopen = () => {
|
|
17204
17683
|
};
|
|
17205
|
-
|
|
17206
|
-
const msg =
|
|
17684
|
+
session.socket.onmessage = (event) => {
|
|
17685
|
+
const msg = parseShellMessage(event.data);
|
|
17686
|
+
if (!msg) return;
|
|
17207
17687
|
switch (msg.type) {
|
|
17208
17688
|
case "ready":
|
|
17209
17689
|
context2.spinner?.hide();
|
|
17210
17690
|
context2.writer.writeInfo(
|
|
17211
17691
|
`Connected to ${serverName} (${msg.os}, ${msg.shell})`
|
|
17212
17692
|
);
|
|
17213
|
-
context2.enterFullScreenMode(this);
|
|
17693
|
+
context2.enterFullScreenMode(this.fullScreenHandler(session));
|
|
17694
|
+
fullScreen = true;
|
|
17214
17695
|
context2.terminal.write("\x1B[2J\x1B[H\x1B[?25h");
|
|
17215
17696
|
break;
|
|
17216
17697
|
case "stdout":
|
|
@@ -17220,70 +17701,82 @@ var CliSshCommandProcessor = class {
|
|
|
17220
17701
|
context2.terminal.write(msg.data);
|
|
17221
17702
|
break;
|
|
17222
17703
|
case "exit":
|
|
17223
|
-
context2.exitFullScreenMode();
|
|
17704
|
+
if (fullScreen) context2.exitFullScreenMode();
|
|
17224
17705
|
context2.writer.writeInfo(
|
|
17225
17706
|
`Shell exited with code ${msg.code}.`
|
|
17226
17707
|
);
|
|
17227
|
-
context2.process.exit(msg.code);
|
|
17228
|
-
this.cleanup();
|
|
17708
|
+
context2.process.exit(msg.code, { silent: true });
|
|
17709
|
+
this.cleanup(session);
|
|
17229
17710
|
resolveOnce();
|
|
17230
17711
|
break;
|
|
17231
17712
|
case "error":
|
|
17232
17713
|
context2.spinner?.hide();
|
|
17233
|
-
context2.exitFullScreenMode();
|
|
17714
|
+
if (fullScreen) context2.exitFullScreenMode();
|
|
17234
17715
|
context2.writer.writeError(
|
|
17235
17716
|
`Server error: ${msg.message}`
|
|
17236
17717
|
);
|
|
17237
|
-
context2.process.exit(1);
|
|
17238
|
-
this.cleanup();
|
|
17718
|
+
context2.process.exit(1, { silent: true });
|
|
17719
|
+
this.cleanup(session);
|
|
17239
17720
|
resolveOnce();
|
|
17240
17721
|
break;
|
|
17241
17722
|
}
|
|
17242
17723
|
};
|
|
17243
|
-
|
|
17724
|
+
let errored = false;
|
|
17725
|
+
session.socket.onclose = (event) => {
|
|
17244
17726
|
context2.spinner?.hide();
|
|
17245
|
-
if (
|
|
17246
|
-
context2.exitFullScreenMode();
|
|
17247
|
-
|
|
17248
|
-
|
|
17249
|
-
);
|
|
17250
|
-
context2.
|
|
17727
|
+
if (!session.disposed && !session.resolved) {
|
|
17728
|
+
if (fullScreen) context2.exitFullScreenMode();
|
|
17729
|
+
const reason = describeShellClose(event ?? {}, serverName);
|
|
17730
|
+
if (reason) context2.writer.writeError(reason);
|
|
17731
|
+
else if (errored) context2.writer.writeError(`WebSocket error connecting to '${serverName}'.`);
|
|
17732
|
+
else context2.writer.writeWarning(`Connection to '${serverName}' closed.`);
|
|
17733
|
+
context2.process.exit(1, { silent: true });
|
|
17251
17734
|
}
|
|
17252
|
-
this.cleanup();
|
|
17735
|
+
this.cleanup(session);
|
|
17253
17736
|
resolveOnce();
|
|
17254
17737
|
};
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
if (!this.resolved) {
|
|
17258
|
-
context2.writer.writeError(
|
|
17259
|
-
`WebSocket error connecting to '${serverName}'.`
|
|
17260
|
-
);
|
|
17261
|
-
context2.process.exit(1);
|
|
17262
|
-
}
|
|
17263
|
-
this.cleanup();
|
|
17264
|
-
resolveOnce();
|
|
17738
|
+
session.socket.onerror = () => {
|
|
17739
|
+
errored = true;
|
|
17265
17740
|
};
|
|
17266
17741
|
});
|
|
17267
17742
|
}
|
|
17268
17743
|
async executeOneShot(connection, serverName, cmd, context2) {
|
|
17269
17744
|
const cols = context2.terminal.cols;
|
|
17270
17745
|
const rows = context2.terminal.rows;
|
|
17271
|
-
const wsUrl = this.buildShellUrl(connection, cols, rows, cmd);
|
|
17746
|
+
const wsUrl = await this.buildShellUrl(connection, cols, rows, cmd);
|
|
17272
17747
|
context2.spinner?.show(`Running on ${serverName}...`);
|
|
17273
|
-
|
|
17748
|
+
const session = { socket: null, resolved: false, disposed: false };
|
|
17749
|
+
return new Promise((resolvePromise) => {
|
|
17750
|
+
const signal = context2.signal;
|
|
17751
|
+
const resolve = () => {
|
|
17752
|
+
signal?.removeEventListener("abort", onAbort);
|
|
17753
|
+
resolvePromise();
|
|
17754
|
+
};
|
|
17755
|
+
const onAbort = () => {
|
|
17756
|
+
context2.spinner?.hide();
|
|
17757
|
+
this.cleanup(session);
|
|
17758
|
+
context2.process.exit(130, { silent: true });
|
|
17759
|
+
resolve();
|
|
17760
|
+
};
|
|
17761
|
+
if (signal?.aborted) {
|
|
17762
|
+
onAbort();
|
|
17763
|
+
return;
|
|
17764
|
+
}
|
|
17765
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
17274
17766
|
try {
|
|
17275
|
-
|
|
17767
|
+
session.socket = new WebSocket(wsUrl);
|
|
17276
17768
|
} catch (e) {
|
|
17277
17769
|
context2.spinner?.hide();
|
|
17278
17770
|
context2.writer.writeError(
|
|
17279
17771
|
`Failed to connect to '${serverName}': ${e.message}`
|
|
17280
17772
|
);
|
|
17281
|
-
context2.process.exit(1);
|
|
17773
|
+
context2.process.exit(1, { silent: true });
|
|
17282
17774
|
resolve();
|
|
17283
17775
|
return;
|
|
17284
17776
|
}
|
|
17285
|
-
|
|
17286
|
-
const msg =
|
|
17777
|
+
session.socket.onmessage = (event) => {
|
|
17778
|
+
const msg = parseShellMessage(event.data);
|
|
17779
|
+
if (!msg) return;
|
|
17287
17780
|
switch (msg.type) {
|
|
17288
17781
|
case "ready":
|
|
17289
17782
|
context2.spinner?.hide();
|
|
@@ -17296,9 +17789,9 @@ var CliSshCommandProcessor = class {
|
|
|
17296
17789
|
break;
|
|
17297
17790
|
case "exit":
|
|
17298
17791
|
if (msg.code !== 0) {
|
|
17299
|
-
context2.process.exit(msg.code);
|
|
17792
|
+
context2.process.exit(msg.code, { silent: true });
|
|
17300
17793
|
}
|
|
17301
|
-
this.cleanup();
|
|
17794
|
+
this.cleanup(session);
|
|
17302
17795
|
resolve();
|
|
17303
17796
|
break;
|
|
17304
17797
|
case "error":
|
|
@@ -17306,50 +17799,82 @@ var CliSshCommandProcessor = class {
|
|
|
17306
17799
|
context2.writer.writeError(
|
|
17307
17800
|
`Server error: ${msg.message}`
|
|
17308
17801
|
);
|
|
17309
|
-
context2.process.exit(1);
|
|
17310
|
-
this.cleanup();
|
|
17802
|
+
context2.process.exit(1, { silent: true });
|
|
17803
|
+
this.cleanup(session);
|
|
17311
17804
|
resolve();
|
|
17312
17805
|
break;
|
|
17313
17806
|
}
|
|
17314
17807
|
};
|
|
17315
|
-
|
|
17808
|
+
let errored = false;
|
|
17809
|
+
session.socket.onclose = (event) => {
|
|
17316
17810
|
context2.spinner?.hide();
|
|
17317
|
-
|
|
17811
|
+
const reason = describeShellClose(event ?? {}, serverName);
|
|
17812
|
+
if (reason || errored) {
|
|
17813
|
+
context2.writer.writeError(reason ?? `WebSocket error connecting to '${serverName}'.`);
|
|
17814
|
+
context2.process.exit(1, { silent: true });
|
|
17815
|
+
}
|
|
17816
|
+
this.cleanup(session);
|
|
17318
17817
|
resolve();
|
|
17319
17818
|
};
|
|
17320
|
-
|
|
17321
|
-
|
|
17322
|
-
context2.writer.writeError(
|
|
17323
|
-
`WebSocket error connecting to '${serverName}'.`
|
|
17324
|
-
);
|
|
17325
|
-
context2.process.exit(1);
|
|
17326
|
-
this.cleanup();
|
|
17327
|
-
resolve();
|
|
17819
|
+
session.socket.onerror = () => {
|
|
17820
|
+
errored = true;
|
|
17328
17821
|
};
|
|
17329
17822
|
});
|
|
17330
17823
|
}
|
|
17824
|
+
/** `ssh <server> <cmd...>` → `<cmd...>` exactly as typed */
|
|
17825
|
+
remoteCommandFromRaw(raw, serverName) {
|
|
17826
|
+
const match = raw?.trim().match(/^\S+\s+(\S+)\s+([\s\S]+)$/);
|
|
17827
|
+
return match && match[1] === serverName ? match[2].trim() : null;
|
|
17828
|
+
}
|
|
17331
17829
|
buildShellUrl(connection, cols, rows, cmd) {
|
|
17332
|
-
|
|
17333
|
-
const wsBase = baseUrl.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
|
|
17334
|
-
let url = `${wsBase}/ws/v1/qcli/shell?cols=${cols}&rows=${rows}`;
|
|
17830
|
+
let path = `/ws/v1/qcli/shell?cols=${cols}&rows=${rows}`;
|
|
17335
17831
|
if (cmd) {
|
|
17336
|
-
|
|
17832
|
+
path += `&cmd=${encodeURIComponent(cmd)}`;
|
|
17337
17833
|
}
|
|
17338
|
-
return
|
|
17834
|
+
return connection.buildWebSocketUrl(path);
|
|
17339
17835
|
}
|
|
17340
|
-
cleanup() {
|
|
17341
|
-
|
|
17342
|
-
|
|
17343
|
-
|
|
17344
|
-
|
|
17345
|
-
|
|
17346
|
-
|
|
17836
|
+
cleanup(session) {
|
|
17837
|
+
const socket = session.socket;
|
|
17838
|
+
if (socket) {
|
|
17839
|
+
socket.onmessage = null;
|
|
17840
|
+
socket.onclose = null;
|
|
17841
|
+
socket.onerror = null;
|
|
17842
|
+
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
17843
|
+
socket.close();
|
|
17347
17844
|
}
|
|
17348
|
-
|
|
17845
|
+
session.socket = null;
|
|
17349
17846
|
}
|
|
17350
|
-
this.context = null;
|
|
17351
17847
|
}
|
|
17352
17848
|
};
|
|
17849
|
+
function parseShellMessage(data) {
|
|
17850
|
+
try {
|
|
17851
|
+
const msg = typeof data === "string" ? JSON.parse(data) : null;
|
|
17852
|
+
return msg && typeof msg === "object" && typeof msg.type === "string" ? msg : null;
|
|
17853
|
+
} catch {
|
|
17854
|
+
return null;
|
|
17855
|
+
}
|
|
17856
|
+
}
|
|
17857
|
+
function describeShellClose(event, serverName) {
|
|
17858
|
+
const reason = (event.reason ?? "").toLowerCase();
|
|
17859
|
+
switch (event.code) {
|
|
17860
|
+
case 4401:
|
|
17861
|
+
if (reason === "session ended") return `ssh: shell closed by '${serverName}' (session ended or shell access revoked)`;
|
|
17862
|
+
if (reason === "shell access is not configured") {
|
|
17863
|
+
return `ssh: shell access is not configured on '${serverName}'`;
|
|
17864
|
+
}
|
|
17865
|
+
return `ssh: login required on '${serverName}'`;
|
|
17866
|
+
case 4403:
|
|
17867
|
+
return `ssh: permission denied on '${serverName}' (requires shell:execute or a valid shell token)`;
|
|
17868
|
+
case 4404:
|
|
17869
|
+
return `ssh: the shell is disabled on '${serverName}'`;
|
|
17870
|
+
case 4408:
|
|
17871
|
+
return `ssh: shell timed out on '${serverName}'`;
|
|
17872
|
+
case 4429:
|
|
17873
|
+
return `ssh: too many shell sessions on '${serverName}'`;
|
|
17874
|
+
default:
|
|
17875
|
+
return null;
|
|
17876
|
+
}
|
|
17877
|
+
}
|
|
17353
17878
|
|
|
17354
17879
|
// src/lib/server/cli-server-module.ts
|
|
17355
17880
|
function createServerModule() {
|
|
@@ -17384,6 +17909,11 @@ function initializeTerminal(container, opts) {
|
|
|
17384
17909
|
terminal.open(container);
|
|
17385
17910
|
fitAddon.fit();
|
|
17386
17911
|
requestAnimationFrame(() => fitAddon.fit());
|
|
17912
|
+
if (document.fonts?.ready) {
|
|
17913
|
+
document.fonts.ready.then(() => {
|
|
17914
|
+
requestAnimationFrame(() => fitAddon.fit());
|
|
17915
|
+
});
|
|
17916
|
+
}
|
|
17387
17917
|
container.classList.add("terminal-container");
|
|
17388
17918
|
container.style.background = opts.theme?.background ?? "#000";
|
|
17389
17919
|
const wheelListener = (e) => e.preventDefault();
|
|
@@ -17626,19 +18156,21 @@ async function initializeServices(options) {
|
|
|
17626
18156
|
const logger = new CliLogger();
|
|
17627
18157
|
const commandHistory = new CliCommandHistory(store);
|
|
17628
18158
|
await commandHistory.initialize();
|
|
17629
|
-
services.set([{ provide:
|
|
18159
|
+
services.set([{ provide: CliKeyValueStore_TOKEN, useValue: store, sealed: true }]);
|
|
17630
18160
|
const stateStoreManager = new CliStateStoreManager(services, registry);
|
|
17631
18161
|
const processRegistry = new CliProcessRegistry();
|
|
17632
18162
|
services.set([
|
|
17633
18163
|
{
|
|
17634
18164
|
provide: CliStateStoreManager_TOKEN,
|
|
17635
|
-
useValue: stateStoreManager
|
|
18165
|
+
useValue: stateStoreManager,
|
|
18166
|
+
sealed: true
|
|
17636
18167
|
},
|
|
17637
|
-
{ provide: CliProcessorsRegistry_TOKEN, useValue: registry },
|
|
17638
|
-
{ provide: CliCommandHistory_TOKEN, useValue: commandHistory },
|
|
18168
|
+
{ provide: CliProcessorsRegistry_TOKEN, useValue: registry, sealed: true },
|
|
18169
|
+
{ provide: CliCommandHistory_TOKEN, useValue: commandHistory, sealed: true },
|
|
17639
18170
|
{
|
|
17640
18171
|
provide: CliProcessRegistry_TOKEN,
|
|
17641
|
-
useValue: processRegistry
|
|
18172
|
+
useValue: processRegistry,
|
|
18173
|
+
sealed: true
|
|
17642
18174
|
}
|
|
17643
18175
|
]);
|
|
17644
18176
|
if (pendingServices.length > 0) {
|
|
@@ -17649,7 +18181,8 @@ async function initializeServices(options) {
|
|
|
17649
18181
|
services.set([
|
|
17650
18182
|
{
|
|
17651
18183
|
provide: ICliPingServerService_TOKEN,
|
|
17652
|
-
|
|
18184
|
+
useClass: CliDefaultPingServerService,
|
|
18185
|
+
sealed: true
|
|
17653
18186
|
}
|
|
17654
18187
|
]);
|
|
17655
18188
|
}
|
|
@@ -17659,25 +18192,41 @@ async function initializeServices(options) {
|
|
|
17659
18192
|
syntaxRegistry.register(new MarkdownHighlighter());
|
|
17660
18193
|
syntaxRegistry.register(new YamlHighlighter());
|
|
17661
18194
|
services.set([
|
|
17662
|
-
{ provide:
|
|
18195
|
+
{ provide: SyntaxHighlighterRegistry_TOKEN, useValue: syntaxRegistry, sealed: true }
|
|
17663
18196
|
]);
|
|
17664
18197
|
if (!pendingTokens.has(ICliEnvironment_TOKEN)) {
|
|
17665
18198
|
services.set([
|
|
17666
18199
|
{
|
|
17667
18200
|
provide: ICliEnvironment_TOKEN,
|
|
17668
|
-
|
|
18201
|
+
useClass: CliEnvironment,
|
|
18202
|
+
sealed: true
|
|
17669
18203
|
}
|
|
17670
18204
|
]);
|
|
17671
18205
|
}
|
|
17672
18206
|
services.set([
|
|
17673
18207
|
{
|
|
17674
18208
|
provide: cliCore.ICliDragDropService_TOKEN,
|
|
17675
|
-
useValue: dragDropService
|
|
18209
|
+
useValue: dragDropService,
|
|
18210
|
+
sealed: true
|
|
18211
|
+
}
|
|
18212
|
+
]);
|
|
18213
|
+
services.set(
|
|
18214
|
+
cliCore.cliAccessMetadataGuards.map((guard) => ({
|
|
18215
|
+
provide: cliCore.ICliCommandGuard_TOKEN,
|
|
18216
|
+
useValue: guard,
|
|
18217
|
+
multi: true
|
|
18218
|
+
}))
|
|
18219
|
+
);
|
|
18220
|
+
services.set([
|
|
18221
|
+
{
|
|
18222
|
+
provide: cliCore.ICliPermissionRegistry_TOKEN,
|
|
18223
|
+
useValue: new CliPermissionRegistry(),
|
|
18224
|
+
sealed: true
|
|
17676
18225
|
}
|
|
17677
18226
|
]);
|
|
17678
18227
|
const translator = new CliTranslationService();
|
|
17679
18228
|
services.set([
|
|
17680
|
-
{ provide: cliCore.ICliTranslationService_TOKEN, useValue: translator }
|
|
18229
|
+
{ provide: cliCore.ICliTranslationService_TOKEN, useValue: translator, sealed: true }
|
|
17681
18230
|
]);
|
|
17682
18231
|
return {
|
|
17683
18232
|
services,
|
|
@@ -17746,7 +18295,7 @@ var CliEngine = class {
|
|
|
17746
18295
|
* Initialize the terminal, wire up services, boot modules, and show welcome message.
|
|
17747
18296
|
*/
|
|
17748
18297
|
async start() {
|
|
17749
|
-
initWasmAccelerator().catch(() => {
|
|
18298
|
+
initWasmAccelerator(this.options?.wasmUrl).catch(() => {
|
|
17750
18299
|
});
|
|
17751
18300
|
await waitForLayout(this.container);
|
|
17752
18301
|
const terminalOpts = getTerminalOptions(this.options?.terminalOptions);
|
|
@@ -17789,10 +18338,18 @@ var CliEngine = class {
|
|
|
17789
18338
|
provide: CliBackgroundServiceRegistry_TOKEN,
|
|
17790
18339
|
useValue: this.executionContext.backgroundServices
|
|
17791
18340
|
}]);
|
|
17792
|
-
const
|
|
18341
|
+
const serverAuthService = new CliServerAuthService(services);
|
|
17793
18342
|
services.set([
|
|
17794
|
-
{ provide:
|
|
18343
|
+
{ provide: cliCore.ICliServerAuthService_TOKEN, useValue: serverAuthService, sealed: true }
|
|
18344
|
+
]);
|
|
18345
|
+
services.set([
|
|
18346
|
+
{
|
|
18347
|
+
provide: CliServerManager_TOKEN,
|
|
18348
|
+
useClass: CliServerManager,
|
|
18349
|
+
deps: [CliProcessorsRegistry_TOKEN, cliCore.ICliServerAuthService_TOKEN]
|
|
18350
|
+
}
|
|
17795
18351
|
]);
|
|
18352
|
+
const serverManager = services.getRequired(CliServerManager_TOKEN);
|
|
17796
18353
|
if (this.options?.servers && this.options.servers.length > 0) {
|
|
17797
18354
|
await serverManager.connectAll(this.options.servers, {
|
|
17798
18355
|
warn: (msg) => this.executionContext.logger.warn(msg),
|
|
@@ -17812,13 +18369,9 @@ var CliEngine = class {
|
|
|
17812
18369
|
new CliCommandCompletionProvider(this.registry),
|
|
17813
18370
|
new CliParameterCompletionProvider(this.registry, executor)
|
|
17814
18371
|
];
|
|
17815
|
-
|
|
17816
|
-
|
|
17817
|
-
|
|
17818
|
-
cliCore.ICliCompletionProvider_TOKEN
|
|
17819
|
-
) ?? [];
|
|
17820
|
-
} catch {
|
|
17821
|
-
}
|
|
18372
|
+
const pluginProviders = services.getAll(
|
|
18373
|
+
cliCore.ICliCompletionProvider_TOKEN
|
|
18374
|
+
);
|
|
17822
18375
|
this.executionContext.completionEngine.setProviders([
|
|
17823
18376
|
...pluginProviders,
|
|
17824
18377
|
...defaultProviders
|
|
@@ -17926,7 +18479,7 @@ var CliEngine = class {
|
|
|
17926
18479
|
if (!this.executionContext) {
|
|
17927
18480
|
throw new Error("Cannot snapshot before engine has started");
|
|
17928
18481
|
}
|
|
17929
|
-
const stateStoreManager = this.executionContext.services.
|
|
18482
|
+
const stateStoreManager = this.executionContext.services.getRequired(
|
|
17930
18483
|
CliStateStoreManager_TOKEN
|
|
17931
18484
|
);
|
|
17932
18485
|
return {
|
|
@@ -17953,7 +18506,7 @@ var CliEngine = class {
|
|
|
17953
18506
|
});
|
|
17954
18507
|
}
|
|
17955
18508
|
await this.executionContext.commandHistory.setHistory(snap.commandHistory);
|
|
17956
|
-
const stateStoreManager = this.executionContext.services.
|
|
18509
|
+
const stateStoreManager = this.executionContext.services.getRequired(
|
|
17957
18510
|
CliStateStoreManager_TOKEN
|
|
17958
18511
|
);
|
|
17959
18512
|
for (const entry of snap.stateStores) {
|
|
@@ -18013,7 +18566,7 @@ var CliTestHarness = class {
|
|
|
18013
18566
|
this.services = new CliServiceContainer();
|
|
18014
18567
|
this.processRegistry = new CliProcessRegistry();
|
|
18015
18568
|
this.services.set({
|
|
18016
|
-
provide:
|
|
18569
|
+
provide: CliKeyValueStore_TOKEN,
|
|
18017
18570
|
useValue: createInMemoryKvStore()
|
|
18018
18571
|
});
|
|
18019
18572
|
this.services.set({
|
|
@@ -18036,6 +18589,24 @@ var CliTestHarness = class {
|
|
|
18036
18589
|
provide: ICliEnvironment_TOKEN,
|
|
18037
18590
|
useValue: new CliEnvironment()
|
|
18038
18591
|
});
|
|
18592
|
+
this.services.set({
|
|
18593
|
+
provide: cliCore.ICliPermissionRegistry_TOKEN,
|
|
18594
|
+
useValue: new CliPermissionRegistry()
|
|
18595
|
+
});
|
|
18596
|
+
this.services.set(
|
|
18597
|
+
cliCore.cliAccessMetadataGuards.map((guard) => ({
|
|
18598
|
+
provide: cliCore.ICliCommandGuard_TOKEN,
|
|
18599
|
+
useValue: guard,
|
|
18600
|
+
multi: true
|
|
18601
|
+
}))
|
|
18602
|
+
);
|
|
18603
|
+
}
|
|
18604
|
+
/**
|
|
18605
|
+
* Resolve `context.userSession` on every command from this function
|
|
18606
|
+
* (e.g. a session service), instead of the value set via setUserSession().
|
|
18607
|
+
*/
|
|
18608
|
+
setUserSessionProvider(provider) {
|
|
18609
|
+
this.userSessionProvider = provider;
|
|
18039
18610
|
}
|
|
18040
18611
|
/**
|
|
18041
18612
|
* Register a service in the test container.
|
|
@@ -18120,9 +18691,10 @@ var CliTestHarness = class {
|
|
|
18120
18691
|
options: void 0,
|
|
18121
18692
|
logger: createNoopLogger(),
|
|
18122
18693
|
process,
|
|
18123
|
-
userSession: this.userSession,
|
|
18694
|
+
userSession: this.userSessionProvider ? this.userSessionProvider() : this.userSession,
|
|
18124
18695
|
state: this.stateStoreManager.getStateStore("shared"),
|
|
18125
18696
|
backgroundServices: createNoopBackgroundServices(),
|
|
18697
|
+
http: new CliHttpClient(),
|
|
18126
18698
|
promptLength: 0,
|
|
18127
18699
|
currentLine: "",
|
|
18128
18700
|
cursorPosition: 0,
|
|
@@ -18145,11 +18717,7 @@ var CliTestHarness = class {
|
|
|
18145
18717
|
submitCommand: async (command2) => {
|
|
18146
18718
|
await this.executor.executeCommand(command2, context2);
|
|
18147
18719
|
},
|
|
18148
|
-
|
|
18149
|
-
},
|
|
18150
|
-
clearStatusText: () => {
|
|
18151
|
-
},
|
|
18152
|
-
getStatusText: () => void 0,
|
|
18720
|
+
notifier: new CliNotifier(),
|
|
18153
18721
|
createInterval: (cb, ms) => {
|
|
18154
18722
|
const id = setInterval(cb, ms);
|
|
18155
18723
|
return {
|
|
@@ -18402,18 +18970,22 @@ exports.CliHelpCommandProcessor = CliHelpCommandProcessor;
|
|
|
18402
18970
|
exports.CliHistoryCommandProcessor = CliHistoryCommandProcessor;
|
|
18403
18971
|
exports.CliHotKeysCommandProcessor = CliHotKeysCommandProcessor;
|
|
18404
18972
|
exports.CliHtopCommandProcessor = CliHtopCommandProcessor;
|
|
18973
|
+
exports.CliHttpClient = CliHttpClient;
|
|
18405
18974
|
exports.CliInputReader = CliInputReader;
|
|
18406
18975
|
exports.CliJsonCommandProcessor = CliJsonCommandProcessor;
|
|
18407
18976
|
exports.CliKeyValueStore = CliKeyValueStore;
|
|
18977
|
+
exports.CliKeyValueStore_TOKEN = CliKeyValueStore_TOKEN;
|
|
18408
18978
|
exports.CliKillCommandProcessor = CliKillCommandProcessor;
|
|
18409
18979
|
exports.CliLogger = CliLogger;
|
|
18410
18980
|
exports.CliLoremCommandProcessor = CliLoremCommandProcessor;
|
|
18411
18981
|
exports.CliModuleRegistry_TOKEN = CliModuleRegistry_TOKEN;
|
|
18412
18982
|
exports.CliNanoCommandProcessor = CliNanoCommandProcessor;
|
|
18983
|
+
exports.CliNotifier = CliNotifier;
|
|
18413
18984
|
exports.CliOpenCommandProcessor = CliOpenCommandProcessor;
|
|
18414
18985
|
exports.CliPackageManagerService = CliPackageManagerService;
|
|
18415
18986
|
exports.CliPackageManagerService_TOKEN = CliPackageManagerService_TOKEN;
|
|
18416
18987
|
exports.CliPackagesCommandProcessor = CliPackagesCommandProcessor;
|
|
18988
|
+
exports.CliPermissionRegistry = CliPermissionRegistry;
|
|
18417
18989
|
exports.CliPingCommandProcessor = CliPingCommandProcessor;
|
|
18418
18990
|
exports.CliProcessRegistry = CliProcessRegistry;
|
|
18419
18991
|
exports.CliProcessRegistry_TOKEN = CliProcessRegistry_TOKEN;
|
|
@@ -18459,12 +19031,14 @@ exports.LIBRARY_VERSION = LIBRARY_VERSION;
|
|
|
18459
19031
|
exports.OverlayAddon = OverlayAddon;
|
|
18460
19032
|
exports.ProcessExitedError = ProcessExitedError;
|
|
18461
19033
|
exports.ScriptLoaderService = ScriptLoaderService;
|
|
19034
|
+
exports.SyntaxHighlighterRegistry_TOKEN = SyntaxHighlighterRegistry_TOKEN;
|
|
18462
19035
|
exports.appendOutputToFile = appendOutputToFile;
|
|
18463
19036
|
exports.appendStderrToFile = appendStderrToFile;
|
|
18464
19037
|
exports.builtinProcessors = builtinProcessors;
|
|
18465
19038
|
exports.computeDiff = computeDiff;
|
|
18466
19039
|
exports.contextGlobalParameter = contextGlobalParameter;
|
|
18467
19040
|
exports.createServerModule = createServerModule;
|
|
19041
|
+
exports.describeShellClose = describeShellClose;
|
|
18468
19042
|
exports.executeOnServer = executeOnServer;
|
|
18469
19043
|
exports.expandEnvironmentVars = expandEnvironmentVars;
|
|
18470
19044
|
exports.formatDiff = formatDiff;
|