zammy 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,244 +1,42 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ box,
4
+ bubble,
5
+ categoryIcons,
6
+ checkConflicts,
7
+ detectSourceType,
8
+ discoverPlugins,
9
+ formatPermissions,
10
+ getAllCommands,
11
+ getCommand,
12
+ getDiscoveredPlugins,
13
+ getPluginCommands,
14
+ initPluginLoader,
15
+ installFromGit,
16
+ installFromGithub,
17
+ installFromLocal,
18
+ installFromNpm,
19
+ isPluginLoaded,
20
+ loadPlugin,
21
+ progressBar,
22
+ registerCommand,
23
+ registerPluginCommand,
24
+ removePlugin,
25
+ spinnerFrames,
26
+ symbols,
27
+ theme,
28
+ unloadPlugin
29
+ } from "./chunk-LLLEINP6.js";
2
30
 
3
31
  // src/index.ts
4
- import * as readline4 from "readline";
32
+ import * as readline from "readline";
5
33
 
6
34
  // src/ui/banner.ts
7
35
  import figlet from "figlet";
8
- import chalk3 from "chalk";
9
-
10
- // src/ui/colors.ts
11
- import chalk from "chalk";
12
- var palette = {
13
- rose: "#FF6B6B",
14
- coral: "#FF8E72",
15
- peach: "#FFEAA7",
16
- mint: "#96CEB4",
17
- teal: "#4ECDC4",
18
- sky: "#45B7D1",
19
- lavender: "#DDA0DD",
20
- purple: "#9B59B6",
21
- gold: "#FFD700",
22
- silver: "#C0C0C0"
23
- };
24
- var theme = {
25
- primary: chalk.hex(palette.teal),
26
- secondary: chalk.hex(palette.lavender),
27
- success: chalk.hex("#2ECC71"),
28
- warning: chalk.hex("#F39C12"),
29
- error: chalk.hex("#E74C3C"),
30
- dim: chalk.hex("#6C7A89"),
31
- highlight: chalk.bold.white,
32
- command: chalk.bold.hex(palette.teal),
33
- prompt: chalk.bold.hex(palette.lavender),
34
- accent: chalk.hex(palette.rose),
35
- info: chalk.hex(palette.sky),
36
- muted: chalk.dim.hex("#95A5A6"),
37
- gold: chalk.hex(palette.gold),
38
- rose: chalk.hex(palette.rose),
39
- mint: chalk.hex(palette.mint),
40
- peach: chalk.hex(palette.peach),
41
- // Gradient text effects
42
- gradient: (text) => {
43
- const colors = [palette.rose, palette.coral, palette.peach, palette.mint, palette.teal];
44
- return text.split("").map(
45
- (char, i) => chalk.hex(colors[i % colors.length])(char)
46
- ).join("");
47
- },
48
- rainbow: (text) => {
49
- const colors = ["#FF6B6B", "#FF8E72", "#FFEAA7", "#96CEB4", "#4ECDC4", "#45B7D1", "#DDA0DD"];
50
- return text.split("").map(
51
- (char, i) => chalk.hex(colors[i % colors.length])(char)
52
- ).join("");
53
- },
54
- ocean: (text) => {
55
- const colors = ["#0077B6", "#00B4D8", "#48CAE4", "#90E0EF", "#CAF0F8"];
56
- return text.split("").map(
57
- (char, i) => chalk.hex(colors[i % colors.length])(char)
58
- ).join("");
59
- },
60
- sunset: (text) => {
61
- const colors = ["#FF6B6B", "#FF8E53", "#FFA07A", "#FFB347", "#FFD700"];
62
- return text.split("").map(
63
- (char, i) => chalk.hex(colors[i % colors.length])(char)
64
- ).join("");
65
- },
66
- // Bold variants
67
- b: {
68
- primary: chalk.bold.hex(palette.teal),
69
- secondary: chalk.bold.hex(palette.lavender),
70
- success: chalk.bold.hex("#2ECC71"),
71
- warning: chalk.bold.hex("#F39C12"),
72
- error: chalk.bold.hex("#E74C3C")
73
- }
74
- };
75
- var symbols = {
76
- // Basic UI
77
- arrow: "\u276F",
78
- // ❯
79
- check: "\u2714",
80
- // ✔
81
- cross: "\u2718",
82
- // ✘
83
- info: "\u2139",
84
- // ℹ
85
- warning: "\u26A0",
86
- // ⚠
87
- bullet: "\u2022",
88
- // •
89
- // Decorative
90
- star: "\u2605",
91
- // ★
92
- heart: "\u2665",
93
- // ♥
94
- diamond: "\u2666",
95
- // ♦
96
- sparkle: "\u2728",
97
- // ✨
98
- lightning: "\u26A1",
99
- // ⚡
100
- // Emoji icons
101
- fire: "\u{1F525}",
102
- // 🔥
103
- rocket: "\u{1F680}",
104
- // 🚀
105
- dice: "\u{1F3B2}",
106
- // 🎲
107
- coin: "\u{1FA99}",
108
- // 🪙
109
- lock: "\u{1F512}",
110
- // 🔒
111
- clock: "\u{1F552}",
112
- // 🕒
113
- chart: "\u{1F4CA}",
114
- // 📊
115
- note: "\u{1F4DD}",
116
- // 📝
117
- scroll: "\u{1F4DC}",
118
- // 📜
119
- clipboard: "\u{1F4CB}",
120
- // 📋
121
- palette: "\u{1F3A8}",
122
- // 🎨
123
- tomato: "\u{1F345}",
124
- // 🍅
125
- coffee: "\u2615",
126
- // ☕
127
- bell: "\u{1F514}",
128
- // 🔔
129
- gear: "\u2699",
130
- // ⚙
131
- folder: "\u{1F4C1}",
132
- // 📁
133
- terminal: "\u{1F4BB}",
134
- // 💻
135
- key: "\u{1F511}",
136
- // 🔑
137
- link: "\u{1F517}",
138
- // 🔗
139
- hourglass: "\u23F3"
140
- // ⏳
141
- };
142
- var boxChars = {
143
- rounded: { tl: "\u256D", tr: "\u256E", bl: "\u2570", br: "\u256F", h: "\u2500", v: "\u2502" },
144
- sharp: { tl: "\u250C", tr: "\u2510", bl: "\u2514", br: "\u2518", h: "\u2500", v: "\u2502" },
145
- double: { tl: "\u2554", tr: "\u2557", bl: "\u255A", br: "\u255D", h: "\u2550", v: "\u2551" },
146
- heavy: { tl: "\u250F", tr: "\u2513", bl: "\u2517", br: "\u251B", h: "\u2501", v: "\u2503" }
147
- };
148
- var box = {
149
- topLeft: "\u256D",
150
- // ╭
151
- topRight: "\u256E",
152
- // ╮
153
- bottomLeft: "\u2570",
154
- // ╰
155
- bottomRight: "\u256F",
156
- // ╯
157
- horizontal: "\u2500",
158
- // ─
159
- vertical: "\u2502",
160
- // │
161
- draw: (content, width = 50, style = "rounded") => {
162
- const chars = boxChars[style];
163
- const lines = [];
164
- const innerWidth = width - 2;
165
- lines.push(theme.dim(`${chars.tl}${chars.h.repeat(innerWidth)}${chars.tr}`));
166
- content.forEach((line) => {
167
- const stripped = line.replace(/\x1B\[[0-9;]*m/g, "");
168
- const padding = innerWidth - stripped.length;
169
- lines.push(theme.dim(chars.v) + line + " ".repeat(Math.max(0, padding)) + theme.dim(chars.v));
170
- });
171
- lines.push(theme.dim(`${chars.bl}${chars.h.repeat(innerWidth)}${chars.br}`));
172
- return lines.join("\n");
173
- },
174
- // Simple title box
175
- title: (title, width = 50) => {
176
- const chars = boxChars.rounded;
177
- const innerWidth = width - 2;
178
- const titleLen = title.replace(/\x1B\[[0-9;]*m/g, "").length;
179
- const leftPad = Math.floor((innerWidth - titleLen - 2) / 2);
180
- const rightPad = innerWidth - titleLen - 2 - leftPad;
181
- return theme.dim(`${chars.tl}${chars.h.repeat(leftPad)} `) + title + theme.dim(` ${chars.h.repeat(rightPad)}${chars.tr}`);
182
- }
183
- };
184
- var progressBar = (percent, width = 30, showPercent = true) => {
185
- const filled = Math.round(percent / 100 * width);
186
- const empty = width - filled;
187
- let color = theme.success;
188
- if (percent > 70) color = theme.warning;
189
- if (percent > 90) color = theme.error;
190
- const bar = color("\u2588".repeat(filled)) + theme.dim("\u2591".repeat(empty));
191
- return showPercent ? `${bar} ${percent.toFixed(0)}%` : bar;
192
- };
193
- var bubble = {
194
- say: (text, width = 50) => {
195
- const lines = [];
196
- const innerWidth = width - 4;
197
- const words = text.split(" ");
198
- let currentLine = "";
199
- const wrappedLines = [];
200
- for (const word of words) {
201
- if ((currentLine + " " + word).trim().length <= innerWidth) {
202
- currentLine = (currentLine + " " + word).trim();
203
- } else {
204
- if (currentLine) wrappedLines.push(currentLine);
205
- currentLine = word;
206
- }
207
- }
208
- if (currentLine) wrappedLines.push(currentLine);
209
- lines.push(theme.dim(" \u256D" + "\u2500".repeat(innerWidth + 2) + "\u256E"));
210
- for (const line of wrappedLines) {
211
- const padding = innerWidth - line.length;
212
- lines.push(theme.dim(" \u2502 ") + line + " ".repeat(padding) + theme.dim(" \u2502"));
213
- }
214
- lines.push(theme.dim(" \u2570" + "\u2500".repeat(innerWidth + 2) + "\u256F"));
215
- lines.push(theme.dim(" \u2572"));
216
- lines.push(theme.dim(" \u2572"));
217
- return lines.join("\n");
218
- },
219
- think: (text, width = 50) => {
220
- const lines = [];
221
- const innerWidth = width - 4;
222
- lines.push(theme.dim(" \u256D" + "\u2500".repeat(innerWidth + 2) + "\u256E"));
223
- const padding = innerWidth - text.length;
224
- lines.push(theme.dim(" \u2502 ") + text + " ".repeat(Math.max(0, padding)) + theme.dim(" \u2502"));
225
- lines.push(theme.dim(" \u2570" + "\u2500".repeat(innerWidth + 2) + "\u256F"));
226
- lines.push(theme.dim(" \u25CB"));
227
- lines.push(theme.dim(" \u25CB"));
228
- return lines.join("\n");
229
- }
230
- };
231
- var categoryIcons = {
232
- "Utilities": "\u{1F527}",
233
- "Fun": "\u{1F3AE}",
234
- "Creative": "\u{1F3A8}",
235
- "Dev": "\u{1F4BB}",
236
- "Info": "\u{1F4E1}"
237
- };
238
- var spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
36
+ import chalk2 from "chalk";
239
37
 
240
38
  // src/ui/slime-animated.ts
241
- import chalk2 from "chalk";
39
+ import chalk from "chalk";
242
40
  var C = {
243
41
  P1: "#4A235A",
244
42
  // Darkest edge
@@ -265,15 +63,15 @@ var C = {
265
63
  RD: "#E74C3C"
266
64
  // Red (angry)
267
65
  };
268
- var b = (hex) => chalk2.bgHex(hex)(" ");
269
- var dot = chalk2.hex(C.WH)("\xB7");
270
- var star = chalk2.hex(C.WH)("\u2726");
271
- var heart = chalk2.hex(C.PK)("\u2665");
272
- var z = chalk2.hex(C.CY)("z");
273
- var Z = chalk2.hex(C.CY)("Z");
274
- var eye = chalk2.bgHex(C.BK).hex(C.WH)(" \xB7");
275
- var shine = chalk2.bgHex(C.P3).hex(C.WH)(" \xB7");
276
- var shine2 = chalk2.bgHex(C.P4).hex(C.WH)("\xB7 ");
66
+ var b = (hex) => chalk.bgHex(hex)(" ");
67
+ var dot = chalk.hex(C.WH)("\xB7");
68
+ var star = chalk.hex(C.WH)("\u2726");
69
+ var heart = chalk.hex(C.PK)("\u2665");
70
+ var z = chalk.hex(C.CY)("z");
71
+ var Z = chalk.hex(C.CY)("Z");
72
+ var eye = chalk.bgHex(C.BK).hex(C.WH)(" \xB7");
73
+ var shine = chalk.bgHex(C.P3).hex(C.WH)(" \xB7");
74
+ var shine2 = chalk.bgHex(C.P4).hex(C.WH)("\xB7 ");
277
75
  var slimeFrames = {
278
76
  happy: () => {
279
77
  const { P1, P2, P3, P4, P5, BK, PK } = C;
@@ -290,7 +88,7 @@ var slimeFrames = {
290
88
  },
291
89
  excited: () => {
292
90
  const { P1, P2, P3, P4, P5, BK, PK, YL } = C;
293
- const starEye = chalk2.bgHex(YL).hex(C.WH)("\u2605 ");
91
+ const starEye = chalk.bgHex(YL).hex(C.WH)("\u2605 ");
294
92
  return [
295
93
  ` ${star} ${dot} ${star} ${dot} ${star}`,
296
94
  ` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
@@ -304,7 +102,7 @@ var slimeFrames = {
304
102
  },
305
103
  love: () => {
306
104
  const { P1, P2, P3, P4, P5, BK, PK } = C;
307
- const heartEye = chalk2.bgHex(PK).hex(C.WH)("\u2665 ");
105
+ const heartEye = chalk.bgHex(PK).hex(C.WH)("\u2665 ");
308
106
  return [
309
107
  ` ${heart} ${heart}`,
310
108
  ` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
@@ -318,7 +116,7 @@ var slimeFrames = {
318
116
  },
319
117
  sleepy: () => {
320
118
  const { P1, P2, P3, P4, P5, BK } = C;
321
- const closedEye = chalk2.bgHex(P3).hex(BK)("\u2500\u2500");
119
+ const closedEye = chalk.bgHex(P3).hex(BK)("\u2500\u2500");
322
120
  return [
323
121
  ` ${z} ${z} ${Z}`,
324
122
  ` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
@@ -332,10 +130,10 @@ var slimeFrames = {
332
130
  },
333
131
  thinking: () => {
334
132
  const { P1, P2, P3, P4, P5, BK, YL } = C;
335
- const thinkEye = chalk2.bgHex(C.BK).hex(C.WH)(" \xB7");
336
- const lookUpEye = chalk2.bgHex(C.BK).hex(C.WH)("\xB7 ");
133
+ const thinkEye = chalk.bgHex(C.BK).hex(C.WH)(" \xB7");
134
+ const lookUpEye = chalk.bgHex(C.BK).hex(C.WH)("\xB7 ");
337
135
  return [
338
- ` ${chalk2.hex(YL)("?")}`,
136
+ ` ${chalk.hex(YL)("?")}`,
339
137
  ` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
340
138
  ` ${b(P5)}${b(P4)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}${b(P5)}`,
341
139
  ` ${b(P4)}${b(P3)}${thinkEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${lookUpEye}${b(P3)}${b(P4)}`,
@@ -347,9 +145,9 @@ var slimeFrames = {
347
145
  },
348
146
  surprised: () => {
349
147
  const { P1, P2, P3, P4, P5, BK, YL } = C;
350
- const bigEye = chalk2.bgHex(BK).hex(C.WH)("\u25C9 ");
148
+ const bigEye = chalk.bgHex(BK).hex(C.WH)("\u25C9 ");
351
149
  return [
352
- ` ${chalk2.hex(YL)("!!")}`,
150
+ ` ${chalk.hex(YL)("!!")}`,
353
151
  ` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
354
152
  ` ${b(P5)}${b(P4)}${b(P3)}${shine2}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}${b(P5)}`,
355
153
  ` ${b(P4)}${b(P3)}${bigEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${bigEye}${b(P3)}${b(P4)}`,
@@ -361,8 +159,8 @@ var slimeFrames = {
361
159
  },
362
160
  sad: () => {
363
161
  const { P1, P2, P3, P4, P5, BK, BL } = C;
364
- const sadEye = chalk2.bgHex(BK).hex(C.WH)(" \xB7");
365
- const tear = chalk2.bgHex(BL)(" ");
162
+ const sadEye = chalk.bgHex(BK).hex(C.WH)(" \xB7");
163
+ const tear = chalk.bgHex(BL)(" ");
366
164
  return [
367
165
  ` ${dot} ${dot} ${dot}`,
368
166
  ` ${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}`,
@@ -376,7 +174,7 @@ var slimeFrames = {
376
174
  },
377
175
  wink: () => {
378
176
  const { P1, P2, P3, P4, P5, BK, PK } = C;
379
- const winkEye = chalk2.bgHex(P3).hex(BK)("> ");
177
+ const winkEye = chalk.bgHex(P3).hex(BK)("> ");
380
178
  return [
381
179
  ` ${star} ${dot}`,
382
180
  ` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
@@ -390,10 +188,10 @@ var slimeFrames = {
390
188
  },
391
189
  angry: () => {
392
190
  const { P1, P2, P3, P4, BK, RD } = C;
393
- const angryEye = chalk2.bgHex(BK).hex(RD)("> ");
394
- const angryEye2 = chalk2.bgHex(BK).hex(RD)(" <");
191
+ const angryEye = chalk.bgHex(BK).hex(RD)("> ");
192
+ const angryEye2 = chalk.bgHex(BK).hex(RD)(" <");
395
193
  return [
396
- ` ${chalk2.hex(RD)("# @!")}`,
194
+ ` ${chalk.hex(RD)("# @!")}`,
397
195
  ` ${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}`,
398
196
  ` ${b(P4)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}`,
399
197
  ` ${b(P4)}${b(P3)}${angryEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${angryEye2}${b(P3)}${b(P4)}`,
@@ -439,15 +237,15 @@ function getStartupMood() {
439
237
  return "happy";
440
238
  }
441
239
  var miniSlime = {
442
- happy: chalk2.hex(C.P3)("(") + chalk2.hex(C.BK)("\u25D5") + chalk2.hex(C.P3)("\u1D17") + chalk2.hex(C.BK)("\u25D5") + chalk2.hex(C.P3)(")"),
443
- excited: chalk2.hex(C.P3)("(") + chalk2.hex(C.YL)("\u2605") + chalk2.hex(C.P3)("\u1D17") + chalk2.hex(C.YL)("\u2605") + chalk2.hex(C.P3)(")"),
444
- love: chalk2.hex(C.P3)("(") + chalk2.hex(C.PK)("\u2665") + chalk2.hex(C.P3)("\u1D17") + chalk2.hex(C.PK)("\u2665") + chalk2.hex(C.P3)(")"),
445
- sleepy: chalk2.hex(C.P3)("(") + chalk2.hex(C.BK)("\u2013") + chalk2.hex(C.P3)("\u03C9") + chalk2.hex(C.BK)("\u2013") + chalk2.hex(C.P3)(") zZ"),
446
- sad: chalk2.hex(C.P3)("(") + chalk2.hex(C.BK)("\u25D5") + chalk2.hex(C.P3)("\uFE35") + chalk2.hex(C.BK)("\u25D5") + chalk2.hex(C.P3)(")"),
447
- surprised: chalk2.hex(C.P3)("(") + chalk2.hex(C.BK)("\u25CE") + chalk2.hex(C.P3)("\u25CB") + chalk2.hex(C.BK)("\u25CE") + chalk2.hex(C.P3)(")!"),
448
- wink: chalk2.hex(C.P3)("(") + chalk2.hex(C.BK)("\u25D5") + chalk2.hex(C.P3)("\u1D17") + chalk2.hex(C.BK)(">") + chalk2.hex(C.P3)(")"),
449
- thinking: chalk2.hex(C.P3)("(") + chalk2.hex(C.BK)("\u25D5") + chalk2.hex(C.P3)("\uFF5E") + chalk2.hex(C.BK)("\u25D4") + chalk2.hex(C.P3)(")"),
450
- angry: chalk2.hex(C.P3)("(") + chalk2.hex(C.RD)(">") + chalk2.hex(C.P3)("_") + chalk2.hex(C.RD)("<") + chalk2.hex(C.P3)(")")
240
+ happy: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)(")"),
241
+ excited: chalk.hex(C.P3)("(") + chalk.hex(C.YL)("\u2605") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.YL)("\u2605") + chalk.hex(C.P3)(")"),
242
+ love: chalk.hex(C.P3)("(") + chalk.hex(C.PK)("\u2665") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.PK)("\u2665") + chalk.hex(C.P3)(")"),
243
+ sleepy: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u2013") + chalk.hex(C.P3)("\u03C9") + chalk.hex(C.BK)("\u2013") + chalk.hex(C.P3)(") zZ"),
244
+ sad: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\uFE35") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)(")"),
245
+ surprised: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25CE") + chalk.hex(C.P3)("\u25CB") + chalk.hex(C.BK)("\u25CE") + chalk.hex(C.P3)(")!"),
246
+ wink: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.BK)(">") + chalk.hex(C.P3)(")"),
247
+ thinking: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\uFF5E") + chalk.hex(C.BK)("\u25D4") + chalk.hex(C.P3)(")"),
248
+ angry: chalk.hex(C.P3)("(") + chalk.hex(C.RD)(">") + chalk.hex(C.P3)("_") + chalk.hex(C.RD)("<") + chalk.hex(C.P3)(")")
451
249
  };
452
250
  var validMoods = Object.keys(slimeFrames);
453
251
  function react(mood, message) {
@@ -517,16 +315,16 @@ var C2 = {
517
315
  PK: "#E91E63"
518
316
  // Pink (tongue)
519
317
  };
520
- var b2 = (hex) => chalk3.bgHex(hex)(" ");
521
- var dot2 = chalk3.hex(C2.WH)("\xB7");
318
+ var b2 = (hex) => chalk2.bgHex(hex)(" ");
319
+ var dot2 = chalk2.hex(C2.WH)("\xB7");
522
320
  function getSlimeLines(isBlinking, _mood) {
523
321
  const { P1, P2, P3, P4, P5, WH, BK, PK } = C2;
524
- const openEye = chalk3.bgHex(BK).hex(WH)(" \xB7");
525
- const closedEye = chalk3.bgHex(P3).hex(BK)("\u2500\u2500");
322
+ const openEye = chalk2.bgHex(BK).hex(WH)(" \xB7");
323
+ const closedEye = chalk2.bgHex(P3).hex(BK)("\u2500\u2500");
526
324
  const eyeL = isBlinking ? closedEye : openEye;
527
325
  const eyeR = isBlinking ? closedEye : openEye;
528
- const shine3 = chalk3.bgHex(P3).hex(WH)(" \xB7");
529
- const shine22 = chalk3.bgHex(P4).hex(WH)("\xB7 ");
326
+ const shine3 = chalk2.bgHex(P3).hex(WH)(" \xB7");
327
+ const shine22 = chalk2.bgHex(P4).hex(WH)("\xB7 ");
530
328
  const miniBlob = `${b2(P3)}`;
531
329
  return [
532
330
  ` ${dot2} ${dot2}`,
@@ -543,7 +341,7 @@ var MIN_WIDTH_FOR_MASCOT2 = 90;
543
341
  var MIN_WIDTH_FOR_FULL_LOGO = 55;
544
342
  var MIN_WIDTH_FOR_COMPACT = 30;
545
343
  async function displayBanner(simple = false) {
546
- return new Promise((resolve6) => {
344
+ return new Promise((resolve5) => {
547
345
  const termWidth = process.stdout.columns || 80;
548
346
  figlet("ZAMMY", {
549
347
  font: "ANSI Shadow",
@@ -557,7 +355,7 @@ async function displayBanner(simple = false) {
557
355
  console.log(theme.secondary(` "${greeting}"`));
558
356
  console.log(theme.dim(" Type /help for commands"));
559
357
  console.log("");
560
- resolve6();
358
+ resolve5();
561
359
  return;
562
360
  }
563
361
  let figletLines = [];
@@ -590,7 +388,7 @@ async function displayBanner(simple = false) {
590
388
  console.log(theme.dim(` ${symbols.arrow} Type ${theme.primary("/")} to browse commands or ${theme.primary("/help")} for full list`));
591
389
  console.log(theme.dim(` ${symbols.arrow} Shell commands start with ${theme.primary("!")} (e.g., ${theme.primary("!ls")}, ${theme.primary("!git")})`));
592
390
  console.log("");
593
- resolve6();
391
+ resolve5();
594
392
  return;
595
393
  }
596
394
  const figletWidth = 50;
@@ -620,7 +418,7 @@ async function displayBanner(simple = false) {
620
418
  console.log(theme.dim(` ${symbols.arrow} Type ${theme.primary("/")} to browse commands or ${theme.primary("/help")} for full list`));
621
419
  console.log(theme.dim(` ${symbols.arrow} Shell commands start with ${theme.primary("!")} (e.g., ${theme.primary("!ls")}, ${theme.primary("!git")})`));
622
420
  console.log("");
623
- resolve6();
421
+ resolve5();
624
422
  });
625
423
  });
626
424
  }
@@ -630,42 +428,6 @@ function getPrompt() {
630
428
  return `${theme.b.primary("zammy")}${theme.dim(symbols.arrow)} `;
631
429
  }
632
430
 
633
- // src/commands/registry.ts
634
- var commands = /* @__PURE__ */ new Map();
635
- function registerCommand(command) {
636
- commands.set(command.name, { ...command, source: "core" });
637
- }
638
- function registerPluginCommand(command, pluginName) {
639
- commands.set(command.name, { ...command, source: "plugin", pluginName });
640
- }
641
- function unregisterPluginCommands(pluginName) {
642
- for (const [name, cmd] of commands.entries()) {
643
- if (cmd.source === "plugin" && cmd.pluginName === pluginName) {
644
- commands.delete(name);
645
- }
646
- }
647
- }
648
- function getCommand(name) {
649
- return commands.get(name);
650
- }
651
- function getAllCommands() {
652
- return Array.from(commands.values());
653
- }
654
- function getPluginCommands() {
655
- return Array.from(commands.values()).filter((cmd) => cmd.source === "plugin");
656
- }
657
- function checkCommandConflict(name) {
658
- const existing = commands.get(name);
659
- if (!existing) {
660
- return { exists: false };
661
- }
662
- return {
663
- exists: true,
664
- source: existing.source,
665
- pluginName: existing.pluginName
666
- };
667
- }
668
-
669
431
  // src/commands/utilities/help.ts
670
432
  var categories = {
671
433
  "Utilities": ["help", "exit", "calc", "password", "stats", "time", "countdown", "timer", "todo", "history"],
@@ -680,10 +442,10 @@ registerCommand({
680
442
  description: "Show all available commands",
681
443
  usage: "/help [command]",
682
444
  async execute(args2) {
683
- const commands2 = getAllCommands();
445
+ const commands = getAllCommands();
684
446
  if (args2.length > 0) {
685
447
  const cmdName = args2[0].replace(/^\//, "");
686
- const cmd = commands2.find((c) => c.name === cmdName);
448
+ const cmd = commands.find((c) => c.name === cmdName);
687
449
  if (cmd) {
688
450
  console.log("");
689
451
  console.log(box.draw([
@@ -711,9 +473,9 @@ registerCommand({
711
473
  console.log(` ${symbols.rocket} ${theme.gradient("ZAMMY COMMANDS")} ${symbols.rocket}`);
712
474
  console.log(` ${theme.rainbow("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501")}`);
713
475
  console.log("");
714
- const maxNameLength = Math.max(...commands2.map((c) => c.name.length));
476
+ const maxNameLength = Math.max(...commands.map((c) => c.name.length));
715
477
  for (const [category, cmdNames] of Object.entries(categories)) {
716
- const categoryCommands = commands2.filter((c) => cmdNames.includes(c.name));
478
+ const categoryCommands = commands.filter((c) => cmdNames.includes(c.name));
717
479
  if (categoryCommands.length === 0) continue;
718
480
  const icon = categoryIcons[category] || symbols.folder;
719
481
  console.log(` ${icon} ${theme.b.secondary(category)}`);
@@ -741,7 +503,7 @@ registerCommand({
741
503
  }
742
504
  const categorizedNames = Object.values(categories).flat();
743
505
  const pluginCmdNames = pluginCmds.map((c) => c.name);
744
- const uncategorized = commands2.filter(
506
+ const uncategorized = commands.filter(
745
507
  (c) => !categorizedNames.includes(c.name) && !pluginCmdNames.includes(c.name) && c.source === "core"
746
508
  );
747
509
  if (uncategorized.length > 0) {
@@ -814,21 +576,126 @@ registerCommand({
814
576
  });
815
577
 
816
578
  // src/handlers/utilities/calc.ts
817
- function evaluate(expression) {
818
- const expr = expression.replace(/\s+/g, "");
819
- if (!/^[\d+\-*/().%^]+$/.test(expr)) {
579
+ function tokenize(expression) {
580
+ const tokens = [];
581
+ let i = 0;
582
+ while (i < expression.length) {
583
+ const char = expression[i];
584
+ if (/\s/.test(char)) {
585
+ i++;
586
+ continue;
587
+ }
588
+ if (/\d/.test(char) || char === "." && /\d/.test(expression[i + 1])) {
589
+ let numStr = "";
590
+ while (i < expression.length && (/\d/.test(expression[i]) || expression[i] === ".")) {
591
+ numStr += expression[i];
592
+ i++;
593
+ }
594
+ const value = parseFloat(numStr);
595
+ if (isNaN(value)) return null;
596
+ tokens.push({ type: "number", value });
597
+ continue;
598
+ }
599
+ if (["+", "-", "*", "/", "%", "^"].includes(char)) {
600
+ tokens.push({ type: "op", value: char });
601
+ i++;
602
+ continue;
603
+ }
604
+ if (char === "(" || char === ")") {
605
+ tokens.push({ type: "paren", value: char });
606
+ i++;
607
+ continue;
608
+ }
820
609
  return null;
821
610
  }
822
- try {
823
- const sanitized = expr.replace(/\^/g, "**");
824
- const result = new Function(`return (${sanitized})`)();
825
- if (typeof result !== "number" || !isFinite(result)) {
826
- return null;
827
- }
611
+ return tokens;
612
+ }
613
+ var Parser = class {
614
+ tokens;
615
+ pos = 0;
616
+ constructor(tokens) {
617
+ this.tokens = tokens;
618
+ }
619
+ parse() {
620
+ const result = this.expr();
621
+ if (this.pos !== this.tokens.length) return null;
828
622
  return result;
829
- } catch {
623
+ }
624
+ current() {
625
+ return this.tokens[this.pos];
626
+ }
627
+ consume() {
628
+ return this.tokens[this.pos++];
629
+ }
630
+ expr() {
631
+ let left = this.term();
632
+ if (left === null) return null;
633
+ while (this.current()?.type === "op" && ["+", "-"].includes(this.current().value)) {
634
+ const op = this.consume().value;
635
+ const right = this.term();
636
+ if (right === null) return null;
637
+ left = op === "+" ? left + right : left - right;
638
+ }
639
+ return left;
640
+ }
641
+ term() {
642
+ let left = this.power();
643
+ if (left === null) return null;
644
+ while (this.current()?.type === "op" && ["*", "/", "%"].includes(this.current().value)) {
645
+ const op = this.consume().value;
646
+ const right = this.power();
647
+ if (right === null) return null;
648
+ if ((op === "/" || op === "%") && right === 0) return null;
649
+ left = op === "*" ? left * right : op === "/" ? left / right : left % right;
650
+ }
651
+ return left;
652
+ }
653
+ power() {
654
+ const base = this.unary();
655
+ if (base === null) return null;
656
+ if (this.current()?.type === "op" && this.current().value === "^") {
657
+ this.consume();
658
+ const exp = this.power();
659
+ if (exp === null) return null;
660
+ return Math.pow(base, exp);
661
+ }
662
+ return base;
663
+ }
664
+ unary() {
665
+ if (this.current()?.type === "op" && this.current().value === "-") {
666
+ this.consume();
667
+ const val = this.factor();
668
+ if (val === null) return null;
669
+ return -val;
670
+ }
671
+ return this.factor();
672
+ }
673
+ factor() {
674
+ const token = this.current();
675
+ if (token?.type === "number") {
676
+ this.consume();
677
+ return token.value;
678
+ }
679
+ if (token?.type === "paren" && token.value === "(") {
680
+ this.consume();
681
+ const result = this.expr();
682
+ if (result === null) return null;
683
+ if (this.current()?.type !== "paren" || this.current().value !== ")") {
684
+ return null;
685
+ }
686
+ this.consume();
687
+ return result;
688
+ }
830
689
  return null;
831
690
  }
691
+ };
692
+ function evaluate(expression) {
693
+ const tokens = tokenize(expression);
694
+ if (!tokens || tokens.length === 0) return null;
695
+ const parser = new Parser(tokens);
696
+ const result = parser.parse();
697
+ if (result === null || !isFinite(result)) return null;
698
+ return result;
832
699
  }
833
700
  function formatNumber(num) {
834
701
  if (Math.abs(num) < 1e-4 || Math.abs(num) > 1e10) {
@@ -1192,15 +1059,16 @@ registerCommand({
1192
1059
  console.log("");
1193
1060
  let remaining = totalSeconds;
1194
1061
  let spinnerIndex = 0;
1195
- return new Promise((resolve6) => {
1062
+ return new Promise((resolve5) => {
1196
1063
  const interval = setInterval(() => {
1197
1064
  process.stdout.write("\r\x1B[K");
1198
1065
  if (remaining <= 0) {
1199
1066
  clearInterval(interval);
1067
+ process.removeListener("SIGINT", cleanup);
1200
1068
  console.log(` ${symbols.sparkle} ${theme.success("TIME'S UP!")} ${symbols.sparkle}`);
1201
1069
  console.log("");
1202
1070
  process.stdout.write("\x07");
1203
- resolve6();
1071
+ resolve5();
1204
1072
  return;
1205
1073
  }
1206
1074
  const spinner = spinnerFrames[spinnerIndex % spinnerFrames.length];
@@ -1212,6 +1080,14 @@ registerCommand({
1212
1080
  remaining--;
1213
1081
  spinnerIndex++;
1214
1082
  }, 1e3);
1083
+ const cleanup = () => {
1084
+ clearInterval(interval);
1085
+ process.stdout.write("\r\x1B[K");
1086
+ console.log(` ${symbols.cross} ${theme.secondary("Countdown cancelled")}`);
1087
+ console.log("");
1088
+ resolve5();
1089
+ };
1090
+ process.once("SIGINT", cleanup);
1215
1091
  process.stdout.write(` ${theme.secondary(spinnerFrames[0])} ${theme.primary(formatTime(remaining))} remaining...`);
1216
1092
  });
1217
1093
  }
@@ -1473,7 +1349,7 @@ registerCommand({
1473
1349
  let history = [];
1474
1350
  try {
1475
1351
  if (existsSync2(HISTORY_FILE)) {
1476
- const lines = readFileSync2(HISTORY_FILE, "utf8").split("\n").filter((l) => l);
1352
+ const lines = readFileSync2(HISTORY_FILE, "utf8").split(/\r?\n/).filter((l) => l);
1477
1353
  history = lines.map((line) => {
1478
1354
  const [time, ...rest] = line.split("|");
1479
1355
  return { time, cmd: rest.join("|") };
@@ -1868,7 +1744,7 @@ registerCommand({
1868
1744
  console.log("");
1869
1745
  console.log(bubble.say(joke.setup, 55));
1870
1746
  console.log(` ${symbols.sparkle}`);
1871
- await new Promise((resolve6) => setTimeout(resolve6, 1500));
1747
+ await new Promise((resolve5) => setTimeout(resolve5, 1500));
1872
1748
  console.log("");
1873
1749
  console.log(` ${theme.gold(" \u2726")} ${theme.b.success(joke.punchline)} ${theme.gold("\u2726")}`);
1874
1750
  console.log("");
@@ -2318,7 +2194,10 @@ registerCommand({
2318
2194
  console.log(theme.dim(" Use /pomodoro status to check progress"));
2319
2195
  console.log(theme.dim(" Use /pomodoro skip to skip to break"));
2320
2196
  console.log("");
2321
- if (state.interval) clearTimeout(state.interval);
2197
+ if (state.interval) {
2198
+ clearTimeout(state.interval);
2199
+ state.interval = null;
2200
+ }
2322
2201
  state.interval = setTimeout(() => {
2323
2202
  if (state.running) {
2324
2203
  console.log("\n");
@@ -2327,6 +2206,7 @@ registerCommand({
2327
2206
  console.log("\n");
2328
2207
  state.sessions++;
2329
2208
  state.running = false;
2209
+ state.interval = null;
2330
2210
  }
2331
2211
  }, DURATIONS.work);
2332
2212
  return;
@@ -2336,7 +2216,10 @@ registerCommand({
2336
2216
  console.log(theme.dim(" Pomodoro is not running"));
2337
2217
  return;
2338
2218
  }
2339
- if (state.interval) clearTimeout(state.interval);
2219
+ if (state.interval) {
2220
+ clearTimeout(state.interval);
2221
+ state.interval = null;
2222
+ }
2340
2223
  state.running = false;
2341
2224
  console.log("");
2342
2225
  console.log(` ${symbols.cross} ${theme.secondary("Pomodoro stopped")}`);
@@ -2349,7 +2232,10 @@ registerCommand({
2349
2232
  console.log(theme.dim(" Pomodoro is not running"));
2350
2233
  return;
2351
2234
  }
2352
- if (state.interval) clearTimeout(state.interval);
2235
+ if (state.interval) {
2236
+ clearTimeout(state.interval);
2237
+ state.interval = null;
2238
+ }
2353
2239
  if (state.mode === "work") {
2354
2240
  state.sessions++;
2355
2241
  state.mode = state.sessions % 4 === 0 ? "longbreak" : "break";
@@ -2372,6 +2258,7 @@ registerCommand({
2372
2258
  ${symbols.bell} ${state.mode === "work" ? "Focus session" : "Break"} complete!
2373
2259
  `);
2374
2260
  state.running = false;
2261
+ state.interval = null;
2375
2262
  }
2376
2263
  }, state.endTime - Date.now());
2377
2264
  return;
@@ -2884,7 +2771,7 @@ registerCommand({
2884
2771
  });
2885
2772
 
2886
2773
  // src/commands/creative/color.ts
2887
- import chalk4 from "chalk";
2774
+ import chalk3 from "chalk";
2888
2775
 
2889
2776
  // src/handlers/creative/color.ts
2890
2777
  function hexToRgb(hex) {
@@ -3033,7 +2920,7 @@ registerCommand({
3033
2920
  console.log("");
3034
2921
  console.log(` ${symbols.palette} ${theme.gradient("COLOR CONVERTER")} ${symbols.palette}`);
3035
2922
  console.log("");
3036
- const colorBlock = chalk4.bgHex(hex).hex(textColor);
2923
+ const colorBlock = chalk3.bgHex(hex).hex(textColor);
3037
2924
  console.log(` ${colorBlock(" ")}`);
3038
2925
  console.log(` ${colorBlock(" ")}`);
3039
2926
  console.log(` ${colorBlock(` ${hex.toUpperCase()} `.slice(0, 40))}`);
@@ -3048,14 +2935,14 @@ registerCommand({
3048
2935
  let shadesLine = " ";
3049
2936
  const shades = generateShades(rgb);
3050
2937
  for (const shade of shades) {
3051
- shadesLine += chalk4.bgRgb(shade.r, shade.g, shade.b)(" ");
2938
+ shadesLine += chalk3.bgRgb(shade.r, shade.g, shade.b)(" ");
3052
2939
  }
3053
2940
  console.log(shadesLine);
3054
2941
  console.log(` ${theme.dim("Tints:")}`);
3055
2942
  let tintsLine = " ";
3056
2943
  const tints = generateTints(rgb);
3057
2944
  for (const tint of tints) {
3058
- tintsLine += chalk4.bgRgb(tint.r, tint.g, tint.b)(" ");
2945
+ tintsLine += chalk3.bgRgb(tint.r, tint.g, tint.b)(" ");
3059
2946
  }
3060
2947
  console.log(tintsLine);
3061
2948
  console.log("");
@@ -3162,8 +3049,18 @@ var SUPPORTED_METHODS = ["base64", "url", "hex"];
3162
3049
  function isValidMethod(method) {
3163
3050
  return SUPPORTED_METHODS.includes(method.toLowerCase());
3164
3051
  }
3052
+ function isValidBase64(str) {
3053
+ if (!str || str.length === 0) return false;
3054
+ const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
3055
+ return base64Regex.test(str) && str.length % 4 === 0;
3056
+ }
3057
+ function isValidHex(str) {
3058
+ if (!str || str.length === 0) return false;
3059
+ return str.length % 2 === 0 && /^[0-9A-Fa-f]+$/.test(str);
3060
+ }
3165
3061
  function encodeText(text, method, direction) {
3166
3062
  let output;
3063
+ let error;
3167
3064
  if (direction === "encode") {
3168
3065
  switch (method) {
3169
3066
  case "base64":
@@ -3179,13 +3076,38 @@ function encodeText(text, method, direction) {
3179
3076
  } else {
3180
3077
  switch (method) {
3181
3078
  case "base64":
3182
- output = Buffer.from(text, "base64").toString("utf-8");
3079
+ try {
3080
+ if (!isValidBase64(text)) {
3081
+ output = "";
3082
+ error = "Invalid base64 input";
3083
+ } else {
3084
+ output = Buffer.from(text, "base64").toString("utf-8");
3085
+ }
3086
+ } catch (e) {
3087
+ output = "";
3088
+ error = "Failed to decode base64: invalid input";
3089
+ }
3183
3090
  break;
3184
3091
  case "url":
3185
- output = decodeURIComponent(text);
3092
+ try {
3093
+ output = decodeURIComponent(text);
3094
+ } catch (e) {
3095
+ output = "";
3096
+ error = "Failed to decode URL: malformed URI sequence";
3097
+ }
3186
3098
  break;
3187
3099
  case "hex":
3188
- output = Buffer.from(text, "hex").toString("utf-8");
3100
+ try {
3101
+ if (!isValidHex(text)) {
3102
+ output = "";
3103
+ error = "Invalid hex input: must be even length and contain only 0-9, A-F";
3104
+ } else {
3105
+ output = Buffer.from(text, "hex").toString("utf-8");
3106
+ }
3107
+ } catch (e) {
3108
+ output = "";
3109
+ error = "Failed to decode hex: invalid input";
3110
+ }
3189
3111
  break;
3190
3112
  }
3191
3113
  }
@@ -3193,7 +3115,8 @@ function encodeText(text, method, direction) {
3193
3115
  method: method.toUpperCase(),
3194
3116
  direction,
3195
3117
  input: text,
3196
- output
3118
+ output,
3119
+ ...error && { error }
3197
3120
  };
3198
3121
  }
3199
3122
 
@@ -3509,9 +3432,9 @@ import http from "http";
3509
3432
  import { URL } from "url";
3510
3433
  async function makeRequest(urlStr, options = { method: "GET" }) {
3511
3434
  const startTime2 = Date.now();
3512
- return new Promise((resolve6) => {
3435
+ return new Promise((resolve5) => {
3513
3436
  const timeout = setTimeout(() => {
3514
- resolve6({ success: false, error: "Request timed out" });
3437
+ resolve5({ success: false, error: "Request timed out" });
3515
3438
  }, options.timeout || 3e4);
3516
3439
  try {
3517
3440
  const url = new URL(urlStr.startsWith("http") ? urlStr : `https://${urlStr}`);
@@ -3533,7 +3456,7 @@ async function makeRequest(urlStr, options = { method: "GET" }) {
3533
3456
  });
3534
3457
  res.on("end", () => {
3535
3458
  clearTimeout(timeout);
3536
- resolve6({
3459
+ resolve5({
3537
3460
  success: true,
3538
3461
  statusCode: res.statusCode,
3539
3462
  statusMessage: res.statusMessage,
@@ -3545,7 +3468,7 @@ async function makeRequest(urlStr, options = { method: "GET" }) {
3545
3468
  });
3546
3469
  req.on("error", (error) => {
3547
3470
  clearTimeout(timeout);
3548
- resolve6({ success: false, error: error.message });
3471
+ resolve5({ success: false, error: error.message });
3549
3472
  });
3550
3473
  if (options.body) {
3551
3474
  req.write(options.body);
@@ -3553,7 +3476,7 @@ async function makeRequest(urlStr, options = { method: "GET" }) {
3553
3476
  req.end();
3554
3477
  } catch (error) {
3555
3478
  clearTimeout(timeout);
3556
- resolve6({ success: false, error: error instanceof Error ? error.message : "Request failed" });
3479
+ resolve5({ success: false, error: error instanceof Error ? error.message : "Request failed" });
3557
3480
  }
3558
3481
  });
3559
3482
  }
@@ -3852,408 +3775,6 @@ registerCommand({
3852
3775
  }
3853
3776
  });
3854
3777
 
3855
- // src/plugins/loader.ts
3856
- import { existsSync as existsSync8, readdirSync as readdirSync2, readFileSync as readFileSync7, mkdirSync as mkdirSync2 } from "fs";
3857
- import { join as join6, dirname as dirname3 } from "path";
3858
- import { homedir as homedir3 } from "os";
3859
- import { pathToFileURL, fileURLToPath as fileURLToPath2 } from "url";
3860
-
3861
- // src/plugins/api.ts
3862
- import { execSync, spawn as nodeSpawn } from "child_process";
3863
- import { join as join5 } from "path";
3864
-
3865
- // src/plugins/storage.ts
3866
- import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync } from "fs";
3867
- import { join as join4 } from "path";
3868
- function createPluginStorage(pluginName, dataDir) {
3869
- const storagePath = join4(dataDir, "data.json");
3870
- if (!existsSync7(dataDir)) {
3871
- mkdirSync(dataDir, { recursive: true });
3872
- }
3873
- function loadData() {
3874
- try {
3875
- if (existsSync7(storagePath)) {
3876
- const content = readFileSync5(storagePath, "utf-8");
3877
- return JSON.parse(content);
3878
- }
3879
- } catch {
3880
- }
3881
- return {};
3882
- }
3883
- function saveData(data) {
3884
- try {
3885
- writeFileSync3(storagePath, JSON.stringify(data, null, 2), "utf-8");
3886
- } catch (error) {
3887
- console.error(`Failed to save plugin storage for ${pluginName}:`, error);
3888
- }
3889
- }
3890
- return {
3891
- get(key) {
3892
- const data = loadData();
3893
- return data[key];
3894
- },
3895
- set(key, value) {
3896
- const data = loadData();
3897
- data[key] = value;
3898
- saveData(data);
3899
- },
3900
- delete(key) {
3901
- const data = loadData();
3902
- delete data[key];
3903
- saveData(data);
3904
- },
3905
- clear() {
3906
- saveData({});
3907
- },
3908
- getAll() {
3909
- return loadData();
3910
- }
3911
- };
3912
- }
3913
-
3914
- // src/plugins/api.ts
3915
- import { readFileSync as readFileSync6 } from "fs";
3916
- import { fileURLToPath } from "url";
3917
- import { dirname as dirname2 } from "path";
3918
- function getZammyVersion() {
3919
- try {
3920
- const __filename = fileURLToPath(import.meta.url);
3921
- const __dirname = dirname2(__filename);
3922
- const pkgPath = join5(__dirname, "..", "..", "package.json");
3923
- const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
3924
- return pkg.version || "0.0.0";
3925
- } catch {
3926
- return "0.0.0";
3927
- }
3928
- }
3929
- function createPluginUI() {
3930
- return {
3931
- theme: {
3932
- primary: theme.primary,
3933
- secondary: theme.secondary,
3934
- accent: theme.accent,
3935
- success: theme.success,
3936
- warning: theme.warning,
3937
- error: theme.error,
3938
- info: theme.info,
3939
- dim: theme.dim,
3940
- gradient: theme.gradient
3941
- },
3942
- symbols: {
3943
- check: symbols.check,
3944
- cross: symbols.cross,
3945
- star: symbols.star,
3946
- arrow: symbols.arrow,
3947
- bullet: symbols.bullet,
3948
- folder: symbols.folder,
3949
- file: "\u{1F4C4}",
3950
- // 📄
3951
- warning: symbols.warning,
3952
- info: symbols.info,
3953
- rocket: symbols.rocket,
3954
- sparkles: symbols.sparkle
3955
- },
3956
- box: (content, options) => {
3957
- const lines = content.split("\n");
3958
- const width = Math.max(...lines.map((l) => l.replace(/\x1B\[[0-9;]*m/g, "").length)) + 4;
3959
- return box.draw(lines, width);
3960
- },
3961
- progressBar: (current, total, width) => {
3962
- const percent = Math.round(current / total * 100);
3963
- return progressBar(percent, width || 30);
3964
- }
3965
- };
3966
- }
3967
- function createPluginLogger(pluginName) {
3968
- const prefix = theme.dim(`[${pluginName}]`);
3969
- return {
3970
- info: (message) => console.log(`${prefix} ${theme.info(message)}`),
3971
- warn: (message) => console.log(`${prefix} ${theme.warning(message)}`),
3972
- error: (message) => console.log(`${prefix} ${theme.error(message)}`),
3973
- debug: (message) => {
3974
- if (process.env.ZAMMY_DEBUG) {
3975
- console.log(`${prefix} ${theme.dim(message)}`);
3976
- }
3977
- }
3978
- };
3979
- }
3980
- function createPluginShell(manifest) {
3981
- if (!manifest.permissions?.shell) {
3982
- return void 0;
3983
- }
3984
- return {
3985
- exec: (command, options) => {
3986
- try {
3987
- return execSync(command, {
3988
- encoding: "utf-8",
3989
- timeout: options?.timeout || 3e4,
3990
- stdio: ["pipe", "pipe", "pipe"]
3991
- });
3992
- } catch (error) {
3993
- if (error && typeof error === "object" && "stdout" in error) {
3994
- return error.stdout || "";
3995
- }
3996
- throw error;
3997
- }
3998
- },
3999
- spawn: (command, args2) => {
4000
- return new Promise((resolve6) => {
4001
- const proc = nodeSpawn(command, args2 || [], {
4002
- shell: true,
4003
- stdio: ["pipe", "pipe", "pipe"]
4004
- });
4005
- let stdout = "";
4006
- let stderr = "";
4007
- proc.stdout?.on("data", (data) => {
4008
- stdout += data.toString();
4009
- });
4010
- proc.stderr?.on("data", (data) => {
4011
- stderr += data.toString();
4012
- });
4013
- proc.on("close", (code) => {
4014
- resolve6({ stdout, stderr, code: code || 0 });
4015
- });
4016
- proc.on("error", () => {
4017
- resolve6({ stdout, stderr, code: 1 });
4018
- });
4019
- });
4020
- }
4021
- };
4022
- }
4023
- function createPluginAPI(manifest, pluginPath) {
4024
- const dataDir = pluginPath;
4025
- const context = {
4026
- pluginName: manifest.name,
4027
- pluginVersion: manifest.version,
4028
- zammyVersion: getZammyVersion(),
4029
- dataDir,
4030
- cwd: process.cwd()
4031
- };
4032
- return {
4033
- registerCommand: (command) => {
4034
- registerPluginCommand(command, manifest.name);
4035
- },
4036
- registerCommands: (commands2) => {
4037
- for (const command of commands2) {
4038
- registerPluginCommand(command, manifest.name);
4039
- }
4040
- },
4041
- ui: createPluginUI(),
4042
- storage: createPluginStorage(manifest.name, dataDir),
4043
- log: createPluginLogger(manifest.name),
4044
- context,
4045
- shell: createPluginShell(manifest)
4046
- };
4047
- }
4048
-
4049
- // src/plugins/loader.ts
4050
- var PLUGINS_DIR = join6(homedir3(), ".zammy", "plugins");
4051
- function getZammyVersion2() {
4052
- try {
4053
- const __filename = fileURLToPath2(import.meta.url);
4054
- const __dirname = dirname3(__filename);
4055
- const possiblePaths = [
4056
- join6(__dirname, "package.json"),
4057
- // Same dir (bundled: dist/)
4058
- join6(__dirname, "..", "package.json"),
4059
- // One up (bundled: project root)
4060
- join6(__dirname, "..", "..", "package.json")
4061
- // Two up (source: src/plugins/)
4062
- ];
4063
- for (const pkgPath of possiblePaths) {
4064
- if (existsSync8(pkgPath)) {
4065
- const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
4066
- if (pkg.name === "zammy" && pkg.version) {
4067
- return pkg.version;
4068
- }
4069
- }
4070
- }
4071
- return "0.0.0";
4072
- } catch {
4073
- return "0.0.0";
4074
- }
4075
- }
4076
- function compareVersions(a, b3) {
4077
- const partsA = a.split(".").map((n) => parseInt(n, 10) || 0);
4078
- const partsB = b3.split(".").map((n) => parseInt(n, 10) || 0);
4079
- for (let i = 0; i < 3; i++) {
4080
- const numA = partsA[i] || 0;
4081
- const numB = partsB[i] || 0;
4082
- if (numA < numB) return -1;
4083
- if (numA > numB) return 1;
4084
- }
4085
- return 0;
4086
- }
4087
- function checkVersionCompatibility(manifest, zammyVersion) {
4088
- const minVersion = manifest.zammy?.minVersion;
4089
- const maxVersion = manifest.zammy?.maxVersion;
4090
- if (minVersion && compareVersions(zammyVersion, minVersion) < 0) {
4091
- return {
4092
- compatible: false,
4093
- reason: `Requires Zammy v${minVersion}+, but you have v${zammyVersion}`
4094
- };
4095
- }
4096
- if (maxVersion && compareVersions(zammyVersion, maxVersion) > 0) {
4097
- return {
4098
- compatible: false,
4099
- reason: `Incompatible with Zammy v${zammyVersion} (max: v${maxVersion})`
4100
- };
4101
- }
4102
- return { compatible: true };
4103
- }
4104
- var discoveredPlugins = /* @__PURE__ */ new Map();
4105
- var loadedPlugins = /* @__PURE__ */ new Map();
4106
- function ensurePluginsDir() {
4107
- if (!existsSync8(PLUGINS_DIR)) {
4108
- mkdirSync2(PLUGINS_DIR, { recursive: true });
4109
- }
4110
- }
4111
- function getPluginsDir() {
4112
- return PLUGINS_DIR;
4113
- }
4114
- async function discoverPlugins() {
4115
- ensurePluginsDir();
4116
- discoveredPlugins.clear();
4117
- if (!existsSync8(PLUGINS_DIR)) {
4118
- return [];
4119
- }
4120
- const zammyVersion = getZammyVersion2();
4121
- const entries = readdirSync2(PLUGINS_DIR, { withFileTypes: true });
4122
- const manifests = [];
4123
- for (const entry of entries) {
4124
- if (!entry.isDirectory()) continue;
4125
- const pluginPath = join6(PLUGINS_DIR, entry.name);
4126
- const manifestPath = join6(pluginPath, "zammy-plugin.json");
4127
- if (!existsSync8(manifestPath)) continue;
4128
- try {
4129
- const manifestContent = readFileSync7(manifestPath, "utf-8");
4130
- const manifest = JSON.parse(manifestContent);
4131
- if (!manifest.name || !manifest.version || !manifest.main || !manifest.commands) {
4132
- console.log(theme.warning(` ${symbols.warning} Invalid manifest for plugin in ${entry.name}`));
4133
- continue;
4134
- }
4135
- const compatibility = checkVersionCompatibility(manifest, zammyVersion);
4136
- if (!compatibility.compatible) {
4137
- console.log(theme.warning(` ${symbols.warning} Plugin '${manifest.name}' skipped: ${compatibility.reason}`));
4138
- continue;
4139
- }
4140
- discoveredPlugins.set(manifest.name, { manifest, path: pluginPath });
4141
- manifests.push(manifest);
4142
- } catch (error) {
4143
- console.log(theme.warning(` ${symbols.warning} Failed to read manifest for ${entry.name}`));
4144
- }
4145
- }
4146
- return manifests;
4147
- }
4148
- async function loadPlugin(name) {
4149
- if (loadedPlugins.has(name)) {
4150
- const existing = loadedPlugins.get(name);
4151
- if (existing.state === "error") {
4152
- return null;
4153
- }
4154
- return existing;
4155
- }
4156
- const discovered = discoveredPlugins.get(name);
4157
- if (!discovered) {
4158
- return null;
4159
- }
4160
- const { manifest, path: pluginPath } = discovered;
4161
- try {
4162
- const mainPath = join6(pluginPath, manifest.main);
4163
- if (!existsSync8(mainPath)) {
4164
- throw new Error(`Plugin entry point not found: ${mainPath}`);
4165
- }
4166
- const moduleUrl = pathToFileURL(mainPath).href;
4167
- const module = await import(moduleUrl);
4168
- const plugin = module.default;
4169
- if (!plugin || typeof plugin.activate !== "function") {
4170
- throw new Error("Plugin must export a default object with an activate function");
4171
- }
4172
- const api = createPluginAPI(manifest, pluginPath);
4173
- try {
4174
- await plugin.activate(api);
4175
- } catch (activationError) {
4176
- const msg = activationError instanceof Error ? activationError.message : String(activationError);
4177
- throw new Error(`Plugin activation failed: ${msg}`);
4178
- }
4179
- const loaded = {
4180
- manifest,
4181
- instance: plugin,
4182
- path: pluginPath,
4183
- state: "active"
4184
- };
4185
- loadedPlugins.set(name, loaded);
4186
- return loaded;
4187
- } catch (error) {
4188
- const errorMessage = error instanceof Error ? error.message : String(error);
4189
- console.log(theme.error(` ${symbols.cross} Failed to load plugin '${name}': ${errorMessage}`));
4190
- const failedPlugin = {
4191
- manifest,
4192
- instance: { activate: async () => {
4193
- } },
4194
- path: pluginPath,
4195
- state: "error"
4196
- };
4197
- loadedPlugins.set(name, failedPlugin);
4198
- return null;
4199
- }
4200
- }
4201
- async function unloadPlugin(name) {
4202
- const loaded = loadedPlugins.get(name);
4203
- if (!loaded) {
4204
- return false;
4205
- }
4206
- try {
4207
- if (loaded.instance.deactivate) {
4208
- await loaded.instance.deactivate();
4209
- }
4210
- unregisterPluginCommands(name);
4211
- loadedPlugins.delete(name);
4212
- return true;
4213
- } catch (error) {
4214
- const errorMessage = error instanceof Error ? error.message : String(error);
4215
- console.log(theme.error(` ${symbols.cross} Failed to unload plugin '${name}': ${errorMessage}`));
4216
- return false;
4217
- }
4218
- }
4219
- function getDiscoveredPlugins() {
4220
- return Array.from(discoveredPlugins.values()).map((p) => p.manifest);
4221
- }
4222
- function isPluginLoaded(name) {
4223
- return loadedPlugins.has(name);
4224
- }
4225
- async function initPluginLoader() {
4226
- const manifests = await discoverPlugins();
4227
- for (const manifest of manifests) {
4228
- for (const cmdName of manifest.commands) {
4229
- const lazyExecute = async (args2) => {
4230
- const loaded = await loadPlugin(manifest.name);
4231
- if (!loaded) {
4232
- console.log(theme.error(` ${symbols.cross} Failed to load plugin '${manifest.name}'`));
4233
- console.log(theme.dim(` Try reinstalling: /plugin remove ${manifest.name} && /plugin install ${manifest.name}`));
4234
- return;
4235
- }
4236
- const realCommand = getCommand(cmdName);
4237
- if (realCommand && realCommand.execute !== lazyExecute) {
4238
- await realCommand.execute(args2);
4239
- } else {
4240
- console.log(theme.error(` ${symbols.cross} Plugin '${manifest.name}' did not register command '${cmdName}'`));
4241
- console.log(theme.dim(` The plugin may be misconfigured or corrupted.`));
4242
- }
4243
- };
4244
- registerPluginCommand(
4245
- {
4246
- name: cmdName,
4247
- description: `[${manifest.displayName || manifest.name}] Plugin command`,
4248
- usage: `/${cmdName}`,
4249
- execute: lazyExecute
4250
- },
4251
- manifest.name
4252
- );
4253
- }
4254
- }
4255
- }
4256
-
4257
3778
  // src/commands/plugin/list.ts
4258
3779
  async function listPlugins() {
4259
3780
  await discoverPlugins();
@@ -4291,358 +3812,96 @@ async function listPlugins() {
4291
3812
  }
4292
3813
  }
4293
3814
 
4294
- // src/plugins/installer.ts
4295
- import { existsSync as existsSync9, mkdirSync as mkdirSync3, cpSync, rmSync, readFileSync as readFileSync8, readdirSync as readdirSync3, createReadStream, createWriteStream } from "fs";
4296
- import { join as join7, resolve as resolve3, dirname as dirname4 } from "path";
4297
- import { execSync as execSync2 } from "child_process";
4298
- import { tmpdir, platform as platform2 } from "os";
4299
- import { createGunzip } from "zlib";
4300
- import { pipeline } from "stream/promises";
4301
- import { fileURLToPath as fileURLToPath3 } from "url";
4302
- var isWindows = platform2() === "win32";
4303
- function getZammyVersion3() {
4304
- try {
4305
- const __filename = fileURLToPath3(import.meta.url);
4306
- const __dirname = dirname4(__filename);
4307
- const possiblePaths = [
4308
- join7(__dirname, "package.json"),
4309
- join7(__dirname, "..", "package.json"),
4310
- join7(__dirname, "..", "..", "package.json")
4311
- ];
4312
- for (const pkgPath of possiblePaths) {
4313
- if (existsSync9(pkgPath)) {
4314
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
4315
- if (pkg.name === "zammy" && pkg.version) {
4316
- return pkg.version;
4317
- }
3815
+ // src/ui/input.ts
3816
+ async function confirm(message, defaultNo = true, options = {}) {
3817
+ const stdin = options.stdin || process.stdin;
3818
+ const stdout = options.stdout || process.stdout;
3819
+ const suffix = defaultNo ? "[y/N]" : "[Y/n]";
3820
+ stdout.write(`${message} ${theme.dim(suffix)} `);
3821
+ return new Promise((resolve5) => {
3822
+ const isTTY2 = "isTTY" in stdin && stdin.isTTY;
3823
+ const wasRaw = "isRaw" in stdin ? stdin.isRaw : false;
3824
+ if (isTTY2 && stdin.setRawMode) {
3825
+ stdin.setRawMode(true);
3826
+ }
3827
+ stdin.resume();
3828
+ const onData = (data) => {
3829
+ const char = data.toString()[0]?.toLowerCase() || "";
3830
+ if (isTTY2 && stdin.setRawMode) {
3831
+ stdin.setRawMode(wasRaw || false);
4318
3832
  }
4319
- }
4320
- return "0.0.0";
4321
- } catch {
4322
- return "0.0.0";
4323
- }
4324
- }
4325
- function compareVersions2(a, b3) {
4326
- const partsA = a.split(".").map((n) => parseInt(n, 10) || 0);
4327
- const partsB = b3.split(".").map((n) => parseInt(n, 10) || 0);
4328
- for (let i = 0; i < 3; i++) {
4329
- const numA = partsA[i] || 0;
4330
- const numB = partsB[i] || 0;
4331
- if (numA < numB) return -1;
4332
- if (numA > numB) return 1;
4333
- }
4334
- return 0;
4335
- }
4336
- function checkVersionCompatibility2(manifest) {
4337
- const zammyVersion = getZammyVersion3();
4338
- const minVersion = manifest.zammy?.minVersion;
4339
- const maxVersion = manifest.zammy?.maxVersion;
4340
- if (minVersion && compareVersions2(zammyVersion, minVersion) < 0) {
4341
- return {
4342
- compatible: false,
4343
- reason: `Requires Zammy v${minVersion}+, but you have v${zammyVersion}`
4344
- };
4345
- }
4346
- if (maxVersion && compareVersions2(zammyVersion, maxVersion) > 0) {
4347
- return {
4348
- compatible: false,
4349
- reason: `Incompatible with Zammy v${zammyVersion} (max supported: v${maxVersion})`
4350
- };
4351
- }
4352
- return { compatible: true };
4353
- }
4354
- async function extractTarGz(tarGzPath, destDir) {
4355
- try {
4356
- execSync2(`tar -xzf "${tarGzPath}" -C "${destDir}"`, {
4357
- encoding: "utf-8",
4358
- stdio: ["pipe", "pipe", "pipe"]
4359
- });
4360
- return;
4361
- } catch {
4362
- }
4363
- const tarPath = tarGzPath.replace(/\.tgz$|\.tar\.gz$/, ".tar");
4364
- await pipeline(
4365
- createReadStream(tarGzPath),
4366
- createGunzip(),
4367
- createWriteStream(tarPath)
4368
- );
4369
- try {
4370
- execSync2(`tar -xf "${tarPath}" -C "${destDir}"`, {
4371
- encoding: "utf-8",
4372
- stdio: ["pipe", "pipe", "pipe"]
4373
- });
4374
- rmSync(tarPath, { force: true });
4375
- return;
4376
- } catch {
4377
- rmSync(tarPath, { force: true });
4378
- }
4379
- if (isWindows) {
4380
- try {
4381
- execSync2(`powershell -Command "tar -xf '${tarPath}' -C '${destDir}'"`, {
4382
- encoding: "utf-8",
4383
- stdio: ["pipe", "pipe", "pipe"]
4384
- });
4385
- return;
4386
- } catch {
4387
- throw new Error(
4388
- "Unable to extract plugin archive. Please ensure tar is available.\nOn Windows 10+, tar should be built-in. Try running: tar --version"
4389
- );
4390
- }
4391
- }
4392
- throw new Error("Unable to extract plugin archive. Please ensure tar is installed.");
4393
- }
4394
- function validateManifest(manifest) {
4395
- const errors = [];
4396
- if (!manifest || typeof manifest !== "object") {
4397
- return { valid: false, errors: ["Manifest must be an object"] };
4398
- }
4399
- const m = manifest;
4400
- if (!m.name || typeof m.name !== "string") {
4401
- errors.push('Missing or invalid "name" field');
4402
- }
4403
- if (!m.version || typeof m.version !== "string") {
4404
- errors.push('Missing or invalid "version" field');
4405
- }
4406
- if (!m.main || typeof m.main !== "string") {
4407
- errors.push('Missing or invalid "main" field');
4408
- }
4409
- if (!m.commands || !Array.isArray(m.commands) || m.commands.length === 0) {
4410
- errors.push('Missing or invalid "commands" field (must be non-empty array)');
4411
- }
4412
- if (!m.zammy || typeof m.zammy !== "object") {
4413
- errors.push('Missing or invalid "zammy" field');
4414
- } else {
4415
- const zammy = m.zammy;
4416
- if (!zammy.minVersion || typeof zammy.minVersion !== "string") {
4417
- errors.push('Missing or invalid "zammy.minVersion" field');
4418
- }
4419
- }
4420
- return { valid: errors.length === 0, errors };
4421
- }
4422
- function checkConflicts(manifest) {
4423
- const conflicts = [];
4424
- for (const cmd of manifest.commands) {
4425
- const conflict = checkCommandConflict(cmd);
4426
- if (conflict.exists) {
4427
- if (conflict.source === "core") {
4428
- conflicts.push(`Command '/${cmd}' conflicts with core zammy command`);
3833
+ stdin.removeListener("data", onData);
3834
+ stdin.pause();
3835
+ if (char === "y") {
3836
+ stdout.write("y\n");
3837
+ resolve5(true);
3838
+ } else if (char === "n") {
3839
+ stdout.write("n\n");
3840
+ resolve5(false);
3841
+ } else if (char === "\r" || char === "\n") {
3842
+ stdout.write(defaultNo ? "n\n" : "y\n");
3843
+ resolve5(!defaultNo);
3844
+ } else if (char === "") {
3845
+ stdout.write("\n");
3846
+ resolve5(false);
4429
3847
  } else {
4430
- conflicts.push(`Command '/${cmd}' conflicts with plugin '${conflict.pluginName}'`);
3848
+ stdout.write("\n");
3849
+ resolve5(false);
4431
3850
  }
4432
- }
4433
- }
4434
- return { hasConflicts: conflicts.length > 0, conflicts };
4435
- }
4436
- function formatPermissions(manifest) {
4437
- const perms = [];
4438
- const p = manifest.permissions;
4439
- if (!p) return perms;
4440
- if (p.shell) {
4441
- perms.push(`${symbols.warning} shell: Can run system commands`);
4442
- }
4443
- if (p.filesystem) {
4444
- if (p.filesystem === true) {
4445
- perms.push(`${symbols.warning} filesystem: Full file system access`);
4446
- } else if (Array.isArray(p.filesystem)) {
4447
- perms.push(`${symbols.info} filesystem: Access to ${p.filesystem.join(", ")}`);
4448
- }
4449
- }
4450
- if (p.network) {
4451
- if (p.network === true) {
4452
- perms.push(`${symbols.warning} network: Full network access`);
4453
- } else if (Array.isArray(p.network)) {
4454
- perms.push(`${symbols.info} network: Access to ${p.network.join(", ")}`);
4455
- }
4456
- }
4457
- return perms;
4458
- }
4459
- async function installFromLocal(sourcePath) {
4460
- try {
4461
- const absPath = resolve3(sourcePath);
4462
- if (!existsSync9(absPath)) {
4463
- return { success: false, error: `Path not found: ${absPath}` };
4464
- }
4465
- const manifestPath = join7(absPath, "zammy-plugin.json");
4466
- if (!existsSync9(manifestPath)) {
4467
- return { success: false, error: "No zammy-plugin.json found in source directory" };
4468
- }
4469
- const manifestContent = readFileSync8(manifestPath, "utf-8");
4470
- let manifest;
4471
- try {
4472
- manifest = JSON.parse(manifestContent);
4473
- } catch {
4474
- return { success: false, error: "Invalid JSON in zammy-plugin.json" };
4475
- }
4476
- const validation = validateManifest(manifest);
4477
- if (!validation.valid) {
4478
- return { success: false, error: `Invalid manifest: ${validation.errors.join(", ")}` };
4479
- }
4480
- const versionCheck = checkVersionCompatibility2(manifest);
4481
- if (!versionCheck.compatible) {
4482
- return { success: false, error: versionCheck.reason };
4483
- }
4484
- const mainPath = join7(absPath, manifest.main);
4485
- if (!existsSync9(mainPath)) {
4486
- return { success: false, error: `Entry point not found: ${manifest.main}` };
4487
- }
4488
- ensurePluginsDir();
4489
- const targetDir = join7(getPluginsDir(), manifest.name);
4490
- if (existsSync9(targetDir)) {
4491
- rmSync(targetDir, { recursive: true, force: true });
4492
- }
4493
- cpSync(absPath, targetDir, { recursive: true });
4494
- return { success: true, manifest };
4495
- } catch (error) {
4496
- const message = error instanceof Error ? error.message : String(error);
4497
- return { success: false, error: message };
4498
- }
4499
- }
4500
- async function installFromNpm(packageName) {
4501
- const tempDir = join7(tmpdir(), `zammy-plugin-${Date.now()}`);
4502
- try {
4503
- mkdirSync3(tempDir, { recursive: true });
4504
- console.log(theme.dim(` Downloading ${packageName}...`));
4505
- execSync2(`npm pack ${packageName} --pack-destination="${tempDir}"`, {
4506
- encoding: "utf-8",
4507
- stdio: ["pipe", "pipe", "pipe"],
4508
- timeout: 6e4
4509
- });
4510
- const files = readdirSync3(tempDir);
4511
- const tarball = files.find((f) => f.endsWith(".tgz"));
4512
- if (!tarball) {
4513
- return { success: false, error: "Failed to download package" };
4514
- }
4515
- const extractDir = join7(tempDir, "extract");
4516
- mkdirSync3(extractDir);
4517
- await extractTarGz(join7(tempDir, tarball), extractDir);
4518
- const packageDir = join7(extractDir, "package");
4519
- if (!existsSync9(packageDir)) {
4520
- return { success: false, error: "Invalid package structure" };
4521
- }
4522
- return await installFromLocal(packageDir);
4523
- } catch (error) {
4524
- const message = error instanceof Error ? error.message : String(error);
4525
- return { success: false, error: `npm install failed: ${message}` };
4526
- } finally {
4527
- try {
4528
- rmSync(tempDir, { recursive: true, force: true });
4529
- } catch {
4530
- }
4531
- }
4532
- }
4533
- async function installFromGithub(repo) {
4534
- const tempDir = join7(tmpdir(), `zammy-plugin-${Date.now()}`);
4535
- try {
4536
- let repoPath = repo.replace(/^github:/, "");
4537
- let branch = "main";
4538
- if (repoPath.includes("#")) {
4539
- [repoPath, branch] = repoPath.split("#");
4540
- }
4541
- mkdirSync3(tempDir, { recursive: true });
4542
- console.log(theme.dim(` Cloning ${repoPath}...`));
4543
- execSync2(`git clone --depth 1 --branch ${branch} https://github.com/${repoPath}.git "${tempDir}"`, {
4544
- encoding: "utf-8",
4545
- stdio: ["pipe", "pipe", "pipe"],
4546
- timeout: 12e4
4547
- });
4548
- const pkgJsonPath = join7(tempDir, "package.json");
4549
- if (existsSync9(pkgJsonPath)) {
4550
- const pkgJson = JSON.parse(readFileSync8(pkgJsonPath, "utf-8"));
4551
- if (pkgJson.scripts?.build) {
4552
- console.log(theme.dim(` Installing dependencies...`));
4553
- execSync2("npm install", { cwd: tempDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 12e4 });
4554
- console.log(theme.dim(` Building...`));
4555
- execSync2("npm run build", { cwd: tempDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 12e4 });
4556
- }
4557
- }
4558
- return await installFromLocal(tempDir);
4559
- } catch (error) {
4560
- const message = error instanceof Error ? error.message : String(error);
4561
- return { success: false, error: `GitHub install failed: ${message}` };
4562
- } finally {
4563
- try {
4564
- rmSync(tempDir, { recursive: true, force: true });
4565
- } catch {
4566
- }
4567
- }
3851
+ };
3852
+ stdin.once("data", onData);
3853
+ });
4568
3854
  }
4569
- async function installFromGit(url) {
4570
- const tempDir = join7(tmpdir(), `zammy-plugin-${Date.now()}`);
4571
- try {
4572
- mkdirSync3(tempDir, { recursive: true });
4573
- console.log(theme.dim(` Cloning from ${url}...`));
4574
- execSync2(`git clone --depth 1 "${url}" "${tempDir}"`, {
4575
- encoding: "utf-8",
4576
- stdio: ["pipe", "pipe", "pipe"],
4577
- timeout: 12e4
4578
- });
4579
- const pkgJsonPath = join7(tempDir, "package.json");
4580
- if (existsSync9(pkgJsonPath)) {
4581
- const pkgJson = JSON.parse(readFileSync8(pkgJsonPath, "utf-8"));
4582
- if (pkgJson.scripts?.build) {
4583
- console.log(theme.dim(` Installing dependencies...`));
4584
- execSync2("npm install", { cwd: tempDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 12e4 });
4585
- console.log(theme.dim(` Building...`));
4586
- execSync2("npm run build", { cwd: tempDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 12e4 });
3855
+ async function prompt(message, defaultValue, options = {}) {
3856
+ const stdin = options.stdin || process.stdin;
3857
+ const stdout = options.stdout || process.stdout;
3858
+ const suffix = defaultValue ? ` ${theme.dim(`(${defaultValue})`)}` : "";
3859
+ stdout.write(` ${message}${suffix}: `);
3860
+ return new Promise((resolve5) => {
3861
+ let input = "";
3862
+ const isTTY2 = "isTTY" in stdin && stdin.isTTY;
3863
+ const wasRaw = "isRaw" in stdin ? stdin.isRaw : false;
3864
+ if (isTTY2 && stdin.setRawMode) {
3865
+ stdin.setRawMode(true);
3866
+ }
3867
+ stdin.resume();
3868
+ const onData = (data) => {
3869
+ const chars = data.toString();
3870
+ for (const char of chars) {
3871
+ if (char === "\r" || char === "\n") {
3872
+ if (isTTY2 && stdin.setRawMode) {
3873
+ stdin.setRawMode(wasRaw || false);
3874
+ }
3875
+ stdin.removeListener("data", onData);
3876
+ stdin.pause();
3877
+ stdout.write("\n");
3878
+ resolve5(input.trim() || defaultValue || "");
3879
+ return;
3880
+ } else if (char === "") {
3881
+ if (isTTY2 && stdin.setRawMode) {
3882
+ stdin.setRawMode(wasRaw || false);
3883
+ }
3884
+ stdin.removeListener("data", onData);
3885
+ stdin.pause();
3886
+ stdout.write("\n");
3887
+ resolve5(defaultValue || "");
3888
+ return;
3889
+ } else if (char === "\x7F" || char === "\b") {
3890
+ if (input.length > 0) {
3891
+ input = input.slice(0, -1);
3892
+ stdout.write("\b \b");
3893
+ }
3894
+ } else if (char >= " " && char <= "~") {
3895
+ input += char;
3896
+ stdout.write(char);
3897
+ }
4587
3898
  }
4588
- }
4589
- return await installFromLocal(tempDir);
4590
- } catch (error) {
4591
- const message = error instanceof Error ? error.message : String(error);
4592
- return { success: false, error: `Git install failed: ${message}` };
4593
- } finally {
4594
- try {
4595
- rmSync(tempDir, { recursive: true, force: true });
4596
- } catch {
4597
- }
4598
- }
4599
- }
4600
- function removePlugin(name) {
4601
- try {
4602
- const pluginDir = join7(getPluginsDir(), name);
4603
- if (!existsSync9(pluginDir)) {
4604
- return { success: false, error: `Plugin '${name}' not found` };
4605
- }
4606
- rmSync(pluginDir, { recursive: true, force: true });
4607
- return { success: true };
4608
- } catch (error) {
4609
- const message = error instanceof Error ? error.message : String(error);
4610
- return { success: false, error: message };
4611
- }
4612
- }
4613
- function detectSourceType(source) {
4614
- if (source.startsWith("./") || source.startsWith("/") || source.startsWith("..") || /^[A-Za-z]:/.test(source)) {
4615
- return "local";
4616
- }
4617
- if (source.startsWith("github:")) {
4618
- return "github";
4619
- }
4620
- if (source.includes("github.com")) {
4621
- return "github";
4622
- }
4623
- if (source.endsWith(".git") || source.startsWith("git@") || source.startsWith("git://")) {
4624
- return "git";
4625
- }
4626
- if (/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(source)) {
4627
- return "npm";
4628
- }
4629
- return "unknown";
3899
+ };
3900
+ stdin.on("data", onData);
3901
+ });
4630
3902
  }
4631
3903
 
4632
3904
  // src/commands/plugin/install.ts
4633
- import * as readline from "readline";
4634
- async function confirm(message) {
4635
- const rl = readline.createInterface({
4636
- input: process.stdin,
4637
- output: process.stdout
4638
- });
4639
- return new Promise((resolve6) => {
4640
- rl.question(`${message} [y/N] `, (answer) => {
4641
- rl.close();
4642
- resolve6(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
4643
- });
4644
- });
4645
- }
4646
3905
  async function installPlugin(args2) {
4647
3906
  const source = args2[0];
4648
3907
  if (!source) {
@@ -4749,19 +4008,6 @@ async function installPlugin(args2) {
4749
4008
  }
4750
4009
 
4751
4010
  // src/commands/plugin/remove.ts
4752
- import * as readline2 from "readline";
4753
- async function confirm2(message) {
4754
- const rl = readline2.createInterface({
4755
- input: process.stdin,
4756
- output: process.stdout
4757
- });
4758
- return new Promise((resolve6) => {
4759
- rl.question(`${message} [y/N] `, (answer) => {
4760
- rl.close();
4761
- resolve6(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
4762
- });
4763
- });
4764
- }
4765
4011
  async function removePluginCommand(args2) {
4766
4012
  const forceIndex = args2.findIndex((a) => a === "-y" || a === "--yes");
4767
4013
  const skipConfirm = forceIndex !== -1;
@@ -4809,7 +4055,7 @@ async function removePluginCommand(args2) {
4809
4055
  console.log(` ${theme.dim("Commands:")} ${plugin.commands.map((c) => "/" + c).join(", ")}`);
4810
4056
  console.log("");
4811
4057
  if (!skipConfirm) {
4812
- const proceed = await confirm2(` ${theme.warning("Remove this plugin?")}`);
4058
+ const proceed = await confirm(` ${theme.warning("Remove this plugin?")}`);
4813
4059
  if (!proceed) {
4814
4060
  console.log(theme.dim(" Removal cancelled"));
4815
4061
  return;
@@ -4828,22 +4074,8 @@ async function removePluginCommand(args2) {
4828
4074
  }
4829
4075
 
4830
4076
  // src/commands/plugin/create.ts
4831
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
4832
- import { join as join8, resolve as resolve4 } from "path";
4833
- import * as readline3 from "readline";
4834
- async function prompt(message, defaultValue) {
4835
- const rl = readline3.createInterface({
4836
- input: process.stdin,
4837
- output: process.stdout
4838
- });
4839
- const suffix = defaultValue ? ` ${theme.dim(`(${defaultValue})`)}` : "";
4840
- return new Promise((resolvePromise) => {
4841
- rl.question(` ${message}${suffix}: `, (answer) => {
4842
- rl.close();
4843
- resolvePromise(answer.trim() || defaultValue || "");
4844
- });
4845
- });
4846
- }
4077
+ import { existsSync as existsSync7, mkdirSync, writeFileSync as writeFileSync3 } from "fs";
4078
+ import { join as join4, resolve as resolve3 } from "path";
4847
4079
  function generateManifest(name, displayName, description, commandName) {
4848
4080
  return JSON.stringify({
4849
4081
  name,
@@ -4865,12 +4097,17 @@ function generatePackageJson(name, description) {
4865
4097
  description,
4866
4098
  type: "module",
4867
4099
  main: "dist/index.js",
4100
+ types: "dist/index.d.ts",
4868
4101
  scripts: {
4869
4102
  build: "tsc",
4870
4103
  dev: "tsc --watch"
4871
4104
  },
4872
- keywords: ["zammy-plugin"],
4105
+ keywords: ["zammy-plugin", "zammy", "cli", "plugin"],
4106
+ peerDependencies: {
4107
+ zammy: "^1.3.0"
4108
+ },
4873
4109
  devDependencies: {
4110
+ zammy: "^1.3.0",
4874
4111
  typescript: "^5.3.0"
4875
4112
  }
4876
4113
  }, null, 2);
@@ -4894,65 +4131,7 @@ function generateTsConfig() {
4894
4131
  function generateEntryPoint(commandName, displayName) {
4895
4132
  return `// ${displayName} - A zammy plugin
4896
4133
 
4897
- // Plugin types (these match zammy's PluginAPI interface)
4898
- interface Command {
4899
- name: string;
4900
- description: string;
4901
- usage: string;
4902
- execute: (args: string[]) => Promise<void>;
4903
- }
4904
-
4905
- interface PluginAPI {
4906
- registerCommand(command: Command): void;
4907
- ui: {
4908
- theme: {
4909
- primary: (text: string) => string;
4910
- secondary: (text: string) => string;
4911
- accent: (text: string) => string;
4912
- success: (text: string) => string;
4913
- warning: (text: string) => string;
4914
- error: (text: string) => string;
4915
- info: (text: string) => string;
4916
- dim: (text: string) => string;
4917
- gradient: (text: string) => string;
4918
- };
4919
- symbols: {
4920
- check: string;
4921
- cross: string;
4922
- star: string;
4923
- arrow: string;
4924
- bullet: string;
4925
- folder: string;
4926
- file: string;
4927
- warning: string;
4928
- info: string;
4929
- rocket: string;
4930
- sparkles: string;
4931
- };
4932
- };
4933
- storage: {
4934
- get<T>(key: string): T | undefined;
4935
- set<T>(key: string, value: T): void;
4936
- delete(key: string): void;
4937
- };
4938
- log: {
4939
- info(message: string): void;
4940
- warn(message: string): void;
4941
- error(message: string): void;
4942
- };
4943
- context: {
4944
- pluginName: string;
4945
- pluginVersion: string;
4946
- zammyVersion: string;
4947
- dataDir: string;
4948
- cwd: string;
4949
- };
4950
- }
4951
-
4952
- interface ZammyPlugin {
4953
- activate(api: PluginAPI): Promise<void> | void;
4954
- deactivate?(): Promise<void> | void;
4955
- }
4134
+ import type { PluginAPI, ZammyPlugin } from 'zammy/plugins';
4956
4135
 
4957
4136
  const plugin: ZammyPlugin = {
4958
4137
  activate(api: PluginAPI) {
@@ -5033,22 +4212,22 @@ async function createPlugin(args2) {
5033
4212
  const displayName = await prompt("Display name", name.replace(/^zammy-plugin-/, "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
5034
4213
  const description = await prompt("Description", "A zammy plugin");
5035
4214
  const commandName = await prompt("Main command name", name.replace(/^zammy-plugin-/, "").replace(/-/g, ""));
5036
- const targetDir = resolve4(process.cwd(), name);
5037
- if (existsSync10(targetDir)) {
4215
+ const targetDir = resolve3(process.cwd(), name);
4216
+ if (existsSync7(targetDir)) {
5038
4217
  console.log(theme.error(` ${symbols.cross} Directory already exists: ${name}`));
5039
4218
  return;
5040
4219
  }
5041
4220
  console.log("");
5042
4221
  console.log(theme.dim(` Creating plugin in ${targetDir}...`));
5043
4222
  try {
5044
- mkdirSync4(targetDir);
5045
- mkdirSync4(join8(targetDir, "src"));
5046
- mkdirSync4(join8(targetDir, "dist"));
5047
- writeFileSync5(join8(targetDir, "zammy-plugin.json"), generateManifest(name, displayName, description, commandName));
5048
- writeFileSync5(join8(targetDir, "package.json"), generatePackageJson(name, description));
5049
- writeFileSync5(join8(targetDir, "tsconfig.json"), generateTsConfig());
5050
- writeFileSync5(join8(targetDir, "src", "index.ts"), generateEntryPoint(commandName, displayName));
5051
- writeFileSync5(join8(targetDir, "README.md"), generateReadme(name, displayName, description, commandName));
4223
+ mkdirSync(targetDir);
4224
+ mkdirSync(join4(targetDir, "src"));
4225
+ mkdirSync(join4(targetDir, "dist"));
4226
+ writeFileSync3(join4(targetDir, "zammy-plugin.json"), generateManifest(name, displayName, description, commandName));
4227
+ writeFileSync3(join4(targetDir, "package.json"), generatePackageJson(name, description));
4228
+ writeFileSync3(join4(targetDir, "tsconfig.json"), generateTsConfig());
4229
+ writeFileSync3(join4(targetDir, "src", "index.ts"), generateEntryPoint(commandName, displayName));
4230
+ writeFileSync3(join4(targetDir, "README.md"), generateReadme(name, displayName, description, commandName));
5052
4231
  console.log("");
5053
4232
  console.log(` ${symbols.check} ${theme.success("Plugin created successfully!")}`);
5054
4233
  console.log("");
@@ -5121,14 +4300,14 @@ registerCommand({
5121
4300
  });
5122
4301
 
5123
4302
  // src/cli.ts
5124
- import { exec, execSync as execSync3, spawn } from "child_process";
5125
- import { existsSync as existsSync11, statSync as statSync2, readFileSync as readFileSync9, readdirSync as readdirSync4, writeFileSync as writeFileSync6, watchFile, unwatchFile } from "fs";
5126
- import { resolve as resolve5, extname, basename as basename4, join as join9 } from "path";
5127
- import { homedir as homedir5, platform as platform3, networkInterfaces } from "os";
5128
- import chalk5 from "chalk";
5129
- var isWindows2 = platform3() === "win32";
4303
+ import { exec, execSync, spawn } from "child_process";
4304
+ import { existsSync as existsSync8, statSync as statSync2, readFileSync as readFileSync5, readdirSync as readdirSync2, writeFileSync as writeFileSync4, watchFile, unwatchFile } from "fs";
4305
+ import { resolve as resolve4, extname, basename as basename3, join as join5 } from "path";
4306
+ import { homedir as homedir3, platform as platform2, networkInterfaces } from "os";
4307
+ import chalk4 from "chalk";
4308
+ var isWindows = platform2() === "win32";
5130
4309
  function translateCommand(cmd) {
5131
- if (!isWindows2) return cmd;
4310
+ if (!isWindows) return cmd;
5132
4311
  const parts = cmd.trim().split(/\s+/);
5133
4312
  const command = parts[0].toLowerCase();
5134
4313
  const args2 = parts.slice(1);
@@ -5180,16 +4359,16 @@ function translateCommand(cmd) {
5180
4359
  function handleCd(args2) {
5181
4360
  let targetPath = args2.trim();
5182
4361
  if (!targetPath || targetPath === "~") {
5183
- targetPath = homedir5();
4362
+ targetPath = homedir3();
5184
4363
  } else if (targetPath.startsWith("~/")) {
5185
- targetPath = resolve5(homedir5(), targetPath.slice(2));
4364
+ targetPath = resolve4(homedir3(), targetPath.slice(2));
5186
4365
  } else if (targetPath === "-") {
5187
4366
  console.log(theme.dim(process.cwd()));
5188
4367
  return;
5189
4368
  } else {
5190
- targetPath = resolve5(process.cwd(), targetPath);
4369
+ targetPath = resolve4(process.cwd(), targetPath);
5191
4370
  }
5192
- if (!existsSync11(targetPath)) {
4371
+ if (!existsSync8(targetPath)) {
5193
4372
  console.log(`${miniSlime.sad} ${theme.error(`Directory not found: ${targetPath}`)}`);
5194
4373
  return;
5195
4374
  }
@@ -5209,13 +4388,13 @@ function handlePwd() {
5209
4388
  console.log(theme.primary(process.cwd()));
5210
4389
  }
5211
4390
  function handleCat(args2) {
5212
- const filePath = resolve5(process.cwd(), args2.trim());
5213
- if (!existsSync11(filePath)) {
4391
+ const filePath = resolve4(process.cwd(), args2.trim());
4392
+ if (!existsSync8(filePath)) {
5214
4393
  console.log(`${miniSlime.sad} ${theme.error(`File not found: ${args2}`)}`);
5215
4394
  return;
5216
4395
  }
5217
4396
  try {
5218
- const content = readFileSync9(filePath, "utf-8");
4397
+ const content = readFileSync5(filePath, "utf-8");
5219
4398
  const ext = extname(filePath).toLowerCase();
5220
4399
  if ([".js", ".ts", ".jsx", ".tsx", ".json", ".css", ".html", ".py", ".go", ".rs"].includes(ext)) {
5221
4400
  console.log(highlightSyntax(content, ext));
@@ -5232,13 +4411,13 @@ function highlightSyntax(content, ext) {
5232
4411
  py: ["def", "class", "import", "from", "return", "if", "elif", "else", "for", "while", "try", "except", "with", "as", "True", "False", "None", "and", "or", "not", "in", "is", "lambda", "async", "await"]
5233
4412
  };
5234
4413
  const kw = ext === ".py" ? keywords.py : keywords.js;
5235
- return content.split("\n").map((line) => {
5236
- line = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, (match) => chalk5.hex("#98C379")(match));
5237
- line = line.replace(/(\/\/.*$|#.*$)/g, (match) => chalk5.hex("#5C6370")(match));
5238
- line = line.replace(/\b(\d+\.?\d*)\b/g, (match) => chalk5.hex("#D19A66")(match));
4414
+ return content.split(/\r?\n/).map((line) => {
4415
+ line = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, (match) => chalk4.hex("#98C379")(match));
4416
+ line = line.replace(/(\/\/.*$|#.*$)/g, (match) => chalk4.hex("#5C6370")(match));
4417
+ line = line.replace(/\b(\d+\.?\d*)\b/g, (match) => chalk4.hex("#D19A66")(match));
5239
4418
  kw.forEach((keyword) => {
5240
4419
  const regex = new RegExp(`\\b(${keyword})\\b`, "g");
5241
- line = line.replace(regex, chalk5.hex("#C678DD")(keyword));
4420
+ line = line.replace(regex, chalk4.hex("#C678DD")(keyword));
5242
4421
  });
5243
4422
  return line;
5244
4423
  }).join("\n");
@@ -5303,24 +4482,24 @@ var fileIcons = {
5303
4482
  "default": { icon: "\u{1F4C4}", color: "#6C7A89" }
5304
4483
  };
5305
4484
  function formatSize(bytes) {
5306
- if (bytes === 0) return chalk5.dim(" 0 B");
4485
+ if (bytes === 0) return chalk4.dim(" 0 B");
5307
4486
  const units = ["B", "KB", "MB", "GB", "TB"];
5308
4487
  const i = Math.floor(Math.log(bytes) / Math.log(1024));
5309
4488
  const size = (bytes / Math.pow(1024, i)).toFixed(i > 0 ? 1 : 0);
5310
- return chalk5.hex("#98C379")(size.padStart(5) + " " + units[i].padEnd(2));
4489
+ return chalk4.hex("#98C379")(size.padStart(5) + " " + units[i].padEnd(2));
5311
4490
  }
5312
4491
  function handleLs(args2) {
5313
4492
  const parts = args2.trim().split(/\s+/).filter(Boolean);
5314
4493
  const showAll = parts.some((a) => a === "-a" || a === "-la" || a === "-al");
5315
4494
  const showLong = parts.some((a) => a === "-l" || a === "-la" || a === "-al");
5316
4495
  const pathArgs = parts.filter((a) => !a.startsWith("-"));
5317
- const targetPath = pathArgs.length > 0 ? resolve5(process.cwd(), pathArgs[0]) : process.cwd();
5318
- if (!existsSync11(targetPath)) {
4496
+ const targetPath = pathArgs.length > 0 ? resolve4(process.cwd(), pathArgs[0]) : process.cwd();
4497
+ if (!existsSync8(targetPath)) {
5319
4498
  console.log(theme.error(`Directory not found: ${targetPath}`));
5320
4499
  return;
5321
4500
  }
5322
4501
  try {
5323
- const entries = readdirSync4(targetPath, { withFileTypes: true });
4502
+ const entries = readdirSync2(targetPath, { withFileTypes: true });
5324
4503
  const filtered = showAll ? entries : entries.filter((e) => !e.name.startsWith("."));
5325
4504
  console.log("");
5326
4505
  console.log(theme.dim(` ${targetPath}`));
@@ -5336,7 +4515,7 @@ function handleLs(args2) {
5336
4515
  return a.name.localeCompare(b3.name);
5337
4516
  });
5338
4517
  for (const entry of sorted) {
5339
- const fullPath = resolve5(targetPath, entry.name);
4518
+ const fullPath = resolve4(targetPath, entry.name);
5340
4519
  const isDir = entry.isDirectory();
5341
4520
  const ext = isDir ? "dir" : extname(entry.name).toLowerCase();
5342
4521
  const iconInfo = fileIcons[ext] || fileIcons["default"];
@@ -5344,14 +4523,14 @@ function handleLs(args2) {
5344
4523
  if (showLong) {
5345
4524
  try {
5346
4525
  const stats = statSync2(fullPath);
5347
- const size = isDir ? chalk5.dim(" <DIR>") : formatSize(stats.size);
4526
+ const size = isDir ? chalk4.dim(" <DIR>") : formatSize(stats.size);
5348
4527
  const date = stats.mtime.toLocaleDateString("en-US", { month: "short", day: "2-digit", year: "numeric" });
5349
- line += chalk5.dim(date.padEnd(13)) + size + " ";
4528
+ line += chalk4.dim(date.padEnd(13)) + size + " ";
5350
4529
  } catch {
5351
- line += chalk5.dim(" ") + " ";
4530
+ line += chalk4.dim(" ") + " ";
5352
4531
  }
5353
4532
  }
5354
- const name = isDir ? chalk5.hex(iconInfo.color).bold(entry.name + "/") : chalk5.hex(iconInfo.color)(entry.name);
4533
+ const name = isDir ? chalk4.hex(iconInfo.color).bold(entry.name + "/") : chalk4.hex(iconInfo.color)(entry.name);
5355
4534
  line += name;
5356
4535
  console.log(line);
5357
4536
  }
@@ -5365,19 +4544,19 @@ function handleLs(args2) {
5365
4544
  function handleTree(args2, maxDepth = 3) {
5366
4545
  const parts = args2.trim().split(/\s+/).filter(Boolean);
5367
4546
  const pathArgs = parts.filter((a) => !a.startsWith("-"));
5368
- const targetPath = pathArgs.length > 0 ? resolve5(process.cwd(), pathArgs[0]) : process.cwd();
5369
- if (!existsSync11(targetPath)) {
4547
+ const targetPath = pathArgs.length > 0 ? resolve4(process.cwd(), pathArgs[0]) : process.cwd();
4548
+ if (!existsSync8(targetPath)) {
5370
4549
  console.log(theme.error(`Directory not found: ${targetPath}`));
5371
4550
  return;
5372
4551
  }
5373
4552
  console.log("");
5374
- console.log(theme.primary(` \u{1F4C1} ${basename4(targetPath)}/`));
4553
+ console.log(theme.primary(` \u{1F4C1} ${basename3(targetPath)}/`));
5375
4554
  let dirCount = 0;
5376
4555
  let fileCount = 0;
5377
4556
  function printTree(dir, prefix, depth) {
5378
4557
  if (depth > maxDepth) return;
5379
4558
  try {
5380
- const entries = readdirSync4(dir, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") && !["node_modules", ".git", "dist", "build"].includes(e.name)).sort((a, b3) => {
4559
+ const entries = readdirSync2(dir, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") && !["node_modules", ".git", "dist", "build"].includes(e.name)).sort((a, b3) => {
5381
4560
  if (a.isDirectory() && !b3.isDirectory()) return -1;
5382
4561
  if (!a.isDirectory() && b3.isDirectory()) return 1;
5383
4562
  return a.name.localeCompare(b3.name);
@@ -5389,11 +4568,11 @@ function handleTree(args2, maxDepth = 3) {
5389
4568
  const iconInfo = fileIcons[ext] || fileIcons["default"];
5390
4569
  if (entry.isDirectory()) {
5391
4570
  dirCount++;
5392
- console.log(theme.dim(prefix + connector) + iconInfo.icon + " " + chalk5.hex(iconInfo.color).bold(entry.name + "/"));
5393
- printTree(resolve5(dir, entry.name), prefix + (isLast ? " " : "\u2502 "), depth + 1);
4571
+ console.log(theme.dim(prefix + connector) + iconInfo.icon + " " + chalk4.hex(iconInfo.color).bold(entry.name + "/"));
4572
+ printTree(resolve4(dir, entry.name), prefix + (isLast ? " " : "\u2502 "), depth + 1);
5394
4573
  } else {
5395
4574
  fileCount++;
5396
- console.log(theme.dim(prefix + connector) + iconInfo.icon + " " + chalk5.hex(iconInfo.color)(entry.name));
4575
+ console.log(theme.dim(prefix + connector) + iconInfo.icon + " " + chalk4.hex(iconInfo.color)(entry.name));
5397
4576
  }
5398
4577
  });
5399
4578
  } catch {
@@ -5404,18 +4583,18 @@ function handleTree(args2, maxDepth = 3) {
5404
4583
  console.log(theme.dim(` ${dirCount} directories, ${fileCount} files`));
5405
4584
  console.log("");
5406
4585
  }
5407
- var bookmarksFile = join9(homedir5(), ".zammy-bookmarks.json");
4586
+ var bookmarksFile = join5(homedir3(), ".zammy-bookmarks.json");
5408
4587
  function loadBookmarks() {
5409
4588
  try {
5410
- if (existsSync11(bookmarksFile)) {
5411
- return JSON.parse(readFileSync9(bookmarksFile, "utf-8"));
4589
+ if (existsSync8(bookmarksFile)) {
4590
+ return JSON.parse(readFileSync5(bookmarksFile, "utf-8"));
5412
4591
  }
5413
4592
  } catch {
5414
4593
  }
5415
4594
  return {};
5416
4595
  }
5417
4596
  function saveBookmarks(bookmarks) {
5418
- writeFileSync6(bookmarksFile, JSON.stringify(bookmarks, null, 2));
4597
+ writeFileSync4(bookmarksFile, JSON.stringify(bookmarks, null, 2));
5419
4598
  }
5420
4599
  function handleBookmark(args2) {
5421
4600
  const parts = args2.trim().split(/\s+/);
@@ -5471,7 +4650,7 @@ function handleBookmark(args2) {
5471
4650
  console.log(theme.primary(" \u{1F4CD} Directory Bookmarks"));
5472
4651
  console.log("");
5473
4652
  for (const key of keys.sort()) {
5474
- const exists = existsSync11(bookmarks[key]);
4653
+ const exists = existsSync8(bookmarks[key]);
5475
4654
  const status = exists ? theme.success(symbols.check) : theme.error(symbols.cross);
5476
4655
  console.log(` ${status} ${theme.primary(key.padEnd(15))} ${theme.dim("\u2192")} ${bookmarks[key]}`);
5477
4656
  }
@@ -5488,10 +4667,10 @@ function handleFind(args2) {
5488
4667
  function searchDir(dir, depth = 0) {
5489
4668
  if (depth > 5 || results.length >= maxResults) return;
5490
4669
  try {
5491
- const entries = readdirSync4(dir, { withFileTypes: true });
4670
+ const entries = readdirSync2(dir, { withFileTypes: true });
5492
4671
  for (const entry of entries) {
5493
4672
  if (entry.name.startsWith(".") || ["node_modules", ".git", "dist", "build"].includes(entry.name)) continue;
5494
- const fullPath = resolve5(dir, entry.name);
4673
+ const fullPath = resolve4(dir, entry.name);
5495
4674
  const matchPattern = pattern.replace(/\*/g, ".*").replace(/\?/g, ".");
5496
4675
  const regex = new RegExp(matchPattern, "i");
5497
4676
  if (regex.test(entry.name)) {
@@ -5515,9 +4694,9 @@ function handleFind(args2) {
5515
4694
  const relativePath = result.path.replace(searchPath, ".").replace(/\\/g, "/");
5516
4695
  const ext = result.isDir ? "dir" : extname(result.path).toLowerCase();
5517
4696
  const iconInfo = fileIcons[ext] || fileIcons["default"];
5518
- const fileName = basename4(result.path);
4697
+ const fileName = basename3(result.path);
5519
4698
  const dirPath = relativePath.slice(0, -fileName.length);
5520
- console.log(` ${iconInfo.icon} ${theme.dim(dirPath)}${chalk5.hex(iconInfo.color)(fileName)}${result.isDir ? "/" : ""}`);
4699
+ console.log(` ${iconInfo.icon} ${theme.dim(dirPath)}${chalk4.hex(iconInfo.color)(fileName)}${result.isDir ? "/" : ""}`);
5521
4700
  }
5522
4701
  if (results.length >= maxResults) {
5523
4702
  console.log("");
@@ -5527,8 +4706,8 @@ function handleFind(args2) {
5527
4706
  console.log("");
5528
4707
  }
5529
4708
  function handleDu(args2) {
5530
- const targetPath = args2.trim() ? resolve5(process.cwd(), args2.trim()) : process.cwd();
5531
- if (!existsSync11(targetPath)) {
4709
+ const targetPath = args2.trim() ? resolve4(process.cwd(), args2.trim()) : process.cwd();
4710
+ if (!existsSync8(targetPath)) {
5532
4711
  console.log(theme.error(` Path not found: ${targetPath}`));
5533
4712
  return;
5534
4713
  }
@@ -5536,10 +4715,10 @@ function handleDu(args2) {
5536
4715
  console.log("");
5537
4716
  console.log(theme.dim(" Calculating sizes..."));
5538
4717
  try {
5539
- const entries = readdirSync4(targetPath, { withFileTypes: true });
4718
+ const entries = readdirSync2(targetPath, { withFileTypes: true });
5540
4719
  for (const entry of entries) {
5541
4720
  if (entry.name.startsWith(".")) continue;
5542
- const fullPath = resolve5(targetPath, entry.name);
4721
+ const fullPath = resolve4(targetPath, entry.name);
5543
4722
  let size = 0;
5544
4723
  let skipped = false;
5545
4724
  try {
@@ -5565,7 +4744,7 @@ function handleDu(args2) {
5565
4744
  items.sort((a, b3) => b3.size - a.size);
5566
4745
  const totalSize = items.reduce((sum, item) => sum + item.size, 0);
5567
4746
  console.log("");
5568
- console.log(theme.primary(` \u{1F4CA} Disk Usage: ${basename4(targetPath)}`));
4747
+ console.log(theme.primary(` \u{1F4CA} Disk Usage: ${basename3(targetPath)}`));
5569
4748
  console.log(theme.dim(` Total: ${formatSizeSimple(totalSize)}`));
5570
4749
  console.log("");
5571
4750
  const maxItems = 15;
@@ -5579,10 +4758,10 @@ function handleDu(args2) {
5579
4758
  const percent = totalSize > 0 ? item.size / totalSize * 100 : 0;
5580
4759
  const barWidth = 20;
5581
4760
  const filled = Math.round(percent / 100 * barWidth);
5582
- const bar = chalk5.hex("#4ECDC4")("\u2588".repeat(filled)) + chalk5.dim("\u2591".repeat(barWidth - filled));
4761
+ const bar = chalk4.hex("#4ECDC4")("\u2588".repeat(filled)) + chalk4.dim("\u2591".repeat(barWidth - filled));
5583
4762
  const icon = item.isDir ? "\u{1F4C1}" : "\u{1F4C4}";
5584
4763
  const name = item.name.length > 25 ? item.name.slice(0, 22) + "..." : item.name.padEnd(25);
5585
- console.log(` ${icon} ${name} ${bar} ${formatSizeSimple(item.size).padStart(8)} ${chalk5.dim(`${percent.toFixed(1)}%`)}`);
4764
+ console.log(` ${icon} ${name} ${bar} ${formatSizeSimple(item.size).padStart(8)} ${chalk4.dim(`${percent.toFixed(1)}%`)}`);
5586
4765
  }
5587
4766
  if (items.length > maxItems) {
5588
4767
  console.log(theme.dim(` ... and ${items.length - maxItems} more items`));
@@ -5598,10 +4777,10 @@ function getDirSize2(dir, depth = 0, maxDepth = 4) {
5598
4777
  if (depth > maxDepth) return 0;
5599
4778
  let size = 0;
5600
4779
  try {
5601
- const entries = readdirSync4(dir, { withFileTypes: true });
4780
+ const entries = readdirSync2(dir, { withFileTypes: true });
5602
4781
  for (const entry of entries) {
5603
4782
  if (skipDirs.has(entry.name)) continue;
5604
- const fullPath = resolve5(dir, entry.name);
4783
+ const fullPath = resolve4(dir, entry.name);
5605
4784
  if (entry.isDirectory()) {
5606
4785
  size += getDirSize2(fullPath, depth + 1, maxDepth);
5607
4786
  } else {
@@ -5625,7 +4804,7 @@ function handleGit(args2) {
5625
4804
  const subcommand = args2.trim().split(/\s+/)[0] || "status";
5626
4805
  console.log("");
5627
4806
  try {
5628
- execSync3("git rev-parse --is-inside-work-tree", { stdio: "pipe", timeout: 5e3 });
4807
+ execSync("git rev-parse --is-inside-work-tree", { stdio: "pipe", timeout: 5e3 });
5629
4808
  } catch {
5630
4809
  console.log(theme.error(" Not a git repository"));
5631
4810
  console.log("");
@@ -5635,10 +4814,10 @@ function handleGit(args2) {
5635
4814
  switch (subcommand) {
5636
4815
  case "status":
5637
4816
  case "s": {
5638
- const branch = execSync3("git branch --show-current", { encoding: "utf-8", timeout: 5e3 }).trim();
5639
- console.log(` ${symbols.rocket} ${theme.primary("Branch:")} ${chalk5.hex("#98C379")(branch)}`);
4817
+ const branch = execSync("git branch --show-current", { encoding: "utf-8", timeout: 5e3 }).trim();
4818
+ console.log(` ${symbols.rocket} ${theme.primary("Branch:")} ${chalk4.hex("#98C379")(branch)}`);
5640
4819
  console.log("");
5641
- const status = execSync3("git status --porcelain", { encoding: "utf-8", timeout: 5e3 });
4820
+ const status = execSync("git status --porcelain", { encoding: "utf-8", timeout: 5e3 });
5642
4821
  if (!status.trim()) {
5643
4822
  console.log(` ${symbols.check} ${theme.success("Working tree clean")}`);
5644
4823
  } else {
@@ -5661,12 +4840,12 @@ function handleGit(args2) {
5661
4840
  }
5662
4841
  if (staged.length > 0) {
5663
4842
  console.log(theme.success(" Staged changes:"));
5664
- staged.forEach((f) => console.log(` ${symbols.check} ${chalk5.hex("#98C379")(f)}`));
4843
+ staged.forEach((f) => console.log(` ${symbols.check} ${chalk4.hex("#98C379")(f)}`));
5665
4844
  console.log("");
5666
4845
  }
5667
4846
  if (modified.length > 0) {
5668
4847
  console.log(theme.warning(" Modified:"));
5669
- modified.forEach((f) => console.log(` ${symbols.bullet} ${chalk5.hex("#E5C07B")(f)}`));
4848
+ modified.forEach((f) => console.log(` ${symbols.bullet} ${chalk4.hex("#E5C07B")(f)}`));
5670
4849
  console.log("");
5671
4850
  }
5672
4851
  if (untracked.length > 0) {
@@ -5675,35 +4854,35 @@ function handleGit(args2) {
5675
4854
  console.log("");
5676
4855
  }
5677
4856
  }
5678
- const log = execSync3("git log --oneline -3", { encoding: "utf-8", timeout: 3e3 }).trim();
4857
+ const log = execSync("git log --oneline -3", { encoding: "utf-8", timeout: 3e3 }).trim();
5679
4858
  if (log) {
5680
4859
  console.log(theme.dim(" Recent commits:"));
5681
4860
  log.split("\n").forEach((line) => {
5682
4861
  const [hash, ...msg] = line.split(" ");
5683
- console.log(` ${chalk5.hex("#61AFEF")(hash)} ${theme.dim(msg.join(" "))}`);
4862
+ console.log(` ${chalk4.hex("#61AFEF")(hash)} ${theme.dim(msg.join(" "))}`);
5684
4863
  });
5685
4864
  }
5686
4865
  break;
5687
4866
  }
5688
4867
  case "log":
5689
4868
  case "l": {
5690
- const log = execSync3("git log --oneline -10", { encoding: "utf-8", timeout: 3e3 }).trim();
4869
+ const log = execSync("git log --oneline -10", { encoding: "utf-8", timeout: 3e3 }).trim();
5691
4870
  console.log(theme.primary(" \u{1F4DC} Recent Commits"));
5692
4871
  console.log("");
5693
4872
  log.split("\n").forEach((line) => {
5694
4873
  const [hash, ...msg] = line.split(" ");
5695
- console.log(` ${chalk5.hex("#61AFEF")(hash)} ${msg.join(" ")}`);
4874
+ console.log(` ${chalk4.hex("#61AFEF")(hash)} ${msg.join(" ")}`);
5696
4875
  });
5697
4876
  break;
5698
4877
  }
5699
4878
  case "branch":
5700
4879
  case "b": {
5701
- const branches = execSync3("git branch -a", { encoding: "utf-8", timeout: 3e3 }).trim();
4880
+ const branches = execSync("git branch -a", { encoding: "utf-8", timeout: 3e3 }).trim();
5702
4881
  console.log(theme.primary(" \u{1F33F} Branches"));
5703
4882
  console.log("");
5704
4883
  branches.split("\n").forEach((line) => {
5705
4884
  if (line.startsWith("*")) {
5706
- console.log(` ${chalk5.hex("#98C379")(line)}`);
4885
+ console.log(` ${chalk4.hex("#98C379")(line)}`);
5707
4886
  } else {
5708
4887
  console.log(` ${theme.dim(line)}`);
5709
4888
  }
@@ -5711,7 +4890,7 @@ function handleGit(args2) {
5711
4890
  break;
5712
4891
  }
5713
4892
  default:
5714
- const result = execSync3(`git ${args2}`, { encoding: "utf-8", timeout: 1e4 });
4893
+ const result = execSync(`git ${args2}`, { encoding: "utf-8", timeout: 1e4 });
5715
4894
  console.log(result);
5716
4895
  }
5717
4896
  } catch (error) {
@@ -5720,23 +4899,23 @@ function handleGit(args2) {
5720
4899
  }
5721
4900
  console.log("");
5722
4901
  }
5723
- var isMac = platform3() === "darwin";
5724
- var isLinux = platform3() === "linux";
4902
+ var isMac = platform2() === "darwin";
4903
+ var isLinux = platform2() === "linux";
5725
4904
  function getClipboardCopyCmd() {
5726
- if (isWindows2) return "clip";
4905
+ if (isWindows) return "clip";
5727
4906
  if (isMac) return "pbcopy";
5728
4907
  try {
5729
- execSync3("which xclip", { stdio: "pipe" });
4908
+ execSync("which xclip", { stdio: "pipe" });
5730
4909
  return "xclip -selection clipboard";
5731
4910
  } catch {
5732
4911
  return "xsel --clipboard --input";
5733
4912
  }
5734
4913
  }
5735
4914
  function getClipboardPasteCmd() {
5736
- if (isWindows2) return 'powershell -command "Get-Clipboard"';
4915
+ if (isWindows) return 'powershell -command "Get-Clipboard"';
5737
4916
  if (isMac) return "pbpaste";
5738
4917
  try {
5739
- execSync3("which xclip", { stdio: "pipe" });
4918
+ execSync("which xclip", { stdio: "pipe" });
5740
4919
  return "xclip -selection clipboard -o";
5741
4920
  } catch {
5742
4921
  return "xsel --clipboard --output";
@@ -5750,10 +4929,10 @@ function handleClipboard(args2) {
5750
4929
  if (action === "copy" && content) {
5751
4930
  try {
5752
4931
  const copyCmd = getClipboardCopyCmd();
5753
- if (isWindows2) {
5754
- execSync3(`echo ${content} | ${copyCmd}`, { stdio: "pipe", timeout: 3e3 });
4932
+ if (isWindows) {
4933
+ execSync(`echo ${content} | ${copyCmd}`, { stdio: "pipe", timeout: 3e3 });
5755
4934
  } else {
5756
- execSync3(`echo "${content}" | ${copyCmd}`, { stdio: "pipe", timeout: 3e3 });
4935
+ execSync(`echo "${content}" | ${copyCmd}`, { stdio: "pipe", timeout: 3e3 });
5757
4936
  }
5758
4937
  console.log(` ${symbols.check} ${theme.success("Copied to clipboard")}`);
5759
4938
  } catch {
@@ -5765,7 +4944,7 @@ function handleClipboard(args2) {
5765
4944
  } else if (action === "paste") {
5766
4945
  try {
5767
4946
  const pasteCmd = getClipboardPasteCmd();
5768
- const result = execSync3(pasteCmd, { encoding: "utf-8", timeout: 3e3 }).trim();
4947
+ const result = execSync(pasteCmd, { encoding: "utf-8", timeout: 3e3 }).trim();
5769
4948
  console.log(` ${symbols.clipboard} ${theme.dim("Clipboard contents:")}`);
5770
4949
  console.log("");
5771
4950
  console.log(result);
@@ -5776,14 +4955,14 @@ function handleClipboard(args2) {
5776
4955
  }
5777
4956
  }
5778
4957
  } else if (action === "file" && parts[1]) {
5779
- const filePath = resolve5(process.cwd(), parts[1]);
5780
- if (existsSync11(filePath)) {
4958
+ const filePath = resolve4(process.cwd(), parts[1]);
4959
+ if (existsSync8(filePath)) {
5781
4960
  try {
5782
4961
  const copyCmd = getClipboardCopyCmd();
5783
- if (isWindows2) {
5784
- execSync3(`type "${filePath}" | ${copyCmd}`, { stdio: "pipe", timeout: 5e3 });
4962
+ if (isWindows) {
4963
+ execSync(`type "${filePath}" | ${copyCmd}`, { stdio: "pipe", timeout: 5e3 });
5785
4964
  } else {
5786
- execSync3(`cat "${filePath}" | ${copyCmd}`, { stdio: "pipe", timeout: 5e3 });
4965
+ execSync(`cat "${filePath}" | ${copyCmd}`, { stdio: "pipe", timeout: 5e3 });
5787
4966
  }
5788
4967
  console.log(` ${symbols.check} ${theme.success("File contents copied to clipboard")}`);
5789
4968
  } catch {
@@ -5809,14 +4988,14 @@ function handleClipboard(args2) {
5809
4988
  console.log("");
5810
4989
  }
5811
4990
  function handlePretty(args2) {
5812
- const filePath = resolve5(process.cwd(), args2.trim());
5813
- if (!existsSync11(filePath)) {
4991
+ const filePath = resolve4(process.cwd(), args2.trim());
4992
+ if (!existsSync8(filePath)) {
5814
4993
  console.log(theme.error(` File not found: ${args2}`));
5815
4994
  return;
5816
4995
  }
5817
4996
  console.log("");
5818
4997
  try {
5819
- const content = readFileSync9(filePath, "utf-8");
4998
+ const content = readFileSync5(filePath, "utf-8");
5820
4999
  const ext = extname(filePath).toLowerCase();
5821
5000
  if (ext === ".json") {
5822
5001
  const parsed = JSON.parse(content);
@@ -5832,7 +5011,7 @@ function handlePretty(args2) {
5832
5011
  console.log("");
5833
5012
  }
5834
5013
  function highlightJson(json) {
5835
- return json.replace(/"([^"]+)":/g, (_, key) => chalk5.hex("#E06C75")(`"${key}"`) + ":").replace(/: "([^"]*)"/g, (_, val) => ": " + chalk5.hex("#98C379")(`"${val}"`)).replace(/: (\d+)/g, (_, num) => ": " + chalk5.hex("#D19A66")(num)).replace(/: (true|false)/g, (_, bool) => ": " + chalk5.hex("#56B6C2")(bool)).replace(/: (null)/g, (_, n) => ": " + chalk5.hex("#C678DD")(n));
5014
+ return json.replace(/"([^"]+)":/g, (_, key) => chalk4.hex("#E06C75")(`"${key}"`) + ":").replace(/: "([^"]*)"/g, (_, val) => ": " + chalk4.hex("#98C379")(`"${val}"`)).replace(/: (\d+)/g, (_, num) => ": " + chalk4.hex("#D19A66")(num)).replace(/: (true|false)/g, (_, bool) => ": " + chalk4.hex("#56B6C2")(bool)).replace(/: (null)/g, (_, n) => ": " + chalk4.hex("#C678DD")(n));
5836
5015
  }
5837
5016
  var activeWatcher = null;
5838
5017
  function handleWatch(args2) {
@@ -5863,8 +5042,8 @@ function handleWatch(args2) {
5863
5042
  console.log("");
5864
5043
  return;
5865
5044
  }
5866
- const filePath = resolve5(process.cwd(), action);
5867
- if (!existsSync11(filePath)) {
5045
+ const filePath = resolve4(process.cwd(), action);
5046
+ if (!existsSync8(filePath)) {
5868
5047
  console.log(theme.error(` File not found: ${action}`));
5869
5048
  console.log("");
5870
5049
  return;
@@ -5891,8 +5070,8 @@ function handleWatch(args2) {
5891
5070
  console.log(theme.dim(' (Type "!watch stop" to stop watching)'));
5892
5071
  console.log("");
5893
5072
  try {
5894
- const content = readFileSync9(filePath, "utf-8");
5895
- const lines = content.split("\n").slice(-10);
5073
+ const content = readFileSync5(filePath, "utf-8");
5074
+ const lines = content.split(/\r?\n/).slice(-10);
5896
5075
  lines.forEach((line) => console.log(theme.dim(line)));
5897
5076
  } catch {
5898
5077
  console.log(theme.dim(" (Unable to read initial content)"));
@@ -5900,12 +5079,12 @@ function handleWatch(args2) {
5900
5079
  watchFile(filePath, { interval: 500 }, (curr, prev) => {
5901
5080
  if (curr.size > lastSize) {
5902
5081
  try {
5903
- const newContent = readFileSync9(filePath, "utf-8");
5904
- const allLines = newContent.split("\n");
5082
+ const newContent = readFileSync5(filePath, "utf-8");
5083
+ const allLines = newContent.split(/\r?\n/);
5905
5084
  const oldLines = Math.floor(prev.size / 50);
5906
5085
  const newLines = allLines.slice(-Math.max(1, allLines.length - oldLines));
5907
5086
  newLines.forEach((line) => {
5908
- if (line.trim()) console.log(chalk5.hex("#98C379")(line));
5087
+ if (line.trim()) console.log(chalk4.hex("#98C379")(line));
5909
5088
  });
5910
5089
  } catch {
5911
5090
  }
@@ -5918,12 +5097,12 @@ function handleServe(args2) {
5918
5097
  console.log("");
5919
5098
  console.log(` ${symbols.rocket} ${theme.primary("Starting HTTP server...")}`);
5920
5099
  console.log(` ${theme.dim("Serving:")} ${process.cwd()}`);
5921
- console.log(` ${theme.dim("URL:")} ${chalk5.hex("#61AFEF")(`http://localhost:${port}`)}`);
5100
+ console.log(` ${theme.dim("URL:")} ${chalk4.hex("#61AFEF")(`http://localhost:${port}`)}`);
5922
5101
  console.log("");
5923
5102
  console.log(theme.dim(" Press Ctrl+C to stop"));
5924
5103
  console.log("");
5925
5104
  try {
5926
- const npx = isWindows2 ? "npx.cmd" : "npx";
5105
+ const npx = isWindows ? "npx.cmd" : "npx";
5927
5106
  spawn(npx, ["serve", "-p", String(port)], {
5928
5107
  cwd: process.cwd(),
5929
5108
  stdio: "inherit"
@@ -5938,8 +5117,8 @@ function handlePs() {
5938
5117
  console.log("");
5939
5118
  try {
5940
5119
  let result;
5941
- if (isWindows2) {
5942
- result = execSync3('tasklist /FO CSV /NH | findstr /V "System Idle"', { encoding: "utf-8", timeout: 5e3 });
5120
+ if (isWindows) {
5121
+ result = execSync('tasklist /FO CSV /NH | findstr /V "System Idle"', { encoding: "utf-8", timeout: 5e3 });
5943
5122
  const lines = result.trim().split("\n").slice(0, 15);
5944
5123
  console.log(theme.dim(" Name PID Memory"));
5945
5124
  console.log(theme.dim(" \u2500".repeat(25)));
@@ -5949,11 +5128,11 @@ function handlePs() {
5949
5128
  const name = parts[0].slice(0, 28).padEnd(30);
5950
5129
  const pid = parts[1].padStart(8);
5951
5130
  const mem = parts[4];
5952
- console.log(` ${name}${pid} ${chalk5.hex("#98C379")(mem)}`);
5131
+ console.log(` ${name}${pid} ${chalk4.hex("#98C379")(mem)}`);
5953
5132
  }
5954
5133
  });
5955
5134
  } else {
5956
- result = execSync3("ps aux | head -15", { encoding: "utf-8", timeout: 5e3 });
5135
+ result = execSync("ps aux | head -15", { encoding: "utf-8", timeout: 5e3 });
5957
5136
  console.log(result);
5958
5137
  }
5959
5138
  } catch {
@@ -5976,7 +5155,7 @@ function handleEnv(args2) {
5976
5155
  filtered.slice(0, maxShow).forEach((key) => {
5977
5156
  const value = env[key] || "";
5978
5157
  const displayValue = value.length > 50 ? value.slice(0, 47) + "..." : value;
5979
- console.log(` ${chalk5.hex("#E06C75")(key.padEnd(25))} ${theme.dim("=")} ${displayValue}`);
5158
+ console.log(` ${chalk4.hex("#E06C75")(key.padEnd(25))} ${theme.dim("=")} ${displayValue}`);
5980
5159
  });
5981
5160
  if (filtered.length > maxShow) {
5982
5161
  console.log(theme.dim(` ... and ${filtered.length - maxShow} more`));
@@ -6005,22 +5184,22 @@ function handleIp() {
6005
5184
  if (localIps.length === 0) {
6006
5185
  console.log(` ${theme.dim("(No network interfaces found)")}`);
6007
5186
  } else {
6008
- localIps.forEach((ip) => console.log(` ${chalk5.hex("#98C379")(ip)}`));
5187
+ localIps.forEach((ip) => console.log(` ${chalk4.hex("#98C379")(ip)}`));
6009
5188
  }
6010
5189
  console.log("");
6011
5190
  console.log(theme.dim(" Public IP:"));
6012
5191
  try {
6013
5192
  let result;
6014
5193
  try {
6015
- result = execSync3("curl -s ifconfig.me", { encoding: "utf-8", timeout: 5e3 }).trim();
5194
+ result = execSync("curl -s ifconfig.me", { encoding: "utf-8", timeout: 5e3 }).trim();
6016
5195
  } catch {
6017
- if (isWindows2) {
6018
- result = execSync3('powershell -command "(Invoke-WebRequest -Uri ifconfig.me -UseBasicParsing).Content"', { encoding: "utf-8", timeout: 5e3 }).trim();
5196
+ if (isWindows) {
5197
+ result = execSync('powershell -command "(Invoke-WebRequest -Uri ifconfig.me -UseBasicParsing).Content"', { encoding: "utf-8", timeout: 5e3 }).trim();
6019
5198
  } else {
6020
5199
  throw new Error("curl not available");
6021
5200
  }
6022
5201
  }
6023
- console.log(` ${chalk5.hex("#61AFEF")(result)}`);
5202
+ console.log(` ${chalk4.hex("#61AFEF")(result)}`);
6024
5203
  } catch {
6025
5204
  console.log(` ${theme.dim("(Could not fetch - requires curl or internet)")}`);
6026
5205
  }
@@ -6037,21 +5216,21 @@ function handleEpoch(args2) {
6037
5216
  if (!input || input === "now") {
6038
5217
  const now = /* @__PURE__ */ new Date();
6039
5218
  console.log(` ${theme.dim("Current Time:")}`);
6040
- console.log(` ${chalk5.hex("#98C379")(now.toISOString())}`);
6041
- console.log(` ${chalk5.hex("#61AFEF")(Math.floor(now.getTime() / 1e3).toString())} ${theme.dim("(Unix seconds)")}`);
6042
- console.log(` ${chalk5.hex("#E5C07B")(now.getTime().toString())} ${theme.dim("(Unix milliseconds)")}`);
5219
+ console.log(` ${chalk4.hex("#98C379")(now.toISOString())}`);
5220
+ console.log(` ${chalk4.hex("#61AFEF")(Math.floor(now.getTime() / 1e3).toString())} ${theme.dim("(Unix seconds)")}`);
5221
+ console.log(` ${chalk4.hex("#E5C07B")(now.getTime().toString())} ${theme.dim("(Unix milliseconds)")}`);
6043
5222
  } else if (/^\d{10,13}$/.test(input)) {
6044
5223
  const ms = input.length === 10 ? parseInt(input) * 1e3 : parseInt(input);
6045
5224
  const date = new Date(ms);
6046
- console.log(` ${theme.dim("Epoch:")} ${chalk5.hex("#E5C07B")(input)}`);
6047
- console.log(` ${theme.dim("Date:")} ${chalk5.hex("#98C379")(date.toISOString())}`);
6048
- console.log(` ${chalk5.hex("#98C379")(date.toLocaleString())}`);
5225
+ console.log(` ${theme.dim("Epoch:")} ${chalk4.hex("#E5C07B")(input)}`);
5226
+ console.log(` ${theme.dim("Date:")} ${chalk4.hex("#98C379")(date.toISOString())}`);
5227
+ console.log(` ${chalk4.hex("#98C379")(date.toLocaleString())}`);
6049
5228
  } else {
6050
5229
  const date = new Date(input);
6051
5230
  if (!isNaN(date.getTime())) {
6052
- console.log(` ${theme.dim("Date:")} ${chalk5.hex("#98C379")(input)}`);
6053
- console.log(` ${theme.dim("Unix:")} ${chalk5.hex("#61AFEF")(Math.floor(date.getTime() / 1e3).toString())} ${theme.dim("(seconds)")}`);
6054
- console.log(` ${chalk5.hex("#E5C07B")(date.getTime().toString())} ${theme.dim("(milliseconds)")}`);
5231
+ console.log(` ${theme.dim("Date:")} ${chalk4.hex("#98C379")(input)}`);
5232
+ console.log(` ${theme.dim("Unix:")} ${chalk4.hex("#61AFEF")(Math.floor(date.getTime() / 1e3).toString())} ${theme.dim("(seconds)")}`);
5233
+ console.log(` ${chalk4.hex("#E5C07B")(date.getTime().toString())} ${theme.dim("(milliseconds)")}`);
6055
5234
  } else {
6056
5235
  console.log(theme.error(` Cannot parse: ${input}`));
6057
5236
  console.log(theme.dim(' Examples: epoch now, epoch 1703788800, epoch "2024-01-01"'));
@@ -6075,19 +5254,19 @@ async function handleHttp(args2) {
6075
5254
  return;
6076
5255
  }
6077
5256
  const fullUrl = url.startsWith("http") ? url : `https://${url}`;
6078
- console.log(` ${symbols.rocket} ${theme.dim(method)} ${chalk5.hex("#61AFEF")(fullUrl)}`);
5257
+ console.log(` ${symbols.rocket} ${theme.dim(method)} ${chalk4.hex("#61AFEF")(fullUrl)}`);
6079
5258
  console.log("");
6080
5259
  try {
6081
5260
  let result;
6082
5261
  try {
6083
5262
  const curlCmd = method === "HEAD" ? `curl -sI "${fullUrl}"` : `curl -s -X ${method} "${fullUrl}"`;
6084
- result = execSync3(curlCmd, { encoding: "utf-8", timeout: 1e4 });
5263
+ result = execSync(curlCmd, { encoding: "utf-8", timeout: 1e4 });
6085
5264
  } catch {
6086
- if (isWindows2) {
5265
+ if (isWindows) {
6087
5266
  if (method === "HEAD") {
6088
- result = execSync3(`powershell -command "(Invoke-WebRequest -Uri '${fullUrl}' -Method Head -UseBasicParsing).Headers | ConvertTo-Json"`, { encoding: "utf-8", timeout: 1e4 });
5267
+ result = execSync(`powershell -command "(Invoke-WebRequest -Uri '${fullUrl}' -Method Head -UseBasicParsing).Headers | ConvertTo-Json"`, { encoding: "utf-8", timeout: 1e4 });
6089
5268
  } else {
6090
- result = execSync3(`powershell -command "(Invoke-WebRequest -Uri '${fullUrl}' -Method ${method} -UseBasicParsing).Content"`, { encoding: "utf-8", timeout: 1e4 });
5269
+ result = execSync(`powershell -command "(Invoke-WebRequest -Uri '${fullUrl}' -Method ${method} -UseBasicParsing).Content"`, { encoding: "utf-8", timeout: 1e4 });
6091
5270
  }
6092
5271
  } else {
6093
5272
  throw new Error("curl not available");
@@ -6125,22 +5304,22 @@ function handleDiff(args2) {
6125
5304
  console.log("");
6126
5305
  return;
6127
5306
  }
6128
- const path1 = resolve5(process.cwd(), file1);
6129
- const path2 = resolve5(process.cwd(), file2);
6130
- if (!existsSync11(path1)) {
5307
+ const path1 = resolve4(process.cwd(), file1);
5308
+ const path2 = resolve4(process.cwd(), file2);
5309
+ if (!existsSync8(path1)) {
6131
5310
  console.log(theme.error(` File not found: ${file1}`));
6132
5311
  console.log("");
6133
5312
  return;
6134
5313
  }
6135
- if (!existsSync11(path2)) {
5314
+ if (!existsSync8(path2)) {
6136
5315
  console.log(theme.error(` File not found: ${file2}`));
6137
5316
  console.log("");
6138
5317
  return;
6139
5318
  }
6140
5319
  try {
6141
- const content1 = readFileSync9(path1, "utf-8").split("\n");
6142
- const content2 = readFileSync9(path2, "utf-8").split("\n");
6143
- console.log(theme.primary(` Comparing: ${basename4(file1)} \u2194 ${basename4(file2)}`));
5320
+ const content1 = readFileSync5(path1, "utf-8").split(/\r?\n/);
5321
+ const content2 = readFileSync5(path2, "utf-8").split(/\r?\n/);
5322
+ console.log(theme.primary(` Comparing: ${basename3(file1)} \u2194 ${basename3(file2)}`));
6144
5323
  console.log("");
6145
5324
  const maxLines = Math.max(content1.length, content2.length);
6146
5325
  let differences = 0;
@@ -6149,8 +5328,8 @@ function handleDiff(args2) {
6149
5328
  const line2 = content2[i] || "";
6150
5329
  if (line1 !== line2) {
6151
5330
  differences++;
6152
- console.log(chalk5.hex("#E06C75")(` - ${(i + 1).toString().padStart(4)}: ${line1.slice(0, 70)}`));
6153
- console.log(chalk5.hex("#98C379")(` + ${(i + 1).toString().padStart(4)}: ${line2.slice(0, 70)}`));
5331
+ console.log(chalk4.hex("#E06C75")(` - ${(i + 1).toString().padStart(4)}: ${line1.slice(0, 70)}`));
5332
+ console.log(chalk4.hex("#98C379")(` + ${(i + 1).toString().padStart(4)}: ${line2.slice(0, 70)}`));
6154
5333
  console.log("");
6155
5334
  }
6156
5335
  }
@@ -6167,18 +5346,18 @@ function handleDiff(args2) {
6167
5346
  }
6168
5347
  console.log("");
6169
5348
  }
6170
- var aliasesFile = join9(homedir5(), ".zammy-aliases.json");
5349
+ var aliasesFile = join5(homedir3(), ".zammy-aliases.json");
6171
5350
  function loadAliases() {
6172
5351
  try {
6173
- if (existsSync11(aliasesFile)) {
6174
- return JSON.parse(readFileSync9(aliasesFile, "utf-8"));
5352
+ if (existsSync8(aliasesFile)) {
5353
+ return JSON.parse(readFileSync5(aliasesFile, "utf-8"));
6175
5354
  }
6176
5355
  } catch {
6177
5356
  }
6178
5357
  return {};
6179
5358
  }
6180
5359
  function saveAliases(aliases) {
6181
- writeFileSync6(aliasesFile, JSON.stringify(aliases, null, 2));
5360
+ writeFileSync4(aliasesFile, JSON.stringify(aliases, null, 2));
6182
5361
  }
6183
5362
  function handleAlias(args2) {
6184
5363
  const parts = args2.trim().split(/\s+/);
@@ -6208,7 +5387,7 @@ function handleAlias(args2) {
6208
5387
  console.log(theme.dim(` Running: ${aliases[name]}`));
6209
5388
  console.log("");
6210
5389
  try {
6211
- const result = execSync3(aliases[name], { encoding: "utf-8", cwd: process.cwd(), timeout: 3e4 });
5390
+ const result = execSync(aliases[name], { encoding: "utf-8", cwd: process.cwd(), timeout: 3e4 });
6212
5391
  console.log(result);
6213
5392
  } catch (error) {
6214
5393
  const err = error;
@@ -6240,7 +5419,7 @@ function handleNotify(args2) {
6240
5419
  const message = args2.trim() || "Notification from Zammy CLI";
6241
5420
  console.log("");
6242
5421
  try {
6243
- if (isWindows2) {
5422
+ if (isWindows) {
6244
5423
  const ps = `
6245
5424
  [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
6246
5425
  [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
@@ -6249,10 +5428,10 @@ function handleNotify(args2) {
6249
5428
  $notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Zammy CLI")
6250
5429
  $notifier.Show([Windows.UI.Notifications.ToastNotification]::new($template))
6251
5430
  `;
6252
- execSync3(`powershell -command "${ps.replace(/\n/g, " ")}"`, { stdio: "pipe", timeout: 5e3 });
5431
+ execSync(`powershell -command "${ps.replace(/\n/g, " ")}"`, { stdio: "pipe", timeout: 5e3 });
6253
5432
  } else {
6254
- const cmd = platform3() === "darwin" ? `osascript -e 'display notification "${message}" with title "Zammy CLI"'` : `notify-send "Zammy CLI" "${message}"`;
6255
- execSync3(cmd, { stdio: "pipe", timeout: 3e3 });
5433
+ const cmd = platform2() === "darwin" ? `osascript -e 'display notification "${message}" with title "Zammy CLI"'` : `notify-send "Zammy CLI" "${message}"`;
5434
+ execSync(cmd, { stdio: "pipe", timeout: 3e3 });
6256
5435
  }
6257
5436
  console.log(` ${symbols.check} ${theme.success("Notification sent")}`);
6258
5437
  } catch {
@@ -6282,8 +5461,8 @@ function handleGrep(args2) {
6282
5461
  function searchFile(filePath) {
6283
5462
  if (results.length >= maxResults) return;
6284
5463
  try {
6285
- const content = readFileSync9(filePath, "utf-8");
6286
- const lines = content.split("\n");
5464
+ const content = readFileSync5(filePath, "utf-8");
5465
+ const lines = content.split(/\r?\n/);
6287
5466
  lines.forEach((line, index) => {
6288
5467
  if (results.length >= maxResults) return;
6289
5468
  if (regex.test(line)) {
@@ -6300,11 +5479,11 @@ function handleGrep(args2) {
6300
5479
  function searchDir(dir, depth = 0) {
6301
5480
  if (depth > 4 || results.length >= maxResults) return;
6302
5481
  try {
6303
- const entries = readdirSync4(dir, { withFileTypes: true });
5482
+ const entries = readdirSync2(dir, { withFileTypes: true });
6304
5483
  for (const entry of entries) {
6305
5484
  if (results.length >= maxResults) break;
6306
5485
  if (entry.name.startsWith(".") || ["node_modules", ".git", "dist", "build"].includes(entry.name)) continue;
6307
- const fullPath = resolve5(dir, entry.name);
5486
+ const fullPath = resolve4(dir, entry.name);
6308
5487
  if (entry.isDirectory()) {
6309
5488
  searchDir(fullPath, depth + 1);
6310
5489
  } else {
@@ -6327,9 +5506,9 @@ function handleGrep(args2) {
6327
5506
  for (const result of results) {
6328
5507
  const highlightedContent = result.content.replace(
6329
5508
  regex,
6330
- (match) => chalk5.hex("#FF6B6B").bold(match)
5509
+ (match) => chalk4.hex("#FF6B6B").bold(match)
6331
5510
  );
6332
- console.log(` ${theme.dim(result.file)}:${chalk5.hex("#61AFEF")(result.line)}`);
5511
+ console.log(` ${theme.dim(result.file)}:${chalk4.hex("#61AFEF")(result.line)}`);
6333
5512
  console.log(` ${highlightedContent}`);
6334
5513
  console.log("");
6335
5514
  }
@@ -6340,30 +5519,30 @@ function handleGrep(args2) {
6340
5519
  console.log("");
6341
5520
  }
6342
5521
  function handleWc(args2) {
6343
- const filePath = resolve5(process.cwd(), args2.trim());
5522
+ const filePath = resolve4(process.cwd(), args2.trim());
6344
5523
  console.log("");
6345
5524
  if (!args2.trim()) {
6346
5525
  console.log(theme.error(" Usage: wc <file>"));
6347
5526
  console.log("");
6348
5527
  return;
6349
5528
  }
6350
- if (!existsSync11(filePath)) {
5529
+ if (!existsSync8(filePath)) {
6351
5530
  console.log(theme.error(` File not found: ${args2}`));
6352
5531
  console.log("");
6353
5532
  return;
6354
5533
  }
6355
5534
  try {
6356
- const content = readFileSync9(filePath, "utf-8");
6357
- const lines = content.split("\n").length;
5535
+ const content = readFileSync5(filePath, "utf-8");
5536
+ const lines = content.split(/\r?\n/).length;
6358
5537
  const words = content.split(/\s+/).filter((w) => w.length > 0).length;
6359
5538
  const chars = content.length;
6360
5539
  const bytes = Buffer.byteLength(content, "utf-8");
6361
- console.log(theme.primary(` \u{1F4CA} ${basename4(args2)}`));
5540
+ console.log(theme.primary(` \u{1F4CA} ${basename3(args2)}`));
6362
5541
  console.log("");
6363
- console.log(` ${chalk5.hex("#61AFEF")(lines.toLocaleString().padStart(8))} ${theme.dim("lines")}`);
6364
- console.log(` ${chalk5.hex("#98C379")(words.toLocaleString().padStart(8))} ${theme.dim("words")}`);
6365
- console.log(` ${chalk5.hex("#E5C07B")(chars.toLocaleString().padStart(8))} ${theme.dim("characters")}`);
6366
- console.log(` ${chalk5.hex("#C678DD")(bytes.toLocaleString().padStart(8))} ${theme.dim("bytes")}`);
5542
+ console.log(` ${chalk4.hex("#61AFEF")(lines.toLocaleString().padStart(8))} ${theme.dim("lines")}`);
5543
+ console.log(` ${chalk4.hex("#98C379")(words.toLocaleString().padStart(8))} ${theme.dim("words")}`);
5544
+ console.log(` ${chalk4.hex("#E5C07B")(chars.toLocaleString().padStart(8))} ${theme.dim("characters")}`);
5545
+ console.log(` ${chalk4.hex("#C678DD")(bytes.toLocaleString().padStart(8))} ${theme.dim("bytes")}`);
6367
5546
  } catch {
6368
5547
  console.log(theme.error(" Failed to read file"));
6369
5548
  }
@@ -6383,19 +5562,19 @@ function handleHead(args2) {
6383
5562
  console.log("");
6384
5563
  return;
6385
5564
  }
6386
- const fullPath = resolve5(process.cwd(), filePath);
6387
- if (!existsSync11(fullPath)) {
5565
+ const fullPath = resolve4(process.cwd(), filePath);
5566
+ if (!existsSync8(fullPath)) {
6388
5567
  console.log(theme.error(` File not found: ${filePath}`));
6389
5568
  console.log("");
6390
5569
  return;
6391
5570
  }
6392
5571
  try {
6393
- const content = readFileSync9(fullPath, "utf-8");
6394
- const fileLines = content.split("\n").slice(0, lines);
6395
- console.log(theme.dim(` First ${lines} lines of ${basename4(filePath)}:`));
5572
+ const content = readFileSync5(fullPath, "utf-8");
5573
+ const fileLines = content.split(/\r?\n/).slice(0, lines);
5574
+ console.log(theme.dim(` First ${lines} lines of ${basename3(filePath)}:`));
6396
5575
  console.log("");
6397
5576
  fileLines.forEach((line, i) => {
6398
- console.log(` ${chalk5.dim((i + 1).toString().padStart(4))} ${line}`);
5577
+ console.log(` ${chalk4.dim((i + 1).toString().padStart(4))} ${line}`);
6399
5578
  });
6400
5579
  } catch {
6401
5580
  console.log(theme.error(" Failed to read file"));
@@ -6597,19 +5776,19 @@ async function parseAndExecute(input) {
6597
5776
  }
6598
5777
 
6599
5778
  // src/index.ts
6600
- import { readdirSync as readdirSync5, readFileSync as readFileSync10 } from "fs";
6601
- import { fileURLToPath as fileURLToPath4 } from "url";
6602
- import { dirname as dirname5, join as join10 } from "path";
6603
- import chalk6 from "chalk";
5779
+ import { readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
5780
+ import { fileURLToPath } from "url";
5781
+ import { dirname, join as join6 } from "path";
5782
+ import chalk5 from "chalk";
6604
5783
  var SLIME_COLOR = "#9B59B6";
6605
5784
  var EYE_COLOR = "#1A1A2E";
6606
5785
  var MIN_WIDTH_FOR_IDLE = 40;
6607
5786
  var MIN_WIDTH_FOR_MENU = 50;
6608
5787
  var miniSlimeFrames = [
6609
5788
  // Open eyes
6610
- chalk6.hex(SLIME_COLOR)("(") + chalk6.hex(EYE_COLOR)("\u25CF") + chalk6.hex(SLIME_COLOR)("\u1D17") + chalk6.hex(EYE_COLOR)("\u25CF") + chalk6.hex(SLIME_COLOR)(")"),
5789
+ chalk5.hex(SLIME_COLOR)("(") + chalk5.hex(EYE_COLOR)("\u25CF") + chalk5.hex(SLIME_COLOR)("\u1D17") + chalk5.hex(EYE_COLOR)("\u25CF") + chalk5.hex(SLIME_COLOR)(")"),
6611
5790
  // Blink (closed eyes)
6612
- chalk6.hex(SLIME_COLOR)("(") + chalk6.hex(EYE_COLOR)("\u2500") + chalk6.hex(SLIME_COLOR)("\u1D17") + chalk6.hex(EYE_COLOR)("\u2500") + chalk6.hex(SLIME_COLOR)(")")
5791
+ chalk5.hex(SLIME_COLOR)("(") + chalk5.hex(EYE_COLOR)("\u2500") + chalk5.hex(SLIME_COLOR)("\u1D17") + chalk5.hex(EYE_COLOR)("\u2500") + chalk5.hex(SLIME_COLOR)(")")
6613
5792
  ];
6614
5793
  var idleAnimationInterval = null;
6615
5794
  var isUserTyping = false;
@@ -6684,10 +5863,10 @@ function setIdle() {
6684
5863
  var args = process.argv.slice(2);
6685
5864
  if (args.includes("--version") || args.includes("-v")) {
6686
5865
  try {
6687
- const __filename = fileURLToPath4(import.meta.url);
6688
- const __dirname = dirname5(__filename);
6689
- const pkgPath = join10(__dirname, "..", "package.json");
6690
- const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
5866
+ const __filename = fileURLToPath(import.meta.url);
5867
+ const __dirname = dirname(__filename);
5868
+ const pkgPath = join6(__dirname, "..", "package.json");
5869
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
6691
5870
  console.log(`zammy v${pkg.version}`);
6692
5871
  } catch {
6693
5872
  console.log("zammy v1.0.0");
@@ -6768,9 +5947,9 @@ var SHELL_COMMANDS = [
6768
5947
  { name: "mv", description: "Move files" }
6769
5948
  ];
6770
5949
  function getFilteredCommands(filter) {
6771
- const commands2 = getAllCommands().map((c) => ({ name: c.name, description: c.description }));
6772
- if (!filter) return commands2;
6773
- return commands2.filter((c) => c.name.toLowerCase().startsWith(filter.toLowerCase()));
5950
+ const commands = getAllCommands().map((c) => ({ name: c.name, description: c.description }));
5951
+ if (!filter) return commands;
5952
+ return commands.filter((c) => c.name.toLowerCase().startsWith(filter.toLowerCase()));
6774
5953
  }
6775
5954
  function getFilteredShellCommands(filter) {
6776
5955
  if (!filter) return SHELL_COMMANDS;
@@ -6901,14 +6080,14 @@ function navigateMenu(direction, currentLine) {
6901
6080
  renderMenu(currentLine);
6902
6081
  }
6903
6082
  function completer(line) {
6904
- const commands2 = getAllCommands().map((c) => "/" + c.name);
6083
+ const commands = getAllCommands().map((c) => "/" + c.name);
6905
6084
  if (line.startsWith("/")) {
6906
6085
  const input = line.toLowerCase();
6907
6086
  if (input.startsWith("/asciiart ")) {
6908
6087
  const afterCommand = line.slice("/asciiart ".length);
6909
6088
  const searchTerm = afterCommand.startsWith("@") ? afterCommand.slice(1) : afterCommand;
6910
6089
  try {
6911
- const files = readdirSync5(process.cwd());
6090
+ const files = readdirSync3(process.cwd());
6912
6091
  const imageFiles = files.filter((f) => {
6913
6092
  const ext = f.toLowerCase().slice(f.lastIndexOf("."));
6914
6093
  return IMAGE_EXTENSIONS.includes(ext);
@@ -6922,7 +6101,7 @@ function completer(line) {
6922
6101
  return [[], line];
6923
6102
  }
6924
6103
  }
6925
- const matches = commands2.filter((c) => c.toLowerCase().startsWith(input));
6104
+ const matches = commands.filter((c) => c.toLowerCase().startsWith(input));
6926
6105
  return [matches.length ? matches : [], line];
6927
6106
  }
6928
6107
  if (line.startsWith("!")) {
@@ -6939,7 +6118,7 @@ async function main() {
6939
6118
  }
6940
6119
  await displayBanner(isSimpleMode);
6941
6120
  await initPluginLoader();
6942
- const rl = readline4.createInterface({
6121
+ const rl = readline.createInterface({
6943
6122
  input: process.stdin,
6944
6123
  output: process.stdout,
6945
6124
  terminal: isTTY,