@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 +1 -1
- package/src/chat/natural-language.mjs +39 -7
- package/src/index.mjs +27 -12
- package/src/tools/catalog.mjs +2 -2
- package/src/ui/splash.mjs +18 -9
package/package.json
CHANGED
|
@@ -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"))
|
|
33
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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}
|
|
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(` ${
|
|
50
|
-
process.stdout.write(` ${
|
|
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}
|
|
89
|
-
${DIM}Run with JSON:${RESET} ${GOLD}
|
|
90
|
-
${DIM}Full list:${RESET} ${GOLD}
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
}
|
package/src/tools/catalog.mjs
CHANGED
|
@@ -69,9 +69,9 @@ export const QUICK_WINS = [
|
|
|
69
69
|
status: "ready",
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
|
-
command: `${COMMAND_PREFIX}
|
|
72
|
+
command: `${COMMAND_PREFIX} login`,
|
|
73
73
|
title: "Talk To MangoMagic",
|
|
74
|
-
description: "
|
|
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(
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
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
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
}
|