@mangomagic/cli 0.1.11 → 0.1.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mangomagic/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "MangoMagic CLI — sign in, manage episodes, and expose MangoMagic to MCP clients (Claude Desktop, Cursor).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,6 +20,22 @@ function localPlan(text) {
20
20
  if (!t) return { action: "answer", args: { text: "" } };
21
21
 
22
22
  if (/^(exit|quit|bye)$/i.test(t)) return { action: "exit", args: {} };
23
+ if (/^(hi|hey|hello|yo)\??$/i.test(t)) {
24
+ return {
25
+ action: "answer",
26
+ args: {
27
+ text: "Hey. I'm here in the terminal now. Ask for episodes, talking cards, tools, or MCP setup.",
28
+ },
29
+ };
30
+ }
31
+ if (t.includes("understand me")) {
32
+ return {
33
+ action: "answer",
34
+ args: {
35
+ text: "Yes. Type at the mango> prompt and I will route natural language to MangoMagic tools.",
36
+ },
37
+ };
38
+ }
23
39
  if (t.includes("brand doc") || t.includes("brand colour") || t.includes("brand color")) {
24
40
  return { action: "open_brand_doc", args: {} };
25
41
  }
@@ -29,12 +45,20 @@ function localPlan(text) {
29
45
  if (t.includes("mcp") && (t.includes("config") || t.includes("connect") || t.includes("claude") || t.includes("cursor") || t.includes("codex"))) {
30
46
  return { action: "mcp_config", args: {} };
31
47
  }
32
- if (t.includes("tool") || t.includes("what can")) return { action: "show_tools", args: {} };
33
- if (t.includes("latest episode") || t.includes("recent episode") || t === "episodes" || t.includes("list episodes")) {
34
- return { action: "list_episodes", args: { limit: 5 } };
48
+ if (t.includes("tool") || t.includes("what can")) {
49
+ return { action: "show_tools", args: { all: /\b(all|every|full|complete)\b/.test(t) } };
35
50
  }
36
51
  const searchMatch = raw.match(/search(?: my)? episodes? (?:for|about)\s+(.+)/i);
37
52
  if (searchMatch?.[1]) return { action: "search_episodes", args: { query: searchMatch[1] } };
53
+ if (
54
+ t.includes("latest episode") ||
55
+ t.includes("recent episode") ||
56
+ t === "episodes" ||
57
+ t.includes("list episodes") ||
58
+ (/\bepisodes?\b/.test(t) && /\b(what|which|have|got|my|show)\b/.test(t))
59
+ ) {
60
+ return { action: "list_episodes", args: { limit: 5 } };
61
+ }
38
62
  const getMatch = raw.match(/(?:get|show|open)(?: episode)?\s+([a-z0-9][a-z0-9_-]{5,})/i);
39
63
  if (getMatch?.[1]) return { action: "get_episode", args: { episode: getMatch[1] } };
40
64
  if (t.includes("home") || t.includes("help")) return { action: "home", args: {} };
@@ -181,7 +205,7 @@ ${DIM}${err?.message ?? err}${RESET}
181
205
  case "open_brand_doc":
182
206
  return actions.openPath("/carousels/doc");
183
207
  case "show_tools":
184
- return actions.tools();
208
+ return actions.tools({ all: Boolean(args.all) });
185
209
  case "mcp_config":
186
210
  return actions.mcpConfig();
187
211
  case "home":
@@ -223,17 +247,25 @@ ${DIM}${err?.message ?? err}${RESET}
223
247
  }
224
248
  }
225
249
 
226
- export async function chat(actions) {
250
+ export async function chat(actions, { showHeader = true } = {}) {
227
251
  const rl = readline.createInterface({ input, output });
228
- process.stdout.write(`
252
+ if (showHeader) {
253
+ process.stdout.write(`
229
254
  ${BOLD}MangoMagic Chat${RESET}
230
255
  Type what you want. Try: ${GOLD}create talking cards about AI adoption${RESET}
231
256
  Type ${DIM}exit${RESET} to leave.
232
257
 
233
258
  `);
259
+ }
234
260
  try {
235
261
  while (true) {
236
- const text = await rl.question(`${GOLD}mango>${RESET} `);
262
+ let text;
263
+ try {
264
+ text = await rl.question(`${GOLD}mango>${RESET} `);
265
+ } catch (err) {
266
+ if (err?.message === "readline was closed") break;
267
+ throw err;
268
+ }
237
269
  const result = await handleNaturalLanguage(text, actions);
238
270
  if (result === "exit") break;
239
271
  process.stdout.write("\n");
package/src/index.mjs CHANGED
@@ -35,7 +35,20 @@ ${BOLD}mangomagic${RESET} ${DIM}— sign into MangoMagic and bring your account
35
35
  Token cache: ${credentialsPath()}
36
36
 
37
37
  If \`mangomagic\` is not installed globally, use:
38
- ${GOLD}${COMMAND_PREFIX} chat${RESET}
38
+ ${GOLD}${COMMAND_PREFIX} login${RESET}
39
+ `);
40
+ }
41
+
42
+ function sessionIntro() {
43
+ process.stdout.write(`
44
+ ${BOLD}You can type naturally now.${RESET}
45
+
46
+ Try:
47
+ ${GOLD}what episodes do I have?${RESET}
48
+ ${GOLD}create 3 talking cards about founder-led sales${RESET}
49
+ ${GOLD}show me all of your tools${RESET}
50
+
51
+ ${DIM}Type ${BOLD}exit${RESET}${DIM} to leave. Add ${BOLD}--home${RESET}${DIM} next time if you only want the menu.${RESET}
39
52
  `);
40
53
  }
41
54
 
@@ -46,8 +59,9 @@ ${BOLD}What can MangoMagic do now?${RESET}
46
59
  ${DIM}Fast wins:${RESET}
47
60
  `);
48
61
  for (const item of QUICK_WINS) {
49
- process.stdout.write(` ${GOLD}${item.command.padEnd(24)}${RESET} ${BOLD}${item.title}${RESET}\n`);
50
- process.stdout.write(` ${DIM}${"".padEnd(24)} ${item.description}${RESET}\n`);
62
+ process.stdout.write(` ${BOLD}${item.title}${RESET}\n`);
63
+ process.stdout.write(` ${GOLD}${item.command}${RESET}\n`);
64
+ process.stdout.write(` ${DIM}${item.description}${RESET}\n\n`);
51
65
  }
52
66
  process.stdout.write(`
53
67
  ${DIM}Try this in Claude, Cursor, or Codex after MCP is connected:${RESET}
@@ -85,9 +99,9 @@ ${DIM}Core tools available now:${RESET}
85
99
 
86
100
  process.stdout.write(`
87
101
  ${DIM}Catalog:${RESET} ${ALL_MCP_TOOL_CATALOG.length} tools total (${MCP_TOOL_CATALOG.length} core, ${ALL_MCP_TOOL_CATALOG.length - MCP_TOOL_CATALOG.length} business/admin/raw tools).
88
- ${DIM}Run:${RESET} ${GOLD}mangomagic tool get_user_stats${RESET}
89
- ${DIM}Run with JSON:${RESET} ${GOLD}mangomagic tool get_user_episodes '{"limit":3}'${RESET}
90
- ${DIM}Full list:${RESET} ${GOLD}mangomagic tools --all${RESET}
102
+ ${DIM}Run:${RESET} ${GOLD}${COMMAND_PREFIX} tool get_user_stats${RESET}
103
+ ${DIM}Run with JSON:${RESET} ${GOLD}${COMMAND_PREFIX} tool get_user_episodes '{"limit":3}'${RESET}
104
+ ${DIM}Full list:${RESET} ${GOLD}${COMMAND_PREFIX} tools --all${RESET}
91
105
  `);
92
106
 
93
107
  if (all) {
@@ -150,15 +164,15 @@ function splashMode() {
150
164
 
151
165
  async function enterChatAfterLogin(startChat) {
152
166
  if (!startChat) return;
153
- process.stdout.write(`\n${DIM}You're in chat mode now. Type ${BOLD}exit${RESET}${DIM} to leave.${RESET}\n`);
154
- await chat(actions());
167
+ sessionIntro();
168
+ await chat(actions(), { showHeader: false });
155
169
  }
156
170
 
157
171
  async function login({ openInBrowser = true, startChat = false } = {}) {
158
172
  if (loadToken()) {
159
- process.stdout.write(`${DIM}You're already signed in. Run \`mangomagic logout\` first to switch accounts.${RESET}\n`);
173
+ process.stdout.write(`${DIM}You're already signed in. Continuing in MangoMagic.${RESET}\n`);
160
174
  await playSplash({ mode: splashMode(), greetingLine: "Welcome back to MangoMagic." });
161
- home();
175
+ if (!startChat) home();
162
176
  await enterChatAfterLogin(startChat);
163
177
  return;
164
178
  }
@@ -180,7 +194,7 @@ ${BOLD}Sign in to MangoMagic${RESET}
180
194
  saveToken(creds);
181
195
  process.stdout.write("\n\n");
182
196
  await playSplash({ mode: splashMode(), greetingLine: "You're in. Welcome to MangoMagic." });
183
- home();
197
+ if (!startChat) home();
184
198
  await enterChatAfterLogin(startChat);
185
199
  });
186
200
  }
@@ -69,9 +69,9 @@ export const QUICK_WINS = [
69
69
  status: "ready",
70
70
  },
71
71
  {
72
- command: `${COMMAND_PREFIX} chat`,
72
+ command: `${COMMAND_PREFIX} login`,
73
73
  title: "Talk To MangoMagic",
74
- description: "Type natural language and let the CLI choose the right MangoMagic action.",
74
+ description: "Enter chat mode, type natural language, and let the CLI choose the right MangoMagic action.",
75
75
  status: "ready",
76
76
  },
77
77
  {
package/src/ui/splash.mjs CHANGED
@@ -35,6 +35,7 @@ const WHITEC = [255, 255, 255];
35
35
  const DIMC = [110, 78, 12];
36
36
 
37
37
  const RESET = "\x1b[0m";
38
+ const ESC = "\x1b[";
38
39
 
39
40
  const rgb = (c) => `\x1b[38;2;${c[0]};${c[1]};${c[2]}m`;
40
41
  const lerp = (a, b, t) => [
@@ -217,9 +218,15 @@ export async function playSplash({ mode = "static", greetingLine = null } = {})
217
218
  }
218
219
 
219
220
  const fps = 14;
220
- const total = mode === "loop" ? Number.MAX_SAFE_INTEGER : Math.floor(2.8 * fps);
221
-
222
- process.stdout.write("\x1b[?25l"); // hide cursor
221
+ const total = mode === "loop" ? Number.MAX_SAFE_INTEGER : Math.floor(1.15 * fps);
222
+ const useAltScreen = process.stdout.isTTY && process.env.MANGOMAGIC_SPLASH_INLINE !== "1";
223
+ const renderFrame = (body) => {
224
+ process.stdout.write(`${ESC}H${ESC}2J`);
225
+ process.stdout.write(body);
226
+ process.stdout.write("\n\n" + tag + greet + "\n");
227
+ };
228
+
229
+ process.stdout.write(useAltScreen ? `${ESC}?1049h${ESC}?25l` : `${ESC}?25l`);
223
230
  let interrupted = false;
224
231
  const onSig = () => { interrupted = true; };
225
232
  process.on("SIGINT", onSig);
@@ -229,15 +236,17 @@ export async function playSplash({ mode = "static", greetingLine = null } = {})
229
236
  if (Math.random() < 0.08 && shooters.length < 2) shooters.push(new Shooter(width, height));
230
237
  for (const sh of shooters) sh.life += 1;
231
238
  shooters = shooters.filter(s => s.life < 6);
232
- process.stdout.write("\x1b[H\x1b[2J");
233
- process.stdout.write(render(width, height, iconTop, wordTop, stars, shooters, f));
234
- process.stdout.write("\n\n" + tag + greet + "\n");
239
+ renderFrame(render(width, height, iconTop, wordTop, stars, shooters, f));
235
240
  await sleep(1000 / fps);
236
241
  }
237
242
  } finally {
238
243
  process.off("SIGINT", onSig);
239
- process.stdout.write("\x1b[H\x1b[2J");
240
- process.stdout.write(renderSettled());
241
- process.stdout.write("\n\n" + tag + greet + "\n\x1b[?25h");
244
+ if (useAltScreen) {
245
+ process.stdout.write(`${ESC}?25h${ESC}?1049l`);
246
+ process.stdout.write(renderSettled() + "\n\n" + tag + greet + "\n");
247
+ } else {
248
+ renderFrame(renderSettled());
249
+ process.stdout.write(`${ESC}?25h`);
250
+ }
242
251
  }
243
252
  }