@qodalis/cli 2.0.0-beta.15 → 2.0.0-beta.17

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.mjs CHANGED
@@ -1,12 +1,12 @@
1
- import { CliLogLevel, DefaultThemes, DefaultThemeInfos, DefaultLibraryAuthor, CliIcon, CliForegroundColor, LIBRARY_VERSION as LIBRARY_VERSION$1, resolveConfigurationCategories, ICliTranslationService_TOKEN, ICliAuthorizationService_TOKEN, resolveHeaders, appendQueryParams, buildAuthenticatedWebSocketUrl, ServerVersionNegotiator, CliHttpError, formatJson, visibleLength, stripAnsi, getRightOfWord, CancellablePromise, isCliAccessDeniedError, getParameterValue, ICliCommandGuard_TOKEN, CLI_CONFIGURE_STORE_NAME, CliModuleRegistry, initializeBrowserEnvironment, ICliPermissionRegistry_TOKEN, satisfiesVersionRange, CliServerPermissions, ICliDragDropService_TOKEN, cliAccessMetadataGuards, ICliServerAuthService_TOKEN, ICliCompletionProvider_TOKEN, delay, colorFirstWord, clearTerminalLine, ICliServerAuthTokenProvider_TOKEN } from '@qodalis/cli-core';
1
+ import { CliLogLevel, DefaultThemes, DefaultThemeInfos, DefaultLibraryAuthor, CliIcon, CliForegroundColor, LIBRARY_VERSION as LIBRARY_VERSION$1, resolveConfigurationCategories, ICliTranslationService_TOKEN, ICliAuthorizationService_TOKEN, resolveHeaders, appendQueryParams, buildAuthenticatedWebSocketUrl, ServerVersionNegotiator, CliHttpError, formatJson, visibleLength, stripAnsi, getRightOfWord, CancellablePromise, isCliAccessDeniedError, getParameterValue, ICliCommandGuard_TOKEN, CLI_CONFIGURE_STORE_NAME, CliModuleRegistry, initializeBrowserEnvironment, ICliPermissionRegistry_TOKEN, satisfiesVersionRange, CliServerPermissions, ICliDragDropService_TOKEN, cliAccessMetadataGuards, ICliServerAuthService_TOKEN, ICliCompletionProvider_TOKEN, delay, colorFirstWord, clearTerminalLine, ICliServerAuthTokenProvider_TOKEN, truncateToWidth } from '@qodalis/cli-core';
2
2
  export { ICliUserSessionService_TOKEN, ICliUsersStoreService_TOKEN } from '@qodalis/cli-core';
3
- import { Subject, BehaviorSubject } from 'rxjs';
4
- import { map, distinctUntilChanged } from 'rxjs/operators';
5
3
  import { Terminal } from '@xterm/xterm';
6
4
  import { FitAddon } from '@xterm/addon-fit';
7
5
  import { WebLinksAddon } from '@xterm/addon-web-links';
8
6
  import { Unicode11Addon } from '@xterm/addon-unicode11';
9
7
  import { SerializeAddon } from '@xterm/addon-serialize';
8
+ import { Subject, BehaviorSubject } from 'rxjs';
9
+ import { map, distinctUntilChanged } from 'rxjs/operators';
10
10
 
11
11
  // src/lib/parsers/command-parser.ts
12
12
  var CommandParser = class {
@@ -412,7 +412,7 @@ var CliKeyValueStore_TOKEN = "cli-key-value-store";
412
412
  var SyntaxHighlighterRegistry_TOKEN = "syntax-highlighter-registry";
413
413
 
414
414
  // src/lib/version.ts
415
- var LIBRARY_VERSION = "2.0.0-beta.15";
415
+ var LIBRARY_VERSION = "2.0.0-beta.17";
416
416
  var API_VERSION = 2;
417
417
  var ANONYMOUS = "\0anonymous";
418
418
  function aliasOwner(context2) {
@@ -2698,6 +2698,150 @@ var CliYesCommandProcessor = class {
2698
2698
  );
2699
2699
  }
2700
2700
  };
2701
+
2702
+ // src/lib/addons/overlay.ts
2703
+ var OverlayAddon = class {
2704
+ constructor() {
2705
+ this.overlayNode = document.createElement("div");
2706
+ this.overlayNode.style.cssText = `border-radius: 15px;
2707
+ font-size: xx-large;
2708
+ opacity: 0.75;
2709
+ padding: 0.2em 0.5em 0.2em 0.5em;
2710
+ position: absolute;
2711
+ -webkit-user-select: none;
2712
+ -webkit-transition: opacity 180ms ease-in;
2713
+ -moz-user-select: none;
2714
+ -moz-transition: opacity 180ms ease-in;`;
2715
+ this.overlayNode.addEventListener(
2716
+ "mousedown",
2717
+ (e) => {
2718
+ e.preventDefault();
2719
+ e.stopPropagation();
2720
+ },
2721
+ true
2722
+ );
2723
+ }
2724
+ activate(terminal) {
2725
+ this.terminal = terminal;
2726
+ }
2727
+ dispose() {
2728
+ }
2729
+ showOverlay(msg, timeout) {
2730
+ const { terminal, overlayNode } = this;
2731
+ if (!terminal.element) return;
2732
+ overlayNode.style.color = "#101010";
2733
+ overlayNode.style.backgroundColor = "#f0f0f0";
2734
+ overlayNode.textContent = msg;
2735
+ overlayNode.style.opacity = "0.75";
2736
+ if (!overlayNode.parentNode) {
2737
+ terminal.element.appendChild(overlayNode);
2738
+ }
2739
+ const divSize = terminal.element.getBoundingClientRect();
2740
+ const overlaySize = overlayNode.getBoundingClientRect();
2741
+ overlayNode.style.top = (divSize.height - overlaySize.height) / 2 + "px";
2742
+ overlayNode.style.left = (divSize.width - overlaySize.width) / 2 + "px";
2743
+ if (this.overlayTimeout) clearTimeout(this.overlayTimeout);
2744
+ if (!timeout) return;
2745
+ this.overlayTimeout = window.setTimeout(() => {
2746
+ overlayNode.style.opacity = "0";
2747
+ this.overlayTimeout = window.setTimeout(() => {
2748
+ if (overlayNode.parentNode) {
2749
+ overlayNode.parentNode.removeChild(overlayNode);
2750
+ }
2751
+ this.overlayTimeout = void 0;
2752
+ overlayNode.style.opacity = "0.75";
2753
+ }, 200);
2754
+ }, timeout || 1500);
2755
+ }
2756
+ };
2757
+ var CliDragDropService = class {
2758
+ constructor(_container) {
2759
+ this._container = _container;
2760
+ this._subject = new Subject();
2761
+ this._dragOver = (e) => e.preventDefault();
2762
+ this._drop = (e) => {
2763
+ e.preventDefault();
2764
+ const files = Array.from(e.dataTransfer?.files ?? []);
2765
+ if (files.length > 0) {
2766
+ this._subject.next(files);
2767
+ }
2768
+ };
2769
+ this._container.addEventListener("dragover", this._dragOver);
2770
+ this._container.addEventListener("drop", this._drop);
2771
+ }
2772
+ get onFileDrop() {
2773
+ return this._subject.asObservable();
2774
+ }
2775
+ destroy() {
2776
+ this._container.removeEventListener("dragover", this._dragOver);
2777
+ this._container.removeEventListener("drop", this._drop);
2778
+ this._subject.complete();
2779
+ }
2780
+ };
2781
+
2782
+ // src/lib/engine/cli-terminal-setup.ts
2783
+ var NARROW_VIEWPORT = 640;
2784
+ function defaultFontSize() {
2785
+ const width = typeof window !== "undefined" ? window.innerWidth : 0;
2786
+ return width > 0 && width <= NARROW_VIEWPORT ? 14 : 20;
2787
+ }
2788
+ function getTerminalOptions(userOptions) {
2789
+ return {
2790
+ cursorBlink: true,
2791
+ allowProposedApi: true,
2792
+ fontSize: defaultFontSize(),
2793
+ theme: DefaultThemes.default,
2794
+ convertEol: true,
2795
+ ...userOptions ?? {}
2796
+ };
2797
+ }
2798
+ function initializeTerminal(container, opts) {
2799
+ const terminal = new Terminal(opts);
2800
+ const fitAddon = new FitAddon();
2801
+ terminal.loadAddon(fitAddon);
2802
+ terminal.loadAddon(new WebLinksAddon());
2803
+ terminal.loadAddon(new OverlayAddon());
2804
+ terminal.loadAddon(new Unicode11Addon());
2805
+ const serializeAddon = new SerializeAddon();
2806
+ terminal.loadAddon(serializeAddon);
2807
+ terminal.open(container);
2808
+ fitAddon.fit();
2809
+ requestAnimationFrame(() => fitAddon.fit());
2810
+ if (document.fonts?.ready) {
2811
+ document.fonts.ready.then(() => {
2812
+ requestAnimationFrame(() => fitAddon.fit());
2813
+ });
2814
+ }
2815
+ container.classList.add("terminal-container");
2816
+ container.style.background = opts.theme?.background ?? "#000";
2817
+ const wheelListener = (e) => e.preventDefault();
2818
+ container.addEventListener("wheel", wheelListener, { passive: false });
2819
+ terminal.focus();
2820
+ const dragDropService = new CliDragDropService(container);
2821
+ return { terminal, fitAddon, serializeAddon, dragDropService, wheelListener };
2822
+ }
2823
+ var LAYOUT_TIMEOUT_MS = 1e4;
2824
+ function waitForLayout(container) {
2825
+ return new Promise((resolve, reject) => {
2826
+ const deadline = Date.now() + LAYOUT_TIMEOUT_MS;
2827
+ const check = () => {
2828
+ if (container.offsetWidth > 0 && container.offsetHeight > 0) {
2829
+ resolve();
2830
+ return;
2831
+ }
2832
+ if (Date.now() >= deadline) {
2833
+ reject(new Error(
2834
+ `CliEngine.start(): container has zero dimensions after ${LAYOUT_TIMEOUT_MS}ms. Ensure the container element is visible and laid out before calling start().`
2835
+ ));
2836
+ return;
2837
+ }
2838
+ requestAnimationFrame(check);
2839
+ };
2840
+ check();
2841
+ });
2842
+ }
2843
+
2844
+ // src/lib/processors/configure/cli-configure-command-processor.ts
2701
2845
  var SYSTEM_OPTIONS = [
2702
2846
  {
2703
2847
  key: "logLevel",
@@ -2774,7 +2918,7 @@ var SYSTEM_OPTIONS = [
2774
2918
  label: "Font Size",
2775
2919
  description: "Terminal font size in pixels",
2776
2920
  type: "number",
2777
- defaultValue: 20,
2921
+ defaultValue: defaultFontSize(),
2778
2922
  validator: (value) => {
2779
2923
  if (value < 8 || value > 40) {
2780
2924
  return { valid: false, message: "Font size must be between 8 and 40" };
@@ -2854,7 +2998,7 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
2854
2998
  async initialize(context2) {
2855
2999
  const state = context2.state.getState();
2856
3000
  if (state?.system) {
2857
- this.applySystemSettings(state.system, context2);
3001
+ this.applySystemSettings(state.system, context2, true);
2858
3002
  }
2859
3003
  }
2860
3004
  writeDescription(context2) {
@@ -3089,7 +3233,11 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
3089
3233
  }
3090
3234
  return result;
3091
3235
  }
3092
- applySystemSettings(settings, context2) {
3236
+ /**
3237
+ * @param onBoot at startup, terminal options still at their default are skipped so the
3238
+ * host's `terminalOptions` (e.g. its own fontSize) are not overridden.
3239
+ */
3240
+ applySystemSettings(settings, context2, onBoot = false) {
3093
3241
  if (settings["logLevel"]) {
3094
3242
  const level = LOG_LEVEL_MAP[settings["logLevel"]];
3095
3243
  if (level !== void 0) {
@@ -3103,23 +3251,29 @@ var CliConfigureCommandProcessor = class _CliConfigureCommandProcessor {
3103
3251
  translator?.setLocale(settings["language"]);
3104
3252
  }
3105
3253
  if (context2.terminal?.options) {
3106
- if (settings["cursorBlink"] !== void 0) {
3107
- context2.terminal.options.cursorBlink = settings["cursorBlink"];
3254
+ const terminal = onBoot ? Object.fromEntries(
3255
+ Object.entries(settings).filter(([key, value]) => {
3256
+ const option = SYSTEM_OPTIONS.find((o) => o.key === key);
3257
+ return !option || value !== option.defaultValue;
3258
+ })
3259
+ ) : settings;
3260
+ if (terminal["cursorBlink"] !== void 0) {
3261
+ context2.terminal.options.cursorBlink = terminal["cursorBlink"];
3108
3262
  }
3109
- if (settings["cursorStyle"]) {
3110
- context2.terminal.options.cursorStyle = settings["cursorStyle"];
3263
+ if (terminal["cursorStyle"]) {
3264
+ context2.terminal.options.cursorStyle = terminal["cursorStyle"];
3111
3265
  }
3112
- if (settings["scrollback"] !== void 0) {
3113
- context2.terminal.options.scrollback = settings["scrollback"];
3266
+ if (terminal["scrollback"] !== void 0) {
3267
+ context2.terminal.options.scrollback = terminal["scrollback"];
3114
3268
  }
3115
- if (settings["fontSize"] !== void 0) {
3116
- context2.terminal.options.fontSize = settings["fontSize"];
3269
+ if (terminal["fontSize"] !== void 0) {
3270
+ context2.terminal.options.fontSize = terminal["fontSize"];
3117
3271
  }
3118
- if (settings["fontFamily"]) {
3119
- context2.terminal.options.fontFamily = settings["fontFamily"];
3272
+ if (terminal["fontFamily"]) {
3273
+ context2.terminal.options.fontFamily = terminal["fontFamily"];
3120
3274
  }
3121
- if (settings["smoothScrollDuration"] !== void 0) {
3122
- context2.terminal.options.smoothScrollDuration = settings["smoothScrollDuration"];
3275
+ if (terminal["smoothScrollDuration"] !== void 0) {
3276
+ context2.terminal.options.smoothScrollDuration = terminal["smoothScrollDuration"];
3123
3277
  }
3124
3278
  }
3125
3279
  }
@@ -3717,6 +3871,7 @@ var CliHelpCommandProcessor = class {
3717
3871
  return 0;
3718
3872
  }
3719
3873
  );
3874
+ const narrow = isNarrow(context2);
3720
3875
  sortedModules.forEach(([module, processors]) => {
3721
3876
  const displayName = this.formatModuleName(module);
3722
3877
  writer.writeln(
@@ -3725,7 +3880,7 @@ var CliHelpCommandProcessor = class {
3725
3880
  processors.forEach((processor) => {
3726
3881
  const icon = processor?.metadata?.icon || CliIcon.Extension;
3727
3882
  const name = writer.wrapInColor(
3728
- processor.command.padEnd(20),
3883
+ narrow ? processor.command : processor.command.padEnd(20),
3729
3884
  CliForegroundColor.Cyan
3730
3885
  );
3731
3886
  const aliasText = processor.aliases?.length ? `${DIM} ${processor.aliases.join(", ")}${RESET}` : "";
@@ -3734,6 +3889,11 @@ var CliHelpCommandProcessor = class {
3734
3889
  processor.command,
3735
3890
  context2
3736
3891
  );
3892
+ if (narrow) {
3893
+ writer.writeln(` ${icon} ${name}${aliasText}`);
3894
+ writer.writeln(` ${desc}`);
3895
+ return;
3896
+ }
3737
3897
  writer.writeln(` ${icon} ${name} ${desc}${aliasText}`);
3738
3898
  });
3739
3899
  writer.writeln();
@@ -3843,9 +4003,10 @@ var CliHelpCommandProcessor = class {
3843
4003
  writer.writeln(
3844
4004
  ` ${BOLD}${writer.wrapInColor(t.t("cli.help.subcommands", "Subcommands"), CliForegroundColor.Yellow)}${RESET}`
3845
4005
  );
4006
+ const narrow = isNarrow(context2);
3846
4007
  processor.processors.forEach((sub) => {
3847
4008
  const subName = writer.wrapInColor(
3848
- sub.command.padEnd(16),
4009
+ narrow ? sub.command : sub.command.padEnd(16),
3849
4010
  CliForegroundColor.Cyan
3850
4011
  );
3851
4012
  const subAliases = sub.aliases?.length ? `${DIM} (${sub.aliases.join(", ")})${RESET}` : "";
@@ -3854,6 +4015,11 @@ var CliHelpCommandProcessor = class {
3854
4015
  `${processor.command}.${sub.command}`,
3855
4016
  context2
3856
4017
  );
4018
+ if (narrow) {
4019
+ writer.writeln(` ${subName}${subAliases}`);
4020
+ writer.writeln(` ${subDesc}`);
4021
+ return;
4022
+ }
3857
4023
  writer.writeln(
3858
4024
  ` ${subName} ${subDesc}${subAliases}`
3859
4025
  );
@@ -3867,7 +4033,7 @@ var CliHelpCommandProcessor = class {
3867
4033
  ` ${BOLD}${writer.wrapInColor(t.t("cli.help.options", "Options"), CliForegroundColor.Yellow)}${RESET}`
3868
4034
  );
3869
4035
  commandParams.forEach((param) => {
3870
- this.writeParameter(param, writer, t);
4036
+ this.writeParameter(param, writer, t, isNarrow(context2));
3871
4037
  });
3872
4038
  }
3873
4039
  if (globalParams.length > 0) {
@@ -3876,7 +4042,7 @@ var CliHelpCommandProcessor = class {
3876
4042
  ` ${BOLD}${writer.wrapInColor(t.t("cli.help.global_options", "Global options"), CliForegroundColor.Yellow)}${RESET}`
3877
4043
  );
3878
4044
  globalParams.forEach((param) => {
3879
- this.writeParameter(param, writer, t);
4045
+ this.writeParameter(param, writer, t, isNarrow(context2));
3880
4046
  });
3881
4047
  }
3882
4048
  if (processor.metadata?.requireServer) {
@@ -3898,7 +4064,7 @@ var CliHelpCommandProcessor = class {
3898
4064
  }
3899
4065
  return module.charAt(0).toUpperCase() + module.slice(1);
3900
4066
  }
3901
- writeParameter(param, writer, translator) {
4067
+ writeParameter(param, writer, translator, narrow = false) {
3902
4068
  const aliases = param.aliases?.length ? `, ${param.aliases.map((a) => `-${a}`).join(", ")}` : "";
3903
4069
  const nameStr = writer.wrapInColor(
3904
4070
  `--${param.name}${aliases}`,
@@ -3907,11 +4073,19 @@ var CliHelpCommandProcessor = class {
3907
4073
  const typeStr = `${DIM}<${param.type}>${RESET}`;
3908
4074
  const required = param.required ? writer.wrapInColor(` ${translator.t("cli.help.required", "(required)")}`, CliForegroundColor.Red) : "";
3909
4075
  const defaultVal = param.defaultValue !== void 0 && !param.required ? `${DIM} [${param.defaultValue}]${RESET}` : "";
4076
+ if (narrow) {
4077
+ writer.writeln(` ${nameStr} ${typeStr}${required}${defaultVal}`);
4078
+ writer.writeln(` ${param.description}`);
4079
+ return;
4080
+ }
3910
4081
  writer.writeln(
3911
4082
  ` ${nameStr} ${typeStr} ${param.description}${required}${defaultVal}`
3912
4083
  );
3913
4084
  }
3914
4085
  };
4086
+ function isNarrow(context2) {
4087
+ return (context2.terminal?.cols ?? 80) < 60;
4088
+ }
3915
4089
 
3916
4090
  // src/lib/constants/index.ts
3917
4091
  var CLi_Name_Art_Full = `
@@ -9831,11 +10005,12 @@ function hexToRgb(hex) {
9831
10005
  const n = parseInt(m[1], 16);
9832
10006
  return { r: n >> 16 & 255, g: n >> 8 & 255, b: n & 255 };
9833
10007
  }
9834
- function colorSwatch(hex) {
9835
- if (!hex) return " ";
10008
+ function colorSwatch(hex, width = 2) {
10009
+ const cell = " ".repeat(width);
10010
+ if (!hex) return cell;
9836
10011
  const rgb = hexToRgb(hex);
9837
- if (!rgb) return " ";
9838
- return `\x1B[48;2;${rgb.r};${rgb.g};${rgb.b}m \x1B[0m`;
10012
+ if (!rgb) return cell;
10013
+ return `\x1B[48;2;${rgb.r};${rgb.g};${rgb.b}m${cell}\x1B[0m`;
9839
10014
  }
9840
10015
  function colorText(text, hex) {
9841
10016
  if (!hex) return text;
@@ -9902,11 +10077,20 @@ var CliThemeCommandProcessor = class {
9902
10077
  )
9903
10078
  );
9904
10079
  context2.writer.writeln();
10080
+ const narrow = (context2.terminal?.cols ?? 80) < 60;
9905
10081
  for (const [name, info] of entries) {
9906
10082
  const active = name === currentName ? " (active)" : "";
9907
10083
  const swatches = PALETTE_KEYS.map(
9908
10084
  (k) => colorSwatch(info.theme[k])
9909
10085
  ).join("");
10086
+ if (narrow) {
10087
+ const compact = PALETTE_KEYS.slice(0, 8).map((k) => colorSwatch(info.theme[k], 1)).join("");
10088
+ context2.writer.writeln(
10089
+ ` ${compact} ${context2.writer.wrapInColor(name, CliForegroundColor.Cyan)}${active}`
10090
+ );
10091
+ context2.writer.writeln(` ${info.description}`);
10092
+ continue;
10093
+ }
9910
10094
  const nameLabel = context2.writer.wrapInColor(
9911
10095
  name.padEnd(22),
9912
10096
  CliForegroundColor.Cyan
@@ -10608,37 +10792,106 @@ var CliPingCommandProcessor = class {
10608
10792
  var ICliEnvironment_TOKEN = "cli-environment";
10609
10793
  var CliEnvironment = class {
10610
10794
  constructor() {
10611
- this.vars = /* @__PURE__ */ new Map();
10612
- this.vars.set("SHELL", "/bin/sh");
10613
- this.vars.set("TERM", "xterm-256color");
10614
- this.vars.set("LANG", "en_US.UTF-8");
10615
- this.vars.set("PWD", "/");
10616
- this.vars.set("HOME", "/home/user");
10617
- this.vars.set("USER", "user");
10618
- this.vars.set("PATH", "/usr/local/bin:/usr/bin:/bin");
10795
+ this.defaults = /* @__PURE__ */ new Map();
10796
+ /** Variables computed on read; a user's own value wins over them. */
10797
+ this.bound = /* @__PURE__ */ new Map();
10798
+ this.profiles = /* @__PURE__ */ new Map();
10799
+ this.profileKey = () => "";
10800
+ this.defaults.set("SHELL", "/bin/sh");
10801
+ this.defaults.set("TERM", "xterm-256color");
10802
+ this.defaults.set("LANG", "en_US.UTF-8");
10803
+ this.defaults.set("PWD", "/");
10804
+ this.defaults.set("HOME", "/home/user");
10805
+ this.defaults.set("USER", "user");
10806
+ this.defaults.set("PATH", "/usr/local/bin:/usr/bin:/bin");
10807
+ }
10808
+ /** Compute a variable on every read; the seeded value is the fallback while it returns nothing. */
10809
+ bind(name, resolver) {
10810
+ this.bound.set(name, resolver);
10811
+ }
10812
+ /** Pick whose changes apply (the signed-in user's name, '' when signed out). */
10813
+ setProfileResolver(resolver) {
10814
+ this.profileKey = () => resolver() ?? "";
10815
+ }
10816
+ /** Restore saved profiles (replaces the ones in memory). */
10817
+ load(snapshot) {
10818
+ this.profiles.clear();
10819
+ for (const [key, profile] of Object.entries(snapshot ?? {})) {
10820
+ this.profiles.set(key, {
10821
+ vars: new Map(Object.entries(profile?.vars ?? {})),
10822
+ unset: new Set(profile?.unset ?? [])
10823
+ });
10824
+ }
10825
+ }
10826
+ snapshot() {
10827
+ const result = {};
10828
+ for (const [key, profile] of this.profiles) {
10829
+ if (!profile.vars.size && !profile.unset.size) continue;
10830
+ result[key] = { vars: Object.fromEntries(profile.vars), unset: [...profile.unset] };
10831
+ }
10832
+ return result;
10619
10833
  }
10620
10834
  get(name) {
10621
- return this.vars.get(name);
10835
+ const profile = this.profiles.get(this.profileKey());
10836
+ if (profile?.vars.has(name)) return profile.vars.get(name);
10837
+ if (profile?.unset.has(name)) return void 0;
10838
+ return this.bound.get(name)?.() || this.defaults.get(name);
10622
10839
  }
10623
10840
  set(name, value) {
10624
- this.vars.set(name, value);
10841
+ const profile = this.currentProfile();
10842
+ profile.unset.delete(name);
10843
+ profile.vars.set(name, value);
10844
+ this.onChange?.(this.snapshot());
10625
10845
  }
10626
10846
  unset(name) {
10627
- this.vars.delete(name);
10847
+ const profile = this.currentProfile();
10848
+ profile.vars.delete(name);
10849
+ if (this.defaults.has(name) || this.bound.has(name)) profile.unset.add(name);
10850
+ this.onChange?.(this.snapshot());
10628
10851
  }
10629
10852
  getAll() {
10853
+ const profile = this.profiles.get(this.profileKey());
10854
+ const names = /* @__PURE__ */ new Set([...this.defaults.keys(), ...this.bound.keys(), ...profile?.vars.keys() ?? []]);
10630
10855
  const result = {};
10631
- for (const [k, v] of this.vars) {
10632
- result[k] = v;
10856
+ for (const name of names) {
10857
+ const value = this.get(name);
10858
+ if (value !== void 0) result[name] = value;
10633
10859
  }
10634
10860
  return result;
10635
10861
  }
10636
10862
  has(name) {
10637
- return this.vars.has(name);
10863
+ return this.get(name) !== void 0;
10864
+ }
10865
+ currentProfile() {
10866
+ const key = this.profileKey();
10867
+ let profile = this.profiles.get(key);
10868
+ if (!profile) {
10869
+ profile = { vars: /* @__PURE__ */ new Map(), unset: /* @__PURE__ */ new Set() };
10870
+ this.profiles.set(key, profile);
10871
+ }
10872
+ return profile;
10638
10873
  }
10639
10874
  };
10640
10875
 
10641
10876
  // src/lib/processors/cli-env-command-processor.ts
10877
+ var ASSIGNMENT = /([A-Za-z_][A-Za-z0-9_]*)=("[^"]*"|'[^']*'|\S*)/y;
10878
+ var NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
10879
+ function parseAssignments(raw) {
10880
+ const result = [];
10881
+ for (const token of raw.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) ?? []) {
10882
+ ASSIGNMENT.lastIndex = 0;
10883
+ const match = ASSIGNMENT.exec(token);
10884
+ if (match && ASSIGNMENT.lastIndex === token.length) {
10885
+ const quoted = /^(["']).*\1$/.test(match[2]);
10886
+ result.push({ name: match[1], value: quoted ? match[2].slice(1, -1) : match[2] });
10887
+ } else if (NAME.test(token)) {
10888
+ result.push({ name: token });
10889
+ } else {
10890
+ return null;
10891
+ }
10892
+ }
10893
+ return result;
10894
+ }
10642
10895
  var CliExportCommandProcessor = class {
10643
10896
  constructor() {
10644
10897
  this.command = "export";
@@ -10646,6 +10899,21 @@ var CliExportCommandProcessor = class {
10646
10899
  this.author = DefaultLibraryAuthor;
10647
10900
  this.acceptsRawInput = true;
10648
10901
  this.metadata = { icon: "\u{1F4E6}", module: "system" };
10902
+ this.stateConfiguration = {
10903
+ storeName: "environment",
10904
+ initialState: { profiles: {} }
10905
+ };
10906
+ }
10907
+ /** Restore saved variables and save every later change (export, unset, VAR=value). */
10908
+ async initialize(context2) {
10909
+ const env = context2.services.get(ICliEnvironment_TOKEN);
10910
+ if (!(env instanceof CliEnvironment)) return;
10911
+ const store = context2.state;
10912
+ env.load(store.getState()?.profiles);
10913
+ env.onChange = (profiles) => {
10914
+ store.updateState({ profiles });
10915
+ void store.persist();
10916
+ };
10649
10917
  }
10650
10918
  async processCommand(command2, context2) {
10651
10919
  const env = context2.services.getRequired(
@@ -10662,20 +10930,21 @@ var CliExportCommandProcessor = class {
10662
10930
  }
10663
10931
  return;
10664
10932
  }
10665
- const match = raw.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
10666
- if (!match) {
10933
+ const assignments = parseAssignments(raw);
10934
+ if (!assignments?.length) {
10667
10935
  context2.writer.writeError(
10668
10936
  `export: invalid syntax: ${raw}`
10669
10937
  );
10670
10938
  context2.process.exit(1, { silent: true });
10671
10939
  return;
10672
10940
  }
10673
- const varName = match[1];
10674
- let varValue = match[2];
10675
- if (varValue.startsWith('"') && varValue.endsWith('"') || varValue.startsWith("'") && varValue.endsWith("'")) {
10676
- varValue = varValue.slice(1, -1);
10941
+ for (const { name, value } of assignments) {
10942
+ if (value !== void 0) {
10943
+ env.set(name, value);
10944
+ } else if (!env.has(name)) {
10945
+ env.set(name, "");
10946
+ }
10677
10947
  }
10678
- env.set(varName, varValue);
10679
10948
  }
10680
10949
  writeDescription(context2) {
10681
10950
  const { writer, translator: t } = context2;
@@ -10691,6 +10960,13 @@ var CliExportCommandProcessor = class {
10691
10960
  writer.writeln(
10692
10961
  ` ${writer.wrapInColor('export VAR="hello world"', CliForegroundColor.Cyan)} ${t.t("cli.export.set_spaces", "Set with spaces")}`
10693
10962
  );
10963
+ writer.writeln(
10964
+ ` ${writer.wrapInColor("export A=1 B=2", CliForegroundColor.Cyan)} ${t.t("cli.export.set_many", "Set several at once")}`
10965
+ );
10966
+ writer.writeln();
10967
+ writer.writeln(
10968
+ t.t("cli.export.saved", "Variables are saved for the signed-in user and used as $VAR or ${VAR} in commands.")
10969
+ );
10694
10970
  }
10695
10971
  };
10696
10972
  var CliUnsetCommandProcessor = class {
@@ -10705,16 +10981,15 @@ var CliUnsetCommandProcessor = class {
10705
10981
  const env = context2.services.getRequired(
10706
10982
  ICliEnvironment_TOKEN
10707
10983
  );
10708
- const varName = (command2.value || "").trim();
10709
- if (!varName) {
10984
+ const names = (command2.value || "").trim().split(/\s+/).filter(Boolean);
10985
+ if (!names.length) {
10710
10986
  context2.writer.writeError("unset: missing variable name");
10711
10987
  context2.process.exit(1, { silent: true });
10712
10988
  return;
10713
10989
  }
10714
- if (!env.has(varName)) {
10715
- return;
10990
+ for (const name of names) {
10991
+ if (env.has(name)) env.unset(name);
10716
10992
  }
10717
- env.unset(varName);
10718
10993
  }
10719
10994
  writeDescription(context2) {
10720
10995
  const { writer, translator: t } = context2;
@@ -10722,7 +10997,7 @@ var CliUnsetCommandProcessor = class {
10722
10997
  writer.writeln();
10723
10998
  writer.writeln(t.t("cli.common.usage", "Usage:"));
10724
10999
  writer.writeln(
10725
- ` ${writer.wrapInColor("unset VAR", CliForegroundColor.Cyan)}`
11000
+ ` ${writer.wrapInColor("unset VAR [VAR...]", CliForegroundColor.Cyan)}`
10726
11001
  );
10727
11002
  }
10728
11003
  };
@@ -10772,7 +11047,6 @@ var CliEnvCommandProcessor = class {
10772
11047
  );
10773
11048
  }
10774
11049
  };
10775
- var DEFAULT_FONT_SIZE = 20;
10776
11050
  var MIN_FONT_SIZE = 8;
10777
11051
  var MAX_FONT_SIZE = 40;
10778
11052
  var STEP = 2;
@@ -10785,7 +11059,7 @@ var CliFontSizeCommandProcessor = class {
10785
11059
  this.metadata = { icon: CliIcon.Settings, module: "system" };
10786
11060
  this.stateConfiguration = {
10787
11061
  storeName: "font-size",
10788
- initialState: { fontSize: DEFAULT_FONT_SIZE }
11062
+ initialState: {}
10789
11063
  };
10790
11064
  this.processors = [
10791
11065
  {
@@ -10804,9 +11078,9 @@ var CliFontSizeCommandProcessor = class {
10804
11078
  },
10805
11079
  {
10806
11080
  command: "reset",
10807
- description: `Reset font size to default (${DEFAULT_FONT_SIZE}px)`,
11081
+ description: "Reset font size to the default",
10808
11082
  processCommand: async (_, context2) => {
10809
- await this.setFontSize(context2, DEFAULT_FONT_SIZE);
11083
+ await this.resetFontSize(context2);
10810
11084
  }
10811
11085
  },
10812
11086
  {
@@ -10830,6 +11104,7 @@ var CliFontSizeCommandProcessor = class {
10830
11104
  ];
10831
11105
  }
10832
11106
  async initialize(context2) {
11107
+ this.hostFontSize = context2.terminal?.options?.fontSize;
10833
11108
  const state = context2.state.getState();
10834
11109
  if (state?.fontSize != null && context2.terminal?.options) {
10835
11110
  context2.terminal.options.fontSize = state.fontSize;
@@ -10850,7 +11125,7 @@ var CliFontSizeCommandProcessor = class {
10850
11125
  ` ${context2.writer.wrapInColor("font-size set <n>", CliForegroundColor.Cyan)} Set to exact size`
10851
11126
  );
10852
11127
  context2.writer.writeln(
10853
- ` ${context2.writer.wrapInColor("font-size reset", CliForegroundColor.Cyan)} Reset to default (${DEFAULT_FONT_SIZE}px)`
11128
+ ` ${context2.writer.wrapInColor("font-size reset", CliForegroundColor.Cyan)} Reset to default (${this.getDefault()}px)`
10854
11129
  );
10855
11130
  }
10856
11131
  getCurrent(context2) {
@@ -10859,7 +11134,19 @@ var CliFontSizeCommandProcessor = class {
10859
11134
  return fromTerminal;
10860
11135
  }
10861
11136
  const state = context2.state.getState();
10862
- return state?.fontSize ?? DEFAULT_FONT_SIZE;
11137
+ return state?.fontSize ?? this.getDefault();
11138
+ }
11139
+ getDefault() {
11140
+ return this.hostFontSize ?? defaultFontSize();
11141
+ }
11142
+ async resetFontSize(context2) {
11143
+ const size = this.getDefault();
11144
+ if (context2.terminal?.options) {
11145
+ context2.terminal.options.fontSize = size;
11146
+ }
11147
+ context2.state.updateState({ fontSize: void 0 });
11148
+ await context2.state.persist();
11149
+ context2.writer.writeSuccess(`Font size set to ${size}px`);
10863
11150
  }
10864
11151
  async setFontSize(context2, size) {
10865
11152
  const clamped = Math.min(MAX_FONT_SIZE, Math.max(MIN_FONT_SIZE, size));
@@ -11810,6 +12097,7 @@ var CliTimerManager = class {
11810
12097
  this.managedTimers.clear();
11811
12098
  }
11812
12099
  };
12100
+ var MIN_READABLE_COLUMN = 8;
11813
12101
  var CliTerminalWriter = class {
11814
12102
  constructor(terminal) {
11815
12103
  this.terminal = terminal;
@@ -11941,6 +12229,24 @@ var CliTerminalWriter = class {
11941
12229
  const indent = " ".repeat(level);
11942
12230
  this.writeln(`${indent}${text}`);
11943
12231
  }
12232
+ /** One block per row, header names as keys; used when a table cannot fit the terminal. */
12233
+ writeRecords(headers, rows) {
12234
+ const keyWidth = Math.max(...headers.map((h) => visibleLength(h)));
12235
+ rows.forEach((row, index) => {
12236
+ if (index > 0) this.write("\r\n");
12237
+ headers.forEach((header, i) => {
12238
+ const value = row[i] ?? "";
12239
+ if (!header.trim()) {
12240
+ if (value.trim()) this.write(`${value}\r
12241
+ `);
12242
+ return;
12243
+ }
12244
+ const key = header + " ".repeat(keyWidth - visibleLength(header));
12245
+ this.write(`${this.wrapInColor(key, CliForegroundColor.Yellow)} : ${value}\r
12246
+ `);
12247
+ });
12248
+ });
12249
+ }
11944
12250
  writeTable(headers, rows, options) {
11945
12251
  const cols = this.terminal.cols;
11946
12252
  const naturalWidths = headers.map(
@@ -11978,6 +12284,11 @@ var CliTerminalWriter = class {
11978
12284
  used++;
11979
12285
  }
11980
12286
  }
12287
+ const tooNarrow = colWidths.reduce((s, w) => s + w, 0) > Math.max(available, 0) || colWidths.some((w, i) => w < Math.min(naturalWidths[i], MIN_READABLE_COLUMN));
12288
+ if (tooNarrow) {
12289
+ this.writeRecords(headers, rows);
12290
+ return;
12291
+ }
11981
12292
  const truncateText = (text, maxWidth) => {
11982
12293
  const t = text ?? "";
11983
12294
  const vis = visibleLength(t);
@@ -12343,8 +12654,6 @@ var CliClipboard = class {
12343
12654
  }
12344
12655
  }
12345
12656
  };
12346
-
12347
- // src/lib/input/modes/input-mode-base.ts
12348
12657
  var InputModeBase = class {
12349
12658
  constructor(host, resolve) {
12350
12659
  this.host = host;
@@ -12413,6 +12722,21 @@ var InputModeBase = class {
12413
12722
  }
12414
12723
  this.host.terminal.write(buf);
12415
12724
  }
12725
+ /**
12726
+ * Cut a line to the terminal width. Lines redrawn in place must stay on one row:
12727
+ * a wrapped line takes two rows and breaks the cursor-up arithmetic of the redraw.
12728
+ */
12729
+ /** A prompt label without a trailing colon, for modes that append their own ": ". */
12730
+ label(promptText) {
12731
+ return promptText.replace(/:\s*$/, "");
12732
+ }
12733
+ fitLine(text) {
12734
+ return truncateToWidth(text, Math.max(1, this.host.getTerminalCols() - 1));
12735
+ }
12736
+ /** Start a new row and write `text` cut to the terminal width. */
12737
+ writeRow(text) {
12738
+ this.host.terminal.write("\r\n" + this.fitLine(text));
12739
+ }
12416
12740
  /**
12417
12741
  * Render a dimmed help bar below the current line.
12418
12742
  */
@@ -12420,7 +12744,7 @@ var InputModeBase = class {
12420
12744
  this.extraLines++;
12421
12745
  this.host.terminal.write(
12422
12746
  `\r
12423
- \x1B[2m${text}\x1B[0m\x1B[${this.extraLines}A`
12747
+ ${this.fitLine(` \x1B[2m${text}\x1B[0m`)}\x1B[${this.extraLines}A`
12424
12748
  );
12425
12749
  }
12426
12750
  /**
@@ -12430,7 +12754,7 @@ var InputModeBase = class {
12430
12754
  this.extraLines++;
12431
12755
  this.host.terminal.write(
12432
12756
  `\r
12433
- \x1B[31m\u2718 ${message}\x1B[0m\x1B[${this.extraLines}A`
12757
+ ${this.fitLine(` \x1B[31m\u2718 ${message}\x1B[0m`)}\x1B[${this.extraLines}A`
12434
12758
  );
12435
12759
  }
12436
12760
  /**
@@ -12580,6 +12904,7 @@ var ConfirmInputMode = class extends InputModeBase {
12580
12904
  async handleInput(data) {
12581
12905
  if (data === "\r") {
12582
12906
  if (this.buffer === "") {
12907
+ this.host.terminal.write(this.defaultValue ? "y" : "n");
12583
12908
  this.resolveAndPop(this.defaultValue);
12584
12909
  } else {
12585
12910
  const lower = this.buffer.toLowerCase();
@@ -12761,7 +13086,7 @@ var SelectInputMode = class extends InputModeBase {
12761
13086
  const selectedOpt = this.options.find((o) => o.value === value);
12762
13087
  const label = selectedOpt ? selectedOpt.label : value;
12763
13088
  this.host.terminal.write("\x1B[2K\r");
12764
- this.host.terminal.write(`\x1B[32m\u2714\x1B[0m ${this.promptText} \x1B[36m${label}\x1B[0m`);
13089
+ this.host.terminal.write(`\x1B[32m\u2714\x1B[0m ${this.label(this.promptText)}: \x1B[36m${label}\x1B[0m`);
12765
13090
  this.host.terminal.write("\x1B[?25h");
12766
13091
  super.resolveAndPop(value);
12767
13092
  }
@@ -12771,7 +13096,7 @@ var SelectInputMode = class extends InputModeBase {
12771
13096
  abort() {
12772
13097
  this.clearRenderedLines();
12773
13098
  this.host.terminal.write("\x1B[2K\r");
12774
- this.host.terminal.write(`\x1B[33m\u2718\x1B[0m ${this.promptText} \x1B[2mcancelled\x1B[0m`);
13099
+ this.host.terminal.write(`\x1B[33m\u2718\x1B[0m ${this.label(this.promptText)}: \x1B[2mcancelled\x1B[0m`);
12775
13100
  this.host.terminal.write("\x1B[?25h");
12776
13101
  super.abort();
12777
13102
  }
@@ -12932,15 +13257,15 @@ var SelectInputMode = class extends InputModeBase {
12932
13257
  if (this.selectOptions?.searchable) {
12933
13258
  if (this.filter.length > 0) {
12934
13259
  this.host.terminal.write(
12935
- `\x1B[36m?\x1B[0m ${this.promptText}: ${this.filter}`
13260
+ this.fitLine(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}: ${this.filter}`)
12936
13261
  );
12937
13262
  } else {
12938
13263
  this.host.terminal.write(
12939
- `\x1B[36m?\x1B[0m ${this.promptText}: \x1B[2mType to filter...\x1B[0m`
13264
+ this.fitLine(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}: \x1B[2mType to filter...\x1B[0m`)
12940
13265
  );
12941
13266
  }
12942
13267
  } else {
12943
- this.host.terminal.write(`\x1B[36m?\x1B[0m ${this.promptText}:`);
13268
+ this.host.terminal.write(this.fitLine(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}:`));
12944
13269
  }
12945
13270
  }
12946
13271
  /**
@@ -12955,17 +13280,15 @@ var SelectInputMode = class extends InputModeBase {
12955
13280
  this.scrollOffset + this.maxVisible
12956
13281
  );
12957
13282
  if (visibleStart > 0) {
12958
- this.host.terminal.write(`\r
12959
- \x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
13283
+ this.writeRow(`\x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
12960
13284
  this.renderedLines++;
12961
13285
  }
12962
13286
  let selectableIdx = 0;
12963
13287
  for (const item of items) {
12964
13288
  if (item.type === "group-header") {
12965
13289
  if (this.isGroupVisible(item.groupName, items, visibleStart, visibleEnd)) {
12966
- this.host.terminal.write(
12967
- `\r
12968
- \x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
13290
+ this.writeRow(
13291
+ `\x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
12969
13292
  );
12970
13293
  this.renderedLines++;
12971
13294
  }
@@ -12988,8 +13311,7 @@ var SelectInputMode = class extends InputModeBase {
12988
13311
  }
12989
13312
  const remaining = selectables.length - visibleEnd;
12990
13313
  if (remaining > 0) {
12991
- this.host.terminal.write(`\r
12992
- \x1B[2m \u2193 ${remaining} more below\x1B[0m`);
13314
+ this.writeRow(`\x1B[2m \u2193 ${remaining} more below\x1B[0m`);
12993
13315
  this.renderedLines++;
12994
13316
  }
12995
13317
  }
@@ -13031,19 +13353,16 @@ var SelectInputMode = class extends InputModeBase {
13031
13353
  const label = this.highlightMatch(opt.label);
13032
13354
  const desc = opt.description ? ` \x1B[2;3m\u2014 ${opt.description}\x1B[0m` : "";
13033
13355
  if (opt.disabled) {
13034
- this.host.terminal.write(
13035
- `\r
13036
- \x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
13356
+ this.writeRow(
13357
+ ` \x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
13037
13358
  );
13038
13359
  } else if (isSelected) {
13039
- this.host.terminal.write(
13040
- `\r
13041
- \x1B[48;5;24m\x1B[38;5;117m\u276F ${label}${desc}\x1B[0m`
13360
+ this.writeRow(
13361
+ ` \x1B[48;5;24m\x1B[38;5;117m\u276F ${label}${desc}\x1B[0m`
13042
13362
  );
13043
13363
  } else {
13044
- this.host.terminal.write(
13045
- `\r
13046
- ${label}${desc}`
13364
+ this.writeRow(
13365
+ ` ${label}${desc}`
13047
13366
  );
13048
13367
  }
13049
13368
  }
@@ -13077,8 +13396,7 @@ var SelectInputMode = class extends InputModeBase {
13077
13396
  } else {
13078
13397
  help = "\u2191/\u2193 navigate \xB7 enter to select \xB7 esc to cancel";
13079
13398
  }
13080
- this.host.terminal.write(`\r
13081
- \x1B[2m${help}\x1B[0m`);
13399
+ this.writeRow(` \x1B[2m${help}\x1B[0m`);
13082
13400
  this.renderedLines++;
13083
13401
  }
13084
13402
  };
@@ -13119,7 +13437,7 @@ var InlineSelectInputMode = class extends InputModeBase {
13119
13437
  const selectedOpt = this.selectableOptions.find((o) => o.value === value);
13120
13438
  const label = selectedOpt ? selectedOpt.label : value;
13121
13439
  this.host.terminal.write("\x1B[2K\r");
13122
- this.host.terminal.write(`\x1B[32m\u2714\x1B[0m ${this.promptText}: \x1B[36m${label}\x1B[0m`);
13440
+ this.host.terminal.write(`\x1B[32m\u2714\x1B[0m ${this.label(this.promptText)}: \x1B[36m${label}\x1B[0m`);
13123
13441
  this.host.terminal.write("\x1B[?25h");
13124
13442
  super.resolveAndPop(value);
13125
13443
  }
@@ -13129,7 +13447,7 @@ var InlineSelectInputMode = class extends InputModeBase {
13129
13447
  abort() {
13130
13448
  this.clearExtraLines();
13131
13449
  this.host.terminal.write("\x1B[2K\r");
13132
- this.host.terminal.write(`\x1B[33m\u2718\x1B[0m ${this.promptText}: \x1B[2mcancelled\x1B[0m`);
13450
+ this.host.terminal.write(`\x1B[33m\u2718\x1B[0m ${this.label(this.promptText)}: \x1B[2mcancelled\x1B[0m`);
13133
13451
  this.host.terminal.write("\x1B[?25h");
13134
13452
  super.abort();
13135
13453
  }
@@ -13169,13 +13487,13 @@ var InlineSelectInputMode = class extends InputModeBase {
13169
13487
  * Get the prompt prefix string (without ANSI escapes for width calculation).
13170
13488
  */
13171
13489
  getPromptPrefix() {
13172
- return `? ${this.promptText}: `;
13490
+ return `? ${this.label(this.promptText)}: `;
13173
13491
  }
13174
13492
  /**
13175
13493
  * Get the rendered prompt prefix (with ANSI color codes).
13176
13494
  */
13177
13495
  getRenderedPromptPrefix() {
13178
- return `\x1B[36m?\x1B[0m ${this.promptText}: `;
13496
+ return `\x1B[36m?\x1B[0m ${this.label(this.promptText)}: `;
13179
13497
  }
13180
13498
  /**
13181
13499
  * Calculate the width needed for a single option.
@@ -13372,7 +13690,7 @@ var MultiSelectInputMode = class extends InputModeBase {
13372
13690
  });
13373
13691
  const summary = labels.length > 0 ? labels.join(", ") : "none";
13374
13692
  this.host.terminal.write("\x1B[2K\r");
13375
- this.host.terminal.write(`\x1B[32m\u2714\x1B[0m ${this.promptText} \x1B[36m${summary}\x1B[0m`);
13693
+ this.host.terminal.write(`\x1B[32m\u2714\x1B[0m ${this.label(this.promptText)}: \x1B[36m${summary}\x1B[0m`);
13376
13694
  this.host.terminal.write("\x1B[?25h");
13377
13695
  super.resolveAndPop(value);
13378
13696
  }
@@ -13382,7 +13700,7 @@ var MultiSelectInputMode = class extends InputModeBase {
13382
13700
  abort() {
13383
13701
  this.clearRenderedLines();
13384
13702
  this.host.terminal.write("\x1B[2K\r");
13385
- this.host.terminal.write(`\x1B[33m\u2718\x1B[0m ${this.promptText} \x1B[2mcancelled\x1B[0m`);
13703
+ this.host.terminal.write(`\x1B[33m\u2718\x1B[0m ${this.label(this.promptText)}: \x1B[2mcancelled\x1B[0m`);
13386
13704
  this.host.terminal.write("\x1B[?25h");
13387
13705
  super.abort();
13388
13706
  }
@@ -13556,15 +13874,15 @@ var MultiSelectInputMode = class extends InputModeBase {
13556
13874
  if (this.selectOptions?.searchable) {
13557
13875
  if (this.filter.length > 0) {
13558
13876
  this.host.terminal.write(
13559
- `\x1B[36m?\x1B[0m ${this.promptText}: ${this.filter}`
13877
+ this.fitLine(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}: ${this.filter}`)
13560
13878
  );
13561
13879
  } else {
13562
13880
  this.host.terminal.write(
13563
- `\x1B[36m?\x1B[0m ${this.promptText}: \x1B[2mType to filter...\x1B[0m`
13881
+ this.fitLine(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}: \x1B[2mType to filter...\x1B[0m`)
13564
13882
  );
13565
13883
  }
13566
13884
  } else {
13567
- this.host.terminal.write(`\x1B[36m?\x1B[0m ${this.promptText}:`);
13885
+ this.host.terminal.write(this.fitLine(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}:`));
13568
13886
  }
13569
13887
  }
13570
13888
  /**
@@ -13579,17 +13897,15 @@ var MultiSelectInputMode = class extends InputModeBase {
13579
13897
  this.scrollOffset + this.maxVisible
13580
13898
  );
13581
13899
  if (visibleStart > 0) {
13582
- this.host.terminal.write(`\r
13583
- \x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
13900
+ this.writeRow(`\x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
13584
13901
  this.renderedLines++;
13585
13902
  }
13586
13903
  let selectableIdx = 0;
13587
13904
  for (const item of items) {
13588
13905
  if (item.type === "group-header") {
13589
13906
  if (this.isGroupVisible(item.groupName, items, visibleStart, visibleEnd)) {
13590
- this.host.terminal.write(
13591
- `\r
13592
- \x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
13907
+ this.writeRow(
13908
+ `\x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
13593
13909
  );
13594
13910
  this.renderedLines++;
13595
13911
  }
@@ -13612,8 +13928,7 @@ var MultiSelectInputMode = class extends InputModeBase {
13612
13928
  }
13613
13929
  const remaining = selectables.length - visibleEnd;
13614
13930
  if (remaining > 0) {
13615
- this.host.terminal.write(`\r
13616
- \x1B[2m \u2193 ${remaining} more below\x1B[0m`);
13931
+ this.writeRow(`\x1B[2m \u2193 ${remaining} more below\x1B[0m`);
13617
13932
  this.renderedLines++;
13618
13933
  }
13619
13934
  }
@@ -13658,19 +13973,16 @@ var MultiSelectInputMode = class extends InputModeBase {
13658
13973
  const checkbox = isChecked ? "\x1B[32m\u25C9\x1B[0m" : "\x1B[2m\u25CB\x1B[0m";
13659
13974
  if (opt.disabled) {
13660
13975
  const disabledCheckbox = isChecked ? "\x1B[2m\u25C9\x1B[0m" : "\x1B[2m\u25CB\x1B[0m";
13661
- this.host.terminal.write(
13662
- `\r
13663
- ${disabledCheckbox} \x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
13976
+ this.writeRow(
13977
+ ` ${disabledCheckbox} \x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
13664
13978
  );
13665
13979
  } else if (isSelected) {
13666
- this.host.terminal.write(
13667
- `\r
13668
- \x1B[48;5;24m\x1B[38;5;117m\u276F ${checkbox} ${label}${desc}\x1B[0m`
13980
+ this.writeRow(
13981
+ ` \x1B[48;5;24m\x1B[38;5;117m\u276F ${checkbox} ${label}${desc}\x1B[0m`
13669
13982
  );
13670
13983
  } else {
13671
- this.host.terminal.write(
13672
- `\r
13673
- ${checkbox} ${label}${desc}`
13984
+ this.writeRow(
13985
+ ` ${checkbox} ${label}${desc}`
13674
13986
  );
13675
13987
  }
13676
13988
  }
@@ -13705,8 +14017,7 @@ var MultiSelectInputMode = class extends InputModeBase {
13705
14017
  } else {
13706
14018
  help = `${checkedCount} selected \xB7 space to toggle \xB7 a to select all \xB7 enter to confirm`;
13707
14019
  }
13708
- this.host.terminal.write(`\r
13709
- \x1B[2m${help}\x1B[0m`);
14020
+ this.writeRow(` \x1B[2m${help}\x1B[0m`);
13710
14021
  this.renderedLines++;
13711
14022
  }
13712
14023
  };
@@ -13906,13 +14217,13 @@ var FileInputMode = class extends InputModeBase {
13906
14217
  this.waiting = false;
13907
14218
  if (!results || this.isResolved) {
13908
14219
  this.host.terminal.write("\x1B[2K\r");
13909
- this.host.writeToTerminal(`\x1B[36m?\x1B[0m ${this.promptText}: \x1B[2m(cancelled)\x1B[0m\r
14220
+ this.host.writeToTerminal(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}: \x1B[2m(cancelled)\x1B[0m\r
13910
14221
  `);
13911
14222
  if (!this.isResolved) this.abort();
13912
14223
  return;
13913
14224
  }
13914
14225
  this.host.terminal.write("\x1B[2K\r");
13915
- this.host.writeToTerminal(`\x1B[36m?\x1B[0m ${this.promptText}:\r
14226
+ this.host.writeToTerminal(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}:\r
13916
14227
  `);
13917
14228
  let totalSize = 0;
13918
14229
  for (const file of results) {
@@ -13930,7 +14241,7 @@ var FileInputMode = class extends InputModeBase {
13930
14241
  this.waiting = false;
13931
14242
  if (this.isResolved) return;
13932
14243
  this.host.terminal.write("\x1B[2K\r");
13933
- this.host.writeToTerminal(`\x1B[36m?\x1B[0m ${this.promptText}: \x1B[31m(error)\x1B[0m\r
14244
+ this.host.writeToTerminal(`\x1B[36m?\x1B[0m ${this.label(this.promptText)}: \x1B[31m(error)\x1B[0m\r
13934
14245
  `);
13935
14246
  this.abort();
13936
14247
  }
@@ -15400,7 +15711,7 @@ function substituteVars(input, variables) {
15400
15711
  );
15401
15712
  return result;
15402
15713
  }
15403
- function expandEnvironmentVars(command2, context2) {
15714
+ function expandEnvironmentVars(command2, context2, lastExitCode) {
15404
15715
  const env = context2.services.get(ICliEnvironment_TOKEN);
15405
15716
  if (!env) {
15406
15717
  return command2;
@@ -15408,6 +15719,9 @@ function expandEnvironmentVars(command2, context2) {
15408
15719
  const parts = command2.split("'");
15409
15720
  for (let i = 0; i < parts.length; i++) {
15410
15721
  if (i % 2 === 0) {
15722
+ if (lastExitCode !== void 0) {
15723
+ parts[i] = parts[i].replace(/\$\?/g, String(lastExitCode));
15724
+ }
15411
15725
  parts[i] = parts[i].replace(
15412
15726
  /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g,
15413
15727
  (_, name) => env.get(name) ?? ""
@@ -15416,17 +15730,30 @@ function expandEnvironmentVars(command2, context2) {
15416
15730
  /\$([A-Za-z_][A-Za-z0-9_]*)/g,
15417
15731
  (_, name) => env.get(name) ?? ""
15418
15732
  );
15733
+ const home = env.get("HOME");
15734
+ if (home) {
15735
+ parts[i] = parts[i].replace(
15736
+ /(^|\s)~(?=\/|\s|$)/g,
15737
+ (match, before, offset) => i > 0 && offset === 0 && !before ? match : `${before}${home}`
15738
+ );
15739
+ }
15419
15740
  }
15420
15741
  }
15421
15742
  return parts.join("'");
15422
15743
  }
15423
15744
 
15424
15745
  // src/lib/executor/cli-command-executor.ts
15746
+ function toExitStatus(code) {
15747
+ if (code === void 0) return 0;
15748
+ return code < 0 ? 1 : code;
15749
+ }
15425
15750
  var CliCommandExecutor = class {
15426
15751
  constructor(registry) {
15427
15752
  this.registry = registry;
15428
15753
  this.commandParser = new CommandParser();
15429
15754
  this.globalParameters = [];
15755
+ /** Exit status of the last command, expanded as `$?` (0 = success). */
15756
+ this.lastExitCode = 0;
15430
15757
  this.registerGlobalParameter(versionGlobalParameter);
15431
15758
  this.registerGlobalParameter(helpGlobalParameter);
15432
15759
  this.registerGlobalParameter(contextGlobalParameter);
@@ -15530,6 +15857,7 @@ var CliCommandExecutor = class {
15530
15857
  rootContext
15531
15858
  );
15532
15859
  lastExitSuccess = context2.process.exitCode === void 0 || context2.process.exitCode === 0;
15860
+ this.lastExitCode = toExitStatus(context2.process.exitCode);
15533
15861
  rootContext.lastCommandResult = {
15534
15862
  command: part.value,
15535
15863
  success: lastExitSuccess
@@ -15537,6 +15865,7 @@ var CliCommandExecutor = class {
15537
15865
  pipelineData = context2.process.data;
15538
15866
  } catch (e) {
15539
15867
  lastExitSuccess = false;
15868
+ this.lastExitCode = 1;
15540
15869
  rootContext.lastCommandResult = {
15541
15870
  command: part.value,
15542
15871
  success: false
@@ -15552,7 +15881,7 @@ var CliCommandExecutor = class {
15552
15881
  }
15553
15882
  async executeSingleCommand(command2, data, context2) {
15554
15883
  const process = context2.process;
15555
- command2 = expandEnvironmentVars(command2, context2);
15884
+ command2 = expandEnvironmentVars(command2, context2, this.lastExitCode);
15556
15885
  const assignMatch = command2.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
15557
15886
  if (assignMatch) {
15558
15887
  const env = context2.services.get(ICliEnvironment_TOKEN);
@@ -16608,30 +16937,6 @@ var CliDefaultPingServerService = class {
16608
16937
  return new Promise((resolve) => setTimeout(resolve, 2e3));
16609
16938
  }
16610
16939
  };
16611
- var CliDragDropService = class {
16612
- constructor(_container) {
16613
- this._container = _container;
16614
- this._subject = new Subject();
16615
- this._dragOver = (e) => e.preventDefault();
16616
- this._drop = (e) => {
16617
- e.preventDefault();
16618
- const files = Array.from(e.dataTransfer?.files ?? []);
16619
- if (files.length > 0) {
16620
- this._subject.next(files);
16621
- }
16622
- };
16623
- this._container.addEventListener("dragover", this._dragOver);
16624
- this._container.addEventListener("drop", this._drop);
16625
- }
16626
- get onFileDrop() {
16627
- return this._subject.asObservable();
16628
- }
16629
- destroy() {
16630
- this._container.removeEventListener("dragover", this._dragOver);
16631
- this._container.removeEventListener("drop", this._drop);
16632
- this._subject.complete();
16633
- }
16634
- };
16635
16940
 
16636
16941
  // src/lib/services/cli-permission-registry.ts
16637
16942
  var CliPermissionRegistry = class {
@@ -16656,62 +16961,6 @@ var CliPermissionRegistry = class {
16656
16961
  }
16657
16962
  };
16658
16963
 
16659
- // src/lib/addons/overlay.ts
16660
- var OverlayAddon = class {
16661
- constructor() {
16662
- this.overlayNode = document.createElement("div");
16663
- this.overlayNode.style.cssText = `border-radius: 15px;
16664
- font-size: xx-large;
16665
- opacity: 0.75;
16666
- padding: 0.2em 0.5em 0.2em 0.5em;
16667
- position: absolute;
16668
- -webkit-user-select: none;
16669
- -webkit-transition: opacity 180ms ease-in;
16670
- -moz-user-select: none;
16671
- -moz-transition: opacity 180ms ease-in;`;
16672
- this.overlayNode.addEventListener(
16673
- "mousedown",
16674
- (e) => {
16675
- e.preventDefault();
16676
- e.stopPropagation();
16677
- },
16678
- true
16679
- );
16680
- }
16681
- activate(terminal) {
16682
- this.terminal = terminal;
16683
- }
16684
- dispose() {
16685
- }
16686
- showOverlay(msg, timeout) {
16687
- const { terminal, overlayNode } = this;
16688
- if (!terminal.element) return;
16689
- overlayNode.style.color = "#101010";
16690
- overlayNode.style.backgroundColor = "#f0f0f0";
16691
- overlayNode.textContent = msg;
16692
- overlayNode.style.opacity = "0.75";
16693
- if (!overlayNode.parentNode) {
16694
- terminal.element.appendChild(overlayNode);
16695
- }
16696
- const divSize = terminal.element.getBoundingClientRect();
16697
- const overlaySize = overlayNode.getBoundingClientRect();
16698
- overlayNode.style.top = (divSize.height - overlaySize.height) / 2 + "px";
16699
- overlayNode.style.left = (divSize.width - overlaySize.width) / 2 + "px";
16700
- if (this.overlayTimeout) clearTimeout(this.overlayTimeout);
16701
- if (!timeout) return;
16702
- this.overlayTimeout = window.setTimeout(() => {
16703
- overlayNode.style.opacity = "0";
16704
- this.overlayTimeout = window.setTimeout(() => {
16705
- if (overlayNode.parentNode) {
16706
- overlayNode.parentNode.removeChild(overlayNode);
16707
- }
16708
- this.overlayTimeout = void 0;
16709
- overlayNode.style.opacity = "0.75";
16710
- }, 200);
16711
- }, timeout || 1500);
16712
- }
16713
- };
16714
-
16715
16964
  // src/lib/storage/cli-key-value-store.ts
16716
16965
  var CliKeyValueStore = class {
16717
16966
  constructor() {
@@ -17886,61 +18135,6 @@ function createServerModule() {
17886
18135
  services: []
17887
18136
  };
17888
18137
  }
17889
- function getTerminalOptions(userOptions) {
17890
- return {
17891
- cursorBlink: true,
17892
- allowProposedApi: true,
17893
- fontSize: 20,
17894
- theme: DefaultThemes.default,
17895
- convertEol: true,
17896
- ...userOptions ?? {}
17897
- };
17898
- }
17899
- function initializeTerminal(container, opts) {
17900
- const terminal = new Terminal(opts);
17901
- const fitAddon = new FitAddon();
17902
- terminal.loadAddon(fitAddon);
17903
- terminal.loadAddon(new WebLinksAddon());
17904
- terminal.loadAddon(new OverlayAddon());
17905
- terminal.loadAddon(new Unicode11Addon());
17906
- const serializeAddon = new SerializeAddon();
17907
- terminal.loadAddon(serializeAddon);
17908
- terminal.open(container);
17909
- fitAddon.fit();
17910
- requestAnimationFrame(() => fitAddon.fit());
17911
- if (document.fonts?.ready) {
17912
- document.fonts.ready.then(() => {
17913
- requestAnimationFrame(() => fitAddon.fit());
17914
- });
17915
- }
17916
- container.classList.add("terminal-container");
17917
- container.style.background = opts.theme?.background ?? "#000";
17918
- const wheelListener = (e) => e.preventDefault();
17919
- container.addEventListener("wheel", wheelListener, { passive: false });
17920
- terminal.focus();
17921
- const dragDropService = new CliDragDropService(container);
17922
- return { terminal, fitAddon, serializeAddon, dragDropService, wheelListener };
17923
- }
17924
- var LAYOUT_TIMEOUT_MS = 1e4;
17925
- function waitForLayout(container) {
17926
- return new Promise((resolve, reject) => {
17927
- const deadline = Date.now() + LAYOUT_TIMEOUT_MS;
17928
- const check = () => {
17929
- if (container.offsetWidth > 0 && container.offsetHeight > 0) {
17930
- resolve();
17931
- return;
17932
- }
17933
- if (Date.now() >= deadline) {
17934
- reject(new Error(
17935
- `CliEngine.start(): container has zero dimensions after ${LAYOUT_TIMEOUT_MS}ms. Ensure the container element is visible and laid out before calling start().`
17936
- ));
17937
- return;
17938
- }
17939
- requestAnimationFrame(check);
17940
- };
17941
- check();
17942
- });
17943
- }
17944
18138
 
17945
18139
  // src/lib/editor/syntax/registry.ts
17946
18140
  var SyntaxHighlighterRegistry = class {
@@ -18332,6 +18526,14 @@ var CliEngine = class {
18332
18526
  { ...this.options ?? {}, terminalOptions: terminalOpts }
18333
18527
  );
18334
18528
  this.executionContext.initializeTerminalListeners();
18529
+ const environment = services.get(ICliEnvironment_TOKEN);
18530
+ if (environment instanceof CliEnvironment) {
18531
+ const ctx = this.executionContext;
18532
+ environment.bind("USER", () => ctx.userSession?.user.name);
18533
+ environment.bind("HOME", () => ctx.userSession?.user.homeDir);
18534
+ environment.bind("PWD", () => ctx.promptPathProvider?.());
18535
+ environment.setProfileResolver(() => ctx.userSession?.user.name);
18536
+ }
18335
18537
  this.executionContext.backgroundServices.setProcessRegistry(processRegistry);
18336
18538
  services.set([{
18337
18539
  provide: CliBackgroundServiceRegistry_TOKEN,
@@ -18922,6 +19124,6 @@ function createInMemoryKvStore() {
18922
19124
  };
18923
19125
  }
18924
19126
 
18925
- export { API_VERSION, CLi_Name_Art, CapturingTerminalWriter, CliAliasCommandProcessor, CliArgsParser, CliBackgroundServiceRegistry_TOKEN, CliBoot, CliCalCommandProcessor, CliCaptureCommandProcessor, CliClearCommandProcessor, CliClipboard, CliClipboardCommandProcessor, CliColorCommandProcessor, CliCommandExecutionContext, CliCommandExecutor, CliCommandHistory, CliCommandHistory_TOKEN, CliCommandProcessorRegistry, CliConfigureCommandProcessor, CliConvertCommandProcessor, CliDebugCommandProcessor, CliDefaultPingServerService, CliDiffCommandProcessor, CliDragDropService, CliEchoCommandProcessor, CliEngine, CliEnvCommandProcessor, CliEnvironment, CliEvalCommandProcessor, CliExecutionContext, CliExecutionProcess, CliExportCommandProcessor, CliFeedbackCommandProcessor, CliFontSizeCommandProcessor, CliFullScreenManager, CliHelpCommandProcessor, CliHistoryCommandProcessor, CliHotKeysCommandProcessor, CliHtopCommandProcessor, CliHttpClient, CliInputReader, CliJsonCommandProcessor, CliKeyValueStore, CliKeyValueStore_TOKEN, CliKillCommandProcessor, CliLogger, CliLoremCommandProcessor, CliModuleRegistry_TOKEN, CliNanoCommandProcessor, CliNotifier, CliOpenCommandProcessor, CliPackageManagerService, CliPackageManagerService_TOKEN, CliPackagesCommandProcessor, CliPermissionRegistry, CliPingCommandProcessor, CliProcessRegistry, CliProcessRegistry_TOKEN, CliProcessorsRegistry_TOKEN, CliPsCommandProcessor, CliRandomCommandProcessor, CliScreenCommandProcessor, CliSeqCommandProcessor, CliServerCommandProcessor, CliServerConnection, CliServerManager, CliServerManager_TOKEN, CliServerMultiProxyProcessor, CliServerProxyProcessor, CliServiceContainer, CliServicesCommandProcessor, CliSleepCommandProcessor, CliSnippetCommandProcessor, CliSshCommandProcessor, CliStateStore, CliStateStoreManager, CliStateStoreManager_TOKEN, CliTerminalProgressBar, CliTerminalSpinner, CliTerminalTextAnimator, CliTerminalWriter, CliTestHarness, CliThemeCommandProcessor, CliTimeCommandProcessor, CliTimerManager, CliTimestampCommandProcessor, CliUnAliasCommandProcessor, CliUnameCommandProcessor, CliUnsetCommandProcessor, CliUptimeCommandProcessor, CliVersionCommandProcessor, CliYesCommandProcessor, CommandParser, ICliEnvironment_TOKEN, ICliPingServerService_TOKEN, JsFallbackAccelerator, LIBRARY_VERSION, OverlayAddon, ProcessExitedError, ScriptLoaderService, SyntaxHighlighterRegistry_TOKEN, appendOutputToFile, appendStderrToFile, builtinProcessors, computeDiff, contextGlobalParameter, createServerModule, describeShellClose, executeOnServer, expandEnvironmentVars, formatDiff, getAccelerator, getCliNameArt, getGreetingBasedOnTime, getTerminalOptions, groupBy, helpGlobalParameter, hotkeysInfo, initWasmAccelerator, initializeServices, initializeTerminal, isWasmAccelerated, miscProcessors, openLink, reconcileArgs, renderServerResponse, renderSingleOutput, substituteVars, systemProcessors, themeInfos, themes, tryExecuteScript, versionGlobalParameter, waitForLayout, welcomeModule, writeOutputToFile, writeStderrToFile };
19127
+ export { API_VERSION, CLi_Name_Art, CapturingTerminalWriter, CliAliasCommandProcessor, CliArgsParser, CliBackgroundServiceRegistry_TOKEN, CliBoot, CliCalCommandProcessor, CliCaptureCommandProcessor, CliClearCommandProcessor, CliClipboard, CliClipboardCommandProcessor, CliColorCommandProcessor, CliCommandExecutionContext, CliCommandExecutor, CliCommandHistory, CliCommandHistory_TOKEN, CliCommandProcessorRegistry, CliConfigureCommandProcessor, CliConvertCommandProcessor, CliDebugCommandProcessor, CliDefaultPingServerService, CliDiffCommandProcessor, CliDragDropService, CliEchoCommandProcessor, CliEngine, CliEnvCommandProcessor, CliEnvironment, CliEvalCommandProcessor, CliExecutionContext, CliExecutionProcess, CliExportCommandProcessor, CliFeedbackCommandProcessor, CliFontSizeCommandProcessor, CliFullScreenManager, CliHelpCommandProcessor, CliHistoryCommandProcessor, CliHotKeysCommandProcessor, CliHtopCommandProcessor, CliHttpClient, CliInputReader, CliJsonCommandProcessor, CliKeyValueStore, CliKeyValueStore_TOKEN, CliKillCommandProcessor, CliLogger, CliLoremCommandProcessor, CliModuleRegistry_TOKEN, CliNanoCommandProcessor, CliNotifier, CliOpenCommandProcessor, CliPackageManagerService, CliPackageManagerService_TOKEN, CliPackagesCommandProcessor, CliPermissionRegistry, CliPingCommandProcessor, CliProcessRegistry, CliProcessRegistry_TOKEN, CliProcessorsRegistry_TOKEN, CliPsCommandProcessor, CliRandomCommandProcessor, CliScreenCommandProcessor, CliSeqCommandProcessor, CliServerCommandProcessor, CliServerConnection, CliServerManager, CliServerManager_TOKEN, CliServerMultiProxyProcessor, CliServerProxyProcessor, CliServiceContainer, CliServicesCommandProcessor, CliSleepCommandProcessor, CliSnippetCommandProcessor, CliSshCommandProcessor, CliStateStore, CliStateStoreManager, CliStateStoreManager_TOKEN, CliTerminalProgressBar, CliTerminalSpinner, CliTerminalTextAnimator, CliTerminalWriter, CliTestHarness, CliThemeCommandProcessor, CliTimeCommandProcessor, CliTimerManager, CliTimestampCommandProcessor, CliUnAliasCommandProcessor, CliUnameCommandProcessor, CliUnsetCommandProcessor, CliUptimeCommandProcessor, CliVersionCommandProcessor, CliYesCommandProcessor, CommandParser, ICliEnvironment_TOKEN, ICliPingServerService_TOKEN, JsFallbackAccelerator, LIBRARY_VERSION, OverlayAddon, ProcessExitedError, ScriptLoaderService, SyntaxHighlighterRegistry_TOKEN, appendOutputToFile, appendStderrToFile, builtinProcessors, computeDiff, contextGlobalParameter, createServerModule, defaultFontSize, describeShellClose, executeOnServer, expandEnvironmentVars, formatDiff, getAccelerator, getCliNameArt, getGreetingBasedOnTime, getTerminalOptions, groupBy, helpGlobalParameter, hotkeysInfo, initWasmAccelerator, initializeServices, initializeTerminal, isWasmAccelerated, miscProcessors, openLink, parseAssignments, reconcileArgs, renderServerResponse, renderSingleOutput, substituteVars, systemProcessors, themeInfos, themes, tryExecuteScript, versionGlobalParameter, waitForLayout, welcomeModule, writeOutputToFile, writeStderrToFile };
18926
19128
  //# sourceMappingURL=public-api.mjs.map
18927
19129
  //# sourceMappingURL=public-api.mjs.map