@qodalis/cli 2.0.0-beta.11 → 2.0.0-beta.13

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/public-api.js CHANGED
@@ -409,9 +409,11 @@ 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.11";
416
+ var LIBRARY_VERSION = "2.0.0-beta.13";
415
417
  var API_VERSION = 2;
416
418
  var CliAliasCommandProcessor = class {
417
419
  constructor() {
@@ -474,7 +476,7 @@ var CliAliasCommandProcessor = class {
474
476
  );
475
477
  }
476
478
  async processCommand(command2, context2) {
477
- const registry = context2.services.get(
479
+ const registry = context2.services.getRequired(
478
480
  CliProcessorsRegistry_TOKEN
479
481
  );
480
482
  const { writer } = context2;
@@ -2814,7 +2816,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
2814
2816
  ];
2815
2817
  }
2816
2818
  async processCommand(command2, context2) {
2817
- const registry = context2.services.get(
2819
+ const registry = context2.services.getRequired(
2818
2820
  CliProcessorsRegistry_TOKEN
2819
2821
  );
2820
2822
  const pluginCategories = cliCore.resolveConfigurationCategories(registry);
@@ -2911,10 +2913,10 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
2911
2913
  if (stateKey === "system") {
2912
2914
  const langOption = options.find((o) => o.key === "language");
2913
2915
  if (langOption) {
2914
- try {
2915
- const translator = context2.services.get(
2916
- cliCore.ICliTranslationService_TOKEN
2917
- );
2916
+ const translator = context2.services.get(
2917
+ cliCore.ICliTranslationService_TOKEN
2918
+ );
2919
+ if (translator) {
2918
2920
  const locales = translator.getAvailableLocales();
2919
2921
  if (locales.length > 0) {
2920
2922
  langOption.options = locales.map((l) => ({
@@ -2922,7 +2924,6 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
2922
2924
  value: l
2923
2925
  }));
2924
2926
  }
2925
- } catch {
2926
2927
  }
2927
2928
  }
2928
2929
  }
@@ -3067,13 +3068,10 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
3067
3068
  }
3068
3069
  }
3069
3070
  if (settings["language"]) {
3070
- try {
3071
- const translator = context2.services.get(
3072
- cliCore.ICliTranslationService_TOKEN
3073
- );
3074
- translator.setLocale(settings["language"]);
3075
- } catch {
3076
- }
3071
+ const translator = context2.services.get(
3072
+ cliCore.ICliTranslationService_TOKEN
3073
+ );
3074
+ translator?.setLocale(settings["language"]);
3077
3075
  }
3078
3076
  if (context2.terminal?.options) {
3079
3077
  if (settings["cursorBlink"] !== void 0) {
@@ -3103,7 +3101,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
3103
3101
  aliases: ["ls"],
3104
3102
  description: "List all configuration options and their current values",
3105
3103
  processCommand: async (_, context2) => {
3106
- const registry = context2.services.get(
3104
+ const registry = context2.services.getRequired(
3107
3105
  CliProcessorsRegistry_TOKEN
3108
3106
  );
3109
3107
  const allOptions = this.getAllOptions(registry);
@@ -3165,7 +3163,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
3165
3163
  }
3166
3164
  const category = path.substring(0, dotIndex);
3167
3165
  const key = path.substring(dotIndex + 1);
3168
- const registry = context2.services.get(
3166
+ const registry = context2.services.getRequired(
3169
3167
  CliProcessorsRegistry_TOKEN
3170
3168
  );
3171
3169
  const allOptions = this.getAllOptions(registry);
@@ -3217,7 +3215,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
3217
3215
  }
3218
3216
  const category = path.substring(0, dotIndex);
3219
3217
  const key = path.substring(dotIndex + 1);
3220
- const registry = context2.services.get(
3218
+ const registry = context2.services.getRequired(
3221
3219
  CliProcessorsRegistry_TOKEN
3222
3220
  );
3223
3221
  const allOptions = this.getAllOptions(registry);
@@ -3277,7 +3275,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
3277
3275
  t.t("cli.configure.system_reset", "System configuration reset to defaults")
3278
3276
  );
3279
3277
  } else {
3280
- const registry = context2.services.get(
3278
+ const registry = context2.services.getRequired(
3281
3279
  CliProcessorsRegistry_TOKEN
3282
3280
  );
3283
3281
  const categories2 = cliCore.resolveConfigurationCategories(registry);
@@ -3673,7 +3671,7 @@ var CliHelpCommandProcessor = class {
3673
3671
  async processCommand(command2, context2) {
3674
3672
  const { writer } = context2;
3675
3673
  const t = context2.translator;
3676
- const registry = context2.services.get(
3674
+ const registry = context2.services.getRequired(
3677
3675
  CliProcessorsRegistry_TOKEN
3678
3676
  );
3679
3677
  const [_, ...commandsToHelp] = command2.command.split(" ");
@@ -3773,24 +3771,23 @@ var CliHelpCommandProcessor = class {
3773
3771
  writeProcessorDescription(processor, context2) {
3774
3772
  const { writer } = context2;
3775
3773
  const t = context2.translator;
3776
- const icon = processor.metadata?.icon || "";
3777
- const name = `${BOLD}${writer.wrapInColor(processor.command, cliCore.CliForegroundColor.Cyan)}${RESET}`;
3778
3774
  const version = `${DIM}v${processor.version || "1.0.0"}${RESET}`;
3779
- writer.writeln();
3780
- writer.writeln(` ${icon}${icon ? " " : ""}${name} ${version}`);
3775
+ const headerLines = [];
3781
3776
  if (processor.description) {
3782
- const desc = this.translateDescription(
3783
- processor.description,
3784
- processor.command,
3785
- context2
3777
+ headerLines.push(
3778
+ this.translateDescription(processor.description, processor.command, context2)
3786
3779
  );
3787
- writer.writeln(` ${desc}`);
3788
3780
  }
3789
3781
  if (processor.aliases?.length) {
3790
- writer.writeln(
3791
- ` ${DIM}${t.t("cli.help.aliases", "Aliases:")}${RESET} ${processor.aliases.map((a) => writer.wrapInColor(a, cliCore.CliForegroundColor.Magenta)).join(", ")}`
3782
+ headerLines.push(
3783
+ `${DIM}${t.t("cli.help.aliases", "Aliases:")}${RESET} ${processor.aliases.map((a) => writer.wrapInColor(a, cliCore.CliForegroundColor.Magenta)).join(", ")}`
3792
3784
  );
3793
3785
  }
3786
+ writer.writeln();
3787
+ writer.writeBox(headerLines, {
3788
+ title: `${writer.wrapInColor(processor.command, cliCore.CliForegroundColor.Cyan)} ${version}`,
3789
+ borderColor: cliCore.CliForegroundColor.White
3790
+ });
3794
3791
  if (processor.originalProcessor) {
3795
3792
  writer.writeln();
3796
3793
  writer.writeln(
@@ -3956,20 +3953,13 @@ var CliVersionCommandProcessor = class {
3956
3953
  writer.writeln(
3957
3954
  writer.wrapInColor(getCliNameArt(context2.terminal.cols), cliCore.CliForegroundColor.Cyan)
3958
3955
  );
3959
- writer.writeln(
3960
- ` ${DIM2}CLI${RESET2} ${writer.wrapInColor(`v${LIBRARY_VERSION}`, cliCore.CliForegroundColor.Green)} ${DIM2}Core${RESET2} ${writer.wrapInColor(`v${cliCore.LIBRARY_VERSION}`, cliCore.CliForegroundColor.Green)}`
3961
- );
3962
- let framework = "vanilla";
3963
- try {
3964
- framework = context2.services.get("cli-framework");
3965
- } catch {
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
- );
3956
+ const framework = context2.services.get("cli-framework") ?? "vanilla";
3957
+ writer.writeBox([
3958
+ `${DIM2}CLI${RESET2} ${writer.wrapInColor(`v${LIBRARY_VERSION}`, cliCore.CliForegroundColor.Green)}`,
3959
+ `${DIM2}Core${RESET2} ${writer.wrapInColor(`v${cliCore.LIBRARY_VERSION}`, cliCore.CliForegroundColor.Green)}`,
3960
+ `${DIM2}Framework${RESET2} ${writer.wrapInColor(framework, cliCore.CliForegroundColor.Cyan)}`,
3961
+ `${DIM2}Docs${RESET2} ${writer.wrapInColor("https://cli.qodalis.com/docs/", cliCore.CliForegroundColor.Blue)}`
3962
+ ], { borderColor: cliCore.CliForegroundColor.White });
3973
3963
  writer.writeln();
3974
3964
  }
3975
3965
  writeDescription(context2) {
@@ -4027,11 +4017,7 @@ function collectSystemInfo(context2) {
4027
4017
  const lines = [];
4028
4018
  lines.push(`- **CLI Version:** ${LIBRARY_VERSION}`);
4029
4019
  lines.push(`- **Core Version:** ${cliCore.LIBRARY_VERSION}`);
4030
- let framework = "vanilla";
4031
- try {
4032
- framework = context2.services.get("cli-framework");
4033
- } catch {
4034
- }
4020
+ const framework = context2.services.get("cli-framework") ?? "vanilla";
4035
4021
  lines.push(`- **Framework:** ${framework}`);
4036
4022
  lines.push(`- **Terminal:** ${context2.terminal.cols}x${context2.terminal.rows}`);
4037
4023
  if (typeof navigator !== "undefined") {
@@ -4103,12 +4089,8 @@ async function runInteractiveFlow(type, initialTitle, context2) {
4103
4089
  `${writer.wrapInColor("\u2500\u2500 System Info (auto-attached) \u2500\u2500", cliCore.CliForegroundColor.Cyan)}`
4104
4090
  );
4105
4091
  writer.writeln(` CLI: ${LIBRARY_VERSION} Core: ${cliCore.LIBRARY_VERSION}`);
4106
- let framework = "vanilla";
4107
- try {
4108
- framework = context2.services.get("cli-framework");
4109
- } catch {
4110
- }
4111
- writer.writeln(` Framework: ${framework} Terminal: ${context2.terminal.cols}x${context2.terminal.rows}`);
4092
+ const previewFramework = context2.services.get("cli-framework") ?? "vanilla";
4093
+ writer.writeln(` Framework: ${previewFramework} Terminal: ${context2.terminal.cols}x${context2.terminal.rows}`);
4112
4094
  if (typeof navigator !== "undefined") {
4113
4095
  writer.writeln(` Platform: ${navigator.platform} Language: ${navigator.language}`);
4114
4096
  }
@@ -4250,7 +4232,7 @@ var CliHistoryCommandProcessor = class {
4250
4232
  command: "clear",
4251
4233
  description: "Clears the command history",
4252
4234
  processCommand: async (_, context2) => {
4253
- const commandHistory = context2.services.get(
4235
+ const commandHistory = context2.services.getRequired(
4254
4236
  CliCommandHistory_TOKEN
4255
4237
  );
4256
4238
  await commandHistory.clearHistory();
@@ -4273,7 +4255,7 @@ var CliHistoryCommandProcessor = class {
4273
4255
  description: "Search command history for a pattern",
4274
4256
  parameters: searchParameters,
4275
4257
  processCommand: async (cmd, context2) => {
4276
- const commandHistory = context2.services.get(
4258
+ const commandHistory = context2.services.getRequired(
4277
4259
  CliCommandHistory_TOKEN
4278
4260
  );
4279
4261
  const query = (cmd.value ?? "").trim();
@@ -4327,7 +4309,7 @@ var CliHistoryCommandProcessor = class {
4327
4309
  }
4328
4310
  async processCommand(_, context2) {
4329
4311
  const { writer } = context2;
4330
- const commandHistory = context2.services.get(
4312
+ const commandHistory = context2.services.getRequired(
4331
4313
  CliCommandHistory_TOKEN
4332
4314
  );
4333
4315
  const history = commandHistory.getHistory();
@@ -4774,6 +4756,7 @@ var CliPackagesCommandProcessor = class {
4774
4756
  const { progressBar, writer } = context2;
4775
4757
  const { signal, cleanup } = scope.createAbortSignal(context2);
4776
4758
  progressBar.show();
4759
+ context2.notifier.info("Browsing packages");
4777
4760
  const prefix = packagesManager.QODALIS_COMMAND_PREFIX;
4778
4761
  const knownShortNames = [
4779
4762
  "browser-storage",
@@ -4966,6 +4949,7 @@ var CliPackagesCommandProcessor = class {
4966
4949
  const packages = command2.value.split(" ");
4967
4950
  for (const pkg of packages) {
4968
4951
  if (signal.aborted) break;
4952
+ context2.notifier.info(`Installing ${pkg}`);
4969
4953
  await scope.addPackage(pkg, context2, signal);
4970
4954
  }
4971
4955
  cleanup();
@@ -5006,6 +4990,7 @@ var CliPackagesCommandProcessor = class {
5006
4990
  const packages = command2.value.split(" ");
5007
4991
  for (const pkg of packages) {
5008
4992
  if (signal.aborted) break;
4993
+ context2.notifier.info(`Removing ${pkg}`);
5009
4994
  await scope.removePackage(pkg, context2);
5010
4995
  }
5011
4996
  cleanup();
@@ -5041,6 +5026,7 @@ var CliPackagesCommandProcessor = class {
5041
5026
  const fullName = name.startsWith(prefix) ? name : `${prefix}${name}`;
5042
5027
  progressBar.show();
5043
5028
  progressBar.setText(`Fetching versions for ${name}`);
5029
+ context2.notifier.info(`Fetching versions for ${name}`);
5044
5030
  try {
5045
5031
  const response = await scriptsLoader.getScript(
5046
5032
  `https://registry.npmjs.org/${encodeURIComponent(fullName)}`,
@@ -5504,11 +5490,11 @@ var CliPackagesCommandProcessor = class {
5504
5490
  );
5505
5491
  }
5506
5492
  async initialize(context2) {
5507
- this.registry = context2.services.get(
5493
+ this.registry = context2.services.getRequired(
5508
5494
  CliProcessorsRegistry_TOKEN
5509
5495
  );
5510
- const store = context2.services.get(
5511
- "cli-key-value-store"
5496
+ const store = context2.services.getRequired(
5497
+ CliKeyValueStore_TOKEN
5512
5498
  );
5513
5499
  this.packagesManager.setStore(store);
5514
5500
  context2.services.set([{
@@ -5774,10 +5760,11 @@ var CliPackagesCommandProcessor = class {
5774
5760
  }
5775
5761
  };
5776
5762
  var CliServerConnection = class _CliServerConnection {
5777
- constructor(_config, _backgroundServices, _logger) {
5763
+ constructor(_config, _backgroundServices, _logger, _authService) {
5778
5764
  this._config = _config;
5779
5765
  this._backgroundServices = _backgroundServices;
5780
5766
  this._logger = _logger;
5767
+ this._authService = _authService;
5781
5768
  this._connected = false;
5782
5769
  this._commands = [];
5783
5770
  this._capabilities = null;
@@ -5816,10 +5803,21 @@ var CliServerConnection = class _CliServerConnection {
5816
5803
  get apiVersion() {
5817
5804
  return this._apiVersion;
5818
5805
  }
5806
+ /**
5807
+ * Resolve auth headers for this server connection.
5808
+ * Uses the auth service (which merges config headers with registered
5809
+ * ICliServerAuthTokenProviders), or falls back to config headers directly.
5810
+ */
5811
+ resolveAuthHeaders() {
5812
+ if (this._authService) {
5813
+ return this._authService.getHeaders(this._config.name, this._config.headers);
5814
+ }
5815
+ return cliCore.resolveHeaders(this._config.headers);
5816
+ }
5819
5817
  async connect() {
5820
5818
  try {
5821
5819
  const baseUrl = this.normalizeUrl(this._config.url);
5822
- const negotiated = await cliCore.ServerVersionNegotiator.discover(baseUrl);
5820
+ const negotiated = await cliCore.ServerVersionNegotiator.discover(baseUrl, () => this.resolveAuthHeaders());
5823
5821
  if (negotiated) {
5824
5822
  this._apiVersion = negotiated.apiVersion;
5825
5823
  this._basePath = negotiated.basePath;
@@ -6014,7 +6012,10 @@ var CliServerConnection = class _CliServerConnection {
6014
6012
  type: "daemon",
6015
6013
  onStart: async (ctx) => {
6016
6014
  const baseUrl = this.normalizeUrl(this._config.url);
6017
- const wsUrl = this.toWebSocketUrl(baseUrl) + "/ws/v1/qcli/events";
6015
+ const wsUrl = cliCore.buildAuthenticatedWebSocketUrl(
6016
+ this.toWebSocketUrl(baseUrl) + "/ws/v1/qcli/events",
6017
+ () => this.resolveAuthHeaders()
6018
+ );
6018
6019
  ctx.log(`Connecting to ${wsUrl}`);
6019
6020
  this._eventSocket = new WebSocket(wsUrl);
6020
6021
  this._eventSocket.onopen = () => {
@@ -6064,7 +6065,10 @@ var CliServerConnection = class _CliServerConnection {
6064
6065
  connectEventSocketDirect() {
6065
6066
  try {
6066
6067
  const baseUrl = this.normalizeUrl(this._config.url);
6067
- const wsUrl = this.toWebSocketUrl(baseUrl) + "/ws/v1/qcli/events";
6068
+ const wsUrl = cliCore.buildAuthenticatedWebSocketUrl(
6069
+ this.toWebSocketUrl(baseUrl) + "/ws/v1/qcli/events",
6070
+ () => this.resolveAuthHeaders()
6071
+ );
6068
6072
  this._eventSocket = new WebSocket(wsUrl);
6069
6073
  this._eventSocket.onopen = () => {
6070
6074
  this._wsReconnectAttempts = 0;
@@ -6167,7 +6171,7 @@ var CliServerConnection = class _CliServerConnection {
6167
6171
  const controller = new AbortController();
6168
6172
  const timer = setTimeout(() => controller.abort(), timeout);
6169
6173
  const headers = {
6170
- ...this._config.headers ?? {},
6174
+ ...this.resolveAuthHeaders(),
6171
6175
  ...init?.headers ?? {}
6172
6176
  };
6173
6177
  return fetch(url, {
@@ -6247,6 +6251,8 @@ async function executeOnServer(connection, serverName, descriptor, command2, con
6247
6251
  command: commandPath && commandPath.length > 0 ? commandPath[0] : descriptor.command,
6248
6252
  chainCommands: commandPath && commandPath.length > 1 ? commandPath.slice(1) : []
6249
6253
  };
6254
+ const cmdLabel = commandPath && commandPath.length > 0 ? commandPath.join(" ") : descriptor.command;
6255
+ context2.notifier.info(`executing command: ${cmdLabel} on server ${serverName}`);
6250
6256
  try {
6251
6257
  if (connection.capabilities?.streaming) {
6252
6258
  const result = await connection.executeStream(
@@ -6434,8 +6440,9 @@ var CliServerMultiProxyProcessor = class _CliServerMultiProxyProcessor {
6434
6440
  // src/lib/server/cli-server-manager.ts
6435
6441
  var CliServerManager_TOKEN = "cli-server-manager";
6436
6442
  var CliServerManager = class {
6437
- constructor(registry) {
6443
+ constructor(registry, authService) {
6438
6444
  this.registry = registry;
6445
+ this.authService = authService;
6439
6446
  this.connections = /* @__PURE__ */ new Map();
6440
6447
  this._defaultServer = null;
6441
6448
  }
@@ -6456,7 +6463,7 @@ var CliServerManager = class {
6456
6463
  this._backgroundServices = backgroundServices;
6457
6464
  for (const config of servers) {
6458
6465
  if (config.enabled === false) continue;
6459
- const connection = new CliServerConnection(config, backgroundServices, cliLogger);
6466
+ const connection = new CliServerConnection(config, backgroundServices, cliLogger, this.authService);
6460
6467
  this.connections.set(config.name, connection);
6461
6468
  connection.onDisconnect = () => {
6462
6469
  this.handleDisconnect(config.name);
@@ -7007,7 +7014,7 @@ var CliDebugCommandProcessor = class {
7007
7014
  metadata: { icon: cliCore.CliIcon.Extension, module: "system" },
7008
7015
  processCommand: async (_, context2) => {
7009
7016
  const { writer } = context2;
7010
- const registry = context2.services.get(
7017
+ const registry = context2.services.getRequired(
7011
7018
  CliProcessorsRegistry_TOKEN
7012
7019
  );
7013
7020
  writer.writeln(
@@ -7058,12 +7065,10 @@ var CliDebugCommandProcessor = class {
7058
7065
  metadata: { icon: cliCore.CliIcon.Module, module: "system" },
7059
7066
  processCommand: async (_, context2) => {
7060
7067
  const { writer } = context2;
7061
- let moduleRegistry;
7062
- try {
7063
- moduleRegistry = context2.services.get(
7064
- CliModuleRegistry_TOKEN
7065
- );
7066
- } catch {
7068
+ const moduleRegistry = context2.services.get(
7069
+ CliModuleRegistry_TOKEN
7070
+ );
7071
+ if (!moduleRegistry) {
7067
7072
  writer.writeError("Module registry not available.");
7068
7073
  return;
7069
7074
  }
@@ -7104,7 +7109,7 @@ var CliDebugCommandProcessor = class {
7104
7109
  metadata: { icon: cliCore.CliIcon.Database, module: "system" },
7105
7110
  processCommand: async (_, context2) => {
7106
7111
  const { writer } = context2;
7107
- const storeManager = context2.services.get(
7112
+ const storeManager = context2.services.getRequired(
7108
7113
  CliStateStoreManager_TOKEN
7109
7114
  );
7110
7115
  const entries = storeManager.getStoreEntries();
@@ -7183,11 +7188,7 @@ var CliDebugCommandProcessor = class {
7183
7188
  writer.writeln(
7184
7189
  ` ${writer.wrapInColor("CLI Version:", cliCore.CliForegroundColor.Cyan)} ${LIBRARY_VERSION}`
7185
7190
  );
7186
- let framework = "vanilla";
7187
- try {
7188
- framework = context2.services.get("cli-framework");
7189
- } catch {
7190
- }
7191
+ const framework = context2.services.get("cli-framework") ?? "vanilla";
7191
7192
  writer.writeln(
7192
7193
  ` ${writer.wrapInColor("Framework:", cliCore.CliForegroundColor.Cyan)} ${framework}`
7193
7194
  );
@@ -7228,7 +7229,7 @@ var CliDebugCommandProcessor = class {
7228
7229
  metadata: { icon: cliCore.CliIcon.Logs, module: "system" },
7229
7230
  processCommand: async (_, context2) => {
7230
7231
  const { writer } = context2;
7231
- const history = context2.services.get(
7232
+ const history = context2.services.getRequired(
7232
7233
  CliCommandHistory_TOKEN
7233
7234
  );
7234
7235
  const commands = history.getHistory();
@@ -7317,14 +7318,14 @@ var CliDebugCommandProcessor = class {
7317
7318
  writer.writeln(
7318
7319
  ` ${online ? cliCore.CliIcon.CheckIcon : cliCore.CliIcon.CrossIcon} Network: ${online ? "online" : "offline"}`
7319
7320
  );
7320
- const registry = context2.services.get(
7321
+ const registry = context2.services.getRequired(
7321
7322
  CliProcessorsRegistry_TOKEN
7322
7323
  );
7323
7324
  writer.writeln(
7324
7325
  ` ${cliCore.CliIcon.CheckIcon} Processors: ${registry.processors.length} loaded`
7325
7326
  );
7326
7327
  try {
7327
- const moduleRegistry = context2.services.get(
7328
+ const moduleRegistry = context2.services.getRequired(
7328
7329
  CliModuleRegistry_TOKEN
7329
7330
  );
7330
7331
  const modules = moduleRegistry.getAll();
@@ -7340,7 +7341,7 @@ var CliDebugCommandProcessor = class {
7340
7341
  writer.writeln(
7341
7342
  ` ${wasmActive ? cliCore.CliIcon.CheckIcon : cliCore.CliIcon.WarningIcon} WASM Accelerator: ${wasmActive ? "loaded" : "using JS fallback"}`
7342
7343
  );
7343
- const historyService = context2.services.get(
7344
+ const historyService = context2.services.getRequired(
7344
7345
  CliCommandHistory_TOKEN
7345
7346
  );
7346
7347
  writer.writeln(
@@ -7354,13 +7355,13 @@ var CliDebugCommandProcessor = class {
7354
7355
  metadata: { icon: cliCore.CliIcon.Save, module: "system" },
7355
7356
  processCommand: async (_, context2) => {
7356
7357
  const { writer } = context2;
7357
- const registry = context2.services.get(
7358
+ const registry = context2.services.getRequired(
7358
7359
  CliProcessorsRegistry_TOKEN
7359
7360
  );
7360
- const history = context2.services.get(
7361
+ const history = context2.services.getRequired(
7361
7362
  CliCommandHistory_TOKEN
7362
7363
  );
7363
- const storeManager = context2.services.get(
7364
+ const storeManager = context2.services.getRequired(
7364
7365
  CliStateStoreManager_TOKEN
7365
7366
  );
7366
7367
  const report = {
@@ -7393,7 +7394,7 @@ var CliDebugCommandProcessor = class {
7393
7394
  state: storeManager.getStoreEntries()
7394
7395
  };
7395
7396
  try {
7396
- const moduleRegistry = context2.services.get(
7397
+ const moduleRegistry = context2.services.getRequired(
7397
7398
  CliModuleRegistry_TOKEN
7398
7399
  );
7399
7400
  report["modules"] = moduleRegistry.getAll().map((m) => ({
@@ -7411,7 +7412,7 @@ var CliDebugCommandProcessor = class {
7411
7412
  report["services"] = container.getRegisteredTokens();
7412
7413
  }
7413
7414
  try {
7414
- const serverManager = context2.services.get(
7415
+ const serverManager = context2.services.getRequired(
7415
7416
  CliServerManager_TOKEN
7416
7417
  );
7417
7418
  if (serverManager && serverManager.connections.size > 0) {
@@ -7435,13 +7436,9 @@ var CliDebugCommandProcessor = class {
7435
7436
  metadata: { icon: cliCore.CliIcon.Server, module: "system" },
7436
7437
  processCommand: async (_, context2) => {
7437
7438
  const { writer } = context2;
7438
- let manager;
7439
- try {
7440
- manager = context2.services.get(
7441
- CliServerManager_TOKEN
7442
- );
7443
- } catch {
7444
- }
7439
+ const manager = context2.services.get(
7440
+ CliServerManager_TOKEN
7441
+ );
7445
7442
  if (!manager || manager.connections.size === 0) {
7446
7443
  writer.writeInfo("No servers configured.");
7447
7444
  return;
@@ -7481,70 +7478,48 @@ var CliDebugCommandProcessor = class {
7481
7478
  }
7482
7479
  async processCommand(_, context2) {
7483
7480
  const { writer } = context2;
7484
- const registry = context2.services.get(
7481
+ const registry = context2.services.getRequired(
7485
7482
  CliProcessorsRegistry_TOKEN
7486
7483
  );
7487
- writer.writeln(
7488
- writer.wrapInColor(
7489
- `${cliCore.CliIcon.Bug} CLI Debug Info`,
7490
- cliCore.CliForegroundColor.Yellow
7491
- )
7484
+ const summaryFramework = context2.services.get("cli-framework") ?? "vanilla";
7485
+ const summaryModuleRegistry = context2.services.get(
7486
+ CliModuleRegistry_TOKEN
7492
7487
  );
7493
- writer.writeDivider({ char: "=" });
7494
- writer.writeln(
7495
- ` ${writer.wrapInColor("Core Version:", cliCore.CliForegroundColor.Cyan)} ${cliCore.LIBRARY_VERSION}`
7496
- );
7497
- writer.writeln(
7498
- ` ${writer.wrapInColor("CLI Version:", cliCore.CliForegroundColor.Cyan)} ${LIBRARY_VERSION}`
7499
- );
7500
- let framework = "vanilla";
7501
- try {
7502
- framework = context2.services.get("cli-framework");
7503
- } catch {
7504
- }
7505
- writer.writeln(
7506
- ` ${writer.wrapInColor("Framework:", cliCore.CliForegroundColor.Cyan)} ${framework}`
7507
- );
7508
- writer.writeln(
7509
- ` ${writer.wrapInColor("Terminal:", cliCore.CliForegroundColor.Cyan)} ${context2.terminal.cols}x${context2.terminal.rows}`
7488
+ const summaryServerManager = context2.services.get(
7489
+ CliServerManager_TOKEN
7510
7490
  );
7511
- writer.writeln(
7512
- ` ${writer.wrapInColor("Processors:", cliCore.CliForegroundColor.Cyan)} ${registry.processors.length}`
7491
+ const history = context2.services.getRequired(
7492
+ CliCommandHistory_TOKEN
7513
7493
  );
7514
- try {
7515
- const moduleRegistry = context2.services.get(
7516
- CliModuleRegistry_TOKEN
7517
- );
7518
- writer.writeln(
7519
- ` ${writer.wrapInColor("Modules:", cliCore.CliForegroundColor.Cyan)} ${moduleRegistry.getAll().length}`
7494
+ const wasmStatus = isWasmAccelerated() ? "active" : "inactive (JS fallback)";
7495
+ const lines = [
7496
+ `${writer.wrapInColor("Core Version:", cliCore.CliForegroundColor.Cyan)} ${cliCore.LIBRARY_VERSION}`,
7497
+ `${writer.wrapInColor("CLI Version:", cliCore.CliForegroundColor.Cyan)} ${LIBRARY_VERSION}`,
7498
+ `${writer.wrapInColor("Framework:", cliCore.CliForegroundColor.Cyan)} ${summaryFramework}`,
7499
+ `${writer.wrapInColor("Terminal:", cliCore.CliForegroundColor.Cyan)} ${context2.terminal.cols}x${context2.terminal.rows}`,
7500
+ `${writer.wrapInColor("Processors:", cliCore.CliForegroundColor.Cyan)} ${registry.processors.length}`
7501
+ ];
7502
+ if (summaryModuleRegistry) {
7503
+ lines.push(
7504
+ `${writer.wrapInColor("Modules:", cliCore.CliForegroundColor.Cyan)} ${summaryModuleRegistry.getAll().length}`
7520
7505
  );
7521
- } catch {
7522
7506
  }
7523
- try {
7524
- const serverManager = context2.services.get(
7525
- CliServerManager_TOKEN
7507
+ if (summaryServerManager && summaryServerManager.connections.size > 0) {
7508
+ const connected = Array.from(
7509
+ summaryServerManager.connections.values()
7510
+ ).filter((c) => c.connected).length;
7511
+ lines.push(
7512
+ `${writer.wrapInColor("Servers:", cliCore.CliForegroundColor.Cyan)} ${connected}/${summaryServerManager.connections.size} connected`
7526
7513
  );
7527
- if (serverManager && serverManager.connections.size > 0) {
7528
- const connected = Array.from(
7529
- serverManager.connections.values()
7530
- ).filter((c) => c.connected).length;
7531
- writer.writeln(
7532
- ` ${writer.wrapInColor("Servers:", cliCore.CliForegroundColor.Cyan)} ${connected}/${serverManager.connections.size} connected`
7533
- );
7534
- }
7535
- } catch {
7536
7514
  }
7537
- const history = context2.services.get(
7538
- CliCommandHistory_TOKEN
7539
- );
7540
- writer.writeln(
7541
- ` ${writer.wrapInColor("History:", cliCore.CliForegroundColor.Cyan)} ${history.getHistory().length} commands`
7515
+ lines.push(
7516
+ `${writer.wrapInColor("History:", cliCore.CliForegroundColor.Cyan)} ${history.getHistory().length} commands`,
7517
+ `${writer.wrapInColor("WASM Accelerator:", cliCore.CliForegroundColor.Cyan)} ${wasmStatus}`
7542
7518
  );
7543
- const wasmStatus = isWasmAccelerated() ? "active" : "inactive (JS fallback)";
7544
- writer.writeln(
7545
- ` ${writer.wrapInColor("WASM Accelerator:", cliCore.CliForegroundColor.Cyan)} ${wasmStatus}`
7546
- );
7547
- writer.writeDivider({ char: "=" });
7519
+ writer.writeBox(lines, {
7520
+ title: "CLI Debug Info",
7521
+ borderColor: cliCore.CliForegroundColor.Yellow
7522
+ });
7548
7523
  writer.writeln();
7549
7524
  writer.writeln(`${cliCore.CliIcon.Light} Subcommands:`);
7550
7525
  for (const sub of this.processors || []) {
@@ -8130,7 +8105,7 @@ var CliNanoCommandProcessor = class {
8130
8105
  this.replaceWith = "";
8131
8106
  this.statusMessage = void 0;
8132
8107
  try {
8133
- this.fs = context2.services.get(FS_TOKEN);
8108
+ this.fs = context2.services.getRequired(FS_TOKEN);
8134
8109
  } catch {
8135
8110
  this.fs = null;
8136
8111
  }
@@ -8469,8 +8444,8 @@ var CliNanoCommandProcessor = class {
8469
8444
  return;
8470
8445
  }
8471
8446
  try {
8472
- const registry = this.context.services.get(
8473
- "syntax-highlighter-registry"
8447
+ const registry = this.context.services.getRequired(
8448
+ SyntaxHighlighterRegistry_TOKEN
8474
8449
  );
8475
8450
  const ext = "." + filePath.split(".").pop()?.toLowerCase();
8476
8451
  const highlighter = registry.getByExtension(ext);
@@ -9107,7 +9082,7 @@ var CliPsCommandProcessor = class {
9107
9082
  async processCommand(_command, context2) {
9108
9083
  let registry;
9109
9084
  try {
9110
- registry = context2.services.get(
9085
+ registry = context2.services.getRequired(
9111
9086
  CliProcessRegistry_TOKEN
9112
9087
  );
9113
9088
  } catch {
@@ -9146,7 +9121,7 @@ var CliKillCommandProcessor = class {
9146
9121
  async processCommand(command2, context2) {
9147
9122
  let registry;
9148
9123
  try {
9149
- registry = context2.services.get(
9124
+ registry = context2.services.getRequired(
9150
9125
  CliProcessRegistry_TOKEN
9151
9126
  );
9152
9127
  } catch {
@@ -9261,11 +9236,10 @@ var CliHtopCommandProcessor = class {
9261
9236
  this.errorTimeout = null;
9262
9237
  }
9263
9238
  async processCommand(_command, context2) {
9264
- try {
9265
- this.registry = context2.services.get(
9266
- CliProcessRegistry_TOKEN
9267
- );
9268
- } catch {
9239
+ this.registry = context2.services.get(
9240
+ CliProcessRegistry_TOKEN
9241
+ ) ?? null;
9242
+ if (!this.registry) {
9269
9243
  context2.writer.writeError("Process registry not available");
9270
9244
  return;
9271
9245
  }
@@ -10405,6 +10379,7 @@ var CliPingCommandProcessor = class {
10405
10379
  context2.writer.writeln(
10406
10380
  `PING ${host} (${url}):`
10407
10381
  );
10382
+ context2.notifier.info(`ping ${host}`);
10408
10383
  const times = [];
10409
10384
  let transmitted = 0;
10410
10385
  let received = 0;
@@ -10419,17 +10394,17 @@ var CliPingCommandProcessor = class {
10419
10394
  transmitted++;
10420
10395
  const start = performance.now();
10421
10396
  try {
10422
- const response = await fetch(url, {
10397
+ const response = await context2.http.fetch(url, {
10423
10398
  method: "HEAD",
10424
10399
  mode: "no-cors",
10425
- cache: "no-store",
10426
- signal: context2.signal
10400
+ cache: "no-store"
10427
10401
  });
10428
10402
  const elapsed = performance.now() - start;
10429
10403
  const ms = elapsed.toFixed(1);
10430
10404
  received++;
10431
10405
  times.push(elapsed);
10432
10406
  const status = response.type === "opaque" ? "ok" : `status=${response.status}`;
10407
+ context2.notifier.info(`ping ${host}: seq=${seq} time=${ms}ms`);
10433
10408
  context2.writer.writeln(
10434
10409
  `${url}: seq=${seq} ${status} time=${ms} ms`
10435
10410
  );
@@ -10563,7 +10538,7 @@ var CliExportCommandProcessor = class {
10563
10538
  this.metadata = { icon: "\u{1F4E6}", module: "system" };
10564
10539
  }
10565
10540
  async processCommand(command2, context2) {
10566
- const env = context2.services.get(
10541
+ const env = context2.services.getRequired(
10567
10542
  ICliEnvironment_TOKEN
10568
10543
  );
10569
10544
  const raw = (command2.value || "").trim();
@@ -10617,7 +10592,7 @@ var CliUnsetCommandProcessor = class {
10617
10592
  this.metadata = { icon: "\u{1F5D1}\uFE0F", module: "system" };
10618
10593
  }
10619
10594
  async processCommand(command2, context2) {
10620
- const env = context2.services.get(
10595
+ const env = context2.services.getRequired(
10621
10596
  ICliEnvironment_TOKEN
10622
10597
  );
10623
10598
  const varName = (command2.value || "").trim();
@@ -10651,7 +10626,7 @@ var CliEnvCommandProcessor = class {
10651
10626
  this.metadata = { icon: "\u{1F30D}", module: "system" };
10652
10627
  }
10653
10628
  async processCommand(command2, context2) {
10654
- const env = context2.services.get(
10629
+ const env = context2.services.getRequired(
10655
10630
  ICliEnvironment_TOKEN
10656
10631
  );
10657
10632
  const varName = (command2.value || "").trim();
@@ -10895,10 +10870,13 @@ var CliCommandExecutionContext = class {
10895
10870
  this.reader = context2.reader;
10896
10871
  this.enterFullScreenMode = (p, o) => context2.enterFullScreenMode(p, o);
10897
10872
  this.exitFullScreenMode = () => context2.exitFullScreenMode();
10873
+ this.submitCommand = (command2) => context2.submitCommand(command2);
10898
10874
  this.createInterval = (cb, ms) => context2.createInterval(cb, ms);
10899
10875
  this.createTimeout = (cb, ms) => context2.createTimeout(cb, ms);
10900
10876
  this.backgroundServices = context2.backgroundServices;
10901
- this.state = context2.services.get(CliStateStoreManager_TOKEN).getProcessorStateStore(processor);
10877
+ this.http = context2.http;
10878
+ this.notifier = context2.notifier;
10879
+ this.state = context2.services.getRequired(CliStateStoreManager_TOKEN).getProcessorStateStore(processor);
10902
10880
  }
10903
10881
  get promptLength() {
10904
10882
  return this.context.promptLength;
@@ -11449,6 +11427,172 @@ var CliBackgroundServiceRegistry = class {
11449
11427
  }
11450
11428
  };
11451
11429
 
11430
+ // src/lib/services/cli-http-client.ts
11431
+ var CliHttpClient = class {
11432
+ constructor(signal) {
11433
+ this.signal = signal;
11434
+ }
11435
+ async fetch(url, init) {
11436
+ return fetch(url, {
11437
+ ...init,
11438
+ signal: this.mergeSignal(init?.signal)
11439
+ });
11440
+ }
11441
+ async get(url, options) {
11442
+ return this.jsonRequest("GET", url, void 0, options);
11443
+ }
11444
+ async post(url, body, options) {
11445
+ return this.jsonRequest("POST", url, body, options);
11446
+ }
11447
+ async put(url, body, options) {
11448
+ return this.jsonRequest("PUT", url, body, options);
11449
+ }
11450
+ async patch(url, body, options) {
11451
+ return this.jsonRequest("PATCH", url, body, options);
11452
+ }
11453
+ async delete(url, options) {
11454
+ return this.jsonRequest("DELETE", url, void 0, options);
11455
+ }
11456
+ async head(url, options) {
11457
+ const { timeout, signal: callerSignal, ...fetchOptions } = options ?? {};
11458
+ let timeoutController;
11459
+ let timeoutId;
11460
+ if (timeout) {
11461
+ timeoutController = new AbortController();
11462
+ timeoutId = setTimeout(() => timeoutController.abort(), timeout);
11463
+ }
11464
+ try {
11465
+ return await fetch(url, {
11466
+ ...fetchOptions,
11467
+ method: "HEAD",
11468
+ signal: this.mergeSignal(callerSignal, timeoutController?.signal)
11469
+ });
11470
+ } finally {
11471
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
11472
+ }
11473
+ }
11474
+ async options(url, options) {
11475
+ return this.jsonRequest("OPTIONS", url, void 0, options);
11476
+ }
11477
+ // ── Internals ────────────────────────────────────────────────────
11478
+ async jsonRequest(method, url, body, options) {
11479
+ const { timeout, ...fetchOptions } = options ?? {};
11480
+ const headers = {
11481
+ ...fetchOptions.headers ?? {}
11482
+ };
11483
+ let resolvedBody;
11484
+ if (body !== void 0 && body !== null) {
11485
+ if (this.isRawBody(body)) {
11486
+ resolvedBody = body;
11487
+ } else {
11488
+ resolvedBody = JSON.stringify(body);
11489
+ if (!headers["Content-Type"]) {
11490
+ headers["Content-Type"] = "application/json";
11491
+ }
11492
+ }
11493
+ }
11494
+ let timeoutId;
11495
+ let timeoutController;
11496
+ if (timeout) {
11497
+ timeoutController = new AbortController();
11498
+ timeoutId = setTimeout(() => timeoutController.abort(), timeout);
11499
+ }
11500
+ const signal = this.mergeSignal(
11501
+ fetchOptions.signal,
11502
+ timeoutController?.signal
11503
+ );
11504
+ try {
11505
+ const response = await fetch(url, {
11506
+ ...fetchOptions,
11507
+ method,
11508
+ headers,
11509
+ body: resolvedBody,
11510
+ signal
11511
+ });
11512
+ if (!response.ok) {
11513
+ let errorMessage = `${response.status} ${response.statusText}`;
11514
+ try {
11515
+ const errorBody = await response.json();
11516
+ if (errorBody.error) {
11517
+ errorMessage = errorBody.error;
11518
+ } else if (errorBody.message) {
11519
+ errorMessage = errorBody.message;
11520
+ }
11521
+ } catch {
11522
+ }
11523
+ throw new Error(errorMessage);
11524
+ }
11525
+ const text = await response.text();
11526
+ if (!text) {
11527
+ return void 0;
11528
+ }
11529
+ return JSON.parse(text);
11530
+ } finally {
11531
+ if (timeoutId !== void 0) {
11532
+ clearTimeout(timeoutId);
11533
+ }
11534
+ }
11535
+ }
11536
+ isRawBody(body) {
11537
+ return typeof body === "string" || body instanceof FormData || body instanceof Blob || body instanceof ArrayBuffer || body instanceof URLSearchParams || body instanceof ReadableStream;
11538
+ }
11539
+ /**
11540
+ * Merge the command signal with any additional signals (caller, timeout).
11541
+ * Uses AbortSignal.any() when available, falls back to a manual composite
11542
+ * controller for older browsers (pre-Chrome 116 / Safari 17.4).
11543
+ */
11544
+ mergeSignal(...additional) {
11545
+ const signals = [];
11546
+ if (this.signal) signals.push(this.signal);
11547
+ for (const s of additional) {
11548
+ if (s) signals.push(s);
11549
+ }
11550
+ if (signals.length === 0) return void 0;
11551
+ if (signals.length === 1) return signals[0];
11552
+ if (typeof AbortSignal.any === "function") {
11553
+ return AbortSignal.any(signals);
11554
+ }
11555
+ const controller = new AbortController();
11556
+ for (const s of signals) {
11557
+ if (s.aborted) {
11558
+ controller.abort(s.reason);
11559
+ return controller.signal;
11560
+ }
11561
+ s.addEventListener("abort", () => controller.abort(s.reason), { once: true });
11562
+ }
11563
+ return controller.signal;
11564
+ }
11565
+ };
11566
+ var CliNotifier = class {
11567
+ constructor() {
11568
+ this._change$ = new rxjs.Subject();
11569
+ this.change$ = this._change$.asObservable();
11570
+ }
11571
+ get current() {
11572
+ return this._current;
11573
+ }
11574
+ info(message) {
11575
+ this.set("info", message);
11576
+ }
11577
+ success(message) {
11578
+ this.set("success", message);
11579
+ }
11580
+ warn(message) {
11581
+ this.set("warn", message);
11582
+ }
11583
+ error(message) {
11584
+ this.set("error", message);
11585
+ }
11586
+ clear() {
11587
+ this._current = void 0;
11588
+ this._change$.next(void 0);
11589
+ }
11590
+ set(level, message) {
11591
+ this._current = { level, message, timestamp: Date.now() };
11592
+ this._change$.next(this._current);
11593
+ }
11594
+ };
11595
+
11452
11596
  // src/lib/context/cli-fullscreen-manager.ts
11453
11597
  var CliFullScreenManager = class {
11454
11598
  constructor(terminal, backgroundServices) {
@@ -14076,18 +14220,15 @@ var CommandLineMode = class {
14076
14220
  if (data === "\r") {
14077
14221
  this.clearGhostText();
14078
14222
  this.host.terminal.write("\r\n");
14079
- if (buffer.text) {
14080
- await this.host.commandHistory.addCommand(buffer.text);
14223
+ const text = buffer.text;
14224
+ if (text) {
14081
14225
  this.historyIndex = this.host.commandHistory.getLastIndex();
14082
14226
  this.bufferSetByHistory = false;
14083
- this.isExecutingCommand = true;
14084
- const ctx = this.host.getExecutionContext();
14085
- await ctx.executor.executeCommand(buffer.text, ctx);
14086
- this.isExecutingCommand = false;
14087
- }
14088
- if (!this.host.isRawModeActive()) {
14089
- this.host.showPrompt();
14090
14227
  }
14228
+ this.isExecutingCommand = true;
14229
+ const ctx = this.host.getExecutionContext();
14230
+ await ctx.submitCommand(text);
14231
+ this.isExecutingCommand = false;
14091
14232
  } else if (data === "\x1B[A") {
14092
14233
  this.showPreviousCommand();
14093
14234
  } else if (data === "\x1B[B") {
@@ -14469,6 +14610,11 @@ var CliExecutionContext = class {
14469
14610
  this.onAbort = new rxjs.Subject();
14470
14611
  this.completionEngine = new CliCompletionEngine();
14471
14612
  this.promptLength = 0;
14613
+ /**
14614
+ * Whether a command is currently being executed.
14615
+ * Set by the command executor at start/end of executeCommand().
14616
+ */
14617
+ this.isExecuting = false;
14472
14618
  this.lineBuffer = new CliLineBuffer();
14473
14619
  this.modeStack = [];
14474
14620
  this.timerManager = new CliTimerManager();
@@ -14513,6 +14659,8 @@ var CliExecutionContext = class {
14513
14659
  this.logger.setCliLogLevel(cliOptions?.logLevel || cliCore.CliLogLevel.ERROR);
14514
14660
  this.commandHistory = deps.commandHistory;
14515
14661
  this.lineRenderer = new CliTerminalLineRenderer(terminal, this.writer);
14662
+ this.http = new CliHttpClient();
14663
+ this.notifier = new CliNotifier();
14516
14664
  this.backgroundServices = new CliBackgroundServiceRegistry(
14517
14665
  this.state,
14518
14666
  deps.services,
@@ -14602,6 +14750,20 @@ var CliExecutionContext = class {
14602
14750
  this.getPromptOptions()
14603
14751
  );
14604
14752
  }
14753
+ /**
14754
+ * Submit and execute a command — shared by interactive Enter key
14755
+ * and programmatic engine.execute(). Adds to history, runs the
14756
+ * command, and shows a new prompt afterwards.
14757
+ */
14758
+ async submitCommand(command2) {
14759
+ if (command2.trim()) {
14760
+ await this.commandHistory.addCommand(command2);
14761
+ await this.executor.executeCommand(command2, this);
14762
+ }
14763
+ if (!this.isRawModeActive()) {
14764
+ this.showPrompt();
14765
+ }
14766
+ }
14605
14767
  clearCurrentLine() {
14606
14768
  this.clearLine();
14607
14769
  this.showPrompt();
@@ -14702,12 +14864,8 @@ var CliExecutionContext = class {
14702
14864
  }
14703
14865
  // -- CommandLineModeHost interface --
14704
14866
  getPromptOptions() {
14705
- let hideUserName = false;
14706
- try {
14707
- const config = this.services.get("cli-users-module-config");
14708
- hideUserName = config?.hideUserName ?? false;
14709
- } catch {
14710
- }
14867
+ const usersConfig = this.services.get("cli-users-module-config");
14868
+ const hideUserName = usersConfig?.hideUserName ?? false;
14711
14869
  return {
14712
14870
  userName: this.userSession?.displayName,
14713
14871
  hideUserName,
@@ -14955,10 +15113,8 @@ var contextGlobalParameter = {
14955
15113
  // src/lib/executor/cli-io-redirect-handler.ts
14956
15114
  var FS_TOKEN2 = "cli-file-system-service";
14957
15115
  async function writeOutputToFile(filePath, context2) {
14958
- let fs;
14959
- try {
14960
- fs = context2.services.get(FS_TOKEN2);
14961
- } catch {
15116
+ const fs = context2.services.get(FS_TOKEN2);
15117
+ if (!fs) {
14962
15118
  context2.writer.writeError(
14963
15119
  "> redirect requires @qodalis/cli-files plugin"
14964
15120
  );
@@ -14982,10 +15138,8 @@ async function writeOutputToFile(filePath, context2) {
14982
15138
  }
14983
15139
  }
14984
15140
  async function appendOutputToFile(filePath, context2) {
14985
- let fs;
14986
- try {
14987
- fs = context2.services.get(FS_TOKEN2);
14988
- } catch {
15141
+ const fs = context2.services.get(FS_TOKEN2);
15142
+ if (!fs) {
14989
15143
  context2.writer.writeError(
14990
15144
  ">> redirect requires @qodalis/cli-files plugin"
14991
15145
  );
@@ -15011,10 +15165,8 @@ async function appendOutputToFile(filePath, context2) {
15011
15165
  async function writeStderrToFile(filePath, context2, capturingWriter) {
15012
15166
  const stderr = capturingWriter?.getCapturedStderr();
15013
15167
  if (!stderr) return;
15014
- let fs;
15015
- try {
15016
- fs = context2.services.get(FS_TOKEN2);
15017
- } catch {
15168
+ const fs = context2.services.get(FS_TOKEN2);
15169
+ if (!fs) {
15018
15170
  context2.writer.writeError(
15019
15171
  "2> redirect requires @qodalis/cli-files plugin"
15020
15172
  );
@@ -15035,10 +15187,8 @@ async function writeStderrToFile(filePath, context2, capturingWriter) {
15035
15187
  async function appendStderrToFile(filePath, context2, capturingWriter) {
15036
15188
  const stderr = capturingWriter?.getCapturedStderr();
15037
15189
  if (!stderr) return;
15038
- let fs;
15039
- try {
15040
- fs = context2.services.get(FS_TOKEN2);
15041
- } catch {
15190
+ const fs = context2.services.get(FS_TOKEN2);
15191
+ if (!fs) {
15042
15192
  context2.writer.writeError(
15043
15193
  "2>> redirect requires @qodalis/cli-files plugin"
15044
15194
  );
@@ -15058,10 +15208,8 @@ async function appendStderrToFile(filePath, context2, capturingWriter) {
15058
15208
  }
15059
15209
  async function tryExecuteScript(filePath, context2, executeCommand) {
15060
15210
  const FS_TOKEN3 = "cli-file-system-service";
15061
- let fs;
15062
- try {
15063
- fs = context2.services.get(FS_TOKEN3);
15064
- } catch {
15211
+ const fs = context2.services.get(FS_TOKEN3);
15212
+ if (!fs) {
15065
15213
  return false;
15066
15214
  }
15067
15215
  const resolved = fs.resolvePath(filePath);
@@ -15138,10 +15286,8 @@ function substituteVars(input, variables) {
15138
15286
  return result;
15139
15287
  }
15140
15288
  function expandEnvironmentVars(command2, context2) {
15141
- let env;
15142
- try {
15143
- env = context2.services.get(ICliEnvironment_TOKEN);
15144
- } catch {
15289
+ const env = context2.services.get(ICliEnvironment_TOKEN);
15290
+ if (!env) {
15145
15291
  return command2;
15146
15292
  }
15147
15293
  const parts = command2.split("'");
@@ -15187,92 +15333,106 @@ var CliCommandExecutor = class {
15187
15333
  } else {
15188
15334
  rootContext = context2;
15189
15335
  }
15190
- let lastExitSuccess = true;
15191
- let shouldRunNext = true;
15192
- let pipelineData = void 0;
15193
- let lastCapturingWriter;
15194
- for (let i = 0; i < parts.length; i++) {
15195
- const part = parts[i];
15196
- if (part.type === "&&") {
15197
- shouldRunNext = lastExitSuccess;
15198
- continue;
15199
- } else if (part.type === "||") {
15200
- shouldRunNext = !lastExitSuccess;
15201
- continue;
15202
- } else if (part.type === "|") {
15203
- shouldRunNext = true;
15204
- continue;
15205
- } else if (part.type === ";") {
15206
- shouldRunNext = true;
15207
- pipelineData = void 0;
15208
- continue;
15209
- } else if (part.type === ">>") {
15210
- const nextPart = parts[i + 1];
15211
- i++;
15212
- if (!nextPart || nextPart.type !== "command") {
15213
- context2.writer.writeError("Missing file path after >>");
15214
- lastExitSuccess = false;
15336
+ rootContext.isExecuting = true;
15337
+ try {
15338
+ let lastExitSuccess = true;
15339
+ let shouldRunNext = true;
15340
+ let pipelineData = void 0;
15341
+ let lastCapturingWriter;
15342
+ for (let i = 0; i < parts.length; i++) {
15343
+ const part = parts[i];
15344
+ if (part.type === "&&") {
15345
+ shouldRunNext = lastExitSuccess;
15215
15346
  continue;
15216
- }
15217
- if (shouldRunNext) {
15218
- await appendOutputToFile(nextPart.value, context2);
15219
- pipelineData = void 0;
15220
- }
15221
- continue;
15222
- } else if (part.type === ">") {
15223
- const nextPart = parts[i + 1];
15224
- i++;
15225
- if (!nextPart || nextPart.type !== "command") {
15226
- context2.writer.writeError("Missing file path after >");
15227
- lastExitSuccess = false;
15347
+ } else if (part.type === "||") {
15348
+ shouldRunNext = !lastExitSuccess;
15228
15349
  continue;
15229
- }
15230
- if (shouldRunNext) {
15231
- await writeOutputToFile(nextPart.value, context2);
15350
+ } else if (part.type === "|") {
15351
+ shouldRunNext = true;
15352
+ continue;
15353
+ } else if (part.type === ";") {
15354
+ shouldRunNext = true;
15232
15355
  pipelineData = void 0;
15233
- }
15234
- continue;
15235
- } else if (part.type === "2>>") {
15236
- const nextPart = parts[i + 1];
15237
- i++;
15238
- if (!nextPart || nextPart.type !== "command") {
15239
- context2.writer.writeError("Missing file path after 2>>");
15240
- lastExitSuccess = false;
15356
+ continue;
15357
+ } else if (part.type === ">>") {
15358
+ const nextPart = parts[i + 1];
15359
+ i++;
15360
+ if (!nextPart || nextPart.type !== "command") {
15361
+ context2.writer.writeError("Missing file path after >>");
15362
+ lastExitSuccess = false;
15363
+ continue;
15364
+ }
15365
+ if (shouldRunNext) {
15366
+ await appendOutputToFile(nextPart.value, context2);
15367
+ pipelineData = void 0;
15368
+ }
15369
+ continue;
15370
+ } else if (part.type === ">") {
15371
+ const nextPart = parts[i + 1];
15372
+ i++;
15373
+ if (!nextPart || nextPart.type !== "command") {
15374
+ context2.writer.writeError("Missing file path after >");
15375
+ lastExitSuccess = false;
15376
+ continue;
15377
+ }
15378
+ if (shouldRunNext) {
15379
+ await writeOutputToFile(nextPart.value, context2);
15380
+ pipelineData = void 0;
15381
+ }
15382
+ continue;
15383
+ } else if (part.type === "2>>") {
15384
+ const nextPart = parts[i + 1];
15385
+ i++;
15386
+ if (!nextPart || nextPart.type !== "command") {
15387
+ context2.writer.writeError("Missing file path after 2>>");
15388
+ lastExitSuccess = false;
15389
+ continue;
15390
+ }
15391
+ if (shouldRunNext) {
15392
+ await appendStderrToFile(nextPart.value, context2, lastCapturingWriter);
15393
+ }
15394
+ continue;
15395
+ } else if (part.type === "2>") {
15396
+ const nextPart = parts[i + 1];
15397
+ i++;
15398
+ if (!nextPart || nextPart.type !== "command") {
15399
+ context2.writer.writeError("Missing file path after 2>");
15400
+ lastExitSuccess = false;
15401
+ continue;
15402
+ }
15403
+ if (shouldRunNext) {
15404
+ await writeStderrToFile(nextPart.value, context2, lastCapturingWriter);
15405
+ }
15241
15406
  continue;
15242
15407
  }
15243
- if (shouldRunNext) {
15244
- await appendStderrToFile(nextPart.value, context2, lastCapturingWriter);
15245
- }
15246
- continue;
15247
- } else if (part.type === "2>") {
15248
- const nextPart = parts[i + 1];
15249
- i++;
15250
- if (!nextPart || nextPart.type !== "command") {
15251
- context2.writer.writeError("Missing file path after 2>");
15252
- lastExitSuccess = false;
15408
+ if (!shouldRunNext) {
15253
15409
  continue;
15254
15410
  }
15255
- if (shouldRunNext) {
15256
- await writeStderrToFile(nextPart.value, context2, lastCapturingWriter);
15411
+ try {
15412
+ lastCapturingWriter = await this.executeSingleCommand(
15413
+ part.value,
15414
+ pipelineData,
15415
+ rootContext
15416
+ );
15417
+ lastExitSuccess = context2.process.exitCode === void 0 || context2.process.exitCode === 0;
15418
+ rootContext.lastCommandResult = {
15419
+ command: part.value,
15420
+ success: lastExitSuccess
15421
+ };
15422
+ pipelineData = context2.process.data;
15423
+ } catch (e) {
15424
+ lastExitSuccess = false;
15425
+ rootContext.lastCommandResult = {
15426
+ command: part.value,
15427
+ success: false
15428
+ };
15429
+ context2.writer.writeError(`Command ${part.value} failed: ${e}`);
15257
15430
  }
15258
- continue;
15259
- }
15260
- if (!shouldRunNext) {
15261
- continue;
15262
- }
15263
- try {
15264
- lastCapturingWriter = await this.executeSingleCommand(
15265
- part.value,
15266
- pipelineData,
15267
- rootContext
15268
- );
15269
- lastExitSuccess = context2.process.exitCode === void 0 || context2.process.exitCode === 0;
15270
- pipelineData = context2.process.data;
15271
- } catch (e) {
15272
- lastExitSuccess = false;
15273
- context2.writer.writeError(`Command ${part.value} failed: ${e}`);
15431
+ shouldRunNext = true;
15274
15432
  }
15275
- shouldRunNext = true;
15433
+ } finally {
15434
+ rootContext.isExecuting = false;
15435
+ rootContext.notifier?.clear();
15276
15436
  }
15277
15437
  }
15278
15438
  async executeSingleCommand(command2, data, context2) {
@@ -15280,8 +15440,8 @@ var CliCommandExecutor = class {
15280
15440
  command2 = expandEnvironmentVars(command2, context2);
15281
15441
  const assignMatch = command2.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
15282
15442
  if (assignMatch) {
15283
- try {
15284
- const env = context2.services.get(ICliEnvironment_TOKEN);
15443
+ const env = context2.services.get(ICliEnvironment_TOKEN);
15444
+ if (env) {
15285
15445
  let val = assignMatch[2];
15286
15446
  if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
15287
15447
  val = val.slice(1, -1);
@@ -15290,15 +15450,13 @@ var CliCommandExecutor = class {
15290
15450
  process.start();
15291
15451
  process.end();
15292
15452
  return;
15293
- } catch {
15294
15453
  }
15295
15454
  }
15296
15455
  process.start();
15297
15456
  let processEntry;
15298
- try {
15299
- const procRegistry = context2.services.get(CliProcessRegistry_TOKEN);
15457
+ const procRegistry = context2.services.get(CliProcessRegistry_TOKEN);
15458
+ if (procRegistry) {
15300
15459
  processEntry = procRegistry.register(command2);
15301
- } catch {
15302
15460
  }
15303
15461
  const parsed = this.commandParser.parse(command2);
15304
15462
  let { commandName } = parsed;
@@ -15411,6 +15569,7 @@ var CliCommandExecutor = class {
15411
15569
  );
15412
15570
  const commandAbortController = new AbortController();
15413
15571
  commandContext.signal = commandAbortController.signal;
15572
+ commandContext.http = new CliHttpClient(commandAbortController.signal);
15414
15573
  const abortSub = context2.onAbort.subscribe(() => {
15415
15574
  commandAbortController.abort();
15416
15575
  });
@@ -15475,19 +15634,13 @@ var CliCommandExecutor = class {
15475
15634
  }
15476
15635
  completeProcess(processEntry, context2, exitCode) {
15477
15636
  if (!processEntry) return;
15478
- try {
15479
- const procRegistry = context2.services.get(CliProcessRegistry_TOKEN);
15480
- procRegistry.complete(processEntry.pid, exitCode);
15481
- } catch {
15482
- }
15637
+ const procRegistry = context2.services.get(CliProcessRegistry_TOKEN);
15638
+ procRegistry?.complete(processEntry.pid, exitCode);
15483
15639
  }
15484
15640
  failProcess(processEntry, context2) {
15485
15641
  if (!processEntry) return;
15486
- try {
15487
- const procRegistry = context2.services.get(CliProcessRegistry_TOKEN);
15488
- procRegistry.fail(processEntry.pid);
15489
- } catch {
15490
- }
15642
+ const failRegistry = context2.services.get(CliProcessRegistry_TOKEN);
15643
+ failRegistry?.fail(processEntry.pid);
15491
15644
  }
15492
15645
  async showHelp(command2, context2) {
15493
15646
  try {
@@ -15569,29 +15722,94 @@ var CliCommandExecutor = class {
15569
15722
  // src/lib/services/cli-service-container.ts
15570
15723
  var CliServiceContainer = class {
15571
15724
  constructor() {
15572
- /** Stores single-value providers (resolved or pending). */
15725
+ /** Stores single-value providers (resolved singletons). */
15573
15726
  this.services = /* @__PURE__ */ new Map();
15574
15727
  /** Stores multi-provider arrays. */
15575
15728
  this.multiServices = /* @__PURE__ */ new Map();
15729
+ /** Tokens that cannot be overwritten by subsequent `set()` calls. */
15730
+ this.sealedTokens = /* @__PURE__ */ new Set();
15731
+ /** Stores provider recipes for transient tokens (re-resolved on every get). */
15732
+ this.transientRecipes = /* @__PURE__ */ new Map();
15576
15733
  }
15577
15734
  /**
15578
15735
  * Retrieve a service by its token.
15736
+ * Returns `undefined` when no provider is registered for the token.
15737
+ * For multi-provider tokens, returns the last registered value (use `getAll` for the full array).
15579
15738
  *
15580
15739
  * @param token The token used to register the service.
15581
- * @returns The resolved service instance (or array for multi providers).
15582
- * @throws Error if the token has not been registered.
15740
+ * @returns The resolved service instance, or `undefined` if not registered.
15583
15741
  */
15584
15742
  get(token) {
15743
+ if (this.transientRecipes.has(token)) {
15744
+ return this.resolveProvider(this.transientRecipes.get(token));
15745
+ }
15585
15746
  if (this.multiServices.has(token)) {
15586
- return this.multiServices.get(token);
15747
+ const arr = this.multiServices.get(token);
15748
+ return arr[arr.length - 1];
15587
15749
  }
15588
15750
  if (this.services.has(token)) {
15589
15751
  return this.services.get(token);
15590
15752
  }
15591
- const tokenName = typeof token === "string" ? token : typeof token === "function" ? token.name : String(token);
15592
- throw new Error(
15593
- `CliServiceContainer: No provider found for token "${tokenName}".`
15594
- );
15753
+ return void 0;
15754
+ }
15755
+ /**
15756
+ * Retrieve all registered services for a multi-provider token.
15757
+ * Returns an empty array when no provider is registered for the token.
15758
+ *
15759
+ * @param token The token used to register the service.
15760
+ * @returns Array of all resolved service instances.
15761
+ */
15762
+ getAll(token) {
15763
+ if (this.multiServices.has(token)) {
15764
+ return this.multiServices.get(token);
15765
+ }
15766
+ const single = this.get(token);
15767
+ return single !== void 0 ? [single] : [];
15768
+ }
15769
+ /**
15770
+ * Retrieve a service by its token, throwing if not registered.
15771
+ * Use this when the service is required and its absence is a programming error.
15772
+ * For multi-provider tokens, returns the last registered value (use `getAll` for the full array).
15773
+ *
15774
+ * @param token The token used to register the service.
15775
+ * @returns The resolved service instance.
15776
+ * @throws Error if the token has not been registered.
15777
+ */
15778
+ getRequired(token) {
15779
+ const value = this.get(token);
15780
+ if (value === void 0 && !this.has(token)) {
15781
+ throw new Error(
15782
+ `CliServiceContainer: No provider found for token "${this.tokenToString(token)}".`
15783
+ );
15784
+ }
15785
+ return value;
15786
+ }
15787
+ /**
15788
+ * Check whether a service is registered for the given token.
15789
+ */
15790
+ has(token) {
15791
+ return this.services.has(token) || this.multiServices.has(token) || this.transientRecipes.has(token);
15792
+ }
15793
+ /**
15794
+ * Mark a token as sealed so it cannot be overwritten by future `set()` calls.
15795
+ * Only available on the concrete container — not exposed on `ICliServiceProvider`.
15796
+ */
15797
+ seal(token) {
15798
+ this.sealedTokens.add(token);
15799
+ }
15800
+ /**
15801
+ * Mark multiple tokens as sealed at once.
15802
+ */
15803
+ sealAll(tokens) {
15804
+ for (const token of tokens) {
15805
+ this.sealedTokens.add(token);
15806
+ }
15807
+ }
15808
+ /**
15809
+ * Check whether a token is sealed.
15810
+ */
15811
+ isSealed(token) {
15812
+ return this.sealedTokens.has(token);
15595
15813
  }
15596
15814
  /**
15597
15815
  * Register one or more providers.
@@ -15613,13 +15831,13 @@ var CliServiceContainer = class {
15613
15831
  getRegisteredTokens() {
15614
15832
  const tokens = [];
15615
15833
  for (const key of this.services.keys()) {
15616
- tokens.push(
15617
- typeof key === "string" ? key : typeof key === "function" ? key.name : String(key)
15618
- );
15834
+ tokens.push(this.tokenToString(key));
15835
+ }
15836
+ for (const key of this.transientRecipes.keys()) {
15837
+ tokens.push(`${this.tokenToString(key)} (transient)`);
15619
15838
  }
15620
15839
  for (const key of this.multiServices.keys()) {
15621
- const name = typeof key === "string" ? key : typeof key === "function" ? key.name : String(key);
15622
- tokens.push(`${name} (multi)`);
15840
+ tokens.push(`${this.tokenToString(key)} (multi)`);
15623
15841
  }
15624
15842
  return tokens;
15625
15843
  }
@@ -15630,20 +15848,34 @@ var CliServiceContainer = class {
15630
15848
  const details = [];
15631
15849
  for (const [key, value] of this.services.entries()) {
15632
15850
  details.push({
15633
- token: typeof key === "string" ? key : typeof key === "function" ? key.name : String(key),
15851
+ token: this.tokenToString(key),
15634
15852
  type: this.describeValue(value),
15635
15853
  multi: false
15636
15854
  });
15637
15855
  }
15856
+ for (const [key, provider] of this.transientRecipes.entries()) {
15857
+ const className = provider["useClass"]?.name ?? provider["useFactory"]?.name ?? "transient";
15858
+ details.push({
15859
+ token: this.tokenToString(key),
15860
+ type: `transient(${className})`,
15861
+ multi: false
15862
+ });
15863
+ }
15638
15864
  for (const [key, values] of this.multiServices.entries()) {
15639
15865
  details.push({
15640
- token: typeof key === "string" ? key : typeof key === "function" ? key.name : String(key),
15866
+ token: this.tokenToString(key),
15641
15867
  type: `[${values.map((v) => this.describeValue(v)).join(", ")}]`,
15642
15868
  multi: true
15643
15869
  });
15644
15870
  }
15645
15871
  return details;
15646
15872
  }
15873
+ /**
15874
+ * Convert a token to a human-readable string for diagnostics/errors.
15875
+ */
15876
+ tokenToString(token) {
15877
+ return typeof token === "string" ? token : typeof token === "function" ? token.name : String(token);
15878
+ }
15647
15879
  /**
15648
15880
  * Describe a resolved value for diagnostic display.
15649
15881
  */
@@ -15663,27 +15895,45 @@ var CliServiceContainer = class {
15663
15895
  * Register a single provider.
15664
15896
  */
15665
15897
  registerProvider(provider) {
15666
- const value = this.resolveProvider(provider);
15667
- if (provider.multi) {
15668
- const existing = this.multiServices.get(provider.provide) ?? [];
15669
- existing.push(value);
15670
- this.multiServices.set(provider.provide, existing);
15898
+ if (!provider.multi && this.sealedTokens.has(provider.provide)) {
15899
+ throw new Error(
15900
+ `CliServiceContainer: Cannot override sealed service "${this.tokenToString(provider.provide)}".`
15901
+ );
15902
+ }
15903
+ if (provider["transient"] && !provider.multi) {
15904
+ this.transientRecipes.set(provider.provide, provider);
15905
+ this.services.delete(provider.provide);
15671
15906
  } else {
15672
- this.services.set(provider.provide, value);
15907
+ const value = this.resolveProvider(provider);
15908
+ if (provider.multi) {
15909
+ const existing = this.multiServices.get(provider.provide) ?? [];
15910
+ existing.push(value);
15911
+ this.multiServices.set(provider.provide, existing);
15912
+ } else {
15913
+ this.services.set(provider.provide, value);
15914
+ this.transientRecipes.delete(provider.provide);
15915
+ }
15916
+ }
15917
+ if (provider.sealed) {
15918
+ this.sealedTokens.add(provider.provide);
15673
15919
  }
15674
15920
  }
15675
15921
  /**
15676
15922
  * Resolve a provider definition to a concrete value.
15923
+ *
15924
+ * Note: `deps` are resolved eagerly at registration time, so
15925
+ * dependency tokens must be registered before the provider that needs them.
15677
15926
  */
15678
15927
  resolveProvider(provider) {
15679
15928
  if ("useValue" in provider) {
15680
15929
  return provider.useValue;
15681
15930
  }
15931
+ const deps = (provider["deps"] ?? []).map((dep) => this.getRequired(dep));
15682
15932
  if ("useFactory" in provider) {
15683
- return provider.useFactory();
15933
+ return provider.useFactory(...deps);
15684
15934
  }
15685
15935
  if ("useClass" in provider) {
15686
- return new provider.useClass();
15936
+ return new provider.useClass(...deps);
15687
15937
  }
15688
15938
  throw new Error(
15689
15939
  "CliServiceContainer: Provider must specify useValue, useFactory, or useClass."
@@ -15824,10 +16074,10 @@ var welcomeModule = {
15824
16074
  async onAfterBoot(context2) {
15825
16075
  const config = this.config || {};
15826
16076
  let showOption = config.show;
15827
- try {
15828
- const storeManager = context2.services.get(
15829
- CliStateStoreManager_TOKEN
15830
- );
16077
+ const storeManager = context2.services.get(
16078
+ CliStateStoreManager_TOKEN
16079
+ );
16080
+ if (storeManager) {
15831
16081
  const configureStore = storeManager.getStateStore(
15832
16082
  cliCore.CLI_CONFIGURE_STORE_NAME
15833
16083
  );
@@ -15836,7 +16086,6 @@ var welcomeModule = {
15836
16086
  if (state?.["system"]?.["welcomeMessage"]) {
15837
16087
  showOption = state["system"]["welcomeMessage"];
15838
16088
  }
15839
- } catch {
15840
16089
  }
15841
16090
  if (showOption) {
15842
16091
  if (!shouldDisplayWelcomeMessage(showOption)) {
@@ -15864,11 +16113,11 @@ var welcomeModule = {
15864
16113
  recordWelcomeMessageDisplay();
15865
16114
  context2.showPrompt();
15866
16115
  let showGreeting = true;
15867
- try {
15868
- const storeManager = context2.services.get(
15869
- CliStateStoreManager_TOKEN
15870
- );
15871
- const configureStore = storeManager.getStateStore(
16116
+ const greetingStoreManager = context2.services.get(
16117
+ CliStateStoreManager_TOKEN
16118
+ );
16119
+ if (greetingStoreManager) {
16120
+ const configureStore = greetingStoreManager.getStateStore(
15872
16121
  cliCore.CLI_CONFIGURE_STORE_NAME
15873
16122
  );
15874
16123
  await configureStore.initialize();
@@ -15876,7 +16125,6 @@ var welcomeModule = {
15876
16125
  if (configState?.["system"]?.["greeting"] === false) {
15877
16126
  showGreeting = false;
15878
16127
  }
15879
- } catch {
15880
16128
  }
15881
16129
  if (showGreeting) {
15882
16130
  await context2.textAnimator?.showText(getGreetingBasedOnTime(), {
@@ -15996,8 +16244,8 @@ var CliBoot = class {
15996
16244
  }
15997
16245
  }
15998
16246
  if (module.onSetup) {
15999
- const kvStore = context2.services.get(
16000
- "cli-key-value-store"
16247
+ const kvStore = context2.services.getRequired(
16248
+ CliKeyValueStore_TOKEN
16001
16249
  );
16002
16250
  const setupKey = `cli-module-setup:${module.name}`;
16003
16251
  const setupState = await kvStore.get(setupKey);
@@ -16377,16 +16625,19 @@ var CliStateStore = class {
16377
16625
  this.state$.next(this.initialState);
16378
16626
  }
16379
16627
  async persist() {
16380
- const keyValueStore = this.services.get(
16381
- "cli-key-value-store"
16628
+ const keyValueStore = this.services.getRequired(
16629
+ CliKeyValueStore_TOKEN
16382
16630
  );
16383
16631
  await keyValueStore.set(this.storageKey, this.getState());
16384
16632
  }
16385
16633
  async initialize() {
16634
+ const keyValueStore = this.services.get(
16635
+ CliKeyValueStore_TOKEN
16636
+ );
16637
+ if (!keyValueStore) {
16638
+ return;
16639
+ }
16386
16640
  try {
16387
- const keyValueStore = this.services.get(
16388
- "cli-key-value-store"
16389
- );
16390
16641
  const state = await keyValueStore.get(this.storageKey);
16391
16642
  if (state) {
16392
16643
  this.state$.next(state);
@@ -16453,6 +16704,23 @@ var CliStateStoreManager = class {
16453
16704
  this.stores.clear();
16454
16705
  }
16455
16706
  };
16707
+ var CliServerAuthService = class {
16708
+ constructor(services) {
16709
+ this.services = services;
16710
+ }
16711
+ getHeaders(serverName, configHeaders) {
16712
+ const merged = {
16713
+ ...cliCore.resolveHeaders(configHeaders)
16714
+ };
16715
+ const providers = this.services.getAll(
16716
+ cliCore.ICliServerAuthTokenProvider_TOKEN
16717
+ );
16718
+ for (const provider of providers) {
16719
+ Object.assign(merged, provider.getHeaders(serverName));
16720
+ }
16721
+ return merged;
16722
+ }
16723
+ };
16456
16724
 
16457
16725
  // src/lib/completion/cli-command-completion-provider.ts
16458
16726
  var CliCommandCompletionProvider = class {
@@ -16600,12 +16868,10 @@ var CliPackageNameCompletionProvider = class {
16600
16868
  if (!INSTALLED_PKG_SUBCOMMANDS.has(subCommand)) {
16601
16869
  return [];
16602
16870
  }
16603
- let manager;
16604
- try {
16605
- manager = this.services.get(
16606
- CliPackageManagerService_TOKEN
16607
- );
16608
- } catch {
16871
+ const manager = this.services.get(
16872
+ CliPackageManagerService_TOKEN
16873
+ );
16874
+ if (!manager) {
16609
16875
  return [];
16610
16876
  }
16611
16877
  const packages = await manager.getPackages();
@@ -16808,7 +17074,7 @@ var ServerListProcessor = class {
16808
17074
  this.description = "Show configured servers and their connection status";
16809
17075
  }
16810
17076
  async processCommand(_command, context2) {
16811
- const manager = context2.services.get(
17077
+ const manager = context2.services.getRequired(
16812
17078
  CliServerManager_TOKEN
16813
17079
  );
16814
17080
  if (!manager || manager.connections.size === 0) {
@@ -16847,7 +17113,7 @@ var ServerStatusProcessor = class {
16847
17113
  context2.process.exit(1);
16848
17114
  return;
16849
17115
  }
16850
- const manager = context2.services.get(
17116
+ const manager = context2.services.getRequired(
16851
17117
  CliServerManager_TOKEN
16852
17118
  );
16853
17119
  const connection = manager?.getConnection(serverName);
@@ -16857,6 +17123,7 @@ var ServerStatusProcessor = class {
16857
17123
  return;
16858
17124
  }
16859
17125
  context2.spinner?.show(`Pinging ${serverName}...`);
17126
+ context2.notifier.info(`Pinging ${serverName}`);
16860
17127
  const reachable = await connection.ping();
16861
17128
  context2.spinner?.hide();
16862
17129
  if (reachable) {
@@ -16887,7 +17154,7 @@ var ServerReconnectProcessor = class {
16887
17154
  context2.process.exit(1);
16888
17155
  return;
16889
17156
  }
16890
- const manager = context2.services.get(
17157
+ const manager = context2.services.getRequired(
16891
17158
  CliServerManager_TOKEN
16892
17159
  );
16893
17160
  if (!manager) {
@@ -16896,6 +17163,7 @@ var ServerReconnectProcessor = class {
16896
17163
  return;
16897
17164
  }
16898
17165
  context2.spinner?.show(`Reconnecting to ${serverName}...`);
17166
+ context2.notifier.info(`Reconnecting to ${serverName}`);
16899
17167
  const result = await manager.reconnect(serverName);
16900
17168
  context2.spinner?.hide();
16901
17169
  if (result.success) {
@@ -16925,7 +17193,7 @@ var ServerDefaultProcessor = class {
16925
17193
  ];
16926
17194
  }
16927
17195
  async processCommand(command2, context2) {
16928
- const manager = context2.services.get(
17196
+ const manager = context2.services.getRequired(
16929
17197
  CliServerManager_TOKEN
16930
17198
  );
16931
17199
  if (!manager) {
@@ -16961,8 +17229,6 @@ var ServerDefaultProcessor = class {
16961
17229
  }
16962
17230
  }
16963
17231
  };
16964
-
16965
- // src/lib/server/cli-ssh-command-processor.ts
16966
17232
  var CliSshCommandProcessor = class {
16967
17233
  constructor() {
16968
17234
  this.command = "ssh";
@@ -16986,7 +17252,7 @@ var CliSshCommandProcessor = class {
16986
17252
  this.resolved = false;
16987
17253
  }
16988
17254
  async processCommand(command2, context2) {
16989
- const manager = context2.services.get(
17255
+ const manager = context2.services.getRequired(
16990
17256
  CliServerManager_TOKEN
16991
17257
  );
16992
17258
  if (!manager) {
@@ -17080,7 +17346,7 @@ var CliSshCommandProcessor = class {
17080
17346
  connection: shellServers[0].connection
17081
17347
  };
17082
17348
  }
17083
- const manager = context2.services.get(
17349
+ const manager = context2.services.getRequired(
17084
17350
  CliServerManager_TOKEN
17085
17351
  );
17086
17352
  if (manager?.defaultServer) {
@@ -17273,7 +17539,10 @@ var CliSshCommandProcessor = class {
17273
17539
  if (cmd) {
17274
17540
  url += `&cmd=${encodeURIComponent(cmd)}`;
17275
17541
  }
17276
- return url;
17542
+ return cliCore.buildAuthenticatedWebSocketUrl(
17543
+ url,
17544
+ () => connection.resolveAuthHeaders()
17545
+ );
17277
17546
  }
17278
17547
  cleanup() {
17279
17548
  if (this.socket) {
@@ -17322,6 +17591,11 @@ function initializeTerminal(container, opts) {
17322
17591
  terminal.open(container);
17323
17592
  fitAddon.fit();
17324
17593
  requestAnimationFrame(() => fitAddon.fit());
17594
+ if (document.fonts?.ready) {
17595
+ document.fonts.ready.then(() => {
17596
+ requestAnimationFrame(() => fitAddon.fit());
17597
+ });
17598
+ }
17325
17599
  container.classList.add("terminal-container");
17326
17600
  container.style.background = opts.theme?.background ?? "#000";
17327
17601
  const wheelListener = (e) => e.preventDefault();
@@ -17564,19 +17838,21 @@ async function initializeServices(options) {
17564
17838
  const logger = new CliLogger();
17565
17839
  const commandHistory = new CliCommandHistory(store);
17566
17840
  await commandHistory.initialize();
17567
- services.set([{ provide: "cli-key-value-store", useValue: store }]);
17841
+ services.set([{ provide: CliKeyValueStore_TOKEN, useValue: store, sealed: true }]);
17568
17842
  const stateStoreManager = new CliStateStoreManager(services, registry);
17569
17843
  const processRegistry = new CliProcessRegistry();
17570
17844
  services.set([
17571
17845
  {
17572
17846
  provide: CliStateStoreManager_TOKEN,
17573
- useValue: stateStoreManager
17847
+ useValue: stateStoreManager,
17848
+ sealed: true
17574
17849
  },
17575
- { provide: CliProcessorsRegistry_TOKEN, useValue: registry },
17576
- { provide: CliCommandHistory_TOKEN, useValue: commandHistory },
17850
+ { provide: CliProcessorsRegistry_TOKEN, useValue: registry, sealed: true },
17851
+ { provide: CliCommandHistory_TOKEN, useValue: commandHistory, sealed: true },
17577
17852
  {
17578
17853
  provide: CliProcessRegistry_TOKEN,
17579
- useValue: processRegistry
17854
+ useValue: processRegistry,
17855
+ sealed: true
17580
17856
  }
17581
17857
  ]);
17582
17858
  if (pendingServices.length > 0) {
@@ -17587,7 +17863,8 @@ async function initializeServices(options) {
17587
17863
  services.set([
17588
17864
  {
17589
17865
  provide: ICliPingServerService_TOKEN,
17590
- useValue: new CliDefaultPingServerService()
17866
+ useClass: CliDefaultPingServerService,
17867
+ sealed: true
17591
17868
  }
17592
17869
  ]);
17593
17870
  }
@@ -17597,25 +17874,27 @@ async function initializeServices(options) {
17597
17874
  syntaxRegistry.register(new MarkdownHighlighter());
17598
17875
  syntaxRegistry.register(new YamlHighlighter());
17599
17876
  services.set([
17600
- { provide: "syntax-highlighter-registry", useValue: syntaxRegistry }
17877
+ { provide: SyntaxHighlighterRegistry_TOKEN, useValue: syntaxRegistry, sealed: true }
17601
17878
  ]);
17602
17879
  if (!pendingTokens.has(ICliEnvironment_TOKEN)) {
17603
17880
  services.set([
17604
17881
  {
17605
17882
  provide: ICliEnvironment_TOKEN,
17606
- useValue: new CliEnvironment()
17883
+ useClass: CliEnvironment,
17884
+ sealed: true
17607
17885
  }
17608
17886
  ]);
17609
17887
  }
17610
17888
  services.set([
17611
17889
  {
17612
17890
  provide: cliCore.ICliDragDropService_TOKEN,
17613
- useValue: dragDropService
17891
+ useValue: dragDropService,
17892
+ sealed: true
17614
17893
  }
17615
17894
  ]);
17616
17895
  const translator = new CliTranslationService();
17617
17896
  services.set([
17618
- { provide: cliCore.ICliTranslationService_TOKEN, useValue: translator }
17897
+ { provide: cliCore.ICliTranslationService_TOKEN, useValue: translator, sealed: true }
17619
17898
  ]);
17620
17899
  return {
17621
17900
  services,
@@ -17727,10 +18006,18 @@ var CliEngine = class {
17727
18006
  provide: CliBackgroundServiceRegistry_TOKEN,
17728
18007
  useValue: this.executionContext.backgroundServices
17729
18008
  }]);
17730
- const serverManager = new CliServerManager(this.registry);
18009
+ const serverAuthService = new CliServerAuthService(services);
17731
18010
  services.set([
17732
- { provide: CliServerManager_TOKEN, useValue: serverManager }
18011
+ { provide: cliCore.ICliServerAuthService_TOKEN, useValue: serverAuthService, sealed: true }
17733
18012
  ]);
18013
+ services.set([
18014
+ {
18015
+ provide: CliServerManager_TOKEN,
18016
+ useClass: CliServerManager,
18017
+ deps: [CliProcessorsRegistry_TOKEN, cliCore.ICliServerAuthService_TOKEN]
18018
+ }
18019
+ ]);
18020
+ const serverManager = services.getRequired(CliServerManager_TOKEN);
17734
18021
  if (this.options?.servers && this.options.servers.length > 0) {
17735
18022
  await serverManager.connectAll(this.options.servers, {
17736
18023
  warn: (msg) => this.executionContext.logger.warn(msg),
@@ -17750,13 +18037,9 @@ var CliEngine = class {
17750
18037
  new CliCommandCompletionProvider(this.registry),
17751
18038
  new CliParameterCompletionProvider(this.registry, executor)
17752
18039
  ];
17753
- let pluginProviders = [];
17754
- try {
17755
- pluginProviders = services.get(
17756
- cliCore.ICliCompletionProvider_TOKEN
17757
- ) ?? [];
17758
- } catch {
17759
- }
18040
+ const pluginProviders = services.getAll(
18041
+ cliCore.ICliCompletionProvider_TOKEN
18042
+ );
17760
18043
  this.executionContext.completionEngine.setProviders([
17761
18044
  ...pluginProviders,
17762
18045
  ...defaultProviders
@@ -17779,6 +18062,8 @@ var CliEngine = class {
17779
18062
  if (this.options?.snapshot) {
17780
18063
  await this.restoreSnapshot(this.options.snapshot);
17781
18064
  }
18065
+ this._startedAt = Date.now();
18066
+ this.safeFit();
17782
18067
  }
17783
18068
  /**
17784
18069
  * Clean up terminal and event listeners.
@@ -17837,15 +18122,22 @@ var CliEngine = class {
17837
18122
  return this.registry;
17838
18123
  }
17839
18124
  /**
17840
- * Execute a command programmatically.
18125
+ * Timestamp (ms since epoch) when the engine finished starting.
18126
+ */
18127
+ get startedAt() {
18128
+ return this._startedAt;
18129
+ }
18130
+ /**
18131
+ * Execute a command programmatically, behaving the same as if the user
18132
+ * typed it and pressed Enter: echoes the command, adds it to history,
18133
+ * executes it, and shows a new prompt afterwards.
17841
18134
  */
17842
18135
  async execute(command2) {
17843
- if (this.executionContext) {
17844
- await this.executionContext.executor.executeCommand(
17845
- command2,
17846
- this.executionContext
17847
- );
17848
- }
18136
+ if (!this.executionContext) return;
18137
+ const ctx = this.executionContext;
18138
+ ctx.showPrompt({ reset: true });
18139
+ this.terminal.write(command2 + "\r\n");
18140
+ await ctx.submitCommand(command2);
17849
18141
  }
17850
18142
  /**
17851
18143
  * Capture a snapshot of the current engine state.
@@ -17855,7 +18147,7 @@ var CliEngine = class {
17855
18147
  if (!this.executionContext) {
17856
18148
  throw new Error("Cannot snapshot before engine has started");
17857
18149
  }
17858
- const stateStoreManager = this.executionContext.services.get(
18150
+ const stateStoreManager = this.executionContext.services.getRequired(
17859
18151
  CliStateStoreManager_TOKEN
17860
18152
  );
17861
18153
  return {
@@ -17882,7 +18174,7 @@ var CliEngine = class {
17882
18174
  });
17883
18175
  }
17884
18176
  await this.executionContext.commandHistory.setHistory(snap.commandHistory);
17885
- const stateStoreManager = this.executionContext.services.get(
18177
+ const stateStoreManager = this.executionContext.services.getRequired(
17886
18178
  CliStateStoreManager_TOKEN
17887
18179
  );
17888
18180
  for (const entry of snap.stateStores) {
@@ -17942,7 +18234,7 @@ var CliTestHarness = class {
17942
18234
  this.services = new CliServiceContainer();
17943
18235
  this.processRegistry = new CliProcessRegistry();
17944
18236
  this.services.set({
17945
- provide: "cli-key-value-store",
18237
+ provide: CliKeyValueStore_TOKEN,
17946
18238
  useValue: createInMemoryKvStore()
17947
18239
  });
17948
18240
  this.services.set({
@@ -18052,6 +18344,7 @@ var CliTestHarness = class {
18052
18344
  userSession: this.userSession,
18053
18345
  state: this.stateStoreManager.getStateStore("shared"),
18054
18346
  backgroundServices: createNoopBackgroundServices(),
18347
+ http: new CliHttpClient(),
18055
18348
  promptLength: 0,
18056
18349
  currentLine: "",
18057
18350
  cursorPosition: 0,
@@ -18071,6 +18364,10 @@ var CliTestHarness = class {
18071
18364
  },
18072
18365
  exitFullScreenMode: () => {
18073
18366
  },
18367
+ submitCommand: async (command2) => {
18368
+ await this.executor.executeCommand(command2, context2);
18369
+ },
18370
+ notifier: new CliNotifier(),
18074
18371
  createInterval: (cb, ms) => {
18075
18372
  const id = setInterval(cb, ms);
18076
18373
  return {
@@ -18323,14 +18620,17 @@ exports.CliHelpCommandProcessor = CliHelpCommandProcessor;
18323
18620
  exports.CliHistoryCommandProcessor = CliHistoryCommandProcessor;
18324
18621
  exports.CliHotKeysCommandProcessor = CliHotKeysCommandProcessor;
18325
18622
  exports.CliHtopCommandProcessor = CliHtopCommandProcessor;
18623
+ exports.CliHttpClient = CliHttpClient;
18326
18624
  exports.CliInputReader = CliInputReader;
18327
18625
  exports.CliJsonCommandProcessor = CliJsonCommandProcessor;
18328
18626
  exports.CliKeyValueStore = CliKeyValueStore;
18627
+ exports.CliKeyValueStore_TOKEN = CliKeyValueStore_TOKEN;
18329
18628
  exports.CliKillCommandProcessor = CliKillCommandProcessor;
18330
18629
  exports.CliLogger = CliLogger;
18331
18630
  exports.CliLoremCommandProcessor = CliLoremCommandProcessor;
18332
18631
  exports.CliModuleRegistry_TOKEN = CliModuleRegistry_TOKEN;
18333
18632
  exports.CliNanoCommandProcessor = CliNanoCommandProcessor;
18633
+ exports.CliNotifier = CliNotifier;
18334
18634
  exports.CliOpenCommandProcessor = CliOpenCommandProcessor;
18335
18635
  exports.CliPackageManagerService = CliPackageManagerService;
18336
18636
  exports.CliPackageManagerService_TOKEN = CliPackageManagerService_TOKEN;
@@ -18380,6 +18680,7 @@ exports.LIBRARY_VERSION = LIBRARY_VERSION;
18380
18680
  exports.OverlayAddon = OverlayAddon;
18381
18681
  exports.ProcessExitedError = ProcessExitedError;
18382
18682
  exports.ScriptLoaderService = ScriptLoaderService;
18683
+ exports.SyntaxHighlighterRegistry_TOKEN = SyntaxHighlighterRegistry_TOKEN;
18383
18684
  exports.appendOutputToFile = appendOutputToFile;
18384
18685
  exports.appendStderrToFile = appendStderrToFile;
18385
18686
  exports.builtinProcessors = builtinProcessors;