@mangomagic/cli 0.1.10 → 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.10",
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) {
@@ -140,7 +154,8 @@ async function runToolCommand(argv) {
140
154
 
141
155
  function shouldStartChat(argv) {
142
156
  if (argv.includes("--home") || argv.includes("--no-chat")) return false;
143
- return Boolean(process.stdin.isTTY && process.stdout.isTTY);
157
+ if (process.env.MANGOMAGIC_CLI_NO_CHAT === "1" || process.env.CI === "true") return false;
158
+ return true;
144
159
  }
145
160
 
146
161
  function splashMode() {
@@ -149,15 +164,15 @@ function splashMode() {
149
164
 
150
165
  async function enterChatAfterLogin(startChat) {
151
166
  if (!startChat) return;
152
- process.stdout.write(`\n${DIM}You're in chat mode now. Type ${BOLD}exit${RESET}${DIM} to leave.${RESET}\n`);
153
- await chat(actions());
167
+ sessionIntro();
168
+ await chat(actions(), { showHeader: false });
154
169
  }
155
170
 
156
171
  async function login({ openInBrowser = true, startChat = false } = {}) {
157
172
  if (loadToken()) {
158
- 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`);
159
174
  await playSplash({ mode: splashMode(), greetingLine: "Welcome back to MangoMagic." });
160
- home();
175
+ if (!startChat) home();
161
176
  await enterChatAfterLogin(startChat);
162
177
  return;
163
178
  }
@@ -179,7 +194,7 @@ ${BOLD}Sign in to MangoMagic${RESET}
179
194
  saveToken(creds);
180
195
  process.stdout.write("\n\n");
181
196
  await playSplash({ mode: splashMode(), greetingLine: "You're in. Welcome to MangoMagic." });
182
- home();
197
+ if (!startChat) home();
183
198
  await enterChatAfterLogin(startChat);
184
199
  });
185
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
  }